Index: GTP/trunk/Lib/Vis/Preprocessing/include/Polygon3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/Polygon3.h	(revision 262)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/Polygon3.h	(revision 262)
@@ -0,0 +1,54 @@
+#ifndef _Polygon3_h__
+#define _Polygon3_h__
+
+
+//#include <iostream>
+//#include <math.h>
+//#include "common.h"
+#include "Containers.h"
+#include <queue>
+
+class Mesh;
+class Plane3;
+class Face;
+
+namespace GtpVisibilityPreprocessor {
+
+/** Class representing a general planar polygon in 3d.
+*/
+class Polygon3
+{
+public:
+	Polygon3();
+	Polygon3(const VertexContainer &vertices);
+
+	/** Copies all the vertices of the face.
+	*/
+	Polygon3(Face *face, Mesh *parent);
+	
+	/** Returns supporting plane of this polygon.
+	*/
+	Plane3 GetSupportingPlane();
+
+	/** Splits polygon.
+		@param partition the split plane
+		@param front the front polygon
+		@param back the back polygon
+		@param splits number of splits
+	*/
+	void Split(Plane3 *partition, Polygon3 *front, Polygon3 *back, int &splits);
+
+	enum {BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT};
+
+	/** Side of the plane where the polygon is located.
+	    @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT
+	*/
+	int Side(Plane3 *plane);
+
+	/// vertices are connected in counterclockwise order.
+	VertexContainer mVertices;
+};
+
+}
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/ViewCell.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/ViewCell.h	(revision 219)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/ViewCell.h	(revision 219)
@@ -0,0 +1,24 @@
+#ifndef _ViewCell_H__
+#define _ViewCell_H__
+
+class Mesh;
+
+namespace GtpVisibilityPreprocessor {
+  
+/**
+	View cell represented as a mesh.
+*/
+class ViewCell
+{
+public:
+	ViewCell(Mesh *mesh);
+
+	Mesh *GetMesh() {return mMesh;}
+protected:
+
+	Mesh *mMesh;
+};
+  
+}; // GtpVisibilityPreprocessor
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/ExactPreprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/ExactPreprocessor.h	(revision 68)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/ExactPreprocessor.h	(revision 68)
@@ -0,0 +1,17 @@
+#ifndef _ExactPreprocessor_H__
+#define _ExactPreprocessor_H__
+
+#include "Preprocessor.h"
+
+namespace GtpVisibilityPreprocessor {
+  /** Exact visibility preprocessing. The implementation is based on 6D BSP and
+      Plucker coordinates */
+  class ExactPreprocessor : public Preprocessor {
+  public:
+    virtual bool ComputeVisibility();
+  };
+  
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/Mesh.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/Mesh.h	(revision 68)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/Mesh.h	(revision 68)
@@ -0,0 +1,49 @@
+#ifndef _Mesh_H__
+#define _Mesh_H__
+
+#include <vector>
+#include "Plane3.h"
+
+namespace GtpVisibilityPreprocessor {
+
+  /** Patch used as an element of the mesh */
+  class Patch {
+  public:
+    Patch():mVertices() {}
+  protected:
+    /// list of vertex pointers
+    vector<Vector3 *> mVertices;
+  };
+
+  /** Mesh containing polygonal patches */
+  class Mesh {
+  public:
+    /// default vertex container for Mesh
+    typedef std::vector<Vector3> VertexContainer;
+    /// default patch container for Mesh
+    typedef std::vector<Patch *> PatchContainer;
+
+    /// Default constructor
+    Mesh():mVertices(), mPatches() {}
+
+    /// Constructor with container preallocation
+    Mesh(const int vertices,
+	 const int patches):mVertices(),
+			    mPatches()
+    {
+      mVertices.reserve(vertices);
+      mPatches.reserve(patches);
+    }
+    
+  protected:
+    /** Vertices forming the mesh */
+    VertexContainer mVertices;
+    /** Patches forming the mesh */
+    PatchContainer mPatches;
+  };
+  
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/KdTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/KdTree.h	(revision 68)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/KdTree.h	(revision 68)
@@ -0,0 +1,119 @@
+#ifndef _KdTree_H__
+#define _KdTree_H__
+
+#include "Containers.h"
+#include "AxisAlignedBox3.h"
+
+namespace GtpVisibilityPreprocessor {
+  
+  class KdNode;
+  /** KdTree for indexing scene entities - occluders/occludees/viewcells */
+  class KdTree {
+  public:
+
+    /** Insert occluder into the tree */
+    virtual void InsertOccluder(Mesh *occluder) {
+      //      mRoot->mOccluders.push_back(occluder);
+    }
+
+    /** Insert occludee into the tree */
+    virtual void InsertOccludee(Mesh *occludee) {
+      //      mRoot->mOccludees.push_back(occludee);
+    }
+    
+    /** Insert view cell into the tree */
+    virtual void InsertViewCell(ViewCell *viewCell) {
+      //      mRoot->mViewcells.push_back(viewCell);
+    }
+    
+    /** Check whether subdivision criteria are met for the given subtree.
+	If not subdivide the leafs of the subtree. The criteria are specified in
+	the environment as well as the subdivision method. By default surface area
+	heuristics is used.
+	
+	@param subtree root of the subtree
+
+	@return true if subdivision was performed, false if subdivision criteria
+	were already met
+    */
+    virtual bool Subdivide(KdNode *subtree);
+
+    /** Get the root of the tree */
+    KdNode *GetRoot() const {
+      return mRoot;
+    }
+
+  protected:
+    /// root of the tree
+    KdNode *mRoot;
+    /// bounding box of the tree root
+    AxisAlignedBox3 mBox;
+  };
+  
+  
+  class KdInterior;
+  /** Abstract class for kd-tree node */
+  class KdNode {
+
+    /** Determines whether this node is a leaf or interior node
+	@return true if leaf
+    */
+    virtual bool IsLeaf() const = 0;
+
+    /** Determines whether this node is the root of the tree
+	@return true if root
+    */
+    virtual bool IsRoot() const {
+      return mParent == NULL;
+    }
+
+  protected:
+    /** Parent of the node - the parent is a little overhead for maintanance of the tree,
+	but allows various optimizations of tree traversal algorithms */
+    KdInterior *mParent;
+  };
+
+  /** Implementation of the kd-tree interior node */
+  class KdInterior : public KdNode {
+
+  public:
+    /** \sa KdNode::IsLeaf() */
+    virtual bool IsLeaf() const { return false; }
+
+  protected:
+    /** splitting axis */
+    int axis;
+    /** splitting position, absolute position within the bounding box of this node */
+    float mPosition;
+
+    /** back node */
+    KdNode *mBack;
+    /** front node */
+    KdNode *mFront;
+
+  };
+  
+  
+  /** Implementation of the kd-tree leaf node */
+  class KdLeaf : public KdNode {
+  public:
+    /** \sa KdNode::IsLeaf() */
+    virtual bool IsLeaf() const { return true; }
+
+  protected:
+    /** pointers to occluders contained in this node */
+    MeshContainer mOccluders;
+    /** pointers to occludees contained in this node */
+    MeshContainer mOccludees;
+    /** pointers to viewcells contained in this node */
+    ViewCellContainer mViewCells;
+  };
+  
+  
+  
+};
+
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/SceneGraph.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/SceneGraph.h	(revision 68)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/SceneGraph.h	(revision 68)
@@ -0,0 +1,33 @@
+#ifndef _SceneGraph_H__
+#define _SceneGraph_H__
+
+#include "Containers.h"
+#include "AxisAlignedBox3.h"
+
+namespace GtpVisibilityPreprocessor {
+  
+  /** Basic scene graph node, we are interested only in bounding boxes and topology
+      of the scene graph */
+  class SceneGraphNode {
+  public:
+    
+    
+  protected:
+    MeshContainer mGeometry;
+    NodeContainer mChildren;
+    AxisAlignedBox3 mBox;
+  };
+  
+
+  /** Scene graph class */
+  class SceneGraph {
+    
+  protected:
+    SceneGraphNode *mRoot;
+  };
+  
+
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/ViewCellBsp.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/ViewCellBsp.h	(revision 236)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/ViewCellBsp.h	(revision 236)
@@ -0,0 +1,87 @@
+#ifndef _ViewCellBsp_H__
+#define _ViewCellBsp_H__
+
+#include "Containers.h"
+
+class ViewCell;
+class Plane3;
+
+namespace GtpVisibilityPreprocessor {
+  
+  class BspInterior;
+
+  /**
+     BspNode abstract class serving for interior and leaf node implementation
+  */
+  class BspNode 
+  {
+  public:
+	  /** Determines whether this node is a leaf or not
+	  @return true if leaf
+	  */
+	  virtual bool IsLeaf() const = 0;
+    
+	  /** Determines whether this node is a root
+	  @return true if root
+	  */
+	  virtual bool IsRoot() const;
+  
+  protected:
+
+	  /// parent of this node
+	  BspInterior *mParent;
+  };
+
+  /** BSP interior node implementation */
+  class BspInterior : public BspNode 
+  {    
+	  /** @return false since it is an interior node */
+	  bool IsLeaf() const;
+  
+  protected:
+	  /// Splitting plane corresponding to this node
+	  Plane3 mPlane;
+	  /// back node
+	  BspNode *mBack;
+	  /// front node
+	  BspNode *mFront;
+  };
+  
+  
+  /** BSP leaf node implementation.
+  */
+  class BspLeaf : public BspNode 
+  {
+  public:
+	  BspLeaf(ViewCell *viewCell = NULL);
+	  /** @return true since it is an interior node */
+	  virtual bool IsLeaf();
+
+  protected:
+	  /// polygonal representation of this viewcell
+	  /// if NULL this note does not correspond to feasible viewcell
+	  ViewCell *mViewCell;
+  };
+  
+  /** Implementation of the ViewCell BSP tree.
+  */
+  class BspTree 
+  {
+  public:
+	  /** Default constructor.
+	  */
+	  BspTree();
+        
+  protected:
+
+	  /// Pointer to the root of the tree
+	  BspNode *mRoot;
+	  /// Pointer to the root cell of the viewspace */
+	  ViewCell *mRootCell;
+
+
+  };
+  
+}; // GtpVisibilityPreprocessor
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/SamplingPreprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/SamplingPreprocessor.h	(revision 68)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/SamplingPreprocessor.h	(revision 68)
@@ -0,0 +1,18 @@
+#ifndef _SamplingPreprocessor_H__
+#define _SamplingPreprocessor_H__
+
+#include "Preprocessor.h"
+
+namespace GtpVisibilityPreprocessor {
+
+  /** Sampling based visibility preprocessing. The implementation is based on heuristical
+      sampling of view space */
+  class SamplingPreprocessor : public Preprocessor {
+  public:
+    virtual bool ComputeVisibility();
+  };
+  
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/Plane3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/Plane3.h	(revision 68)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/Plane3.h	(revision 68)
@@ -0,0 +1,20 @@
+#ifndef _Plane3_H__
+#define _Plane3_H__
+
+#include "vector3.h"
+
+namespace GtpVisibilityPreprocessor {
+  
+  /** 3D Plane */
+  class Plane3 {
+  public:
+    Vector3 mNormal;
+    float mD;
+  };
+  
+  
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/AxisAlignedBox3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/AxisAlignedBox3.h	(revision 68)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/AxisAlignedBox3.h	(revision 68)
@@ -0,0 +1,19 @@
+#ifndef _AxisAlignedBox3_H__
+#define _AxisAlignedBox3_H__
+
+#include "vector3.h"
+
+
+namespace GtpVisibilityPreprocessor {
+  
+  /** Axis aligned box */
+  class AxisAlignedBox3 {
+  protected:
+    Vector3 min, max;
+  };
+  
+
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/Containers.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/Containers.h	(revision 68)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/Containers.h	(revision 68)
@@ -0,0 +1,24 @@
+#ifndef _Container_H__
+#define _Container_H__
+
+#include <vector>
+using namespace std;
+
+namespace GtpVisibilityPreprocessor {
+  class Mesh;
+  class ViewCell;
+  class HierarchyNode;
+  /** Container for Mesh pointers primarily for the use within the kDTree and
+      BSP hierarchies */
+  typedef vector<Mesh *> MeshContainer;
+  /** Container for ViewCell pointers primarily for the use within the kDTree and
+      BSP hierarchies */
+  typedef vector<ViewCell *> ViewCellContainer;
+  /** Container for HierarchyNodes pointers primarily for the use within the kDTree and
+      BSP hierarchies */
+  typedef vector<HierarchyNode *> NodeContainer;
+};
+
+
+#endif // _Container_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/include/Vector3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/Vector3.h	(revision 68)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/Vector3.h	(revision 68)
@@ -0,0 +1,17 @@
+#ifndef _Vector3_H__
+#define _Vector3_H__
+
+
+namespace GtpVisibilityPreprocessor {
+  /** 3D vector */
+  class Vector3 {
+  public:
+    float x, y, z;
+  };
+  
+  
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/include/Preprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/include/Preprocessor.h	(revision 439)
+++ GTP/trunk/Lib/Vis/Preprocessing/include/Preprocessor.h	(revision 439)
@@ -0,0 +1,80 @@
+#ifndef _Preprocessor_H__
+#define _Preprocessor_H__
+
+#include "Containers.h"
+#include "Mesh.h"
+#include "KdTree.h"
+#include "ViewCellBsp.h"
+#include "SceneGraph.h"
+#include <string>
+
+/** Namespace for the external visibility preprocessor
+
+    This namespace includes all classes which are created by the VUT (Vienna University
+    of Technology) for the External Visibility Preprocessor of the GTP (GameTools Project)
+    (www.gametools.org).
+ */
+namespace GtpVisibilityPreprocessor {
+  /** Main class of the visibility preprocessor. Responsible for loading and
+      saving of the input and output files. Initiates construction of the kD-tree,
+      viewcell loading/generation and the visibility computation itself.
+  */
+  class Preprocessor {
+  public:
+    /** Load the input scene. 
+	@param filename file to load
+	@return true on success
+    */
+    virtual bool LoadScene(const string filename);
+
+    /** Generate the viewCells automatically. The particular algorithm to be used depends
+	on the environment setting. Initially the generated viewcells will cover the whole
+	bounding volume of the scene. They can be pruned later depending on the results
+	of visibility computations.
+	@return true on successful viewcell generation.
+    */
+    virtual bool GenerateViewCells();
+    
+    /** Export all preprocessed data in a XML format understandable by the
+	PreprocessingInterface of the GtpVisibilityPreprocessor Module. The file can be compressed depending
+	on the environement settings.
+	@return true on successful export
+    */
+    virtual bool ExportPreprocessedData(const string filename);
+
+    /** Build the KdTree of currently loaded occluders/occludees/viewcells. The construction
+	is driven by the environment settings, which also sais which of the three types of
+	entities should be used to drive the heuristical construction (only occluders by default)
+    */
+    virtual bool BuildKdTree();
+
+    /** Compute visibility method. This method has to be reimplemented by the actual
+	Preprocessor implementation (e.g. SamplingPreprocessor, ExactPreprocessor,
+	GlobalSamplingpreprocessor)
+    */
+    virtual bool ComputeVisibility() = 0;
+
+
+  protected:
+    /// scene graph loaded from file
+    SceneGraph *mSceneGraph;
+    /// BSP tree representing the viewcells
+    BspTree *mViewCellBspTree;
+    /// kD-tree organizing the scene graph (occluders + occludees) + viewcells
+    KdTree *mKdTree;
+
+    /// list of all loaded occluders
+    MeshContainer mOccluders;
+    /// list of all loaded occludees
+    MeshContainer mOccludees;
+    /// list of all loaded/generated viewcells
+    ViewCellContainer mViewcells;
+
+  };
+  
+};
+
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/scripts/preprocessor.pro
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/scripts/preprocessor.pro	(revision 177)
+++ GTP/trunk/Lib/Vis/Preprocessing/scripts/preprocessor.pro	(revision 177)
@@ -0,0 +1,21 @@
+
+TEMPLATE = app
+
+TARGET = preprocessor
+
+INCLUDEPATH += ../src 
+
+# debuc config
+CONFIG		+= console warn_on debug thread
+
+# RELEASE CONFIG
+#CONFIG		+= windows warn_on thread
+
+# DEPENDPATH	= ../../include
+
+# Input
+HEADERS += 
+
+	
+SOURCES += Preprocessor.cpp SamplingPreprocessor.cpp ExactPreprocessor.cpp KdTree.cpp
+
Index: GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj	(revision 580)
+++ GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj	(revision 580)
@@ -0,0 +1,491 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="Preprocessor"
+	ProjectGUID="{EABCE292-D598-4600-A1C9-2591E7D62FDA}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\lib\$(ConfigurationName)"
+			IntermediateDirectory="..\obj\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\support;..\support\devil\include;..\support\zlib\include;..\include;&quot;$(QTDIR)&quot;\include;&quot;$(QTDIR)\include\QtCore&quot;;&quot;$(QTDIR)\include\QtGui&quot;;&quot;$(QTDIR)\include&quot;;&quot;$(QTDIR)\include\QtOpenGl&quot;;..\src;&quot;$(CG_INC_PATH)&quot;"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/GtpVisibility.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\bin\$(ConfigurationName)"
+			IntermediateDirectory="..\obj\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\support;..\support\devil\include;..\support\zlib\include;..\include;&quot;$(QTDIR)\include\QtCore&quot;;&quot;$(QTDIR)\include\QtGui&quot;;&quot;$(QTDIR)\include&quot;;&quot;$(QTDIR)\include\QtOpenGl&quot;;..\src;&quot;$(CG_INC_PATH)&quot;"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
+				RuntimeLibrary="2"
+				DisableLanguageExtensions="FALSE"
+				ForceConformanceInForLoopScope="FALSE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="xerces-c_2.lib zdll.lib zziplib.lib devil.lib qtmain.lib QtOpenGL4.lib QtCore4.lib QtGui4.lib Qt3Supportd4.lib QAxContainer.lib glut32.lib OpenGL32.Lib glu32.lib cg.lib cgGL.lib"
+				AdditionalLibraryDirectories="..\support\xercesc\lib\;..\support\zlib\lib\;..\support\devil\lib;&quot;$(QTDIR)\lib&quot;;..\include;..\src\GL;&quot;$(CG_LIB_PATH)&quot;"
+				LargeAddressAware="2"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+			<File
+				RelativePath="..\src\AxisAlignedBox3.cpp">
+			</File>
+			<File
+				RelativePath="..\src\AxisAlignedBox3.h">
+			</File>
+			<File
+				RelativePath="..\src\Beam.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Beam.h">
+			</File>
+			<File
+				RelativePath="..\src\Camera.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Camera.h">
+			</File>
+			<File
+				RelativePath="..\src\common.cpp">
+			</File>
+			<File
+				RelativePath="..\src\common.h">
+			</File>
+			<File
+				RelativePath="..\src\Containers.h">
+			</File>
+			<File
+				RelativePath="..\src\dual_depth.cg">
+			</File>
+			<File
+				RelativePath="..\src\Environment.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Environment.h">
+			</File>
+			<File
+				RelativePath="..\src\ExactPreprocessor.cpp">
+			</File>
+			<File
+				RelativePath="..\src\ExactPreprocessor.h">
+			</File>
+			<File
+				RelativePath="..\src\Exporter.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Exporter.h">
+			</File>
+			<File
+				RelativePath="..\src\GlRenderer.cpp">
+			</File>
+			<File
+				RelativePath="..\src\GlRenderer.h">
+				<FileConfiguration
+					Name="Release|Win32">
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Performing moc on $(InputName).h"
+						CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp
+"
+						Outputs="$(InputDir)moc_$(InputName).cpp"/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\src\gzstream.cpp">
+			</File>
+			<File
+				RelativePath="..\src\gzstream.h">
+			</File>
+			<File
+				RelativePath="..\src\Halton.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Halton.h">
+			</File>
+			<File
+				RelativePath="..\src\Intersectable.h">
+			</File>
+			<File
+				RelativePath="..\src\KdTree.cpp">
+			</File>
+			<File
+				RelativePath="..\src\KdTree.h">
+			</File>
+			<File
+				RelativePath="..\src\main.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Material.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Material.h">
+			</File>
+			<File
+				RelativePath="..\src\Matrix4x4.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Matrix4x4.h">
+			</File>
+			<File
+				RelativePath="..\src\Mesh.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Mesh.h">
+			</File>
+			<File
+				RelativePath="..\src\MeshKdTree.cpp">
+			</File>
+			<File
+				RelativePath="..\src\MeshKdTree.h">
+			</File>
+			<File
+				RelativePath="..\src\moc_GlRenderer.cpp">
+			</File>
+			<File
+				RelativePath="..\src\moc_Preprocessor.cpp">
+			</File>
+			<File
+				RelativePath="..\src\moc_PreprocessorThread.cpp">
+			</File>
+			<File
+				RelativePath="..\src\MutualVisibility.cpp">
+			</File>
+			<File
+				RelativePath="..\src\MutualVisibility.h">
+			</File>
+			<File
+				RelativePath="..\src\Parser.h">
+			</File>
+			<File
+				RelativePath="..\src\Plane3.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Plane3.h">
+			</File>
+			<File
+				RelativePath="..\src\Polygon3.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Polygon3.h">
+			</File>
+			<File
+				RelativePath="..\src\Polytope.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Polytope.h">
+			</File>
+			<File
+				RelativePath="..\src\Preprocessor.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Preprocessor.h">
+				<FileConfiguration
+					Name="Release|Win32">
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Performing moc on $(InputName).h"
+						CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp
+"
+						Outputs="$(InputDir)moc_$(InputName).cpp"/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\src\PreprocessorThread.cpp">
+			</File>
+			<File
+				RelativePath="..\src\PreprocessorThread.h">
+				<FileConfiguration
+					Name="Release|Win32">
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Performing moc on $(InputName).h"
+						CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp
+"
+						Outputs="$(InputDir)moc_$(InputName).cpp"/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\src\Pvs.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Pvs.h">
+			</File>
+			<File
+				RelativePath="..\src\Ray.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Ray.h">
+			</File>
+			<File
+				RelativePath="..\src\RayInfo.cpp">
+			</File>
+			<File
+				RelativePath="..\src\RayInfo.h">
+			</File>
+			<File
+				RelativePath="..\src\Rectangle3.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Rectangle3.h">
+			</File>
+			<File
+				RelativePath="..\src\Renderer.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Renderer.h">
+			</File>
+			<File
+				RelativePath="..\src\RenderSimulator.cpp">
+			</File>
+			<File
+				RelativePath="..\src\RenderSimulator.h">
+			</File>
+			<File
+				RelativePath="..\src\RssPreprocessor.cpp">
+			</File>
+			<File
+				RelativePath="..\src\RssPreprocessor.h">
+			</File>
+			<File
+				RelativePath="..\src\RssTree.cpp">
+			</File>
+			<File
+				RelativePath="..\src\RssTree.h">
+			</File>
+			<File
+				RelativePath="..\src\SamplingPreprocessor.cpp">
+			</File>
+			<File
+				RelativePath="..\src\SamplingPreprocessor.h">
+			</File>
+			<File
+				RelativePath="..\src\SceneGraph.cpp">
+			</File>
+			<File
+				RelativePath="..\src\SceneGraph.h">
+			</File>
+			<File
+				RelativePath="..\src\Statistics.h">
+			</File>
+			<File
+				RelativePath="..\src\Tetrahedron3.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Tetrahedron3.h">
+			</File>
+			<File
+				RelativePath="..\src\Triangle3.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Triangle3.h">
+			</File>
+			<File
+				RelativePath="..\src\UnigraphicsParser.cpp">
+			</File>
+			<File
+				RelativePath="..\src\UnigraphicsParser.h">
+			</File>
+			<File
+				RelativePath="..\src\Vector3.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Vector3.h">
+			</File>
+			<File
+				RelativePath="..\src\ViewCell.cpp">
+			</File>
+			<File
+				RelativePath="..\src\ViewCell.h">
+			</File>
+			<File
+				RelativePath="..\src\ViewCellBsp.cpp">
+			</File>
+			<File
+				RelativePath="..\src\ViewCellBsp.h">
+			</File>
+			<File
+				RelativePath="..\src\ViewCellsManager.cpp">
+			</File>
+			<File
+				RelativePath="..\src\ViewCellsManager.h">
+			</File>
+			<File
+				RelativePath="..\src\ViewCellsParser.cpp">
+			</File>
+			<File
+				RelativePath="..\src\ViewCellsParser.h">
+			</File>
+			<File
+				RelativePath="..\src\ViewCellsParserXerces.h">
+			</File>
+			<File
+				RelativePath="..\src\VspBspTree.cpp">
+			</File>
+			<File
+				RelativePath="..\src\VspBspTree.h">
+			</File>
+			<File
+				RelativePath="..\src\VspKdTree.cpp">
+			</File>
+			<File
+				RelativePath="..\src\VspKdTree.h">
+			</File>
+			<File
+				RelativePath="..\src\VssPreprocessor.cpp">
+			</File>
+			<File
+				RelativePath="..\src\VssPreprocessor.h">
+			</File>
+			<File
+				RelativePath="..\src\VssRay.cpp">
+			</File>
+			<File
+				RelativePath="..\src\VssRay.h">
+			</File>
+			<File
+				RelativePath="..\src\VssTree.cpp">
+			</File>
+			<File
+				RelativePath="..\src\VssTree.h">
+			</File>
+			<File
+				RelativePath="..\src\X3dExporter.cpp">
+			</File>
+			<File
+				RelativePath="..\src\X3dExporter.h">
+			</File>
+			<File
+				RelativePath="..\src\X3dParser.cpp">
+			</File>
+			<File
+				RelativePath="..\src\X3dParser.h">
+			</File>
+			<File
+				RelativePath="..\src\X3dParserXerces.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+			<File
+				RelativePath="..\include\AxisAlignedBox3.h">
+			</File>
+			<File
+				RelativePath="..\include\Containers.h">
+			</File>
+			<File
+				RelativePath="..\include\ExactPreprocessor.h">
+			</File>
+			<File
+				RelativePath="..\include\KdTree.h">
+			</File>
+			<File
+				RelativePath="..\include\Mesh.h">
+			</File>
+			<File
+				RelativePath="..\include\Plane3.h">
+			</File>
+			<File
+				RelativePath="..\include\Polygon3.h">
+			</File>
+			<File
+				RelativePath="..\include\Preprocessor.h">
+			</File>
+			<File
+				RelativePath="..\include\SamplingPreprocessor.h">
+			</File>
+			<File
+				RelativePath="..\include\SceneGraph.h">
+			</File>
+			<File
+				RelativePath="..\include\Vector3.h">
+			</File>
+			<File
+				RelativePath="..\include\ViewCell.h">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: GTP/trunk/Lib/Vis/Preprocessing/scripts/default.env
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/scripts/default.env	(revision 612)
+++ GTP/trunk/Lib/Vis/Preprocessing/scripts/default.env	(revision 612)
@@ -0,0 +1,447 @@
+#############################################################################
+# ERS default configuration file
+# Jiri Bittner 2003
+#############################################################################
+
+Scene {
+
+#	filename glasgow1.x3d
+#	filename vienna.x3d
+#	filename ../data/vienna/vienna-simple.x3d
+#	filename ../data/vienna/vienna-buildings.x3d
+#filename ../data/vienna/vienna-buildings.x3d;../data/vienna/vienna-roofs.x3d
+#;../data/vienna/vienna-plane.x3d
+#	filename ../data/vienna/viewcells-25-sel.x3d
+	filename ../data/atlanta/atlanta2.x3d
+#	filename ../data/soda/soda.dat
+#	filename ../data/soda/soda5.dat
+}
+
+Preprocessor {
+	# stored sample rays
+	samplesFilename rays.out
+	useGlRenderer false
+#	type sampling
+	type vss
+#	type rss
+	detectEmptyViewSpace true
+}
+
+VssPreprocessor {
+	samplesPerPass  100000
+	initialSamples 0
+	vssSamples 0
+	vssSamplesPerPass 500000
+	useImportanceSampling true
+	loadInitialSamples  false
+	storeInitialSamples false
+	useViewSpaceBox true
+#	testBeamSampling true
+}
+
+
+SamplingPreprocessor {
+	totalSamples 500000
+	samplesPerPass  3
+}
+
+
+VssTree {
+	useRss    false
+	epsilon		1e-6
+	
+	maxDepth 	40
+	minPvs		30
+	minRays		800
+	minSize		0.001
+ 	maxCostRatio	1.5
+	maxRayContribution 0.5
+		
+	maxTotalMemory	50
+	maxStaticMemory	20
+	
+	splitType regular
+	#	splitType heuristic
+	#	splitType hybrid
+	splitUseOnlyDrivingAxis true
+	
+	interleaveDirSplits	true
+    dirSplitDepth 0
+	
+	numberOfEndPointDomains	10000
+	ct_div_ci	0.0
+	randomize	false
+	
+	refDirBoxMaxSize	0.1
+}
+
+RssPreprocessor {
+	samplesPerPass  100000
+	#initialSamples 500000
+	#vssSamples 10000000
+	#for view cell construction
+	initialSamples 0
+	vssSamples 0
+	vssSamplesPerPass 500000
+	useImportanceSampling true
+
+	directionalSampling true
+	objectBasedSampling false
+
+	Export {
+		pvs false
+		rssTree false
+		rays true
+		numRays 5000
+	}
+
+	useViewcells true
+	updateSubdivision true
+	loadInitialSamples false
+	storeInitialSamples false
+}
+
+
+RssTree {
+
+	epsilon		1e-6
+
+	maxDepth 	40
+	minPvs		3
+	minRays		30
+	minSize		0.001
+ 	maxCostRatio 1.0
+	maxRayContribution 0.5
+	maxRays		1000000
+	maxTotalMemory	200
+	maxStaticMemory	100
+
+#	splitType regular
+#	splitType heuristic
+	splitType hybrid
+	splitUseOnlyDrivingAxis true
+	importanceBasedCost false
+
+	interleaveDirSplits	true
+    dirSplitDepth 0
+
+	numberOfEndPointDomains	10000
+	ct_div_ci	0.0
+	randomize	false
+
+	refDirBoxMaxSize	0.1
+}
+
+Limits {
+
+       threshold	1e-6
+       small		1e-6
+       infinity		1e9
+}
+
+Unigraphics {
+		meshGrouping 1
+}
+
+KdTree {
+	sahUseFaces true
+	Termination {
+		minCost 1
+		maxDepth 18
+		maxCostRatio 0.9
+		ct_div_ci 0.5
+	}
+
+#	splitMethod spatialMedian
+	splitMethod SAH
+	splitBorder 0.01
+}
+
+MeshKdTree {
+	Termination {
+		minCost 1
+		maxDepth 18
+		maxCostRatio 0.9
+		ct_div_ci 0.5
+	}
+
+#	splitMethod spatialMedian
+	splitMethod SAH
+	splitBorder 0.01
+}
+
+
+
+ViewCells {
+	# samples used for view cell construction
+	Construction {
+		samples 0
+		samplesPerPass 500000
+	}
+
+	#number of active view cells
+	active 2096
+	maxStaticMemory	40
+
+	exportToFile false
+	loadFromFile false
+
+	#type kdTree
+	#type vspKdTree
+	#type bspTree
+	type vspBspTree
+	
+	#type sceneDependent
+	
+	height 5.0
+	maxViewCells 3000
+
+	#percentage of total visible objects where pvs is considered invalid
+	maxPvsRatio 1.0
+		
+	pruneEmptyViewCells false
+	processOnlyValidViewCells false
+	
+	PostProcess {
+		# how much samples are used for post processing
+		samples 300000
+		renderCostWeight 1.0
+		maxCostRatio 0.1
+		minViewCells 1
+		avgCostMaxDeviation 0.01
+		maxMergesPerPass 5000
+		useRaysForMerge false
+		refine false
+		compress true
+		merge true
+	}
+
+	Visualization {
+		# how much samples we use for visualization
+		samples 100000
+		#colorCode PVS
+		#colorCode MergedLeaves
+		#colorCode MergedTreeDiff
+		colorCode Random
+		exportRays false
+		exportGeometry true
+		exportMergedViewCells false
+		useCuttingPlane true
+		cuttingPlaneAxis 1
+	}
+	
+#	filename ../data/atlanta/atlanta_viewcells_large.x3d
+#	filename ../data/vienna/viewcells-25-sel.x3d
+#	filename ../data/vienna/viewcells-25.x3d
+#	filename ../data/vienna/viewcells-large-sel.x3d
+#	filename ../scripts/viewcells_vienna.xml
+	filename ../scripts/viewcells_atlanta.xml
+}
+
+
+Simulation {
+	objRenderCost 1.0
+	vcOverhead 1.0
+	# always between 0 and 1
+	moveSpeed 0.0001
+}
+
+
+VspKdTree {
+	epsilon		1e-6
+
+	Construction {
+		samples 500000
+	}
+	
+	Termination {
+		maxDepth	 	40
+		minPvs			0
+		minRays			1
+		minSize			0.001
+		maxCostRatio		5.9
+		maxViewCells		169
+		missTolerance		4
+		maxRayContribution 	2.5
+	}
+	
+	maxTotalMemory	100
+	maxStaticMemory	40
+
+	splitType 	regular
+	#splitType 	heuristics
+	splitUseOnlyDrivingAxis true
+	ct_div_ci	0.0
+	
+	# maximal cost for merging a view cell
+	PostProcess {
+		maxCostRatio 0.005
+		minViewCells 10000
+		maxPvsSize   5000
+	}
+	
+	
+	Visualization {
+	}
+}
+
+VspBspTree {
+	Construction {
+		samples 300000
+		epsilon 0.005
+		randomize false
+		renderCostWeight 1.0
+	}
+
+
+	# random polygon       = 1
+	# axis aligned         = 2
+	# least ray splits     = 256
+	# balanced rays        = 512
+	# pvs                  = 1024
+	
+	splitPlaneStrategy 1024
+	
+	# maximal candidates for split planes
+	maxPolyCandidates 0
+
+	usePolygonSplitIfAvailable false
+	# maximal tested rays for split cost heuristics
+	maxTests 10000
+	
+	maxTotalMemory	50
+	maxStaticMemory	50
+	
+	# factors for evaluating split plane costs
+	Factor {
+		leastRaySplits 1.0
+	  	balancedRays 1.0
+	  	pvs 1.0
+	}
+	
+	Termination {
+		# parameters used for autopartition
+		minRays 		-15
+		minPolygons 		-1
+		maxDepth		25
+		minPvs 			-15
+		minProbability		0.00000001
+		maxRayContribution	1.8
+		maxCostRatio		1.8
+		missTolerance		6
+		
+		maxViewCells		150000
+		
+		# used for pvs criterium
+		ct_div_ci 0.0
+		
+		AxisAligned {
+			minRays 		50000
+			maxRayContribution	9.9
+		}
+	}
+	
+	useCostHeuristics false
+	splitUseOnlyDrivingAxis false
+	
+	Visualization {
+		# x3d visualization of the split planes
+		exportSplits false
+	}
+}
+
+BspTree {
+	Construction {
+		samples 50000
+		epsilon 0.005
+	}
+
+
+	# random polygon       = 1
+	# axis aligned         = 2
+	# least splits         = 4
+	# balanced polygons    = 8
+	# balanced view cells  = 16
+	# largest polygon area = 32
+	# vertical axis        = 64
+	# blocked rays         = 128
+	# least ray splits     = 256
+	# balanced rays        = 512
+	# pvs                  = 1024
+
+	# least splits + balanced polygons
+	#splitPlaneStrategy 12
+	
+	#axis aligned + vertical axis
+	#splitPlaneStrategy 66
+	
+	# axis aligned + balanced view cells
+	# splitPlaneStrategy 18
+	
+	# largest polygon area
+	#splitPlaneStrategy 32
+	
+	# axus aligned + balanced polygons
+	#splitPlaneStrategy 72
+	
+	# axis aligned + blocked rays
+	#splitPlaneStrategy 130
+	
+	#splitPlaneStrategy 384
+	#splitPlaneStrategy 130
+	
+	splitPlaneStrategy 32
+	
+	maxPolyCandidates 100
+	maxRayCandidates 0
+	
+	maxTests 10000
+	
+	# factors for evaluating split plane costs
+	Factor {
+		verticalSplits 1.0
+	  	largestPolyArea 1.0
+	  	blockedRays 1.0
+	  	leastRaySplits 1.0
+	  	balancedRays 1.0
+	  	pvs 1.0
+	  	leastSplits 1.0
+	  	balancedPolys 1.0
+	  	balancedViewCells 1.0
+	}
+	
+	Termination {
+		# parameters used for autopartition
+		minRays 10
+		minPolygons -1
+		maxDepth 30
+		minPvs -1
+		minProbability 0.001
+		maxRayContribution 9999
+		#maxAccRayLength 100
+		maxViewCells	50000
+
+		# used for pvs criterium
+		ct_div_ci 0.0
+	
+		maxCostRatio 0.9
+		
+		# axis aligned splits
+		AxisAligned {
+			minPolys 5000
+			minRays 500
+			minObjects 10
+			ct_div_ci 0.5
+		}
+	}
+	
+	AxisAligned {
+		splitBorder 0.01
+	}
+	
+	
+	Visualization {
+		# x3d visualization of the split planes
+		exportSplits true
+	}
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/UnigraphicsParser.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/UnigraphicsParser.h	(revision 162)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/UnigraphicsParser.h	(revision 162)
@@ -0,0 +1,23 @@
+#ifndef __UNIGRAPHICSPARSER_H
+#define __UNIGRAPHICSPARSER_H
+
+#include <string>
+using namespace std;
+#include "Parser.h"
+
+class SceneGraphNode;
+
+
+class UnigraphicsParser : public Parser
+{
+public:
+
+  UnigraphicsParser(): Parser() {}
+  
+  virtual bool ParseFile(const string filename, SceneGraphNode **root);
+  
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h	(revision 612)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h	(revision 612)
@@ -0,0 +1,749 @@
+#ifndef _VspBspTree_H__
+#define _VspBspTree_H__
+
+#include "Mesh.h"
+#include "Containers.h"
+#include "Polygon3.h"
+#include <stack>
+#include "Statistics.h"
+#include "VssRay.h"
+#include "RayInfo.h"
+#include "ViewCellBsp.h"
+
+class ViewCell;
+//class BspViewCell;
+class Plane3;
+class VspBspTree;  
+class BspInterior;
+class BspNode;
+class AxisAlignedBox3;
+class Ray;
+class ViewCellsStatistics;
+class ViewCellsManager;
+class MergeCandidate;
+class Beam;
+class ViewCellsTree;
+
+
+struct BspRay;
+
+#define OCTREE_HACK 0
+/**
+	This is a view space partitioning specialised BSPtree.  
+	There are no polygon splits, but we split the sample rays. 
+	The candidates for the next split plane are evaluated only 
+	by checking the sampled	visibility information. 
+	The polygons are employed merely as candidates for the next split planes.
+*/
+class VspBspTree 
+{
+	friend class ViewCellsParseHandlers;
+	friend class VspBspViewCellsManager;
+public:
+	
+	/** Additional data which is passed down the BSP tree during traversal.
+	*/
+	struct VspBspTraversalData
+	{  
+		/// the current node
+		BspNode *mNode;
+		/// polygonal data for splitting
+		PolygonContainer *mPolygons;
+		/// current depth
+		int mDepth;
+		/// rays piercing this node
+		RayInfoContainer *mRays;
+		/// the probability that this node contains view point
+		float mProbability;
+		/// geometry of node as induced by planes
+		BspNodeGeometry *mGeometry;
+		/// pvs size
+		int mPvs;
+		/// how often this branch has missed the max-cost ratio
+		int mMaxCostMisses;
+		/// if this node is a kd-node (i.e., boundaries are axis aligned
+		bool mIsKdNode;
+#if OCTREE_HACK // OCTREE HACK
+		int mAxis;
+#endif
+		/// bounding box of current view space.
+		///AxisAlignedBox3 mBbox;
+		
+		/** Returns average ray contribution.
+		*/
+		float GetAvgRayContribution() const
+		{
+			return (float)mPvs / ((float)mRays->size() + Limits::Small);
+		}
+
+
+		VspBspTraversalData():
+		mNode(NULL),
+		mPolygons(NULL),
+		mDepth(0),
+		mRays(NULL),
+		mPvs(0),
+		mProbability(0.0),
+		mGeometry(NULL),
+		mMaxCostMisses(0), 
+		mIsKdNode(false)
+		{}
+		
+		VspBspTraversalData(BspNode *node, 
+							PolygonContainer *polys, 
+							const int depth, 
+							RayInfoContainer *rays,
+							const int pvs,
+							const float p,
+							BspNodeGeometry *geom): 
+		mNode(node), 
+		mPolygons(polys), 
+		mDepth(depth), 
+		mRays(rays),
+		mPvs(pvs),
+		mProbability(p),
+		mGeometry(geom),
+		mMaxCostMisses(0),
+		mIsKdNode(false)
+		{}
+
+		VspBspTraversalData(PolygonContainer *polys, 
+							const int depth, 
+							RayInfoContainer *rays,
+							BspNodeGeometry *geom): 
+		mNode(NULL), 
+		mPolygons(polys), 
+		mDepth(depth), 
+		mRays(rays),
+		mPvs(0),
+		mProbability(0),
+		mGeometry(geom),
+		mMaxCostMisses(0),
+		mIsKdNode(false)
+		{}
+
+		/** Returns cost of the traversal data.
+		*/
+		float GetCost() const
+		{
+#if 1
+			return mPvs * mProbability;
+#endif
+#if 0
+			return (float) (-mDepth); // for regular grid
+#endif
+#if 0
+			return (float)(mPvs * (int)mRays->size());
+#endif
+#if 0
+			return (float)mPvs;
+#endif
+#if 0
+			return mProbabiliy * (float)mRays->size();
+#endif
+		}
+
+		// deletes contents and sets them to NULL
+		void Clear()
+		{
+			DEL_PTR(mPolygons);
+			DEL_PTR(mRays);
+			DEL_PTR(mGeometry);
+		}
+
+		friend bool operator<(const VspBspTraversalData &a, const VspBspTraversalData &b)
+		{
+			return a.GetCost() < b.GetCost();
+		}
+    };
+	
+	typedef std::priority_queue<VspBspTraversalData> VspBspTraversalQueue;
+	//typedef std::stack<VspBspTraversalData> VspBspTraversalQueue;
+
+	/** Default constructor creating an empty tree.
+	*/ 
+	VspBspTree();
+
+	/** Default destructor.
+	*/
+	~VspBspTree();
+
+	/** Returns BSP Tree statistics.
+	*/
+	const BspTreeStatistics &GetStatistics() const; 
+  
+
+	/** Constructs the tree from a given set of rays.
+		@param sampleRays the set of sample rays the construction is based on
+		@param viewCells if not NULL, new view cells are 
+		created in the leafs and stored in the container
+	*/
+	void Construct(const VssRayContainer &sampleRays,
+				   AxisAlignedBox3 *forcedBoundingBox);
+
+	/** Returns list of BSP leaves with pvs smaller than
+		a certain threshold.
+		@param onlyUnmailed if only the unmailed leaves should be considered
+		@param maxPvs the maximal pvs (-1 means unlimited)
+	*/
+	void CollectLeaves(vector<BspLeaf *> &leaves, 
+					   const bool onlyUnmailed = false,
+					   const int maxPvs = -1) const;
+
+	/** Returns box which bounds the whole tree.
+	*/
+	AxisAlignedBox3 GetBoundingBox()const;
+
+	/** Returns root of BSP tree.
+	*/
+	BspNode *GetRoot() const;
+
+	/** Collects the leaf view cells of the tree
+		@param viewCells returns the view cells 
+	*/
+	void CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const;
+
+	/** A ray is cast possible intersecting the tree.
+		@param the ray that is cast.
+		@returns the number of intersections with objects stored in the tree.
+	*/
+	int CastRay(Ray &ray);
+
+	/// bsp tree construction types
+	enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_SAMPLES};
+
+	/** finds neighbouring leaves of this tree node.
+	*/
+	int FindNeighbors(BspNode *n, 
+					  vector<BspLeaf *> &neighbors, 
+					  const bool onlyUnmailed) const;
+
+	/** Constructs geometry associated with the half space intersections 
+		leading to this node.
+	*/
+	void ConstructGeometry(BspNode *n, BspNodeGeometry &geom) const;
+	
+	/** Construct geometry of view cell.
+	*/
+	void ConstructGeometry(ViewCell *vc, BspNodeGeometry &geom) const;
+
+	/** Returns random leaf of BSP tree.
+		@param halfspace defines the halfspace from which the leaf is taken.
+	*/
+	BspLeaf *GetRandomLeaf(const Plane3 &halfspace);
+
+	/** Returns random leaf of BSP tree.
+		@param onlyUnmailed if only unmailed leaves should be returned.
+	*/
+	BspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
+
+	/** Returns epsilon of this tree.
+	*/
+	float GetEpsilon() const;
+
+	/** Casts line segment into the tree.
+		@param origin the origin of the line segment
+		@param termination the end point of the line segment
+		@returns view cells intersecting the line segment.
+	*/
+    int CastLineSegment(const Vector3 &origin,
+						const Vector3 &termination,
+						ViewCellContainer &viewcells);
+
+		
+	/** Sets pointer to view cells manager.
+	*/
+	void SetViewCellsManager(ViewCellsManager *vcm);
+
+	/** Returns distance from node 1 to node 2.
+	*/
+	int TreeDistance(BspNode *n1, BspNode *n2) const;
+
+	/** Collapses the tree with respect to the view cell partition.
+		@returns number of collapsed nodes
+	*/
+	int CollapseTree();
+
+	/** Returns view cell the current point is located in.
+	*/
+	ViewCell *GetViewCell(const Vector3 &point);
+
+
+	/** Returns true if this view point is in a valid view space,
+		false otherwise.
+	*/
+	bool ViewPointValid(const Vector3 &viewPoint) const;
+
+	/** Returns view cell corresponding to 
+		the invalid view space.
+	*/
+	BspViewCell *GetOutOfBoundsCell();
+
+	/** Writes tree to output stream
+	*/
+	bool Export(ofstream &stream);
+
+	/** Casts beam, i.e. a 5D frustum of rays, into tree.
+		Tests conservative using the bounding box of the nodes.
+		@returns number of view cells it intersected
+	*/
+	int CastBeam(Beam &beam);
+
+	void CollectViewCells(BspNode *root, 
+						  bool onlyValid, 
+						  ViewCellContainer &viewCells,
+						  bool onlyUnmailed = false) const;
+
+	
+	int FindApproximateNeighbors(BspNode *n, 
+							     vector<BspLeaf *> &neighbors,
+								 const bool onlyUnmailed) const;
+
+	/** Checks if tree validity-flags are right 
+		with respect to view cell valitiy.
+		If not, marks subtree as invalid.
+	*/
+	void ValidateTree();
+
+	/** Invalid view cells are added to the unbounded space
+	*/
+	void CollapseViewCells();
+
+	ViewCellsTree *mViewCellsTree;
+protected:
+
+	// --------------------------------------------------------------
+	// For sorting objects
+	// --------------------------------------------------------------
+	struct SortableEntry
+	{
+		enum EType 
+		{
+			ERayMin,
+			ERayMax
+		};
+
+		int type;
+		float value;
+		VssRay *ray;
+  
+		SortableEntry() {}
+		SortableEntry(const int t, const float v, VssRay *r):type(t),
+					  value(v), ray(r) 
+		{
+		}
+		
+		friend bool operator<(const SortableEntry &a, const SortableEntry &b) 
+		{
+			return a.value < b.value;
+		}
+	};
+
+	/** faster evaluation of split plane cost for kd axis aligned cells.
+	*/
+	float EvalAxisAlignedSplitCost(const VspBspTraversalData &data,
+								   const AxisAlignedBox3 &box,
+								   const int axis,
+								   const float &position,
+								   float &pFront,
+								   float &pBack) const;
+
+	/** Returns view cell corresponding to 
+		the invalid view space. If it does not exist, it is created.
+	*/
+	BspViewCell *GetOrCreateOutOfBoundsCell();
+
+	/** Collapses the tree with respect to the view cell partition,
+		i.e. leaves having the same view cell are collapsed.
+		@param node the root of the subtree to be collapsed
+		@param collapsed returns the number of collapsed nodes
+		@returns node of type leaf if the node could be collapsed, 
+		this node otherwise
+	*/
+	BspNode *CollapseTree(BspNode *node, int &collapsed);
+
+	/** Helper function revalidating the view cell leaf list after merge.
+	*/
+	void RepairViewCellsLeafLists();
+
+	/** Evaluates tree stats in the BSP tree leafs.
+	*/
+	void EvaluateLeafStats(const VspBspTraversalData &data);
+
+	/** Subdivides node with respect to the traversal data.
+	    @param tStack current traversal stack
+		@param tData traversal data also holding node to be subdivided
+		@returns new root of the subtree
+	*/
+	BspNode *Subdivide(VspBspTraversalQueue &tStack, 
+					   VspBspTraversalData &tData);
+
+	/** Constructs the tree from the given traversal data.
+		@param polys stores set of polygons on which subdivision may be based
+		@param rays storesset of rays on which subdivision may be based
+	*/
+	void Construct(const PolygonContainer &polys, RayInfoContainer *rays);
+
+	/** Selects the best possible splitting plane. 
+		@param plane returns the split plane
+		@param leaf the leaf to be split
+		@param polys the polygon list on which the split decition is based
+		@param rays ray container on which selection may be based
+		@note the polygons can be reordered in the process
+		@returns true if the cost of the split is under maxCostRatio
+
+	*/
+	bool SelectPlane(Plane3 &plane, 
+					 BspLeaf *leaf, 
+					 VspBspTraversalData &data,
+					 VspBspTraversalData &frontData,
+					 VspBspTraversalData &backData,
+					 int &splitAxis);
+	
+	/** Strategies where the effect of the split plane is tested
+	    on all input rays.
+
+		@returns the cost of the candidate split plane
+	*/
+	float EvalSplitPlaneCost(const Plane3 &candidatePlane, 
+							 const VspBspTraversalData &data,
+							 BspNodeGeometry &geomFront,
+							 BspNodeGeometry &geomBack,
+							 float &pFront,
+							 float &pBack) const;
+
+	/** Subdivide leaf.
+		@param leaf the leaf to be subdivided
+		
+		@param polys the polygons to be split
+		@param frontPolys returns the polygons in front of the split plane
+		@param backPolys returns the polygons in the back of the split plane
+		
+		@param rays the polygons to be filtered
+		@param frontRays returns the polygons in front of the split plane
+		@param backRays returns the polygons in the back of the split plane
+
+		@returns the root of the subdivision
+	*/
+
+	BspNode *SubdivideNode(VspBspTraversalData &tData,
+						   VspBspTraversalData &frontData,
+						   VspBspTraversalData &backData,
+						   PolygonContainer &coincident);
+
+	/** Extracts the meshes of the objects and adds them to polygons. 
+		Adds object aabb to the aabb of the tree.
+		@param maxPolys the maximal number of objects to be stored as polygons
+		@returns the number of polygons
+	*/
+	int AddToPolygonSoup(const ObjectContainer &objects, 
+						 PolygonContainer &polys, 
+						 int maxObjects = 0);
+
+	/** Extracts the meshes of the view cells and and adds them to polygons.
+		Adds view cell aabb to the aabb of the tree.
+		@param maxPolys the maximal number of objects to be stored as polygons
+		@returns the number of polygons
+	*/
+	int AddToPolygonSoup(const ViewCellContainer &viewCells, 
+						 PolygonContainer &polys, 
+						 int maxObjects = 0);
+
+	/** Extract polygons of this mesh and add to polygon container.
+		@param mesh the mesh that drives the polygon construction
+		@param parent the parent intersectable this polygon is constructed from
+		@returns number of polygons
+	*/
+	int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
+
+	/** Selects an axis aligned for the next split.
+		@returns cost for this split
+	*/
+	float SelectAxisAlignedPlane(Plane3 &plane, 
+								 const VspBspTraversalData &tData,
+								 int &axis,
+								 BspNodeGeometry **frontGeom,
+								 BspNodeGeometry **backGeom,
+								 float &pFront,
+								 float &pBack,
+								 const bool useKdSplit);
+
+	/** Sorts split candidates for surface area heuristics for axis aligned splits.
+		@param polys the input for choosing split candidates
+		@param axis the current split axis
+		@param splitCandidates returns sorted list of split candidates
+	*/
+	void SortSplitCandidates(const RayInfoContainer &rays, const int axis);
+
+	/** Computes best cost for axis aligned planes.
+	*/
+	float BestCostRatioHeuristics(const RayInfoContainer &rays,
+								  const AxisAlignedBox3 &box,
+								  const int pvsSize,
+								  const int &axis,
+								  float &position);
+
+	/** Selects an axis aligned split plane.
+		@Returns true if split is valied
+	*/
+	bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;
+
+	/** Subdivides the rays into front and back rays according to the split plane.
+		
+		@param plane the split plane
+		@param rays contains the rays to be split. The rays are 
+			   distributed into front and back rays.
+		@param frontRays returns rays on the front side of the plane
+		@param backRays returns rays on the back side of the plane
+		
+		@returns the number of splits
+	*/
+	int SplitRays(const Plane3 &plane,
+				  RayInfoContainer &rays, 
+			      RayInfoContainer &frontRays, 
+				  RayInfoContainer &backRays);
+
+
+	/** Extracts the split planes representing the space bounded by node n.
+	*/
+	void ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const;
+
+	/** Adds the object to the pvs of the front and back leaf with a given classification.
+
+		@param obj the object to be added
+		@param cf the ray classification regarding the split plane
+		@param frontPvs returns the PVS of the front partition
+		@param backPvs returns the PVS of the back partition
+	
+	*/
+	void AddObjToPvs(Intersectable *obj, 
+					 const int cf, 
+					 int &frontPvs, 
+					 int &backPvs, 
+					 int &totalPvs) const;
+	
+	/** Computes PVS size induced by the rays.
+	*/
+	int ComputePvsSize(const RayInfoContainer &rays) const;
+
+	/** Returns true if tree can be terminated.
+	*/
+	inline bool TerminationCriteriaMet(const VspBspTraversalData &data) const;
+
+	/** Computes accumulated ray lenght of this rays.
+	*/
+	float AccumulatedRayLength(const RayInfoContainer &rays) const;
+
+	/** Splits polygons with respect to the split plane.
+
+		@param plane the split plane
+		@param polys the polygons to be split. the polygons are consumed and
+			   distributed to the containers frontPolys, backPolys, coincident.
+		@param frontPolys returns the polygons in the front of the split plane
+		@param backPolys returns the polygons in the back of the split plane
+		@param coincident returns the polygons coincident to the split plane
+
+		@returns the number of splits	
+	*/
+	int SplitPolygons(const Plane3 &plane,
+					  PolygonContainer &polys, 
+					  PolygonContainer &frontPolys, 
+					  PolygonContainer &backPolys, 
+					  PolygonContainer &coincident) const;
+
+	/** Adds ray sample contributions to the PVS.
+		@param sampleContributions the number contributions of the samples
+		@param contributingSampels the number of contributing rays
+		
+	*/
+	void AddToPvs(BspLeaf *leaf,
+				  const RayInfoContainer &rays, 
+				  float &sampleContributions,
+				  int &contributingSamples);
+
+
+
+
+
+	
+	/** Take 3 ray endpoints, where two are minimum and one a maximum
+		point or the other way round.
+	*/
+	Plane3 ChooseCandidatePlane(const RayInfoContainer &rays) const;
+
+	/** Take plane normal as plane normal and the midpoint of the ray.
+		PROBLEM: does not resemble any point where visibility is 
+		likely to change
+	*/
+	Plane3 ChooseCandidatePlane2(const RayInfoContainer &rays) const;
+
+	/** Fit the plane between the two lines so that the plane 
+		has equal shortest distance to both lines.
+	*/
+	Plane3 ChooseCandidatePlane3(const RayInfoContainer &rays) const;
+  
+	/** Collects candidates for merging.
+		@param leaves the leaves to be merged
+		@returns number of leaves in queue
+	*/
+	int CollectMergeCandidates(const vector<BspLeaf *> leaves, vector<MergeCandidate> &candidates);
+
+	/** Collects candidates for the merge in the merge queue.
+		@returns number of leaves in queue
+	*/
+	int CollectMergeCandidates(const VssRayContainer &rays, vector<MergeCandidate> &candidates);
+	
+	
+	
+	/** Propagates valid flag up the tree.
+	*/
+	void PropagateUpValidity(BspNode *node);
+
+	/** Writes the node to disk
+		@note: should be implemented as visitor
+	*/
+	void ExportNode(BspNode *node, ofstream &stream);
+
+	/** Returns estimated memory usage of tree.
+	*/
+	//float GetMemUsage(const VspBspTraversalQueue &tstack) const;
+	float GetMemUsage() const;
+
+
+
+	/// Pointer to the root of the tree
+	BspNode *mRoot;
+		
+	BspTreeStatistics mBspStats;
+
+	/// Strategies for choosing next split plane.
+	enum {NO_STRATEGY = 0,
+		  RANDOM_POLYGON = 1, 
+		  AXIS_ALIGNED = 2,
+		  LEAST_RAY_SPLITS = 256,
+		  BALANCED_RAYS = 512,
+		  PVS = 1024
+		};
+
+	/// box around the whole view domain
+	AxisAlignedBox3 mBox;
+
+	bool mUseCostHeuristics;
+
+	/// minimal number of rays before subdivision termination
+	int mTermMinRays;
+	/// maximal possible depth
+	int mTermMaxDepth;
+	/// mininum probability
+	float mTermMinProbability;
+	/// mininum PVS
+	int mTermMinPvs;
+	/// maximal contribution per ray
+	float mTermMaxRayContribution;
+	/// minimal accumulated ray length
+	float mTermMinAccRayLength;
+
+	//HACK
+	int mTermMinPolygons;
+
+	//-- termination criteria for axis aligned split
+
+	/// minimal number of rays for axis aligned split
+	int mTermMinRaysForAxisAligned;
+	// max ray contribution
+	float mTermMaxRayContriForAxisAligned;
+
+	/// strategy to get the best split plane
+	int mSplitPlaneStrategy;
+	/// number of candidates evaluated for the next split plane
+	int mMaxPolyCandidates;
+	/// number of candidates for split planes evaluated using the rays
+	int mMaxRayCandidates;
+	/// balancing factor for PVS criterium
+	float mCtDivCi;
+
+	//-- axis aligned split criteria
+	float mAxisAlignedCtDivCi;
+	/// spezifies the split border of the axis aligned split
+	float mAxisAlignedSplitBorder;
+
+	/// maximal acceptable cost ratio
+	float mTermMaxCostRatio;
+	/// tolerance value indicating how often the max cost ratio can be failed
+	int mTermMissTolerance;
+
+	//-- factors guiding the split plane heuristics
+	float mLeastRaySplitsFactor;
+	float mBalancedRaysFactor;
+	float mPvsFactor;
+
+	/// if area or volume should be used for PVS heuristics
+	bool mUseAreaForPvs;
+	/// tolerance for polygon split
+	float mEpsilon;
+	/// maximal number of test rays used to evaluate candidate split plane
+	int mMaxTests;
+	/// normalizes different bsp split plane criteria
+	float mCostNormalizer;
+	/// maximal number of view cells
+	int mMaxViewCells;
+	
+	ofstream  mSubdivisionStats;
+
+	// if rays should be stored in leaves
+	bool mStoreRays;
+	
+	/// if only driving axis should be used for split
+	bool mOnlyDrivingAxis;
+
+	ViewCellsManager *mViewCellsManager;
+
+	vector<SortableEntry> *mSplitCandidates;
+
+	
+	float mRenderCostWeight;
+	/// View cell corresponding to the space outside the valid view space
+	BspViewCell *mOutOfBoundsCell;
+
+	/// maximal tree memory
+	float mMaxMemory;
+	/// the tree is out of memory
+	bool mOutOfMemory;
+	
+	float mTotalCost;
+	int mTotalPvsSize;
+
+	//int mSplits;
+
+	ofstream mSubdivsionStats;
+
+	bool mUseRandomAxis;
+
+	bool mUsePolygonSplitIfAvailable;
+
+	int mTimeStamp;
+
+	int mCreatedViewCells;
+
+private:
+
+
+	static const float sLeastRaySplitsTable[5];
+	/** Evaluates split plane classification with respect to the plane's 
+		contribution for balanced rays.
+	*/
+	static const float sBalancedRaysTable[5];
+
+	/// Generates unique ids for PVS criterium
+	static void GenerateUniqueIdsForPvs();
+
+	//-- unique ids for PVS criterium
+	static int sFrontId; 
+	static int sBackId;
+	static int sFrontAndBackId;
+};
+
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Material.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Material.h	(revision 608)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Material.h	(revision 608)
@@ -0,0 +1,51 @@
+#ifndef __MATERIAL_H
+#define __MATERIAL_H
+
+
+
+class RgbColor 
+{
+public:
+  float r, g, b;
+
+  RgbColor():r(0.5f),g(0.5f),b(0.5f)
+  {
+  }
+
+  RgbColor(const float _r,
+	   const float _g,
+	   const float _b):r(_r),g(_g),b(_b)
+  {
+  }
+
+  friend RgbColor
+  RandomColor(const float a=0.0f, const float b=1.0f);
+
+};
+
+
+class Material 
+{
+public:
+  RgbColor mDiffuseColor;
+  RgbColor mSpecularColor;
+  RgbColor mAmbientColor;
+  
+  Material() 
+  {
+  }
+  
+  Material(const RgbColor &color):mDiffuseColor(color),
+								  mAmbientColor(color),
+								  mSpecularColor(0,0,0)
+  {
+  }
+  
+  friend Material RandomMaterial();
+  
+};
+
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Beam.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Beam.cpp	(revision 542)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Beam.cpp	(revision 542)
@@ -0,0 +1,210 @@
+#include "VssRay.h"
+#include "Beam.h"
+#include "Mesh.h"
+#include "Polygon3.h"
+
+
+void
+Beam::Construct(const AxisAlignedBox3 &box, const AxisAlignedBox3 &dBox)
+{
+  // the frustum is defined by set of negative halfspace described by mPlanes
+  
+  // construct
+  Vector3 center = box.Center();
+  Vector3 dCenter = dBox.Center();
+
+  // "back plane"
+  mPlanes.push_back(Plane3(-VssRay::GetDirection(dCenter.x, dCenter.y), center));
+  
+  Vector3 directions[4];
+  directions[0] = VssRay::GetDirection(dBox.Min().x, dBox.Min().y);
+  directions[1] = VssRay::GetDirection(dBox.Max().x, dBox.Min().y);
+  directions[2] = VssRay::GetDirection(dBox.Max().x, dBox.Max().y);
+  directions[3] = VssRay::GetDirection(dBox.Min().x, dBox.Max().y);
+  
+  // side planes
+  mPlanes.push_back(Plane3(-CrossProd(directions[0], directions[1]), center));
+  mPlanes.push_back(Plane3(-CrossProd(directions[1], directions[2]), center));
+  mPlanes.push_back(Plane3(-CrossProd(directions[2], directions[3]), center));
+  mPlanes.push_back(Plane3(-CrossProd(directions[3], directions[0]), center));
+
+  // now make sure all planes contain the spatial box
+  int i, j;
+  for (i=0; i < mPlanes.size(); i++) 
+  {
+	  float maxDist = 0;
+	  
+	  for (j=0; j < 8; j++) 
+	  {
+		float dist = mPlanes[i].Distance(box.GetVertex(j));
+	
+		if (dist > maxDist)
+			maxDist = dist;
+	  }
+
+	  mPlanes[i].mD -= maxDist;
+  }
+
+  mBox = box;
+  mDirBox = dBox;
+  
+  SetValid();
+}
+
+// conservative frustum box intersection
+// returns
+// 0 - box intersects the frustum
+// -1 - box intersects the frustum and is fully inside
+// 1 - box does not intersect the frustum
+
+int
+Beam::ComputeIntersection(const AxisAlignedBox3 &box)
+{
+  int i;
+  int result = -1;
+  for (i=0; i < mPlanes.size(); i++) {
+	int side = box.Side(mPlanes[i]);
+	if (side == 1)
+	  return 1;
+	if (side > result)
+	  result = side;
+  }
+  return result;
+}
+
+
+Beam::~Beam()
+{
+	DEL_PTR(mMesh);
+}
+
+
+void Beam::ComputePerspectiveFrustum(float &left, float &right,
+									 float &bottom, float &top,
+									 float &near, float &far,
+									 const AxisAlignedBox3 &sceneBBox) const
+{
+	const float xDirRange = mDirBox.Max().x - mDirBox.Min().x;
+	const float yDirRange = mDirBox.Max().y - mDirBox.Min().y;
+	//Debug << "xdir range: " << xDirRange << endl;
+	//Debug << "ydir range: " << yDirRange << endl;
+
+	near = 0.1f; // NOTE: what is the best value for near and far plane?
+	far = 2.0f * Magnitude(sceneBBox.Diagonal());
+	
+	right = fabs(near * tan(xDirRange * 0.5f));
+	left = -right;
+
+	top = fabs(near * tan(yDirRange * 0.5f));
+	bottom = -top;
+}
+
+
+void Beam::ComputeOrthoFrustum(float &left, float &right,
+							   float &bottom, float &top,
+							   float &near, float &far,
+							   const AxisAlignedBox3 &sceneBBox) const
+{
+	const int vAxis = GetMainDirection().DrivingAxis();
+	const int axis2 = (vAxis + 1) % 3;
+	const int axis3 = (vAxis + 2) % 3;
+
+	const float xDirRange = mBox.Max()[axis2] - mDirBox.Min()[axis2];
+	const float yDirRange = mDirBox.Max()[axis3] - mDirBox.Min()[axis3];
+
+	near = 0.1f; // NOTE: what is the best value for near and far plane?
+	far = 2.0f * Magnitude(sceneBBox.Diagonal());
+
+	right = xDirRange * 0.5f;
+	left = -right;
+
+	top = yDirRange * 0.5;
+	bottom = -top;
+}
+
+
+Vector3 Beam::GetMainDirection() const
+{
+	return - mPlanes[0].mNormal;
+}
+
+
+void BeamSampleStatistics::Print(ostream &app) const
+{
+  app << "===== Beam sample statistics ===============\n";
+
+  app << "#N_PVSSIZE ( size of pvs )\n" << pvsSize << "\n";
+
+  app << "#N_RAYS ( Number of rays )\n" << rays << "\n";
+
+  app << "#N_RAYCONTRIBUTIONS ( number of ray constributions )\n" <<
+    rayContributions << "\n";
+
+  app << "#N_RAYLENGHTENTROPY  ( Ray lenght entropy )\n" <<
+    rayLengthEntropy << "\n";
+
+  app << "#N_IMPORTANCE  ( importance )\n" <<
+    importance << "\n";
+
+  app << "#N_CTIME  ( Construction time [s] )\n"
+      << Time() << " \n";
+
+  app << "===== END OF KdTree statistics ==========\n";
+
+}
+
+
+void Beam::CreateMesh(const float zfar)
+{
+	if (mMesh)
+		return;
+
+	mMesh = new Mesh();
+	
+	// -- compute far plane
+
+	// box should not never remove part of beam polygons
+	Vector3 bmin = mBox.Min() - Vector3(zfar * 2.0);
+	Vector3 bmax = mBox.Max() + Vector3(zfar * 2.0);
+
+	AxisAlignedBox3 bbox(bmin, bmax);
+	Plane3 fplane;
+	fplane.mNormal = -mPlanes[0].mNormal;
+
+	// NOTE: beam far plane must not not be culled by gl far plane
+	fplane.mD = mPlanes[0].mD - zfar - 1.0f; 
+	mPlanes.push_back(fplane);
+
+	for (int i = 0; i < mPlanes.size(); ++ i)
+	{
+		Polygon3 *poly = bbox.CrossSection(mPlanes[i]);
+		
+		if (!poly->Valid(Limits::Small))
+			DEL_PTR(poly);
+		
+		for (int j = 0; (j < mPlanes.size()) && poly; ++ j)
+		{
+			if (j != i)
+			{
+				Polygon3 *front = new Polygon3();
+				Polygon3 *back = new Polygon3();
+				
+				poly->Split(mPlanes[j], *front, *back, Limits::Small);
+				DEL_PTR(poly);
+				DEL_PTR(front);
+
+				if (!back->Valid(Limits::Small))
+					DEL_PTR(back);
+				poly = back;
+			}
+		}
+	
+		if (poly)
+		{
+			poly->AddToMesh(*mMesh);
+		}
+	}
+
+	// remove far plane
+	mPlanes.pop_back();
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspKdTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspKdTree.cpp	(revision 598)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspKdTree.cpp	(revision 598)
@@ -0,0 +1,2644 @@
+
+// ================================================================
+// $Id: lsds_kdtree.cpp,v 1.18 2005/04/16 09:34:21 bittner Exp $
+// ****************************************************************
+/**
+   The KD tree based LSDS
+*/
+// Initial coding by
+/**
+   @author Jiri Bittner
+*/
+
+// Standard headers
+#include <stack>
+#include <queue>
+#include <algorithm>
+#include <fstream>
+#include <string>
+
+#include "VspKdTree.h"
+
+#include "Environment.h"
+#include "VssRay.h"
+#include "Intersectable.h"
+#include "Ray.h"
+#include "RayInfo.h"
+#include "ViewCellsManager.h"
+#include "ViewCellBsp.h"
+
+// Static variables
+int VspKdLeaf::sMailId = 0;
+int VspKdMergeCandidate::sMaxPvsSize = 150;
+float VspKdMergeCandidate::sOverallCost = Limits::Small;
+#define USE_FIXEDPOINT_T 0
+
+/// Adds object to the pvs of the front and back node
+inline void AddObject2Pvs(Intersectable *object,
+						  const int side,
+						  int &pvsBack,
+						  int &pvsFront)
+{
+	if (!object)
+		return;
+
+	if (side <= 0)
+	{
+		if (!object->Mailed() && !object->Mailed(2))
+		{
+			++ pvsBack;
+
+			if (object->Mailed(1))
+				object->Mail(2);
+			else
+				object->Mail();
+		}
+	}
+
+	if (side >= 0)
+	{
+		if (!object->Mailed(1) && !object->Mailed(2))
+		{
+			++ pvsFront;
+
+			if (object->Mailed())
+				object->Mail(2);
+			else
+				object->Mail(1);
+		}
+	}
+}
+
+/**************************************************************/
+/*                class VspKdNode implementation          */
+/**************************************************************/
+
+// Inline constructor
+VspKdNode::VspKdNode(VspKdNode *p):
+mParent(p), mAxis(-1), mDepth(p ? p->mDepth + 1 : 0)
+{}
+
+VspKdNode::~VspKdNode()
+{
+};
+
+inline VspKdNode *VspKdNode::GetParent() const
+{
+	return mParent;
+}
+
+inline void VspKdNode::SetParent(VspKdNode *p)
+{
+	mParent = p;
+}
+
+bool VspKdNode::IsLeaf() const
+{
+	return mAxis == -1;
+}
+
+int VspKdNode::GetAccessTime()
+{
+	return 0x7FFFFFF;
+}
+
+/**************************************************************/
+/*                VspKdInterior implementation            */
+/**************************************************************/
+
+VspKdInterior::VspKdInterior(VspKdInterior *p):
+VspKdNode(p), mBack(NULL), mFront(NULL), mAccesses(0), mLastAccessTime(-1)
+{
+}
+
+int VspKdInterior::GetAccessTime()
+{
+	return mLastAccessTime;
+}
+
+void VspKdInterior::SetupChildLinks(VspKdNode *b, VspKdNode *f)
+{
+	mBack = b;
+	mFront = f;
+	b->SetParent(this);
+	f->SetParent(this);
+}
+
+void VspKdInterior::ReplaceChildLink(VspKdNode *oldChild,
+									 VspKdNode *newChild)
+{
+	if (mBack == oldChild)
+		mBack = newChild;
+	else
+		mFront = newChild;
+}
+
+int VspKdInterior::Type() const
+{
+	return EInterior;
+}
+
+VspKdInterior::~VspKdInterior()
+{
+	DEL_PTR(mBack);
+	DEL_PTR(mFront);
+}
+
+void VspKdInterior::Print(ostream &s) const
+{
+	switch (mAxis)
+	{
+	case 0:
+		s << "x "; break;
+	case 1:
+		s << "y "; break;
+	case 2:
+		s << "z "; break;
+	}
+
+	s << mPosition << " ";
+
+	mBack->Print(s);
+	mFront->Print(s);
+}
+
+int VspKdInterior::ComputeRayIntersection(const RayInfo &rayData, float &t)
+{
+	return rayData.ComputeRayIntersection(mAxis, mPosition, t);
+}
+
+VspKdNode *VspKdInterior::GetBack() const
+{
+	return mBack;
+}
+
+VspKdNode *VspKdInterior::GetFront() const
+{
+	return mFront;
+}
+
+
+/*******************************************************************/
+/*                   class VspKdLeaf implementation                */
+/*******************************************************************/
+
+
+VspKdLeaf::VspKdLeaf(VspKdNode *p, 
+					 const int nRays, 
+					 const int maxCostMisses):
+VspKdNode(p), mRays(), mPvsSize(0), mValidPvs(false), mViewCell(NULL),
+mMaxCostMisses(maxCostMisses), mPvs(NULL), mVolume(0)
+{
+	mRays.reserve(nRays);
+}
+
+VspKdLeaf::~VspKdLeaf()
+{
+	DEL_PTR(mPvs);
+}
+
+
+int VspKdLeaf::GetMaxCostMisses()
+{
+	return mMaxCostMisses;
+}
+
+
+int VspKdLeaf::Type() const
+{
+	return ELeaf;
+}
+
+void VspKdLeaf::Print(ostream &s) const
+{
+	s << endl << "L: r = " << (int)mRays.size() << endl;
+};
+
+void VspKdLeaf::AddRay(const RayInfo &data)
+{
+	mValidPvs = false;
+	mRays.push_back(data);
+	data.mRay->Ref();
+}
+
+int VspKdLeaf::GetPvsSize() const
+{
+	return mPvsSize;
+}
+
+void VspKdLeaf::SetPvsSize(const int s)
+{
+	mPvsSize = s;
+}
+
+void VspKdLeaf::Mail()
+{
+	mMailbox = sMailId;
+}
+
+void VspKdLeaf::NewMail()
+{
+	++ sMailId;
+}
+
+bool VspKdLeaf::Mailed() const
+{
+	return mMailbox == sMailId;
+}
+
+bool VspKdLeaf::Mailed(const int mail) const
+{
+	return mMailbox == mail;
+}
+
+int VspKdLeaf::GetMailbox() const
+{
+	return mMailbox;
+}
+
+float VspKdLeaf::GetAvgRayContribution() const
+{
+	return GetPvsSize() / ((float)mRays.size() + Limits::Small);
+}
+
+float VspKdLeaf::GetSqrRayContribution() const
+{
+	return sqr(GetAvgRayContribution());
+}
+
+RayInfoContainer &VspKdLeaf::GetRays()
+{
+	return mRays;
+}
+
+void VspKdLeaf::ExtractPvs(ObjectContainer &objects) const
+{
+	RayInfoContainer::const_iterator it, it_end = mRays.end();
+
+	for (it = mRays.begin(); it != it_end; ++ it)
+	{
+		if ((*it).mRay->mTerminationObject)
+			objects.push_back((*it).mRay->mTerminationObject);
+		if ((*it).mRay->mOriginObject)
+			objects.push_back((*it).mRay->mOriginObject);
+	}
+}
+
+void VspKdLeaf::GetRays(VssRayContainer &rays)
+{
+	RayInfoContainer::const_iterator it, it_end = mRays.end();
+
+	for (it = mRays.begin(); it != mRays.end(); ++ it)
+		rays.push_back((*it).mRay);
+}
+
+VspKdViewCell *VspKdLeaf::GetViewCell()
+{
+	return mViewCell;
+}
+
+void VspKdLeaf::SetViewCell(VspKdViewCell *viewCell)
+{
+	mViewCell = viewCell;
+}
+
+
+void VspKdLeaf::UpdatePvsSize()
+{
+	if (!mValidPvs)
+	{
+		Intersectable::NewMail();
+		int pvsSize = 0;
+		for(RayInfoContainer::iterator ri = mRays.begin();
+			ri != mRays.end(); ++ ri)
+		{
+			if ((*ri).mRay->IsActive())
+			{
+				Intersectable *object;
+#if BIDIRECTIONAL_RAY
+				object = (*ri).mRay->mOriginObject;
+
+				if (object && !object->Mailed())
+				{
+					++ pvsSize;
+					object->Mail();
+				}
+#endif
+				object = (*ri).mRay->mTerminationObject;
+				if (object && !object->Mailed())
+				{
+					++ pvsSize;
+					object->Mail();
+				}
+			}
+		}
+
+		mPvsSize = pvsSize;
+		mValidPvs = true;
+	}
+}
+
+
+/***************************************************************/
+/*          class VspKdIntermediate implementation             */
+/***************************************************************/
+
+
+VspKdIntermediate::VspKdIntermediate(VspKdInterior *p):
+VspKdNode(p), mBack(NULL), mFront(NULL), mAccesses(0), mLastAccessTime(-1)
+{
+}
+
+
+VspKdIntermediate::~VspKdIntermediate()
+{
+	DEL_PTR(mFront);
+	DEL_PTR(mBack);
+}
+    
+	
+int VspKdIntermediate::Type() const
+{
+	return EIntermediate;
+}
+
+
+VspKdLeaf *VspKdIntermediate::GetBack() const
+{
+	return mBack;
+}
+
+
+VspKdLeaf *VspKdIntermediate::GetFront() const
+{
+	return mFront;
+}
+
+
+void VspKdIntermediate::Print(ostream &s) const
+{
+	s << endl << mSplitPlane << endl;
+}
+
+
+void VspKdIntermediate::SetupChildLinks(VspKdLeaf *b, VspKdLeaf *f)
+{
+	mBack = b;
+	mFront = f;
+
+	b->SetParent(this);
+	f->SetParent(this);
+}
+
+
+int VspKdIntermediate::ComputeRayIntersection(const RayInfo &rayData, float &t)
+{
+	return rayData.ComputeRayIntersection(mSplitPlane, t);
+}
+
+
+/*************************************************************/
+/*              class VspKdTree implementation               */
+/*************************************************************/
+
+
+VspKdTree::VspKdTree(): mOnlyDrivingAxis(false)
+{
+	environment->GetIntValue("VspKdTree.Termination.maxDepth", mTermMaxDepth);
+	environment->GetIntValue("VspKdTree.Termination.minPvs", mTermMinPvs);
+	environment->GetIntValue("VspKdTree.Termination.minRays", mTermMinRays);
+	environment->GetFloatValue("VspKdTree.Termination.maxRayContribution", mTermMaxRayContribution);
+	environment->GetFloatValue("VspKdTree.Termination.maxCostRatio", mTermMaxCostRatio);
+	environment->GetFloatValue("VspKdTree.Termination.minSize", mTermMinSize);
+
+	environment->GetIntValue("VspKdTree.Termination.missTolerance", mTermMissTolerance);
+
+	mTermMinSize = sqr(mTermMinSize);
+
+	environment->GetFloatValue("VspKdTree.epsilon", mEpsilon);
+	environment->GetFloatValue("VspKdTree.ct_div_ci", mCtDivCi);
+
+	environment->GetFloatValue("VspKdTree.maxTotalMemory", mMaxTotalMemory);
+	environment->GetFloatValue("VspKdTree.maxStaticMemory", mMaxStaticMemory);
+
+	environment->GetIntValue("VspKdTree.accessTimeThreshold", mAccessTimeThreshold);
+	environment->GetIntValue("VspKdTree.minCollapseDepth", mMinCollapseDepth);
+
+	//environment->GetIntValue("ViewCells.maxViewCells", mMaxViewCells);
+
+	environment->GetIntValue("VspKdTree.PostProcess.minViewCells", mMergeMinViewCells);
+	environment->GetFloatValue("VspKdTree.PostProcess.maxCostRatio", mMergeMaxCostRatio);
+	environment->GetIntValue("VspKdTree.PostProcess.maxPvsSize",
+							 VspKdMergeCandidate::sMaxPvsSize);
+
+	environment->GetBoolValue("VspKdTree.splitUseOnlyDrivingAxis", mOnlyDrivingAxis);
+	environment->GetIntValue("VspKdTree.Termination.maxViewCells", mMaxViewCells);
+
+	//-- output
+	Debug << "======= vsp kd tree options ========" << endl;
+	Debug << "max depth: "<< mTermMaxDepth << endl;
+	Debug << "min pvs: "<< mTermMinPvs << endl;
+	Debug << "min rays: "<< mTermMinRays << endl;
+	Debug << "max ray contribution: "<< mTermMaxRayContribution << endl;
+	Debug << "max cost ratio: " << mTermMaxCostRatio << endl;
+	Debug << "min size: " << mTermMinSize << endl;
+
+	Debug << "split type: ";
+
+	//-- split type
+	char sname[128];
+	environment->GetStringValue("VspKdTree.splitType", sname);
+	string name(sname);
+
+	if (name.compare("regular") == 0)
+	{
+		Debug << "regular split" << endl;
+		splitType = ESplitRegular;
+	}
+	else
+	{
+		if (name.compare("heuristic") == 0)
+		{
+			Debug << "heuristic split" << endl;
+			splitType = ESplitHeuristic;
+		}
+		else
+		{
+			cerr << "Invalid VspKdTree split type " << name << endl;
+			exit(1);
+		}
+	}
+
+	mRoot = NULL;
+	mSplitCandidates = new vector<SortableEntry>;
+}
+
+
+VspKdTree::~VspKdTree()
+{
+	DEL_PTR(mRoot);
+	DEL_PTR(mSplitCandidates);
+}
+
+void VspKdStatistics::Print(ostream &app) const
+{
+	app << "===== VspKdTree statistics ===============\n";
+
+	app << "#N_RAYS ( Number of rays )\n"
+		<< rays << endl;
+
+	app << "#N_INITPVS ( Initial PVS size )\n"
+		<< initialPvsSize << endl;
+
+	app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
+
+	app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
+
+	app << "#N_SPLITS ( Number of splits in axes x y z\n";
+
+	for (int i = 0; i < 3; ++ i)
+		app << splits[i] << " ";
+	app << endl;
+
+	app << "#N_RAYREFS ( Number of rayRefs )\n" <<
+		rayRefs << "\n";
+
+	app << "#N_RAYRAYREFS  ( Number of rayRefs / ray )\n" <<
+		rayRefs / (double)rays << "\n";
+
+	app << "#N_LEAFRAYREFS  ( Number of rayRefs / leaf )\n" <<
+		rayRefs / (double)Leaves() << "\n";
+
+	app << "#N_MAXRAYREFS  ( Max number of rayRefs / leaf )\n" <<
+		maxRayRefs << "\n";
+
+  //  app << setprecision(4);
+
+	app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maxdepth )\n" <<
+		maxDepthNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMINPVSLEAVES  ( Percentage of leaves with mininimal PVS )\n" <<
+		minPvsNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMINRAYSLEAVES  ( Percentage of leaves with minimal number of rays)\n" <<
+		minRaysNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMINSIZELEAVES  ( Percentage of leaves with minSize )\n"<<
+		minSizeNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMAXRAYCONTRIBLEAVES  ( Percentage of leaves with maximal ray contribution )\n" <<
+		maxRayContribNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMAXRCOSTLEAVES  ( Percentage of leaves with maximal cost ratio )\n" <<
+		maxCostNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_ADDED_RAYREFS  ( Number of dynamically added ray references )\n"<<
+		addedRayRefs << endl;
+
+	app << "#N_REMOVED_RAYREFS  ( Number of dynamically removed ray references )\n"<<
+		removedRayRefs << endl;
+
+	//  app << setprecision(4);
+
+	app << "#N_( Maximal PVS size / leaf)\n"
+		<< maxPvsSize << endl;
+
+	app << "#N_( Average PVS size / leaf)\n"
+		<< (double) accPvsSize / (double)Leaves() << endl;
+
+	app << "#N_CTIME  ( Construction time [s] )\n"
+		<< Time() << " \n";
+
+	app << "===== END OF VspKdTree statistics ==========\n";
+}
+
+
+void VspKdTree::CollectViewCells(ViewCellContainer &viewCells) const
+{
+	stack<VspKdNode *> nodeStack;
+	nodeStack.push(mRoot);
+
+	ViewCell::NewMail();
+
+	while (!nodeStack.empty())
+	{
+		VspKdNode *node = nodeStack.top();
+		nodeStack.pop();
+
+		if (node->IsLeaf())
+		{
+			ViewCell *viewCell = dynamic_cast<VspKdLeaf *>(node)->mViewCell;
+
+			if (!viewCell->Mailed())
+			{
+				viewCell->Mail();
+				viewCells.push_back(viewCell);
+			}
+		}
+		else
+		{
+			VspKdInterior *interior = dynamic_cast<VspKdInterior *>(node);
+
+			nodeStack.push(interior->GetFront());
+			nodeStack.push(interior->GetBack());
+		}
+	}
+}
+
+void VspKdTree::Construct(const VssRayContainer &rays,
+						  AxisAlignedBox3 *forcedBoundingBox)
+{
+	mStat.Start();
+
+	mMaxMemory = mMaxStaticMemory;
+	DEL_PTR(mRoot);
+
+	mRoot = new VspKdLeaf(NULL, (int)rays.size());
+
+	// first construct a leaf that will get subdivided
+	VspKdLeaf *leaf = dynamic_cast<VspKdLeaf *>(mRoot);
+
+	mStat.nodes = 1;
+  	mBox.Initialize();
+
+	//-- compute bounding box
+	if (forcedBoundingBox)
+		mBox = *forcedBoundingBox;
+	else
+		for (VssRayContainer::const_iterator ri = rays.begin(); ri != rays.end(); ++ ri)
+		{
+			if ((*ri)->mOriginObject)
+            	mBox.Include((*ri)->GetOrigin());
+			if ((*ri)->mTerminationObject)
+				mBox.Include((*ri)->GetTermination());
+		}
+
+	Debug << "bbox = " << mBox << endl;
+
+	for (VssRayContainer::const_iterator ri = rays.begin(); ri != rays.end(); ++ ri)
+	{
+		//leaf->AddRay(RayInfo(*ri));
+		VssRay *ray = *ri;
+		float minT, maxT;
+		
+		// TODO: not very efficient to implictly cast between rays types!
+		if (mBox.GetRaySegment(*ray, minT, maxT))
+		{
+			float len = ray->Length();
+
+			if (!len)
+				len = Limits::Small;
+
+			leaf->AddRay(RayInfo(ray, minT / len, maxT / len));
+		}
+	}
+
+	mStat.rays = (int)leaf->mRays.size();
+	leaf->UpdatePvsSize();
+
+	mStat.initialPvsSize = leaf->GetPvsSize();
+
+	// Subdivide();
+	mRoot = Subdivide(TraversalData(leaf, mBox, 0));
+
+	if (mSplitCandidates)
+	{
+		// force release of this vector
+		delete mSplitCandidates;
+		mSplitCandidates = new vector<SortableEntry>;
+	}
+
+	mStat.Stop();
+
+	mStat.Print(cout);
+	Debug << "#Total memory=" << GetMemUsage() << endl;
+}
+
+
+
+VspKdNode *VspKdTree::Subdivide(const TraversalData &tdata)
+{
+	VspKdNode *result = NULL;
+
+	priority_queue<TraversalData> tStack;
+	//stack<TraversalData> tStack;
+
+	tStack.push(tdata);
+
+	AxisAlignedBox3 backBox;
+	AxisAlignedBox3 frontBox;
+
+	int lastMem = 0;
+
+	while (!tStack.empty())
+	{
+		float mem = GetMemUsage();
+
+		if (lastMem / 10 != ((int)mem) / 10)
+		{
+			Debug << mem << " MB" << endl;
+		}
+		lastMem = (int)mem;
+
+		if (1 && mem > mMaxMemory)
+		{
+			Debug << "memory limit reached: " << mem << endl;
+			// count statistics on unprocessed leafs
+			while (!tStack.empty())
+			{
+				EvaluateLeafStats(tStack.top());
+				tStack.pop();
+			}
+			break;
+		}
+
+		TraversalData data = tStack.top();
+		tStack.pop();
+
+		VspKdNode *node = SubdivideNode(dynamic_cast<VspKdLeaf *>(data.mNode),
+										data.mBox, backBox,	frontBox);
+		if (result == NULL)
+			result = node;
+
+		if (!node->IsLeaf())
+		{
+			VspKdInterior *interior = dynamic_cast<VspKdInterior *>(node);
+
+			// push the children on the stack
+			tStack.push(TraversalData(interior->GetBack(), backBox, data.mDepth + 1));
+			tStack.push(TraversalData(interior->GetFront(), frontBox, data.mDepth + 1));
+		}
+		else
+		{
+			EvaluateLeafStats(data);
+		}
+	}
+
+	return result;
+}
+
+
+// returns selected plane for subdivision
+int VspKdTree::SelectPlane(VspKdLeaf *leaf,
+						   const AxisAlignedBox3 &box,
+						   float &position,
+						   int &raysBack,
+						   int &raysFront,
+						   int &pvsBack,
+						   int &pvsFront)
+{
+	int axis = 0;
+	float costRatio = 0;
+
+	if (splitType == ESplitRegular)
+	{
+		costRatio = BestCostRatioRegular(leaf,
+										 box,
+										 axis,
+										 position,
+										 raysBack,
+										 raysFront,
+										 pvsBack,
+										 pvsFront);
+	}
+	else if (splitType == ESplitHeuristic)
+	{
+		costRatio = BestCostRatioHeuristic(leaf,
+										   box,
+										   axis,
+										   position,
+										   raysBack,
+										   raysFront,
+										   pvsBack,
+										   pvsFront);
+	}
+	else
+	{
+		cerr << "VspKdTree: Unknown split heuristics\n";
+		exit(1);
+	}
+
+	if (costRatio > mTermMaxCostRatio)
+	{
+		//Debug << "Too big cost ratio " << costRatio << endl;
+		++ leaf->mMaxCostMisses;
+		if (leaf->mMaxCostMisses > mTermMissTolerance)
+		{
+			++ mStat.maxCostNodes;
+			return -1;
+		}
+	}
+
+	if (0)
+		Debug << "pvs=" << leaf->mPvsSize
+			  << " rays=" << (int)leaf->mRays.size()
+			  << " rc=" << leaf->GetAvgRayContribution()
+			  << " axis=" << axis << endl;
+
+	return axis;
+}
+
+
+
+float VspKdTree::EvalCostRatio(VspKdLeaf *leaf,
+							   const AxisAlignedBox3 &box,
+							   const int axis,
+							   const float position,
+							   int &raysBack,
+							   int &raysFront,
+							   int &pvsBack,
+							   int &pvsFront)
+{
+	raysBack = 0;
+	raysFront = 0;
+	pvsFront = 0;
+	pvsBack = 0;
+
+	Intersectable::NewMail(3);
+
+	// eval pvs size
+	const int pvsSize = leaf->GetPvsSize();
+
+	// this is the main ray classification loop!
+	for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+			ri != leaf->mRays.end(); ++ ri)
+	{
+		if (!(*ri).mRay->IsActive())
+			continue;
+
+		// determine the side of this ray with respect to the plane
+		float t;
+		int side = (*ri).ComputeRayIntersection(axis, position, t);
+			
+		if (side <= 0)
+			++ raysBack;
+
+		if (side >= 0)
+			++ raysFront;
+
+		AddObject2Pvs((*ri).mRay->mTerminationObject, side, pvsBack, pvsFront);
+	}
+
+	//-- only one of these options should be one
+
+	if (0) //-- only pvs
+	{
+		const float sum = float(pvsBack + pvsFront);
+		const float oldCost = (float)pvsSize;
+
+		return sum / oldCost;
+	}
+
+	//-- pvs + probability heuristics
+	float pBack, pFront, pOverall;
+
+	if (1)
+	{
+		// box length substitute for probability
+		const float minBox = box.Min(axis);
+		const float maxBox = box.Max(axis);
+
+		pBack = position - minBox;
+		pFront = maxBox - position;
+		pOverall = maxBox - minBox;
+	}
+
+	if (0) //-- area substitute for probability
+	{
+		pOverall = box.SurfaceArea();
+
+		const bool useMidSplit = true;
+		//const bool useMidSplit = false;	
+					
+		if (!useMidSplit)
+		{
+			Vector3 pos = box.Max(); pos[axis] = position;
+			pBack = AxisAlignedBox3(box.Min(), pos).SurfaceArea();
+
+			pos = box.Min(); pos[axis] = position;
+			pFront = AxisAlignedBox3(pos, box.Max()).SurfaceArea();
+		}
+		else
+		{
+			//-- simplified computation for mid split
+			const int axis2 = (axis + 1) % 3;
+			const int axis3 = (axis + 2) % 3;
+
+			const float faceArea = 
+				(box.Max(axis2) - box.Min(axis2)) *
+				(box.Max(axis3) - box.Min(axis3));
+
+			pBack = pFront = pOverall * 0.5f + faceArea;
+		}
+	}
+
+	//-- ray density substitute for probability
+	if (0)
+	{
+		pBack = (float)raysBack;
+		pFront = (float)raysFront;
+		pOverall = (float)leaf->mRays.size();
+	}
+
+	//Debug << axis << " " << pvsSize << " " << pvsBack << " " << pvsFront << endl;
+	//Debug << pFront << " " << pBack << " " << pOverall << endl;
+
+	// float sum = raysBack*(position - minBox) + raysFront*(maxBox - position);
+	const float newCost = pvsBack * pBack + pvsFront * pFront;
+	//  float oldCost = leaf->mRays.size();
+	const float oldCost = (float)pvsSize * pOverall;
+
+	return  (mCtDivCi + newCost) / oldCost;
+}
+
+
+float VspKdTree::BestCostRatioRegular(VspKdLeaf *leaf,
+									  const AxisAlignedBox3 &box,
+									  int &axis,
+									  float &position,
+									  int &raysBack,
+									  int &raysFront,
+									  int &pvsBack,
+									  int &pvsFront)
+{
+	int nRaysBack[3], nRaysFront[3];
+	int nPvsBack[3], nPvsFront[3];
+
+	float nPosition[3];
+	float nCostRatio[3];
+	int bestAxis = -1;
+
+	//AxisAlignedBox3 sBox = GetBBox(leaf);
+	const int sAxis = box.Size().DrivingAxis();
+
+	for (axis = 0; axis < 3; ++ axis)
+	{
+		if (!mOnlyDrivingAxis || axis == sAxis)
+		{
+
+			nPosition[axis] = (box.Min()[axis] + box.Max()[axis]) * 0.5f;
+
+			nCostRatio[axis] = EvalCostRatio(leaf,
+											 box,
+											 axis,
+											 nPosition[axis],
+											 nRaysBack[axis],
+											 nRaysFront[axis],
+											 nPvsBack[axis],
+											 nPvsFront[axis]);
+			if (bestAxis == -1)
+			{
+				bestAxis = axis;
+			}
+			else if (nCostRatio[axis] < nCostRatio[bestAxis])
+			{
+				/*Debug << "pvs front " << nPvsBack[axis]
+					  << " pvs back " << nPvsFront[axis]
+					  << " overall pvs " << leaf->GetPvsSize() << endl;*/
+				bestAxis = axis;
+			}
+
+		}
+	}
+
+	//-- assign best axis
+	axis = bestAxis;
+	position = nPosition[bestAxis];
+
+	raysBack = nRaysBack[bestAxis];
+	raysFront = nRaysFront[bestAxis];
+
+	pvsBack = nPvsBack[bestAxis];
+	pvsFront = nPvsFront[bestAxis];
+
+	return nCostRatio[bestAxis];
+}
+
+float VspKdTree::BestCostRatioHeuristic(VspKdLeaf *leaf,
+										const AxisAlignedBox3 &box,
+										int &axis,
+										float &position,
+										int &raysBack,
+										int &raysFront,
+										int &pvsBack,
+										int &pvsFront)
+{
+	//AxisAlignedBox3 box = GetBBox(leaf);
+	//	AxisAlignedBox3 dirBox = GetDirBBox(node);
+
+	axis = box.Size().DrivingAxis();
+
+	SortSplitCandidates(leaf, axis);
+
+	// go through the lists, count the number of objects left and right
+	// and evaluate the following cost funcion:
+	// C = ct_div_ci  + (ql*rl + qr*rr)/queries
+
+	int rl = 0, rr = (int)leaf->mRays.size();
+	int pl = 0, pr = leaf->GetPvsSize();
+
+	float minBox = box.Min(axis);
+	float maxBox = box.Max(axis);
+	float sizeBox = maxBox - minBox;
+
+	float minBand = minBox + 0.1f*(maxBox - minBox);
+	float maxBand = minBox + 0.9f*(maxBox - minBox);
+
+	float sum = rr*sizeBox;
+	float minSum = 1e20f;
+
+	Intersectable::NewMail();
+
+	// set all object as belonging to the fron pvs
+	for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+		ri != leaf->mRays.end(); ++ ri)
+	{
+		if ((*ri).mRay->IsActive())
+		{
+			Intersectable *object = (*ri).mRay->mTerminationObject;
+
+			if (object)
+				if (!object->Mailed())
+				{
+					object->Mail();
+					object->mCounter = 1;
+				}
+				else
+					++ object->mCounter;
+		}
+	}
+
+	Intersectable::NewMail();
+
+	for (vector<SortableEntry>::const_iterator ci = mSplitCandidates->begin();
+		ci < mSplitCandidates->end(); ++ ci)
+	{
+		VssRay *ray;
+
+		switch ((*ci).type)
+		{
+			case SortableEntry::ERayMin:
+				{
+					++ rl;
+					ray = (*ci).ray;
+					Intersectable *object = ray->mTerminationObject;
+					if (object && !object->Mailed())
+					{
+						object->Mail();
+						++ pl;
+					}
+					break;
+				}
+			case SortableEntry::ERayMax:
+				{
+					-- rr;
+
+					ray = (*ci).ray;
+					Intersectable *object = ray->mTerminationObject;
+
+					if (object)
+					{
+						if (-- object->mCounter == 0)
+						-- pr;
+					}
+
+					break;
+				}
+		}
+
+		if ((*ci).value > minBand && (*ci).value < maxBand)
+		{
+			sum = pl*((*ci).value - minBox) + pr*(maxBox - (*ci).value);
+
+			//  cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl;
+			// cout<<"cost= "<<sum<<endl;
+
+			if (sum < minSum)
+			{
+				minSum = sum;
+				position = (*ci).value;
+
+				raysBack = rl;
+				raysFront = rr;
+
+				pvsBack = pl;
+				pvsFront = pr;
+
+			}
+		}
+	}
+
+	float oldCost = (float)leaf->GetPvsSize();
+	float newCost = mCtDivCi + minSum / sizeBox;
+	float ratio = newCost / oldCost;
+
+	//Debug << "costRatio=" << ratio << " pos=" << position << " t=" << (position - minBox) / (maxBox - minBox)
+	//     <<"\t q=(" << queriesBack << "," << queriesFront << ")\t r=(" << raysBack << "," << raysFront << ")" << endl;
+
+	return ratio;
+}
+
+void VspKdTree::SortSplitCandidates(VspKdLeaf *node,
+									const int axis)
+{
+	mSplitCandidates->clear();
+
+	int requestedSize = 2 * (int)(node->mRays.size());
+	// creates a sorted split candidates array
+	if (mSplitCandidates->capacity() > 500000 &&
+		requestedSize < (int)(mSplitCandidates->capacity()/10) )
+	{
+    	DEL_PTR(mSplitCandidates);
+   		mSplitCandidates = new vector<SortableEntry>;
+	}
+
+	mSplitCandidates->reserve(requestedSize);
+
+	// insert all queries
+	for(RayInfoContainer::const_iterator ri = node->mRays.begin();
+		ri < node->mRays.end(); ++ ri)
+	{
+		bool positive = (*ri).mRay->HasPosDir(axis);
+		mSplitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMin : SortableEntry::ERayMax,
+												  (*ri).ExtrapOrigin(axis), (*ri).mRay));
+
+		mSplitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMax : SortableEntry::ERayMin,
+												  (*ri).ExtrapTermination(axis), (*ri).mRay));
+	}
+
+	stable_sort(mSplitCandidates->begin(), mSplitCandidates->end());
+}
+
+
+void VspKdTree::EvaluateLeafStats(const TraversalData &data)
+{
+	// the node became a leaf -> evaluate stats for leafs
+	VspKdLeaf *leaf = dynamic_cast<VspKdLeaf *>(data.mNode);
+
+	if (leaf->GetPvsSize() > mStat.maxPvsSize)
+		mStat.maxPvsSize = leaf->GetPvsSize();
+
+	if ((int)(leaf->mRays.size()) > mStat.maxRayRefs)
+		mStat.maxRayRefs = (int)leaf->mRays.size();
+
+	mStat.rays += (int)leaf->mRays.size();
+
+	if (data.mDepth >= mTermMaxDepth)
+		++ mStat.maxDepthNodes;
+
+	if (leaf->GetPvsSize() < mTermMinPvs)
+		++ mStat.minPvsNodes;
+
+	mStat.accPvsSize += leaf->GetPvsSize();
+
+	if ((int)leaf->GetRays().size() < mTermMinRays)
+		++ mStat.minRaysNodes;
+
+	if (leaf->GetAvgRayContribution() > mTermMaxRayContribution)
+		++ mStat.maxRayContribNodes;
+
+	if (SqrMagnitude(data.mBox.Size()) <= mTermMinSize)
+		++ mStat.minSizeNodes;
+}
+
+
+inline bool VspKdTree::TerminationCriteriaMet(const VspKdLeaf *leaf,
+											  const AxisAlignedBox3 &box) const
+{
+	return ((leaf->GetPvsSize() < mTermMinPvs) ||
+		    (leaf->mRays.size() < mTermMinRays) ||
+			(leaf->GetAvgRayContribution() > mTermMaxRayContribution ) ||
+			(leaf->mDepth >= mTermMaxDepth) ||
+			(mStat.Leaves() >= mMaxViewCells) ||
+			(SqrMagnitude(box.Size()) <= mTermMinSize));
+}
+
+
+VspKdNode *VspKdTree::SubdivideNode(VspKdLeaf *leaf,
+									const AxisAlignedBox3 &box,
+									AxisAlignedBox3 &backBBox,
+									AxisAlignedBox3 &frontBBox)
+{
+	if (TerminationCriteriaMet(leaf, box))
+	{
+		if (1 && leaf->mDepth >= mTermMaxDepth)
+		{
+			Debug << "Warning: max depth reached depth=" << (int)leaf->mDepth<<" rays=" << (int)leaf->mRays.size() << endl;
+			Debug << "Bbox: " << GetBBox(leaf) << endl;
+		}
+		//Debug << "depth: " << (int)leaf->mDepth << " pvs: " << leaf->GetPvsSize() << " rays: " << leaf->mRays.size() << endl;
+
+		return leaf;
+	}
+
+	float position;
+	// first count ray sides
+	int raysBack;
+	int raysFront;
+	int pvsBack;
+	int pvsFront;
+
+	// select subdivision axis
+	const int axis = SelectPlane(leaf, box, position, raysBack, raysFront, pvsBack, pvsFront);
+	//Debug << "rays back=" << raysBack << " rays front=" << raysFront << " pvs back=" << pvsBack << " pvs front=" <<	pvsFront << endl;
+
+	if (axis == -1)
+		return leaf;
+	
+	mStat.nodes += 2;
+	++ mStat.splits[axis];
+
+	// add the new nodes to the tree
+	VspKdInterior *node = 
+		new VspKdInterior(dynamic_cast<VspKdInterior *>(leaf->mParent));
+
+	node->mAxis = axis;
+	node->mPosition = position;
+	node->mBox = box;
+
+	backBBox = box;
+	frontBBox = box;
+
+	VspKdLeaf *back = new VspKdLeaf(node, raysBack, leaf->GetMaxCostMisses());
+	back->SetPvsSize(pvsBack);
+	VspKdLeaf *front = new VspKdLeaf(node, raysFront, leaf->GetMaxCostMisses());
+	front->SetPvsSize(pvsFront);
+
+	// replace a link from node's parent
+	if (leaf->mParent)
+	{
+		VspKdInterior *parent = dynamic_cast<VspKdInterior *>(leaf->mParent);
+		parent->ReplaceChildLink(leaf, node);
+	}
+
+	// and setup child links
+	node->SetupChildLinks(back, front);
+
+	if (axis <= VspKdNode::SPLIT_Z)
+	{
+		backBBox.SetMax(axis, position);
+		frontBBox.SetMin(axis, position);
+
+		for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+				ri != leaf->mRays.end(); ++ ri)
+		{
+			if ((*ri).mRay->IsActive())
+			{
+				// first unref ray from the former leaf
+				(*ri).mRay->Unref();
+				  float t;
+				// determine the side of this ray with respect to the plane
+				int side = node->ComputeRayIntersection(*ri, t);
+
+				if (side == 0)
+				{
+					if ((*ri).mRay->HasPosDir(axis))
+					{
+						back->AddRay(RayInfo((*ri).mRay,
+											 (*ri).mMinT,
+											 t));
+						front->AddRay(RayInfo((*ri).mRay,
+									 		  t,
+											  (*ri).mMaxT));
+					}
+					else
+					{
+						back->AddRay(RayInfo((*ri).mRay,
+											 t,
+											 (*ri).mMaxT));
+						front->AddRay(RayInfo((*ri).mRay,
+									 		  (*ri).mMinT,
+											  t));
+					}
+				}
+				else
+					if (side == 1)
+						front->AddRay(*ri);
+					else
+						back->AddRay(*ri);
+			} else
+				(*ri).mRay->Unref();
+		}
+	}
+	else
+	{
+		// rays front/back
+
+        for (RayInfoContainer::iterator ri = leaf->mRays.begin();
+			ri != leaf->mRays.end(); ++ ri)
+		{
+			if ((*ri).mRay->IsActive())
+			{
+				// first unref ray from the former leaf
+				(*ri).mRay->Unref();
+
+				int side;
+				if ((*ri).mRay->GetDirParametrization(axis - 3) > position)
+					side = 1;
+				else
+					side = -1;
+
+				if (side == 1)
+					front->AddRay(*ri);
+				else
+					back->AddRay(*ri);
+			}
+			else
+				(*ri).mRay->Unref();
+		}
+	}
+
+	// update stats
+	mStat.rayRefs -= (int)leaf->mRays.size();
+	mStat.rayRefs += raysBack + raysFront;
+
+	DEL_PTR(leaf);
+
+	return node;
+}
+
+int VspKdTree::ReleaseMemory(const int time)
+{
+	stack<VspKdNode *> tstack;
+
+	// find a node in the tree which subtree will be collapsed
+	int maxAccessTime = time - mAccessTimeThreshold;
+	int released = 0;
+
+	tstack.push(mRoot);
+
+	while (!tstack.empty())
+	{
+		VspKdNode *node = tstack.top();
+		tstack.pop();
+
+		if (!node->IsLeaf())
+		{
+			VspKdInterior *in = dynamic_cast<VspKdInterior *>(node);
+			// cout<<"depth="<<(int)in->depth<<" time="<<in->lastAccessTime<<endl;
+			if (in->mDepth >= mMinCollapseDepth && in->mLastAccessTime <= maxAccessTime)
+			{
+				released = CollapseSubtree(node, time);
+				break;
+			}
+			if (in->GetBack()->GetAccessTime() < in->GetFront()->GetAccessTime())
+			{
+				tstack.push(in->GetFront());
+				tstack.push(in->GetBack());
+			}
+			else
+			{
+				tstack.push(in->GetBack());
+				tstack.push(in->GetFront());
+			}
+		}
+	}
+
+	while (tstack.empty())
+	{
+		// could find node to collaps...
+		// cout<<"Could not find a node to release "<<endl;
+		break;
+	}
+
+	return released;
+}
+
+
+VspKdNode *VspKdTree::SubdivideLeaf(VspKdLeaf *leaf,
+										const float sizeThreshold)
+{
+	VspKdNode *node = leaf;
+
+	AxisAlignedBox3 leafBBox = GetBBox(leaf);
+
+	static int pass = 0;
+	++ pass;
+
+	// check if we should perform a dynamic subdivision of the leaf
+	if (// leaf->mRays.size() > (unsigned)termMinCost &&
+		(leaf->GetPvsSize() >= mTermMinPvs) &&
+		(SqrMagnitude(leafBBox.Size()) > sizeThreshold) )
+	{
+    	// memory check and release
+		if (GetMemUsage() > mMaxTotalMemory)
+			ReleaseMemory(pass);
+
+		AxisAlignedBox3 backBBox, frontBBox;
+
+		// subdivide the node
+		node = SubdivideNode(leaf, leafBBox, backBBox, frontBBox);
+	}
+	return node;
+}
+
+
+
+void VspKdTree::UpdateRays(VssRayContainer &remove,
+						   VssRayContainer &add)
+{
+	VspKdLeaf::NewMail();
+
+	// schedule rays for removal
+	for(VssRayContainer::const_iterator ri = remove.begin();
+		ri != remove.end(); ++ ri)
+	{
+		(*ri)->ScheduleForRemoval();
+	}
+
+	int inactive = 0;
+
+	for (VssRayContainer::const_iterator ri = remove.begin(); ri != remove.end(); ++ ri)
+	{
+		if ((*ri)->ScheduledForRemoval())
+			//      RemoveRay(*ri, NULL, false);
+			// !!! BUG - with true it does not work correctly - aggreated delete
+			RemoveRay(*ri, NULL, true);
+		else
+			++ inactive;
+	}
+
+	//  cout<<"all/inactive"<<remove.size()<<"/"<<inactive<<endl;
+	for (VssRayContainer::const_iterator ri = add.begin(); ri != add.end(); ++ ri)
+	{
+		AddRay(*ri);
+	}
+}
+
+
+void VspKdTree::RemoveRay(VssRay *ray,
+						  vector<VspKdLeaf *> *affectedLeaves,
+						  const bool removeAllScheduledRays)
+{
+	stack<RayTraversalData> tstack;
+
+	tstack.push(RayTraversalData(mRoot, RayInfo(ray)));
+
+	RayTraversalData data;
+
+	// cout<<"Number of ray refs = "<<ray->RefCount()<<endl;
+	while (!tstack.empty())
+	{
+		data = tstack.top();
+		tstack.pop();
+
+		if (!data.mNode->IsLeaf())
+		{
+			// split the set of rays in two groups intersecting the
+			// two subtrees
+			TraverseInternalNode(data, tstack);
+      	}
+		else
+		{
+			// remove the ray from the leaf
+			// find the ray in the leaf and swap it with the last ray...
+			VspKdLeaf *leaf = (VspKdLeaf *)data.mNode;
+
+			if (!leaf->Mailed())
+			{
+				leaf->Mail();
+
+				if (affectedLeaves)
+					affectedLeaves->push_back(leaf);
+
+				if (removeAllScheduledRays)
+				{
+					int tail = (int)leaf->mRays.size() - 1;
+
+					for (int i=0; i < (int)(leaf->mRays.size()); ++ i)
+					{
+						if (leaf->mRays[i].mRay->ScheduledForRemoval())
+						{
+							// find a ray to replace it with
+							while (tail >= i && leaf->mRays[tail].mRay->ScheduledForRemoval())
+							{
+								++ mStat.removedRayRefs;
+								leaf->mRays[tail].mRay->Unref();
+								leaf->mRays.pop_back();
+
+								-- tail;
+							}
+
+							if (tail < i)
+								break;
+
+							++ mStat.removedRayRefs;
+
+							leaf->mRays[i].mRay->Unref();
+							leaf->mRays[i] = leaf->mRays[tail];
+							leaf->mRays.pop_back();
+							-- tail;
+						}
+					}
+				}
+			}
+
+			if (!removeAllScheduledRays)
+				for (int i=0; i < (int)leaf->mRays.size(); i++)
+				{
+					if (leaf->mRays[i].mRay == ray)
+					{
+						++ mStat.removedRayRefs;
+						ray->Unref();
+						leaf->mRays[i] = leaf->mRays[leaf->mRays.size() - 1];
+						leaf->mRays.pop_back();
+					    // check this ray again
+						break;
+					}
+				}
+		}
+	}
+
+	if (ray->RefCount() != 0)
+	{
+		cerr << "Error: Number of remaining refs = " << ray->RefCount() << endl;
+		exit(1);
+	}
+
+}
+
+void VspKdTree::AddRay(VssRay *ray)
+{
+	stack<RayTraversalData> tstack;
+
+	tstack.push(RayTraversalData(mRoot, RayInfo(ray)));
+
+	RayTraversalData data;
+
+	while (!tstack.empty())
+	{
+		data = tstack.top();
+		tstack.pop();
+
+		if (!data.mNode->IsLeaf())
+		{
+			TraverseInternalNode(data, tstack);
+		}
+		else
+		{
+			// remove the ray from the leaf
+			// find the ray in the leaf and swap it with the last ray
+			VspKdLeaf *leaf = dynamic_cast<VspKdLeaf *>(data.mNode);
+
+			leaf->AddRay(data.mRayData);
+			++ mStat.addedRayRefs;
+		}
+	}
+}
+
+void VspKdTree::TraverseInternalNode(RayTraversalData &data,
+									 stack<RayTraversalData> &tstack)
+{
+	VspKdInterior *in = dynamic_cast<VspKdInterior *>(data.mNode);
+
+	if (in->mAxis <= VspKdNode::SPLIT_Z)
+	{
+	    // determine the side of this ray with respect to the plane
+		float t;
+		const int side = in->ComputeRayIntersection(data.mRayData, t);
+
+		if (side == 0)
+		{
+			if (data.mRayData.mRay->HasPosDir(in->mAxis))
+			{
+				tstack.push(RayTraversalData(in->GetBack(),
+							RayInfo(data.mRayData.mRay, data.mRayData.mMinT, t)));
+
+				tstack.push(RayTraversalData(in->GetFront(),
+							RayInfo(data.mRayData.mRay, t, data.mRayData.mMaxT)));
+
+			}
+			else
+			{
+				tstack.push(RayTraversalData(in->GetBack(),
+							RayInfo(data.mRayData.mRay,
+							t,
+							data.mRayData.mMaxT)));
+				tstack.push(RayTraversalData(in->GetFront(),
+							RayInfo(data.mRayData.mRay,
+							data.mRayData.mMinT,
+							t)));
+			}
+		}
+		else
+			if (side == 1)
+				tstack.push(RayTraversalData(in->GetFront(), data.mRayData));
+			else
+				tstack.push(RayTraversalData(in->GetBack(), data.mRayData));
+	}
+	else
+	{
+		// directional split
+		if (data.mRayData.mRay->GetDirParametrization(in->mAxis - 3) > in->mPosition)
+			tstack.push(RayTraversalData(in->GetFront(), data.mRayData));
+		else
+			tstack.push(RayTraversalData(in->GetBack(), data.mRayData));
+	}
+}
+
+
+int VspKdTree::CollapseSubtree(VspKdNode *sroot, const int time)
+{
+	// first count all rays in the subtree
+	// use mail 1 for this purpose
+	stack<VspKdNode *> tstack;
+
+	int rayCount = 0;
+	int totalRayCount = 0;
+	int collapsedNodes = 0;
+
+#if DEBUG_COLLAPSE
+	cout << "Collapsing subtree" << endl;
+	cout << "accessTime=" << sroot->GetAccessTime() << endl;
+	cout << "depth=" << (int)sroot->depth << endl;
+#endif
+
+	// tstat.collapsedSubtrees++;
+	// tstat.collapseDepths += (int)sroot->depth;
+	// tstat.collapseAccessTimes += time - sroot->GetAccessTime();
+	tstack.push(sroot);
+	VssRay::NewMail();
+
+	while (!tstack.empty())
+	{
+		++ collapsedNodes;
+
+		VspKdNode *node = tstack.top();
+		tstack.pop();
+		if (node->IsLeaf())
+		{
+			VspKdLeaf *leaf = (VspKdLeaf *) node;
+
+			for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+					ri != leaf->mRays.end(); ++ ri)
+			{
+				++ totalRayCount;
+
+				if ((*ri).mRay->IsActive() && !(*ri).mRay->Mailed())
+				{
+					(*ri).mRay->Mail();
+					++ rayCount;
+				}
+			}
+		}
+		else
+		{
+			tstack.push(dynamic_cast<VspKdInterior *>(node)->GetFront());
+			tstack.push(dynamic_cast<VspKdInterior *>(node)->GetBack());
+		}
+	}
+
+	VssRay::NewMail();
+
+	// create a new node that will hold the rays
+	VspKdLeaf *newLeaf = new VspKdLeaf(sroot->mParent, rayCount);
+
+	VspKdInterior *parent = 
+		dynamic_cast<VspKdInterior *>(newLeaf->mParent);
+
+	if (parent)
+	{
+		parent->ReplaceChildLink(sroot, newLeaf);
+	}
+	tstack.push(sroot);
+
+	while (!tstack.empty())
+	{
+		VspKdNode *node = tstack.top();
+		tstack.pop();
+
+		if (node->IsLeaf())
+		{
+			VspKdLeaf *leaf = dynamic_cast<VspKdLeaf *>(node);
+
+			for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+					ri != leaf->mRays.end(); ++ ri)
+			{
+				// unref this ray from the old node
+				if ((*ri).mRay->IsActive())
+				{
+					(*ri).mRay->Unref();
+					if (!(*ri).mRay->Mailed())
+					{
+						(*ri).mRay->Mail();
+						newLeaf->AddRay(*ri);
+					}
+				}
+				else
+					(*ri).mRay->Unref();
+			}
+		}
+		else
+		{
+			VspKdInterior *interior =
+				dynamic_cast<VspKdInterior *>(node);
+			tstack.push(interior->GetBack());
+			tstack.push(interior->GetFront());
+		}
+	}
+
+	// delete the node and all its children
+	DEL_PTR(sroot);
+
+	// for(VspKdNode::SRayContainer::iterator ri = newleaf->mRays.begin();
+    //      ri != newleaf->mRays.end(); ++ ri)
+	//     (*ri).ray->UnMail(2);
+
+#if DEBUG_COLLAPSE
+	cout << "Total memory before=" << GetMemUsage() << endl;
+#endif
+
+	mStat.nodes -= collapsedNodes - 1;
+	mStat.rayRefs -= totalRayCount - rayCount;
+
+#if DEBUG_COLLAPSE
+	cout << "collapsed nodes" << collapsedNodes << endl;
+	cout << "collapsed rays" << totalRayCount - rayCount << endl;
+	cout << "Total memory after=" << GetMemUsage() << endl;
+	cout << "================================" << endl;
+#endif
+
+	//  tstat.collapsedNodes += collapsedNodes;
+	//  tstat.collapsedRays += totalRayCount - rayCount;
+    return totalRayCount - rayCount;
+}
+
+
+int VspKdTree::GetPvsSize(VspKdNode *node, const AxisAlignedBox3 &box) const
+{
+	stack<VspKdNode *> tstack;
+	tstack.push(mRoot);
+
+	Intersectable::NewMail();
+	int pvsSize = 0;
+
+	while (!tstack.empty())
+	{
+		VspKdNode *node = tstack.top();
+		tstack.pop();
+
+	  if (node->IsLeaf())
+		{
+			VspKdLeaf *leaf = (VspKdLeaf *)node;
+			for (RayInfoContainer::iterator ri = leaf->mRays.begin();
+				 ri != leaf->mRays.end(); ++ ri)
+			{
+				if ((*ri).mRay->IsActive())
+				{
+					Intersectable *object;
+#if BIDIRECTIONAL_RAY
+					object = (*ri).mRay->mOriginObject;
+
+					if (object && !object->Mailed())
+					{
+						++ pvsSize;
+						object->Mail();
+					}
+#endif
+					object = (*ri).mRay->mTerminationObject;
+					if (object && !object->Mailed())
+					{
+						++ pvsSize;
+						object->Mail();
+					}
+				}
+			}
+		}
+		else
+		{
+			VspKdInterior *in = dynamic_cast<VspKdInterior *>(node);
+
+			if (in->mAxis < 3)
+			{
+				if (box.Max(in->mAxis) >= in->mPosition)
+					tstack.push(in->GetFront());
+
+				if (box.Min(in->mAxis) <= in->mPosition)
+					tstack.push(in->GetBack());
+			}
+			else
+			{
+				// both nodes for directional splits
+				tstack.push(in->GetFront());
+				tstack.push(in->GetBack());
+			}
+		}
+	}
+
+	return pvsSize;
+}
+
+void VspKdTree::GetRayContributionStatistics(float &minRayContribution,
+											 float &maxRayContribution,
+											 float &avgRayContribution)
+{
+	stack<VspKdNode *> tstack;
+	tstack.push(mRoot);
+
+	minRayContribution = 1.0f;
+	maxRayContribution = 0.0f;
+
+	float sumRayContribution = 0.0f;
+	int leaves = 0;
+
+	while (!tstack.empty())
+	{
+		VspKdNode *node = tstack.top();
+		tstack.pop();
+		if (node->IsLeaf())
+		{
+			leaves++;
+			VspKdLeaf *leaf = (VspKdLeaf *)node;
+			float c = leaf->GetAvgRayContribution();
+
+			if (c > maxRayContribution)
+				maxRayContribution = c;
+			if (c < minRayContribution)
+				minRayContribution = c;
+			sumRayContribution += c;
+
+		}
+		else
+		{
+			VspKdInterior *in = (VspKdInterior *)node;
+			
+			tstack.push(in->GetFront());
+			tstack.push(in->GetBack());
+		}
+	}
+
+	Debug << "sum=" << sumRayContribution << endl;
+	Debug << "leaves=" << leaves << endl;
+	avgRayContribution = sumRayContribution / (float)leaves;
+}
+
+
+int VspKdTree::GenerateRays(const float ratioPerLeaf,
+							SimpleRayContainer &rays)
+{
+	stack<VspKdNode *> tstack;
+	tstack.push(mRoot);
+
+	while (!tstack.empty())
+	{
+		VspKdNode *node = tstack.top();
+		tstack.pop();
+
+		if (node->IsLeaf())
+		{
+			VspKdLeaf *leaf = dynamic_cast<VspKdLeaf *>(node);
+
+			float c = leaf->GetAvgRayContribution();
+			int num = (int)(c*ratioPerLeaf + 0.5);
+			//			cout<<num<<" ";
+
+			for (int i=0; i < num; i++)
+			{
+				Vector3 origin = GetBBox(leaf).GetRandomPoint();
+				/*Vector3 dirVector = GetDirBBox(leaf).GetRandomPoint();
+				Vector3 direction = Vector3(sin(dirVector.x), sin(dirVector.y), cos(dirVector.x));
+				//cout<<"dir vector.x="<<dirVector.x<<"direction'.x="<<atan2(direction.x, direction.y)<<endl;
+				rays.push_back(SimpleRay(origin, direction));*/
+			}
+
+		}
+		else
+		{
+			VspKdInterior *in =
+				dynamic_cast<VspKdInterior *>(node);
+		
+			tstack.push(in->GetFront());
+			tstack.push(in->GetBack());
+		}
+	}
+
+	return (int)rays.size();
+}
+
+
+float VspKdTree::GetAvgPvsSize()
+{
+	stack<VspKdNode *> tstack;
+	tstack.push(mRoot);
+
+	int sumPvs = 0;
+	int leaves = 0;
+
+	while (!tstack.empty())
+	{
+		VspKdNode *node = tstack.top();
+		tstack.pop();
+
+		if (node->IsLeaf())
+		{
+			VspKdLeaf *leaf = (VspKdLeaf *)node;
+			// update pvs size
+			leaf->UpdatePvsSize();
+			sumPvs += leaf->GetPvsSize();
+			leaves++;
+		}
+		else
+		{
+			VspKdInterior *in = (VspKdInterior *)node;
+			
+			tstack.push(in->GetFront());
+			tstack.push(in->GetBack());
+		}
+	}
+
+	return sumPvs / (float)leaves;
+}
+
+VspKdNode *VspKdTree::GetRoot() const
+{
+	return mRoot;
+}
+
+AxisAlignedBox3 VspKdTree::GetBBox(VspKdNode *node) const
+{
+	if (node->mParent == NULL)
+		return mBox;
+
+	if (!node->IsLeaf())
+	{
+		if (node->Type() == VspKdNode::EIntermediate)
+            return (dynamic_cast<VspKdInterior *>(node))->mBox;
+		else
+			return (dynamic_cast<VspKdIntermediate *>(node))->mBox;
+	}
+
+	VspKdInterior *parent = dynamic_cast<VspKdInterior *>(node->mParent);
+
+	if (parent->mAxis >= 3)
+		return parent->mBox;
+
+	AxisAlignedBox3 box(parent->mBox);
+	if (parent->GetFront() == node)
+		box.SetMin(parent->mAxis, parent->mPosition);
+	else
+		box.SetMax(parent->mAxis, parent->mPosition);
+
+	return box;
+}
+
+int	VspKdTree::GetRootPvsSize() const
+{
+	return GetPvsSize(mRoot, mBox);
+}
+
+const VspKdStatistics &VspKdTree::GetStatistics() const
+{
+	return mStat;
+}
+
+void VspKdTree::AddRays(VssRayContainer &add)
+{
+	VssRayContainer remove;
+	UpdateRays(remove, add);
+}
+
+// return memory usage in MB
+float VspKdTree::GetMemUsage() const
+{
+	return
+		(sizeof(VspKdTree) +
+		 mStat.Leaves() * sizeof(VspKdLeaf) +
+		 mStat.Interior() * sizeof(VspKdInterior) +
+		 mStat.rayRefs * sizeof(RayInfo)) / (1024.0f * 1024.0f);
+}
+
+float VspKdTree::GetRayMemUsage() const
+{
+	return mStat.rays * (sizeof(VssRay))/(1024.0f * 1024.0f);
+}
+
+
+int VspKdTree::ComputePvsSize(VspKdNode *node,
+							  const RayInfoContainer &globalRays) const
+{
+	int pvsSize = 0;
+
+	const AxisAlignedBox3 box = GetBBox(node);
+
+	RayInfoContainer::const_iterator it, it_end = globalRays.end();
+
+	Intersectable::NewMail();
+
+	// warning: implicit conversion from VssRay to Ray
+	for (it = globalRays.begin(); it != globalRays.end(); ++ it)
+	{
+		VssRay *ray = (*it).mRay;
+
+		// ray intersects node bounding box
+		if (box.GetMinMaxT(*ray, NULL, NULL))
+		{
+			if (ray->mTerminationObject && !ray->mTerminationObject->Mailed())
+			{
+				ray->mTerminationObject->Mail();
+				++ pvsSize;
+			}
+		}
+	}
+	return pvsSize;
+}
+
+
+void VspKdTree::CollectLeaves(vector<VspKdLeaf *> &leaves) const
+{
+	stack<VspKdNode *> nodeStack;
+	nodeStack.push(mRoot);
+
+	while (!nodeStack.empty())
+	{
+		VspKdNode *node = nodeStack.top();
+
+		nodeStack.pop();
+
+		if (node->IsLeaf())
+		{
+			VspKdLeaf *leaf = dynamic_cast<VspKdLeaf *>(node);
+			leaves.push_back(leaf);
+		}
+		else
+		{
+			VspKdInterior *interior = dynamic_cast<VspKdInterior *>(node);
+
+			nodeStack.push(interior->GetBack());
+			nodeStack.push(interior->GetFront());
+		}
+	}
+}
+
+
+int VspKdTree::FindNeighbors(VspKdLeaf *n,
+							 vector<VspKdLeaf *> &neighbors,
+							 bool onlyUnmailed)
+{
+	stack<VspKdNode *> nodeStack;
+
+	nodeStack.push(mRoot);
+
+	AxisAlignedBox3 box = GetBBox(n);
+
+	while (!nodeStack.empty())
+	{
+		VspKdNode *node = nodeStack.top();
+		nodeStack.pop();
+
+		if (node->IsLeaf())
+		{
+			VspKdLeaf *leaf = dynamic_cast<VspKdLeaf *>(node);
+
+			if (leaf != n && (!onlyUnmailed || !leaf->Mailed()))
+				neighbors.push_back(leaf);
+		}
+		else
+		{
+			VspKdInterior *interior = dynamic_cast<VspKdInterior *>(node);
+
+			if (interior->mPosition > box.Max(interior->mAxis))
+				nodeStack.push(interior->mBack);
+			else
+			{
+				if (interior->mPosition < box.Min(interior->mAxis))
+					nodeStack.push(interior->mFront);
+				else
+				{
+					// random decision
+					nodeStack.push(interior->mBack);
+					nodeStack.push(interior->mFront);
+				}
+			}
+		}
+	}
+
+	return (int)neighbors.size();
+}
+
+
+void VspKdTree::SetViewCellsManager(ViewCellsManager *vcm)
+{
+	mViewCellsManager = vcm;
+}
+
+
+int VspKdTree::CastLineSegment(const Vector3 &origin,
+							   const Vector3 &termination,
+							   vector<ViewCell *> &viewcells)
+{
+	int hits = 0;
+
+	float mint = 0.0f, maxt = 1.0f;
+	const Vector3 dir = termination - origin;
+
+	stack<LineTraversalData> tStack;
+
+	Intersectable::NewMail();
+
+	Vector3 entp = origin;
+	Vector3 extp = termination;
+
+	VspKdNode *node = mRoot;
+	VspKdNode *farChild;
+
+	float position;
+	int axis;
+
+	while (1)
+	{
+		if (!node->IsLeaf())
+		{
+			VspKdInterior *in = dynamic_cast<VspKdInterior *>(node);
+			position = in->mPosition;
+			axis = in->mAxis;
+
+			if (entp[axis] <= position)
+			{
+				if (extp[axis] <= position)
+				{
+					node = in->mBack;
+					// cases N1,N2,N3,P5,Z2,Z3
+					continue;
+				} else
+				{
+					// case N4
+					node = in->mBack;
+					farChild = in->mFront;
+				}
+			}
+			else
+			{
+				if (position <= extp[axis])
+				{
+					node = in->mFront;
+					// cases P1,P2,P3,N5,Z1
+					continue;
+				}
+				else
+				{
+					node = in->mFront;
+					farChild = in->mBack;
+					// case P4
+				}
+			}
+
+ 			// $$ modification 3.5.2004 - hints from Kamil Ghais
+			// case N4 or P4
+			float tdist = (position - origin[axis]) / dir[axis];
+			tStack.push(LineTraversalData(farChild, extp, maxt)); //TODO
+			extp = origin + dir * tdist;
+			maxt = tdist;
+		}
+		else
+		{
+			// compute intersection with all objects in this leaf
+			VspKdLeaf *leaf = dynamic_cast<VspKdLeaf *>(node);
+			ViewCell *vc = leaf->GetViewCell();
+
+			if (!vc->Mailed())
+			{
+				vc->Mail();
+				viewcells.push_back(vc);
+				++ hits;
+			}
+
+			if (0) //matt TODO: REMOVE LATER
+				leaf->mRays.push_back(RayInfo(new VssRay(origin, termination, NULL, NULL, 0)));
+
+			// get the next node from the stack
+			if (tStack.empty())
+				break;
+
+			entp = extp;
+			mint = maxt;
+			
+			LineTraversalData &s  = tStack.top();
+			node = s.mNode;
+			extp = s.mExitPoint;
+			maxt = s.mMaxT;
+			tStack.pop();
+		}
+	}
+
+	return hits;
+}
+
+
+void VspKdTree::GenerateViewCell(VspKdLeaf *leaf)
+{
+	RayInfoContainer::const_iterator it, it_end = leaf->GetRays().end();
+
+	VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCellsManager->GenerateViewCell());
+	leaf->SetViewCell(vc);
+
+	vc->SetVolume(GetBBox(leaf).GetVolume());
+	vc->SetArea(GetBBox(leaf).SurfaceArea());
+
+	vc->mLeaf = leaf;
+
+	for (it = leaf->GetRays().begin(); it != it_end; ++ it)
+	{
+		VssRay *ray = (*it).mRay;
+
+		if (ray->mTerminationObject)
+		  vc->GetPvs().AddSample(ray->mTerminationObject, ray->mPdf);
+
+		if (ray->mOriginObject)
+		  vc->GetPvs().AddSample(ray->mOriginObject, ray->mPdf);
+	}
+}
+
+
+bool VspKdTree::MergeViewCells(VspKdLeaf *l1, VspKdLeaf *l2)
+{
+	//-- change pointer to view cells of all leaves associated 
+	//-- with the previous view cells
+	VspKdViewCell *fVc = l1->GetViewCell();
+	VspKdViewCell *bVc = l2->GetViewCell();
+
+	VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(
+		mViewCellsManager->MergeViewCells(fVc, bVc));
+
+	// if merge was unsuccessful
+	if (!vc) return false;
+// TODO
+#if VC_HISTORY
+	// set new size of view cell
+	vc->SetVolume(fVc->GetVolume() + bVc->GetVolume());
+	// new area
+	vc->SetArea(fVc->GetArea() + bVc->GetArea());
+
+	vector<VspKdLeaf *> fLeaves = fVc->mLeaves;
+	vector<VspKdLeaf *> bLeaves = bVc->mLeaves;
+
+	vector<VspKdLeaf *>::const_iterator it;
+
+	//-- change view cells of all the other leaves the view cell belongs to
+	for (it = fLeaves.begin(); it != fLeaves.end(); ++ it)
+	{
+		(*it)->SetViewCell(vc);
+		vc->mLeaves.push_back(*it);
+	}
+
+	for (it = bLeaves.begin(); it != bLeaves.end(); ++ it)
+	{
+		(*it)->SetViewCell(vc);
+		vc->mLeaves.push_back(*it);
+	}
+#endif
+	vc->Mail();
+
+	// clean up old view cells
+	DEL_PTR(fVc);
+	DEL_PTR(bVc);
+
+	return true;
+}
+
+void VspKdTree::CollectMergeCandidates()
+{
+	VspKdMergeCandidate::sOverallCost = 0;
+	vector<VspKdLeaf *> leaves;
+
+	// collect the leaves, e.g., the "voxels" that will build the view cells
+	CollectLeaves(leaves);
+
+	VspKdLeaf::NewMail();
+
+	vector<VspKdLeaf *>::const_iterator it, it_end = leaves.end();
+
+	// generate view cells
+	for (it = leaves.begin(); it != it_end; ++ it)
+		GenerateViewCell(*it);
+
+	// find merge candidates and push them into queue
+	for (it = leaves.begin(); it != it_end; ++ it)
+	{
+		VspKdLeaf *leaf = *it;
+		ViewCell *vc = leaf->GetViewCell();
+		// no leaf is part of two merge candidates
+		leaf->Mail();
+		VspKdMergeCandidate::sOverallCost += 
+			vc->GetVolume() * vc->GetPvs().GetSize();
+		vector<VspKdLeaf *> neighbors;
+		FindNeighbors(leaf, neighbors, true);
+
+		vector<VspKdLeaf *>::const_iterator nit,
+			nit_end = neighbors.end();
+
+		for (nit = neighbors.begin(); nit != nit_end; ++ nit)
+		{
+			mMergeQueue.push(VspKdMergeCandidate(leaf, *nit));
+		}
+	}
+}
+
+
+int VspKdTree::MergeViewCells(const VssRayContainer &rays)
+{
+	CollectMergeCandidates();
+
+	int merged = 0;
+
+	int vcSize = mStat.Leaves();
+	// use priority queue to merge leaves
+	while (!mMergeQueue.empty() && (vcSize > mMergeMinViewCells) &&
+		   (mMergeQueue.top().GetMergeCost() < 
+		    mMergeMaxCostRatio * VspKdMergeCandidate::sOverallCost))
+	{
+		//Debug << "mergecost: " << mergeQueue.top().GetMergeCost() / 
+		//VspKdMergeCandidate::sOverallCost << " " << mMergeMaxCostRatio << endl;
+		VspKdMergeCandidate mc = mMergeQueue.top();
+		mMergeQueue.pop();
+
+		// both view cells equal!
+		if (mc.GetLeaf1()->GetViewCell() == mc.GetLeaf2()->GetViewCell())
+			continue;
+
+		if (mc.Valid())
+		{
+			ViewCell::NewMail();
+			MergeViewCells(mc.GetLeaf1(), mc.GetLeaf2());
+
+			++ merged;
+			-- vcSize;
+			// increase absolute merge cost
+			VspKdMergeCandidate::sOverallCost += mc.GetMergeCost();
+		}
+		// merge candidate not valid, because one of the leaves was already
+		// merged with another one
+		else
+		{
+			// validate and reinsert into queue
+			mc.SetValid();
+			mMergeQueue.push(mc);
+			//Debug << "validate " << mc.GetMergeCost() << endl;
+		}
+	}
+
+	Debug << "merged " << merged << " of " << mStat.Leaves() << " leaves" << endl;
+
+	//TODO: should return sample contributions
+	return merged;
+}
+
+
+void VspKdTree::RepairViewCellsLeafLists()
+{
+	// list not valid anymore => clear
+	stack<VspKdNode *> nodeStack;
+	nodeStack.push(mRoot);
+
+	ViewCell::NewMail();
+
+	while (!nodeStack.empty())
+	{
+		VspKdNode *node = nodeStack.top();
+		nodeStack.pop();
+
+		if (node->IsLeaf())
+		{
+			VspKdLeaf *leaf = dynamic_cast<VspKdLeaf *>(node);
+
+			VspKdViewCell *viewCell = leaf->GetViewCell();
+#if VC_HISTORY
+			if (!viewCell->Mailed())
+			{
+				viewCell->mLeaves.clear();
+				viewCell->Mail();
+			}
+
+			viewCell->mLeaves.push_back(leaf);
+#endif
+		}
+		else
+		{
+			VspKdInterior *interior = dynamic_cast<VspKdInterior *>(node);
+
+			nodeStack.push(interior->GetFront());
+			nodeStack.push(interior->GetBack());
+		}
+	}
+}
+
+
+VspKdNode *VspKdTree::CollapseTree(VspKdNode *node, int &collapsed)
+{
+	if (node->IsLeaf())
+		return node;
+
+	VspKdInterior *interior = dynamic_cast<VspKdInterior *>(node);
+
+	VspKdNode *front = CollapseTree(interior->GetFront(), collapsed);
+	VspKdNode *back = CollapseTree(interior->GetBack(), collapsed);
+
+	if (front->IsLeaf() && back->IsLeaf())
+	{
+		VspKdLeaf *frontLeaf = dynamic_cast<VspKdLeaf *>(front);
+		VspKdLeaf *backLeaf = dynamic_cast<VspKdLeaf *>(back);
+
+		//-- collapse tree
+		if (frontLeaf->GetViewCell() == backLeaf->GetViewCell())
+		{
+			VspKdViewCell *vc = frontLeaf->GetViewCell();
+
+			VspKdLeaf *leaf = new VspKdLeaf(interior->GetParent(), 0);
+			leaf->SetViewCell(vc);
+			//leaf->SetTreeValid(frontLeaf->TreeValid());
+
+			// replace a link from node's parent
+			if (leaf->mParent)
+			{
+				// replace a link from node's parent
+				VspKdInterior *parent = 
+					dynamic_cast<VspKdInterior *>(leaf->mParent);
+				parent->ReplaceChildLink(node, leaf);
+			}
+			++ collapsed;
+			delete interior;
+
+			return leaf;
+		}
+	}
+
+	return node;
+}
+
+
+int VspKdTree::CollapseTree()
+{
+	int collapsed = 0;
+	CollapseTree(mRoot, collapsed);
+	// revalidate leaves
+	RepairViewCellsLeafLists();
+
+	return collapsed;
+}
+
+
+int VspKdTree::RefineViewCells(const VssRayContainer &rays)
+{
+	int shuffled = 0;
+
+	Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl;
+	BspLeaf::NewMail();
+
+	// Use priority queue of remaining leaf pairs 
+	// These candidates either share the same view cells or
+	// are border leaves which share a boundary.
+	// We test if they can be shuffled, i.e.,
+	// either one leaf is made part of one view cell or the other
+	// leaf is made part of the other view cell. It is tested if the
+	// remaining view cells are "better" than the old ones.
+	while (!mMergeQueue.empty())
+	{
+		VspKdMergeCandidate mc = mMergeQueue.top();
+		mMergeQueue.pop();
+
+		// both view cells equal or already shuffled
+		if ((mc.GetLeaf1()->GetViewCell() == mc.GetLeaf2()->GetViewCell()) ||
+			(mc.GetLeaf1()->Mailed()) || (mc.GetLeaf2()->Mailed()))
+			continue;
+		
+		// candidate for shuffling
+		const bool wasShuffled = false;
+			//ShuffleLeaves(mc.GetLeaf1(), mc.GetLeaf2());
+			// matt: restore
+		//-- stats
+		if (wasShuffled)
+			++ shuffled;
+	}
+
+	return shuffled;
+}
+
+
+inline int AddedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
+{
+	return pvs1.AddPvs(pvs2);
+}
+
+
+inline int SubtractedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
+{
+	return pvs1.SubtractPvs(pvs2);
+}
+
+
+float EvalShuffleCost(VspKdLeaf *leaf, VspKdViewCell *vc1, VspKdViewCell *vc2)
+{
+	const int pvs1 = SubtractedPvsSize(vc1->GetPvs(), *leaf->mPvs);
+	const int pvs2 = AddedPvsSize(vc2->GetPvs(), *leaf->mPvs);
+
+	const float vol1 = vc1->GetVolume() - leaf->mVolume;
+	const float vol2 = vc2->GetVolume() + leaf->mVolume;
+
+	const float cost1 = pvs1 * vol1;
+	const float cost2 = pvs2 * vol2;
+
+	return cost1 + cost2;
+}
+
+
+void VspKdTree::ShuffleLeaf(VspKdLeaf *leaf, 
+							VspKdViewCell *vc1, 
+							VspKdViewCell *vc2) const
+{
+	// compute new pvs and area
+	//	TODO
+#if VC_HISTORY
+	vc1->GetPvs().SubtractPvs(*leaf->mPvs);
+	vc2->GetPvs().AddPvs(*leaf->mPvs);
+	
+	vc1->SetArea(vc1->GetVolume() - leaf->mVolume);
+	vc2->SetArea(vc2->GetVolume() + leaf->mVolume);
+
+	/// add to second view cell
+	vc2->mLeaves.push_back(leaf);
+
+	// erase leaf from old view cell
+	vector<VspKdLeaf *>::iterator it = vc1->mLeaves.begin();
+
+	for (; *it != leaf; ++ it);
+	vc1->mLeaves.erase(it);
+
+	leaf->SetViewCell(vc2);  // finally change view cell
+#endif
+}
+
+
+bool VspKdTree::ShuffleLeaves(VspKdLeaf *leaf1, VspKdLeaf *leaf2) const
+{
+	VspKdViewCell *vc1 = leaf1->GetViewCell();
+	VspKdViewCell *vc2 = leaf2->GetViewCell();
+
+	const float cost1 = vc1->GetPvs().GetSize() * vc1->GetArea();
+	const float cost2 = vc2->GetPvs().GetSize() * vc2->GetArea();
+
+	const float oldCost = cost1 + cost2;
+	
+	float shuffledCost1 = Limits::Infinity;
+	float shuffledCost2 = Limits::Infinity;
+
+	// the view cell should not be empty after the shuffle
+//todo
+	/*	if (vc1->mLeaves.size() > 1)
+		shuffledCost1 = EvalShuffleCost(leaf1, vc1, vc2);
+	if (vc2->mLeaves.size() > 1)
+		shuffledCost2 = EvalShuffleCost(leaf2, vc2, vc1);
+
+*/	// shuffling unsuccessful
+	if ((oldCost <= shuffledCost1) && (oldCost <= shuffledCost2))
+		return false;
+	
+	if (shuffledCost1 < shuffledCost2)
+	{
+		ShuffleLeaf(leaf1, vc1, vc2);
+		leaf1->Mail();
+	}
+	else
+	{
+		ShuffleLeaf(leaf2, vc2, vc1);
+		leaf2->Mail();
+	}
+
+	return true;
+}
+
+
+
+
+/*********************************************************************/
+/*                VspKdMergeCandidate implementation                      */
+/*********************************************************************/
+
+
+VspKdMergeCandidate::VspKdMergeCandidate(VspKdLeaf *l1, VspKdLeaf *l2):
+mMergeCost(0),
+mLeaf1(l1),
+mLeaf2(l2),
+mLeaf1Id(l1->GetViewCell()->mMailbox),
+mLeaf2Id(l2->GetViewCell()->mMailbox)
+{
+	EvalMergeCost();
+}
+
+float VspKdMergeCandidate::GetLeaf1Cost() const
+{
+	VspKdViewCell *vc = mLeaf1->GetViewCell();
+	return vc->GetPvs().GetSize() * vc->GetVolume();
+}
+
+float VspKdMergeCandidate::GetLeaf2Cost() const
+{
+	VspKdViewCell *vc = mLeaf2->GetViewCell();
+	return vc->GetPvs().GetSize() * vc->GetVolume();
+}
+
+void VspKdMergeCandidate::EvalMergeCost()
+{
+	//-- compute pvs difference
+	VspKdViewCell *vc1 = mLeaf1->GetViewCell();
+	VspKdViewCell *vc2 = mLeaf2->GetViewCell();
+
+	const int diff1 = vc1->GetPvs().Diff(vc2->GetPvs());
+	const int vcPvs = diff1 + vc1->GetPvs().GetSize();
+
+	//-- compute ratio of old cost
+	//-- (added size of left and right view cell times pvs size)
+	//-- to new rendering cost (size of merged view cell times pvs size)
+	const float oldCost = GetLeaf1Cost() + GetLeaf2Cost();
+	
+	const float newCost =
+		(float)vcPvs * (vc1->GetVolume() + vc2->GetVolume());
+
+	mMergeCost = newCost - oldCost;
+
+//	if (vcPvs > sMaxPvsSize) // strong penalty if pvs size too large
+//		mMergeCost += 1.0;
+}
+
+void VspKdMergeCandidate::SetLeaf1(VspKdLeaf *l)
+{
+	mLeaf1 = l;
+}
+
+void VspKdMergeCandidate::SetLeaf2(VspKdLeaf *l)
+{
+	mLeaf2 = l;
+}
+
+
+VspKdLeaf *VspKdMergeCandidate::GetLeaf1()
+{
+	return mLeaf1;
+}
+
+
+VspKdLeaf *VspKdMergeCandidate::GetLeaf2()
+{
+	return mLeaf2;
+}
+
+
+bool VspKdMergeCandidate::Valid() const
+{
+	return
+		(mLeaf1->GetViewCell()->mMailbox == mLeaf1Id) &&
+		(mLeaf2->GetViewCell()->mMailbox == mLeaf2Id);
+}
+
+
+float VspKdMergeCandidate::GetMergeCost() const
+{
+	return mMergeCost;
+}
+
+
+void VspKdMergeCandidate::SetValid()
+{
+	mLeaf1Id = mLeaf1->GetViewCell()->mMailbox;
+	mLeaf2Id = mLeaf2->GetViewCell()->mMailbox;
+
+	EvalMergeCost();
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Exporter.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Exporter.cpp	(revision 162)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Exporter.cpp	(revision 162)
@@ -0,0 +1,17 @@
+
+#include "X3dExporter.h"
+
+
+Exporter *
+Exporter::GetExporter(const string filename)
+{
+  Exporter *e = NULL;
+
+  if (strstr(filename.c_str(), ".x3d")) {
+    e = new X3dExporter(filename);
+  } else {
+    cerr<<"Error: Currently unsuported export format, filename "<<filename<<endl;
+  }
+  return e;
+}
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Matrix4x4.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Matrix4x4.h	(revision 209)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Matrix4x4.h	(revision 209)
@@ -0,0 +1,103 @@
+#ifndef __MATRIX4x4_H
+#define __MATRIX4x4_H
+
+#include <iostream>
+using namespace std;
+
+class Vector3;
+
+
+
+class Matrix4x4
+{
+public:
+  float x[4][4]; // first index is column [x], the second is row [y]
+
+  Matrix4x4() { }
+
+  // here xXY - 'X' is row, and 'Y' is column - classical mathematical notation
+  Matrix4x4(float x11, float x12, float x13, float x14,
+	   float x21, float x22, float x23, float x24,
+	   float x31, float x32, float x33, float x34,
+	   float x41, float x42, float x43, float x44);
+
+  Matrix4x4(const Vector3 &a, const Vector3 &b, const Vector3 &c);
+
+
+  // Assignment operators
+  Matrix4x4& operator+= (const Matrix4x4 &A); 	// add-to
+  Matrix4x4& operator-= (const Matrix4x4 &A); 	// subtract-from
+  Matrix4x4& operator*= (const Matrix4x4 &A); 	// multiply by matrix
+  Matrix4x4& operator*= (float A); 		// scale by scalar
+
+  // Fundamental operations
+  int Invert();		      // Invert the matrix .. returns 0 = regular
+  void Transpose();				// Transpose the matrix
+
+  void
+  SetColumns(const Vector3 &a, const Vector3 &b, const Vector3 &c);
+
+  float Det3x3() const {
+    return (x[0][0]*x[1][1]*x[2][2] + \
+	    x[1][0]*x[2][1]*x[0][2] + \
+	    x[2][0]*x[0][1]*x[1][2] - \
+	    x[2][0]*x[1][1]*x[0][2] - \
+	    x[0][0]*x[2][1]*x[1][2] - \
+	    x[1][0]*x[0][1]*x[2][2]);
+  }
+  
+
+  friend Matrix4x4 Invert(const Matrix4x4 &M);	// Invert a given matrix
+  friend Matrix4x4 Transpose(const Matrix4x4 &M);	// Transpose a given matrix
+
+  // Create various types of matrix.
+  friend Matrix4x4 IdentityMatrix();
+  friend Matrix4x4 ZeroMatrix();
+  friend Matrix4x4 TranslationMatrix(const Vector3 &Location);
+  friend Matrix4x4 RotationXMatrix(float Angle);
+  friend Matrix4x4 RotationYMatrix(float Angle);
+  friend Matrix4x4 RotationZMatrix(float Angle);
+  friend Matrix4x4 RotationYPRMatrix(float Yaw, float Pitch, float Roll);
+  // about axis 'axis' by angle 'Angle'
+  friend Matrix4x4 RotationAxisMatrix(const Vector3 &axis, float Angle);
+  // create the rotation matrix that rotates 'vecFrom' to 'vecTo'
+  friend Matrix4x4 RotationVectorsMatrix(const Vector3 &vecFrom,
+					 const Vector3 &vecTo);
+  
+  friend Matrix4x4 ScaleMatrix(float X, float Y, float Z);
+  friend Matrix4x4 GenRotation(const Vector3 &x, const Vector3 &y,
+			     const Vector3 &z);
+  friend Matrix4x4 QuadricMatrix(float a, float b, float c, float d, float e,
+			      float f, float g, float h, float j, float k);
+  // returns matrix for transforming normal
+  friend Matrix4x4 NormalTransformMatrix(const Matrix4x4 &M);
+
+  friend Matrix4x4 MirrorX();
+  friend Matrix4x4 MirrorY();
+  friend Matrix4x4 MirrorZ();
+  friend Matrix4x4 RotationOnly(const Matrix4x4 &x);
+
+  // Binary operators
+  friend Matrix4x4 operator+ (const Matrix4x4 &A, const Matrix4x4 &B);
+  friend Matrix4x4 operator- (const Matrix4x4 &A, const Matrix4x4 &B);
+  friend Matrix4x4 operator* (const Matrix4x4 &A, float B);
+  friend Matrix4x4 operator* (const Matrix4x4 &A, const Matrix4x4 &B);
+
+  // friends returning Vector3
+  friend Vector3 operator*(const Matrix4x4 &M, const Vector3 &v);
+  friend Vector3 RotateOnly(const Matrix4x4 &M, const Vector3 &v);
+  friend Vector3 TransformNormal(const Matrix4x4 &M, const Vector3 &v);
+  friend Vector3 GetTranslation(const Matrix4x4 &M);
+
+  // Construct rotation description according VRML'97 specification
+  //  const CVector4D SFRotation(void) const;
+
+  
+
+  // Overloaded output operator.
+  friend ostream& operator<< (ostream &s, const Matrix4x4 &M);
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 613)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 613)
@@ -0,0 +1,1827 @@
+#include "ViewCell.h"
+#include "Mesh.h"
+#include "Intersectable.h"
+#include "MeshKdTree.h"
+#include "Triangle3.h"
+#include "common.h"
+#include "Environment.h"
+#include "ViewCellsManager.h"
+#include "Exporter.h"
+
+#include <time.h>
+#include <iomanip>
+#include <stack>
+
+
+
+template <typename T> class myless
+{
+public:
+	//bool operator() (HierarchyNode *v1, HierarchyNode *v2) const
+	bool operator() (T v1, T v2) const
+	{
+		return (v1->GetMergeCost() < v2->GetMergeCost());
+	}
+};
+
+
+typedef priority_queue<ViewCell *, vector<ViewCell *>, myless<vector<ViewCell *>::value_type> > TraversalQueue;
+
+int ViewCell::sMailId = 21843194198;
+int ViewCell::sReservedMailboxes = 1;
+
+//int upperPvsLimit = 120;
+//int lowerPvsLimit = 5;
+
+float MergeCandidate::sRenderCostWeight = 0;
+
+
+// pvs penalty can be different from pvs size
+inline float EvalPvsPenalty(const int pvs, 
+							const int lower,
+							const int upper)
+{
+	// clamp to minmax values
+	/*if (pvs < lower)
+		return (float)lower;
+	if (pvs > upper)
+		return (float)upper;
+*/
+	return (float)pvs;
+}
+
+
+
+
+inline int CountDiffPvs(ViewCell *vc)
+{
+	int count = 0;
+
+	ObjectPvsMap::const_iterator it, it_end = vc->GetPvs().mEntries.end();
+	for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
+	{
+		if (!(*it).first->Mailed())
+		{
+			(*it).first->Mail();
+			++ count;
+		}
+	}
+
+	return count;
+}
+
+
+int ComputeMergedPvsSize(const ObjectPvs &pvs1, const ObjectPvs &pvs2)
+{
+	int pvs = pvs1.GetSize();
+
+	// compute new pvs size
+	ObjectPvsMap::const_iterator it, it_end =  pvs1.mEntries.end();
+
+	Intersectable::NewMail();
+
+	for (it = pvs1.mEntries.begin(); it != it_end; ++ it)
+	{
+		(*it).first->Mail();
+	}
+
+	it_end = pvs2.mEntries.end();
+
+	for (it = pvs2.mEntries.begin(); it != it_end; ++ it)
+	{
+		Intersectable *obj = (*it).first;
+		if (!obj->Mailed())
+			++ pvs;
+	}
+
+	return pvs;
+}
+
+
+ViewCell::ViewCell(): 
+MeshInstance(NULL), 
+mPiercingRays(0),
+mArea(-1),
+mVolume(-1),
+mValid(true),
+mParent(NULL),
+mMergeCost(0),
+mIsActive(false)
+{
+}
+
+ViewCell::ViewCell(Mesh *mesh): 
+MeshInstance(mesh), 
+mPiercingRays(0),
+mArea(-1),
+mVolume(-1),
+mValid(true),
+mParent(NULL),
+mMergeCost(0),
+mIsActive(false)
+{
+}
+
+
+const ObjectPvs &ViewCell::GetPvs() const
+{
+	return mPvs;
+}
+
+ObjectPvs &ViewCell::GetPvs()
+{
+	return mPvs;
+}
+
+
+int ViewCell::Type() const 
+{ 
+	return VIEW_CELL; 
+}
+
+
+float ViewCell::GetVolume() const
+{
+	return mVolume;
+}
+
+
+void ViewCell::SetVolume(float volume) 
+{
+	mVolume = volume;
+}
+
+
+void ViewCell::SetMesh(Mesh *mesh)
+{
+	mMesh = mesh;
+}
+
+
+float ViewCell::GetArea() const
+{
+	return mArea;
+}
+
+
+void ViewCell::SetArea(float area) 
+{
+	mArea = area;
+}
+
+
+void ViewCell::SetValid(const bool valid)
+{
+	mValid = valid;
+}
+
+
+bool ViewCell::GetValid() const
+{
+	return mValid;
+}
+
+
+/*bool ViewCell::IsLeaf() const
+{
+	return true;
+}*/
+
+
+void ViewCell::SetParent(ViewCellInterior *parent)
+{
+	mParent = parent;
+}
+
+
+bool ViewCell::IsRoot() const
+{
+	return !mParent;
+}
+
+
+ViewCellInterior *ViewCell::GetParent() const
+{
+	return mParent;
+}
+
+
+void ViewCell::SetMergeCost(const float mergeCost)
+{
+	mMergeCost = mergeCost;
+}
+
+
+float ViewCell::GetMergeCost() const
+{
+	return mMergeCost;
+}
+
+
+
+/************************************************************************/
+/*                class ViewCellInterior implementation                 */
+/************************************************************************/
+
+
+ViewCellInterior::ViewCellInterior()
+{
+}
+
+
+ViewCellInterior::~ViewCellInterior()
+{
+	ViewCellContainer::const_iterator it, it_end = mChildren.end();
+
+	for (it = mChildren.begin(); it != it_end; ++ it)
+		delete (*it);
+}
+
+
+ViewCellInterior::ViewCellInterior(Mesh *mesh): 
+ViewCell(mesh)
+{
+}
+
+
+bool ViewCellInterior::IsLeaf() const
+{
+	return false;
+}
+
+
+void ViewCellInterior::SetupChildLink(ViewCell *l)
+{
+    mChildren.push_back(l);
+    l->mParent = this;
+}
+
+
+void ViewCellInterior::RemoveChildLink(ViewCell *l)
+{
+	// erase leaf from old view cell
+	ViewCellContainer::iterator it = mChildren.begin();
+
+	for (; (*it) != l; ++ it);
+	if (it == mChildren.end())
+		Debug << "error" << endl;
+	else
+		mChildren.erase(it);
+}
+
+/************************************************************************/
+/*                class ViewCellsStatistics implementation              */
+/************************************************************************/
+
+
+
+
+void ViewCellsStatistics::Print(ostream &app) const
+{
+	app << "=========== View Cells Statistics ===============\n";
+
+	app << setprecision(4);
+
+	//app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
+
+	app << "#N_OVERALLPVS ( objects in PVS )\n" << pvsSize << endl;
+
+	app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl;
+
+	app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl;
+
+	app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl;
+
+	app << "#N_PEMPTYPVS ( view cells with empty PVS )\n" << emptyPvs << endl;
+
+	app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl;
+
+	app << "#N_AVGLEAVES (average number of leaves per view cell )\n" << AvgLeaves() << endl;
+
+	app << "#N_MAXLEAVES ( maximal number of leaves per view cell )\n" << maxLeaves << endl;
+	
+	app << "#N_INVALID ( number of invalid view cells )\n" << invalid << endl;
+
+	app << "========== End of View Cells Statistics ==========\n";
+}
+
+
+/*************************************************************************/
+/*                    class ViewCellsTree implementation                 */
+/*************************************************************************/
+
+
+ViewCellsTree::ViewCellsTree(ViewCellsManager *vcm):
+mRoot(NULL),
+mUseAreaForPvs(false),
+mViewCellsManager(vcm),
+mIsCompressed(false)
+{
+	environment->GetBoolValue("ViewCells.Visualization.exportMergedViewCells", mExportMergedViewCells);
+	environment->GetFloatValue("ViewCells.maxStaticMemory", mMaxMemory);
+
+	//-- merge options
+	environment->GetFloatValue("ViewCells.PostProcess.renderCostWeight", mRenderCostWeight);
+	environment->GetIntValue("ViewCells.PostProcess.minViewCells", mMergeMinViewCells);
+	environment->GetFloatValue("ViewCells.PostProcess.maxCostRatio", mMergeMaxCostRatio);
+	environment->GetBoolValue("ViewCells.PostProcess.refine", mRefineViewCells);	
+
+
+	Debug << "========= view cell tree options ================\n";
+	Debug << "minimum view cells: " << mMergeMinViewCells << endl;
+	Debug << "max cost ratio: " << mMergeMaxCostRatio << endl;
+	Debug << "max memory: " << mMaxMemory << endl;
+	Debug << "refining view cells: " << mRefineViewCells << endl;
+
+	MergeCandidate::sRenderCostWeight = mRenderCostWeight;
+
+	mStats.open("mergeStats.log");
+}
+
+
+// return memory usage in MB
+float ViewCellsTree::GetMemUsage() const
+{
+	return 0;
+		/*(sizeof(ViewCellsTree) +
+		 mBspStats.Leaves() * sizeof(BspLeaf) +
+		 mBspStats.Interior() * sizeof(BspInterior) +
+		 mBspStats.accumRays * sizeof(RayInfo)) / (1024.0f * 1024.0f);*/
+}
+
+
+int ViewCellsTree::GetSize(ViewCell *vc) const
+{
+	int vcSize = 0;
+
+	stack<ViewCell *> tstack;
+
+	tstack.push(vc);
+
+	while (!tstack.empty())
+	{
+		ViewCell *vc = tstack.top();
+		tstack.pop();
+
+		if (vc->IsLeaf())
+		{
+			++ vcSize;
+		}
+		else
+		{
+			ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+			ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+			for (it = interior->mChildren.begin(); it != it_end; ++ it)
+				tstack.push(*it);
+			
+		}
+	}
+
+	return vcSize;
+}
+
+
+void ViewCellsTree::CollectLeaves(ViewCell *vc, ViewCellContainer &leaves) const
+{
+	stack<ViewCell *> tstack;
+
+	tstack.push(vc);
+
+	while (!tstack.empty())
+	{
+		ViewCell *vc = tstack.top();
+		tstack.pop();
+
+		if (vc->IsLeaf())
+		{
+			leaves.push_back(vc);
+		}
+		else
+		{
+			ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+			ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+			for (it = interior->mChildren.begin(); it != it_end; ++ it)
+				tstack.push(*it);
+			
+		}
+	}
+}
+
+
+ViewCellsTree::~ViewCellsTree()
+{
+	DEL_PTR(mRoot);
+}
+
+
+int ViewCellsTree::ConstructMergeTree(const VssRayContainer &rays, 
+									  const ObjectContainer &objects)
+{
+	mNumActiveViewCells = (int)mViewCellsManager->GetViewCells().size();
+
+	float variance = 0;
+	int totalPvs = 0;
+	float totalRenderCost = 0;
+
+	//-- compute statistics values of initial view cells
+	mViewCellsManager->EvaluateRenderStatistics(totalRenderCost,
+												mExpectedCost,
+												mDeviation,
+												variance,
+												totalPvs,
+												mAvgRenderCost);
+
+
+	//-- fill merge queue
+	vector<MergeCandidate> candidates;
+
+	mViewCellsManager->CollectMergeCandidates(rays, candidates);
+	while(!candidates.empty())
+	{
+		MergeCandidate mc = candidates.back();
+		candidates.pop_back();
+		EvalMergeCost(mc);
+		mMergeQueue.push(mc);
+	}
+
+	Debug << "************************* merge ***********************************" << endl;  
+	Debug << "deviation: " << mDeviation << endl;
+	Debug << "avg render cost: " << mAvgRenderCost << endl;
+	Debug << "expected cost: " << mExpectedCost << endl;
+
+
+	ViewCellsManager::PvsStatistics pvsStats;
+	mViewCellsManager->GetPvsStatistics(pvsStats);
+
+	//static float expectedValue = pvsStats.avgPvs;
+	
+	// the current view cells are kept in this container
+	// we start with the current view cells from the
+	// view cell manager. They will change with
+	// subsequent merges
+	ViewCellContainer &activeViewCells = mViewCellsManager->GetViewCells();
+
+
+	ViewCell::NewMail();
+
+	MergeStatistics mergeStats;
+	mergeStats.Start();
+	
+	long startTime = GetTime();
+
+	mergeStats.collectTime = TimeDiff(startTime, GetTime());
+	mergeStats.candidates = (int)mMergeQueue.size();
+	startTime = GetTime();
+
+	// frequency stats are updated
+	const int statsOut = 1;
+
+	// passes are needed for statistics, because we don't want to record
+	// every merge
+	int pass = 0;
+	int mergedPerPass = 0;
+	float realExpectedCost = mExpectedCost;
+	float realAvgRenderCost = mAvgRenderCost;
+	int realNumActiveViewCells = mNumActiveViewCells;
+	
+	// maximal ratio of old expected render cost to expected render
+	// when the the render queue has to be reset.
+	float avgCostMaxDeviation;
+	int maxMergesPerPass;
+	int numMergedViewCells = 0;
+
+	environment->GetIntValue("ViewCells.PostProcess.maxMergesPerPass", maxMergesPerPass);
+	environment->GetFloatValue("ViewCells.PostProcess.avgCostMaxDeviation", avgCostMaxDeviation);
+
+	cout << "actual merge starts now ... " << endl;
+	
+	mStats << "#Pass\n" << pass << endl
+		   << "#Merged\n" << mergeStats.merged << endl 
+		   << "#ViewCells\n" << realNumActiveViewCells << endl 
+		   << "#RenderCostIncrease\n" << 0 << endl
+		   << "#TotalRenderCost\n" << totalRenderCost << endl
+		   << "#CurrentPvs\n" << 0 << endl
+		   << "#ExpectedCost\n" << realExpectedCost << endl
+		   << "#AvgRenderCost\n" << realAvgRenderCost << endl
+		   << "#Deviation\n" << mDeviation << endl
+		   << "#TotalPvs\n" << totalPvs << endl
+		   << "#PvsSizeDecrease\n0" << endl
+		   << "#Volume\n0" << endl
+		   //<< "#Siblings\n" << mergeStats.siblings << endl
+		   << endl;
+
+	//-- use priority queue to merge leaf pairs
+// HACK
+
+	//const float maxAvgCost = 350;
+	while (!mMergeQueue.empty())//NumActiveViewCells > mMergeMinViewCells))
+	{
+		//-- reset merge queue if the ratio of current expected cost / real expected cost
+		//   too small or after a given number of merges
+		if ((mergedPerPass > maxMergesPerPass) ||
+			(avgCostMaxDeviation > mAvgRenderCost / realAvgRenderCost))
+		{
+			Debug << "************ reset queue *****************\n"
+				  << "ratios: " << avgCostMaxDeviation 
+				  << " real avg render cost " << realAvgRenderCost << " average render cost " << mAvgRenderCost
+				  << " merged per pass : " << mergedPerPass << " of maximal " << maxMergesPerPass << endl;
+
+			Debug << "Values before reset: "  
+				  << " erc: " << mExpectedCost 
+				  << " avgrc: " << mAvgRenderCost
+				  << " dev: " << mDeviation << endl;
+	
+			// adjust render cost
+			++ pass;
+
+			mergedPerPass = 0;
+			mExpectedCost = realExpectedCost;
+			mAvgRenderCost = realAvgRenderCost;
+			mNumActiveViewCells = realNumActiveViewCells;
+			
+			const int numMergedViewCells = UpdateActiveViewCells(activeViewCells);
+		
+			// refines the view cells
+			// then priorities are recomputed
+			// and the candidates are put back into merge queue
+			if (mRefineViewCells)
+				RefineViewCells(rays, objects);
+			else
+				ResetMergeQueue();
+
+			Debug << "Values after reset: "  
+				  << " erc: " << mExpectedCost 
+				  << " avg: " << mAvgRenderCost 
+				  << " dev: " << mDeviation << endl;
+
+			if (mExportMergedViewCells)
+			{
+				ExportMergedViewCells(activeViewCells, objects, numMergedViewCells);
+			}
+		}
+
+
+		MergeCandidate mc = mMergeQueue.top();
+		mMergeQueue.pop();
+	
+		// both view cells equal
+		// NOTE: do I really still need this? probably cannot happen!!
+		if (mc.mLeftViewCell == mc.mRightViewCell)
+			continue;
+
+		if (mc.IsValid())
+		{
+			ViewCell::NewMail();
+
+			//-- update statistical values
+			-- realNumActiveViewCells;
+			++ mergeStats.merged;
+			++ mergedPerPass;
+
+			const float renderCostIncr = mc.GetRenderCost();
+			const float mergeCostIncr = mc.GetMergeCost();
+
+			totalRenderCost += renderCostIncr;
+			mDeviation += mc.GetDeviationIncr();
+			
+			
+			// merge the view cells of leaf1 and leaf2
+			int pvsDiff;
+			ViewCellInterior *mergedVc = 
+				MergeViewCells(mc.mLeftViewCell, mc.mRightViewCell, pvsDiff);
+
+
+			// total render cost and deviation has changed
+			// real expected cost will be larger than expected cost used for the
+			// cost heuristics, but cannot recompute costs on each increase of the 
+			// expected cost
+			totalPvs += pvsDiff;
+			realExpectedCost = totalRenderCost / (float)realNumActiveViewCells;
+			realAvgRenderCost = (float)totalPvs / (float)realNumActiveViewCells;
+	
+			// set merge cost to this node
+			mergedVc->SetMergeCost(totalRenderCost);
+
+			//if (mViewCellsManager->EqualToSpatialNode(mergedVc))
+			//	++ mergeStats.siblings;
+			mergedVc->SetCost(realExpectedCost);
+
+			if (((mergeStats.merged % statsOut) == 0) || 
+			(realNumActiveViewCells == mMergeMinViewCells))
+			{
+				cout << "merged " << mergeStats.merged << " view cells" << endl;
+
+				mStats 
+					<< "#Pass\n" << pass << endl
+					<< "#Merged\n" << mergeStats.merged << endl 
+					<< "#ViewCells\n" << realNumActiveViewCells << endl 
+                    << "#RenderCostIncrease\n" << renderCostIncr << endl
+					<< "#TotalRenderCost\n" << totalRenderCost << endl
+					<< "#CurrentPvs\n" << mergedVc->GetPvs().GetSize() << endl
+                    << "#ExpectedCost\n" << realExpectedCost << endl
+					<< "#AvgRenderCost\n" << realAvgRenderCost << endl
+					<< "#Deviation\n" << mDeviation << endl
+					<< "#TotalPvs\n" << totalPvs << endl
+					<< "#PvsSizeDecrease\n" << -pvsDiff << endl
+					<< "#Volume\n" << mergedVc->GetVolume() << endl
+					<< endl;
+				
+			}
+		}
+		else
+		{ 
+			// merge candidate not valid, because one of the leaves was already
+			// merged with another one => validate and reinsert into queue
+			if (ValidateMergeCandidate(mc))
+			{
+				EvalMergeCost(mc);
+				mMergeQueue.push(mc);
+			}
+		}
+		
+	}
+
+	// adjust stats and reset queue one final time
+	mExpectedCost = realExpectedCost;
+	mAvgRenderCost = realAvgRenderCost;
+	mNumActiveViewCells = realNumActiveViewCells;
+
+	UpdateActiveViewCells(activeViewCells);
+
+	// refine view cells and reset costs
+	if (mRefineViewCells)
+		RefineViewCells(rays, objects);
+	else
+		ResetMergeQueue();
+
+	// create a root node if the merge was not done till root level,
+	// else take the single node as new root
+	if ((int)activeViewCells.size() > 1)
+	{
+		Debug << "creating root of view cell hierarchy for " 
+			  << (int)activeViewCells.size() << " view cells" << endl;
+		
+		ViewCellInterior *root = mViewCellsManager->MergeViewCells(activeViewCells);
+		root->SetMergeCost(totalRenderCost);
+		// $$JB keep this 0 temporarilly
+		root->SetCost(0.0f);
+		
+		mStats 
+			<< "#Pass\n" << pass << endl
+			<< "#Merged\n" << mergeStats.merged << endl 
+			<< "#ViewCells\n" << realNumActiveViewCells << endl 
+            << "#RenderCostIncrease\n" << 0 << endl // TODO
+			<< "#TotalRenderCost\n" << totalRenderCost << endl
+			<< "#CurrentPvs\n" << root->GetPvs().GetSize() << endl
+            << "#ExpectedCost\n" << realExpectedCost << endl
+			<< "#AvgRenderCost\n" << realAvgRenderCost << endl
+			<< "#Deviation\n" << mDeviation << endl
+			<< "#TotalPvs\n" << totalPvs << endl
+			<< "#PvsSizeDecrease\n" << 0 << endl // TODO
+			<< "#Volume\n" << root->GetVolume() << endl
+			<< endl;
+
+		mRoot = root;
+	}
+	else if ((int)activeViewCells.size() == 1)
+	{
+		Debug << "setting root of the merge history" << endl;
+		mRoot = activeViewCells[0];
+	}
+
+
+	while (!mMergeQueue.empty())
+	{
+		mMergeQueue.pop();
+	}
+	
+	
+	// TODO delete because makes no sense here
+	mergeStats.expectedRenderCost = realExpectedCost;
+	mergeStats.deviation = mDeviation;
+
+	// we want to optimize this heuristics
+	mergeStats.heuristics = 
+		mDeviation * (1.0f - mRenderCostWeight) + 
+		mExpectedCost * mRenderCostWeight;
+
+	mergeStats.mergeTime = TimeDiff(startTime, GetTime());
+	mergeStats.Stop();
+
+	Debug << mergeStats << endl << endl;
+
+	// assign colors for the view cells so that at least one is always consistent
+	AssignRandomColors();
+	//TODO: should return sample contributions?
+	return mergeStats.merged;
+}
+
+
+ViewCell *ViewCellsTree::GetRoot() const
+{
+	return mRoot;
+}
+
+
+void ViewCellsTree::ResetMergeQueue()
+{
+	cout << "reset merge queue ... ";
+	
+	vector<MergeCandidate> buf;
+	buf.reserve(mMergeQueue.size());
+			
+	
+	// store merge candidates in intermediate buffer
+	while (!mMergeQueue.empty())
+	{
+		MergeCandidate mc = mMergeQueue.top();
+		mMergeQueue.pop();
+		
+		// recalculate cost
+		if (ValidateMergeCandidate(mc))
+		{
+			EvalMergeCost(mc);
+			buf.push_back(mc);				
+		}
+	}
+
+	vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
+
+	// reinsert back into queue
+	for (bit = buf.begin(); bit != bit_end; ++ bit)
+	{      
+		mMergeQueue.push(*bit);	
+	}
+
+	cout << "finished" << endl;
+}
+
+
+int ViewCellsTree::UpdateActiveViewCells(ViewCellContainer &viewCells)
+{
+	int numMergedViewCells = 0;
+
+	Debug << "updating active vc: " << (int)viewCells.size() << endl;
+	// find all already merged view cells and remove them from view cells
+		
+	// sort out all view cells which are not active anymore, i.e., they
+	// were already part of a merge
+	int i = 0;
+
+	ViewCell::NewMail();
+
+	while (1)
+	{
+		// remove all merged view cells from end of the vector
+		while (!viewCells.empty() && (viewCells.back()->GetParent()))
+		{
+			viewCells.pop_back();
+		}
+
+		// all merged view cells have been found
+		if (i >= viewCells.size()) 
+			break;
+
+		// already merged view cell, put it to end of vector
+		if (viewCells[i]->GetParent())
+			swap(viewCells[i], viewCells.back());
+		
+		viewCells[i ++]->Mail();
+	}
+
+
+	// add new view cells to container only if they don't have been 
+	// merged in the mean time
+	ViewCellContainer::const_iterator ait, ait_end = mMergedViewCells.end();
+	for (ait = mMergedViewCells.begin(); ait != ait_end; ++ ait)
+	{
+		ViewCell *vc = mMergedViewCells.back();
+		if (!vc->GetParent() && !vc->Mailed())
+		{
+			vc->Mail();
+			viewCells.push_back(vc);
+			++ numMergedViewCells;
+		}
+	}
+
+	mMergedViewCells.clear();
+
+	// update standard deviation
+	ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
+	
+	mDeviation = 0;
+
+	for (vit = viewCells.begin(); vit != vit_end; ++ vit)
+	{
+		int lower = mViewCellsManager->GetMinPvsSize();
+		int upper = mViewCellsManager->GetMaxPvsSize();
+		float penalty = EvalPvsPenalty((*vit)->GetPvs().GetSize(), lower, upper);
+		
+		mDeviation += fabs(mAvgRenderCost - penalty);
+	}
+
+	mDeviation /= (float)viewCells.size();
+	
+	return numMergedViewCells;
+}
+
+
+void ViewCellsTree::ExportMergedViewCells(ViewCellContainer &viewCells, 
+										  const ObjectContainer &objects,
+										  const int numMergedViewCells)
+{
+	
+
+	char s[64];
+
+	sprintf(s, "merged_viewcells%07d.x3d", (int)viewCells.size());
+	Exporter *exporter = Exporter::GetExporter(s);
+
+	if (exporter)
+	{
+		cout << "exporting " << (int)viewCells.size() << " merged view cells ... ";
+		exporter->ExportGeometry(objects);
+		//Debug << "vc size " << (int)viewCells.size() << " merge queue size: " << (int)mMergeQueue.size() << endl;
+		ViewCellContainer::const_iterator it, it_end = viewCells.end();
+
+		int i = 0;
+		for (it = viewCells.begin(); it != it_end; ++ it)
+		{
+			Material m;
+			// assign special material to new view cells
+			// new view cells are on the back of container
+			if (i ++ >= (viewCells.size() - numMergedViewCells))
+			{
+				//m = RandomMaterial();
+				m.mDiffuseColor.r = RandomValue(0.5f, 1.0f);
+				m.mDiffuseColor.g = RandomValue(0.5f, 1.0f);
+				m.mDiffuseColor.b = RandomValue(0.5f, 1.0f);
+			}
+			else
+			{
+				float col = RandomValue(0.1f, 0.4f);
+				m.mDiffuseColor.r = col;
+				m.mDiffuseColor.g = col;
+				m.mDiffuseColor.b = col;
+			}
+
+			exporter->SetForcedMaterial(m);
+			mViewCellsManager->ExportViewCellGeometry(exporter, *it);
+		}
+		delete exporter;
+		cout << "finished" << endl;
+	}
+}
+
+
+// TODO: should be done in view cells manager
+ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *l, 
+												ViewCell *r, 
+												int &pvsDiff) //const
+{
+	ViewCellInterior *vc = mViewCellsManager->MergeViewCells(l, r);
+
+	// if merge was unsuccessful
+	if (!vc) return NULL;
+
+	// set new size of view cell
+	if (mUseAreaForPvs)
+		vc->SetArea(l->GetArea() + l->GetArea());
+	else
+	{
+		vc->SetVolume(r->GetVolume() + l->GetVolume());
+	}
+	// important so other merge candidates sharing this view cell
+	// are notified that the merge cost must be updated!!
+	vc->Mail();
+
+	const int pvs1 = l->GetPvs().GetSize();
+	const int pvs2 = r->GetPvs().GetSize();
+
+
+	// new view cells are stored in this vector
+	mMergedViewCells.push_back(vc);
+
+	pvsDiff = vc->GetPvs().GetSize() - pvs1 - pvs2;
+
+	return vc;
+}
+
+
+
+int ViewCellsTree::RefineViewCells(const VssRayContainer &rays, 
+								   const ObjectContainer &objects)
+{
+	Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl;
+
+	// intermediate buffer for shuffled view cells
+	vector<MergeCandidate> buf;
+	buf.reserve(mMergeQueue.size());
+			
+	// Use priority queue of remaining leaf pairs 
+	// The candidates either share the same view cells or
+	// are border leaves which share a boundary.
+	// We test if they can be shuffled, i.e.,
+	// either one leaf is made part of one view cell or the other
+	// leaf is made part of the other view cell. It is tested if the
+	// remaining view cells are "better" than the old ones.
+	
+	const int numPasses = 3;
+	int pass = 0;
+	int passShuffled = 0;
+	int shuffled = 0;
+	int shuffledViewCells = 0;
+
+	ViewCell::NewMail();
+	
+	while (!mMergeQueue.empty())
+	{
+		MergeCandidate mc = mMergeQueue.top();
+		mMergeQueue.pop();
+
+		// both view cells equal or already shuffled
+		if ((mc.GetLeftViewCell() == mc.GetRightViewCell()) ||
+			mc.GetLeftViewCell()->IsLeaf() || mc.GetRightViewCell()->IsLeaf())
+		{			
+			continue;
+		}
+
+		// candidate for shuffling
+		const bool wasShuffled = ShuffleLeaves(mc);
+		
+		// shuffled or put into other queue for further refine
+		if (wasShuffled)
+		{
+			++ passShuffled;
+
+			if (!mc.GetLeftViewCell()->Mailed())
+			{
+				mc.GetLeftViewCell()->Mail();
+				++ shuffledViewCells;
+			}
+			if (!mc.GetRightViewCell()->Mailed())
+			{
+				mc.GetRightViewCell()->Mail();
+				++ shuffledViewCells;
+			}
+		}
+
+		// put back into intermediate vector
+		buf.push_back(mc);
+	}
+
+
+	//-- in the end, the candidates must be in the mergequeue again
+	//   with the correct cost
+
+	cout << "reset merge queue ... ";
+	
+	
+	vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
+	
+	for (bit = buf.begin(); bit != bit_end; ++ bit)
+	{    
+		MergeCandidate mc = *bit;
+		// recalculate cost
+		if (ValidateMergeCandidate(mc))
+		{
+			EvalMergeCost(mc);
+			mMergeQueue.push(mc);	
+		}
+	}
+
+	cout << "finished" << endl;
+
+	return shuffledViewCells;
+}
+
+
+
+
+inline int AddedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
+{
+	return pvs1.AddPvs(pvs2);
+}
+
+
+// recomputes pvs size minus pvs of leaf l
+#if 0
+inline int SubtractedPvsSize(BspViewCell *vc, BspLeaf *l, const ObjectPvs &pvs2)
+{
+	ObjectPvs pvs;
+	vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end();
+	for (it = vc->mLeaves.begin(); it != vc->mLeaves.end(); ++ it)
+		if (*it != l)
+			pvs.AddPvs(*(*it)->mPvs);
+	return pvs.GetSize();
+}
+#endif
+
+
+// computes pvs1 minus pvs2
+inline int SubtractedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
+{
+	return pvs1.SubtractPvs(pvs2);
+}
+
+
+float ViewCellsTree::EvalShuffleCost(ViewCell *leaf, 
+									 ViewCellInterior *vc1, 
+									 ViewCellInterior *vc2) const
+{
+	//const int pvs1 = SubtractedPvsSize(vc1, leaf, *leaf->mPvs);
+	const int pvs1 = SubtractedPvsSize(vc1->GetPvs(), leaf->GetPvs());
+	const int pvs2 = AddedPvsSize(vc2->GetPvs(), leaf->GetPvs());
+
+	const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize();
+	const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize();
+
+	const float pvsPenalty1 = 
+		EvalPvsPenalty(pvs1, lowerPvsLimit, upperPvsLimit);
+
+	const float pvsPenalty2 =
+		EvalPvsPenalty(pvs2, lowerPvsLimit, upperPvsLimit);
+
+
+	// don't shuffle leaves with pvs > max
+	if (0 && (pvs1 + pvs2 > mViewCellsManager->GetMaxPvsSize()))
+	{
+		return 1e20f;
+	}
+
+	float p1, p2;
+
+    if (mUseAreaForPvs)
+	{
+		p1 = vc1->GetArea() - leaf->GetArea();
+		p2 = vc2->GetArea() + leaf->GetArea();
+	}
+	else
+	{
+		p1 = vc1->GetVolume() - leaf->GetVolume();
+		p2 = vc2->GetVolume() + leaf->GetVolume();
+	}
+
+	const float renderCost1 = pvsPenalty1 * p1;
+	const float renderCost2 = pvsPenalty2 * p2;
+
+	float dev1, dev2;
+
+	if (1)
+	{
+		dev1 = fabs(mAvgRenderCost - pvsPenalty1);
+		dev2 = fabs(mAvgRenderCost - pvsPenalty2);
+	}
+	else
+	{
+		dev1 = fabs(mExpectedCost - renderCost1);
+		dev2 = fabs(mExpectedCost - renderCost2);
+	}
+	
+	return mRenderCostWeight * (renderCost1 + renderCost2) +
+		  (1.0f - mRenderCostWeight) * (dev1 + dev2) / (float)mNumActiveViewCells;
+}
+
+
+void ViewCellsTree::ShuffleLeaf(ViewCell *leaf,
+								ViewCellInterior *vc1, 
+								ViewCellInterior *vc2) const
+{
+	// compute new pvs and area
+	// TODO change
+	vc1->GetPvs().SubtractPvs(leaf->GetPvs());
+	vc2->GetPvs().AddPvs(leaf->GetPvs());
+	
+	if (mUseAreaForPvs)
+	{
+		vc1->SetArea(vc1->GetArea() - leaf->GetArea());
+		vc2->SetArea(vc2->GetArea() + leaf->GetArea());
+	}
+	else
+	{
+		vc1->SetVolume(vc1->GetVolume() - leaf->GetVolume());
+		vc2->SetVolume(vc2->GetVolume() + leaf->GetVolume());
+	}
+
+	
+	ViewCellInterior *p = dynamic_cast<ViewCellInterior *>(leaf->GetParent());
+
+	p->RemoveChildLink(leaf);
+	vc2->SetupChildLink(leaf);
+}
+
+
+bool ViewCellsTree::ShuffleLeaves(MergeCandidate &mc) const
+{
+	float cost1, cost2;
+
+	ViewCellInterior *vc1 = dynamic_cast<ViewCellInterior *>(mc.GetLeftViewCell());
+	ViewCellInterior *vc2 = dynamic_cast<ViewCellInterior *>(mc.GetRightViewCell());
+
+	ViewCell *leaf1 = mc.GetInitialLeftViewCell();
+	ViewCell *leaf2 = mc.GetInitialRightViewCell();
+
+	//-- first test if shuffling would decrease cost
+	cost1 = GetCostHeuristics(vc1);
+	cost2 = GetCostHeuristics(vc2);
+
+	const float oldCost = cost1 + cost2;
+	
+	float shuffledCost1 = Limits::Infinity;
+	float shuffledCost2 = Limits::Infinity;
+
+	if (leaf1)
+		shuffledCost1 = EvalShuffleCost(leaf1, vc1, vc2);	
+	if (leaf2)
+		shuffledCost2 = EvalShuffleCost(leaf2, vc2, vc1);
+
+	// if cost of shuffle is less than old cost => shuffle
+	if ((oldCost <= shuffledCost1) && (oldCost <= shuffledCost2))
+		return false;
+	
+	if (shuffledCost1 < shuffledCost2)
+	{
+		if (leaf1)
+			ShuffleLeaf(leaf1, vc1, vc2);
+		mc.mInitialLeftViewCell = NULL;
+	}
+	else
+	{
+		if (leaf2)
+			ShuffleLeaf(leaf2, vc2, vc1);
+		mc.mInitialRightViewCell = NULL;
+	}
+
+	return true;
+}
+
+
+float ViewCellsTree::GetVariance(ViewCell *vc) const
+{
+	const int upper = mViewCellsManager->GetMaxPvsSize();
+	const int lower = mViewCellsManager->GetMinPvsSize();
+
+	if (1)
+	{
+		const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
+		return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
+	}
+
+    const float leafCost = GetRenderCost(vc);
+	return (mExpectedCost - leafCost) * (mExpectedCost - leafCost);
+}
+
+
+float ViewCellsTree::GetDeviation(ViewCell *vc) const
+{
+	const int upper = mViewCellsManager->GetMaxPvsSize();
+	const int lower = mViewCellsManager->GetMinPvsSize();
+
+	if (1)
+	{
+		const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
+		return fabs(mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
+	}
+
+    const float renderCost = GetRenderCost(vc);
+	return fabs(mExpectedCost - renderCost);
+}
+
+
+
+float ViewCellsTree::GetRenderCost(ViewCell *vc) const
+{
+	if (mUseAreaForPvs)
+		return vc->GetPvs().GetSize() * vc->GetArea();
+
+	return vc->GetPvs().GetSize() * vc->GetVolume();
+}
+
+
+float ViewCellsTree::GetCostHeuristics(ViewCell *vc) const
+{
+	return GetRenderCost(vc) * mRenderCostWeight + 
+		   GetDeviation(vc) * (1.0f - mRenderCostWeight);
+}
+
+
+bool ViewCellsTree::ValidateMergeCandidate(MergeCandidate &mc) const
+{
+	while (mc.mLeftViewCell->mParent)
+	{
+		mc.mLeftViewCell = mc.mLeftViewCell->mParent;
+	}
+
+	while (mc.mRightViewCell->mParent)
+	{
+		mc.mRightViewCell = mc.mRightViewCell->mParent;
+	}
+
+	return mc.mLeftViewCell != mc.mRightViewCell;
+}
+
+
+void ViewCellsTree::EvalMergeCost(MergeCandidate &mc) const
+{
+	//-- compute pvs difference
+	const int newPvs = 
+		ComputeMergedPvsSize(mc.mLeftViewCell->GetPvs(), 
+							 mc.mRightViewCell->GetPvs());
+			
+	const float newPenalty = 
+		EvalPvsPenalty(newPvs,
+					   mViewCellsManager->GetMinPvsSize(),
+					   mViewCellsManager->GetMaxPvsSize());
+
+	ViewCell *vc1 = mc.mLeftViewCell;
+	ViewCell *vc2 = mc.mRightViewCell;
+
+	//-- compute ratio of old cost
+	//   (i.e., added size of left and right view cell times pvs size)
+	//   to new rendering cost (i.e, size of merged view cell times pvs size)
+	const float oldCost = GetRenderCost(vc1) + GetRenderCost(vc2);
+
+    const float newCost = mUseAreaForPvs ? 
+		(float)newPenalty * (vc1->GetArea() + vc2->GetArea()) :
+		(float)newPenalty * (vc1->GetVolume() + vc2->GetVolume());
+
+
+	// strong penalty if pvs size too large
+	if (0 && (newPvs > mViewCellsManager->GetMaxPvsSize()))
+	{
+		mc.mRenderCost = 1e20f;
+	}
+	else
+	{
+		mc.mRenderCost = (newCost - oldCost) / 
+			mViewCellsManager->GetViewSpaceBox().GetVolume();
+	}	
+	
+
+	//-- merge cost also takes deviation into account
+	float newDev, oldDev;
+
+	if (1)
+		newDev = fabs(mAvgRenderCost - newPenalty) / (float)mNumActiveViewCells;
+	else
+		newDev = fabs(mExpectedCost - newCost) / (float)mNumActiveViewCells;
+	
+	oldDev = GetDeviation(vc1) + GetDeviation(vc2);
+
+	// compute deviation increase
+	mc.mDeviationIncr = newDev - oldDev;
+	
+	//Debug << "render cost: " << mc.mRenderCost * mRenderCostWeight << endl;
+	//Debug << "standard deviation: " << mc.mDeviationIncr * mRenderCostWeight << endl;
+}
+
+void ViewCellsTree::CompressViewCellsPvs()
+{
+	if (!mIsCompressed)
+	{
+		mIsCompressed = true;
+		CompressViewCellsPvs(mRoot);
+	}
+}
+
+void ViewCellsTree::CompressViewCellsPvs(ViewCell *root)
+{
+	if (!root->IsLeaf())
+	{
+		ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
+
+        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+		
+		// compress child sets first
+		for (it = interior->mChildren.begin(); it != it_end; ++ it)
+		{
+			CompressViewCellsPvs(*it);
+		}
+
+		// compress root node
+		PullUpVisibility(interior);
+	}
+}
+
+
+void ViewCellsTree::CollectBestViewCellSet(ViewCellContainer &viewCells, 
+										   const int numViewCells)
+{
+	TraversalQueue tqueue;
+	tqueue.push(mRoot);
+	
+	while (!tqueue.empty())
+	{
+		ViewCell *vc = tqueue.top();
+		
+		// save the view cells if it is a leaf or if enough view cells have already been traversed
+		// because of the priority queue, this will be the optimal set of v
+		if (vc->IsLeaf() || ((viewCells.size() + tqueue.size()) >= numViewCells))
+		{
+			// todo: should be done with a function taking the active flag and some 
+			// time stamp so I don't have to reset view cells, this also means that 
+			// the leaf view cells can be set active fist
+			vc->mIsActive = true; 
+			viewCells.push_back(vc);
+		}
+		else 
+		{	
+			ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+
+			ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+
+			for (it = interior->mChildren.begin(); it != it_end; ++ it)
+			{
+				tqueue.push(*it);
+			}
+		}
+
+		tqueue.pop();
+	}
+}
+	
+
+void ViewCellsTree::PullUpVisibility(ViewCellInterior *interior)
+{
+	Intersectable::NewMail((int)interior->mChildren.size());
+
+	ViewCellContainer::const_iterator cit, cit_end = interior->mChildren.end();
+
+	ObjectPvsMap::const_iterator oit;
+
+	// mail all objects in the leaf sets
+	// we are interested in the objects which are present in all leaves
+	// => count how often an object is part of a child set
+	for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
+	{
+		ViewCell *vc = *cit;
+
+		ObjectPvsMap::const_iterator oit_end = vc->GetPvs().mEntries.end();
+
+		for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
+		{
+			Intersectable *obj = (*oit).first;
+			if ((cit == interior->mChildren.begin()) && !obj->Mailed())
+				obj->Mail();
+			
+			int incm = obj->IncMail();
+		}
+	}
+
+	interior->GetPvs().mEntries.clear();
+	
+	
+	// only the objects which are present in all leaf pvs 
+	// should remain in the parent pvs
+	// these are the objects which have been mailed in all children
+	for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
+	{
+		ViewCell *vc = *cit;
+
+		ObjectPvsMap::const_iterator oit_end = vc->GetPvs().mEntries.end();
+
+		for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
+		{		
+			if ((*oit).first->Mailed((int)interior->mChildren.size()))
+			{	
+				interior->GetPvs().AddSample((*oit).first, (*oit).second.mSumPdf);
+			}
+		}
+	}
+
+
+
+	// delete all the objects from the leaf sets which were moved to parent pvs
+	ObjectPvsMap::const_iterator oit_end = interior->GetPvs().mEntries.end();
+
+	for (oit = interior->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
+	{
+		for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
+		{
+			if (!(*cit)->GetPvs().RemoveSample((*oit).first, Limits::Infinity))
+				Debug << "should not come here!" << endl;
+		}
+	}
+
+	int dummy = interior->GetPvs().GetSize();
+
+	for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
+	{
+		dummy += (*cit)->GetPvs().GetSize();
+	}
+
+}
+
+
+
+void ViewCellsTree::GetPvs(ViewCell *vc, ObjectPvs &pvs) const
+{
+	Intersectable::NewMail();
+
+	if (!mIsCompressed)
+		pvs = vc->GetPvs();
+
+	int pvsSize = 0;
+	ViewCell *root = vc;
+	
+	// also add pvs from this view cell to root
+	while (root->GetParent())
+	{
+		root = root->GetParent();
+		pvs.AddPvs(root->GetPvs());
+	}
+
+	stack<ViewCell *> tstack;
+	tstack.push(vc);
+
+	while (!tstack.empty())
+	{
+		vc = tstack.top();
+		tstack.pop();
+
+		pvs.AddPvs(vc->GetPvs());
+
+		if (!vc->IsLeaf())
+		{
+			ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+
+			ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+
+			for (it = interior->mChildren.begin(); it != it_end; ++ it)
+			{
+				tstack.push(*it);
+			}		
+		}
+	}
+}
+
+
+int ViewCellsTree::GetPvsSize(ViewCell *vc) const
+{
+	Intersectable::NewMail();
+
+	if (!mIsCompressed)
+		return vc->GetPvs().GetSize();
+
+	int pvsSize = 0;
+	ViewCell *root = vc;
+	
+	// also add pvs from this view cell to root
+	while (root->GetParent())
+	{
+		root = root->GetParent();
+		pvsSize += CountDiffPvs(root);
+	}
+
+	stack<ViewCell *> tstack;
+	tstack.push(vc);
+
+	while (!tstack.empty())
+	{
+		vc = tstack.top();
+		tstack.pop();
+
+		pvsSize += CountDiffPvs(vc);
+
+		if (!vc->IsLeaf())
+		{
+			ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+
+			ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+
+			for (it = interior->mChildren.begin(); it != it_end; ++ it)
+			{
+				tstack.push(*it);
+			}		
+		}
+	}
+
+	return pvsSize;  
+
+}
+
+
+float ViewCellsTree::GetMemoryCost(ViewCell *vc) const
+{
+	const float entrySize = 
+		sizeof(PvsData<Intersectable *>) + sizeof(Intersectable *);
+
+	return (float)GetNumPvsEntries(vc) * entrySize;
+}
+
+
+int ViewCellsTree::GetNumPvsEntries(ViewCell *vc) const
+{
+	int pvsSize = 0;
+	// only count leaves for uncompressed method for fairness
+	if (mIsCompressed || vc->IsLeaf())
+		pvsSize = vc->GetPvs().GetSize();
+
+	if (!vc->IsLeaf())
+	{
+		ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+
+		ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+
+		for (it = interior->mChildren.begin(); it != it_end; ++ it)
+		{
+			pvsSize += GetNumPvsEntries(*it);
+		}
+	}
+
+	return pvsSize;    	
+}
+
+
+bool ViewCellsTree::IsCompressed() const
+{
+	return mIsCompressed;
+}
+
+
+ViewCell *ViewCellsTree::GetActiveViewCell(ViewCell *vc) const
+{
+	while (vc->GetParent() && !vc->mIsActive)
+	{
+		vc = vc->GetParent();
+	}
+
+	return vc;
+}
+
+
+void ViewCellsTree::PropagateUpPvs(ViewCell *vc)
+{
+	while (vc->GetParent())
+	{
+		vc->GetParent()->GetPvs().Merge(vc->GetPvs());
+		vc = vc->GetParent();
+	}
+}
+
+
+void
+ViewCellsTree::AssignRandomColors()
+{
+  TraversalQueue tqueue;
+  tqueue.push(mRoot);
+  mRoot->SetColor(RandomColor(0.3f, 1.0f));
+  while (!tqueue.empty())
+	{
+	  ViewCell *vc = tqueue.top();
+	  
+	  // save the view cells if it is a leaf or if enough view cells have already been traversed
+	  // because of the priority queue, this will be the optimal set of v
+	  if (!vc->IsLeaf()) {	
+		ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+		
+		ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+		float maxProbability = -1.0f;
+		ViewCell *maxViewCell = NULL;
+		for (it = interior->mChildren.begin(); it != it_end; ++ it) {
+		  ViewCell *v = *it;
+		  // set random color
+		  v->SetColor(RandomColor(0.3f, 1.0f));
+		  if (v->GetVolume() > maxProbability) {
+			maxProbability = v->GetVolume();
+			maxViewCell = v;
+		  }
+		  maxViewCell->SetColor(vc->GetColor());
+		  tqueue.push(v);
+		}
+		
+	  }
+	  
+	  tqueue.pop();
+	}
+}
+
+/** Get costs resulting from each merge step. */
+void
+ViewCellsTree::GetCostFunction(vector<float> &costFunction)
+{
+  TraversalQueue tqueue;
+  tqueue.push(mRoot);
+  while (!tqueue.empty()) {
+	ViewCell *vc = tqueue.top();
+	
+	// save the view cells if it is a leaf or if enough view cells have already been traversed
+	// because of the priority queue, this will be the optimal set of v
+	if (!vc->IsLeaf()) {	
+	  ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+	  costFunction.push_back(interior->GetCost());
+	  
+	  ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+	  
+	  for (it = interior->mChildren.begin(); it != it_end; ++ it) {
+		tqueue.push(*it);
+	  }
+	  
+	}
+	
+	tqueue.pop();
+  }
+}
+
+
+void  ViewCellsTree::UpdateViewCellsStats(ViewCell *vc, ViewCellsStatistics &vcStat)
+{
+	++ vcStat.viewCells;
+		
+	const int pvsSize = GetPvsSize(vc);
+
+	vcStat.pvsSize += pvsSize;
+
+	if (pvsSize == 0)
+		++ vcStat.emptyPvs;
+
+	if (pvsSize > vcStat.maxPvs)
+		vcStat.maxPvs = pvsSize;
+
+	if (pvsSize < vcStat.minPvs)
+		vcStat.minPvs = pvsSize;
+
+	if (!vc->GetValid())
+		++ vcStat.invalid;
+
+	/*ViewCellsContainer leaves;
+	CollectLeaves(vc, leaves);
+
+	vcStat.leaves = (int)leaves.size();*/
+}
+
+
+bool ViewCellsTree::Export(ofstream &stream)
+{
+	ExportViewCell(mRoot, stream);
+
+	return true;
+}
+
+
+void ViewCellsTree::ExportViewCell(ViewCell *viewCell, ofstream &stream)
+{
+	ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
+
+	if (0) // test with empty pvs
+	for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
+	{
+		stream << (*it).first->GetId() << " ";
+	}
+
+	stream << "\" />" << endl;
+
+	if (viewCell->IsLeaf())
+	{
+		stream << "<Leaf ";
+		stream << "id=\"" << viewCell->GetId() << "\" ";
+		stream << "active=\"" << viewCell->mIsActive << "\" ";
+		stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
+		stream << "pvs=\"";
+		stream << "</Leaf>" << endl;
+	}
+	else
+	{
+		ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
+	
+		stream << "<Interior ";
+		stream << "id=\"" << viewCell->GetId() << "\" ";
+		stream << "active=\"" << viewCell->mIsActive << "\" ";
+		stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
+		stream << "pvs=\"";
+
+		ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+
+		for (it = interior->mChildren.begin(); it != it_end; ++ it)
+		{
+			ExportViewCell(*it, stream);
+		}
+
+		stream << "</Interior>" << endl;
+	}
+}
+
+
+
+/**************************************************************************/
+/*                     MergeCandidate implementation                      */
+/**************************************************************************/
+
+
+MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r):
+mRenderCost(0),
+mDeviationIncr(0),
+mLeftViewCell(l),
+mRightViewCell(r),
+mInitialLeftViewCell(l),
+mInitialRightViewCell(r)
+{
+	//EvalMergeCost();
+}
+
+
+void MergeCandidate::SetRightViewCell(ViewCell *v)
+{
+	mRightViewCell = v;
+}
+
+
+void MergeCandidate::SetLeftViewCell(ViewCell *v)
+{
+	mLeftViewCell = v;
+}
+
+
+ViewCell *MergeCandidate::GetRightViewCell() const
+{
+	return mRightViewCell;
+}
+
+
+ViewCell *MergeCandidate::GetLeftViewCell() const
+{
+	return mLeftViewCell;
+}
+
+
+ViewCell *MergeCandidate::GetInitialRightViewCell() const
+{
+	return mInitialRightViewCell;
+}
+
+
+ViewCell *MergeCandidate::GetInitialLeftViewCell() const
+{
+	return mInitialLeftViewCell;
+}
+
+
+bool MergeCandidate::IsValid() const
+{
+	return !(mLeftViewCell->mParent || mRightViewCell->mParent);
+}
+
+
+float MergeCandidate::GetRenderCost() const
+{
+	return mRenderCost;
+}
+
+
+float MergeCandidate::GetDeviationIncr() const
+{
+	return mDeviationIncr;
+}
+
+
+float MergeCandidate::GetMergeCost() const
+{
+	return mRenderCost * sRenderCostWeight + 
+		   mDeviationIncr * (1.0f - sRenderCostWeight);
+}
+
+
+
+
+
+
+/************************************************************************/
+/*                    MergeStatistics implementation                    */
+/************************************************************************/
+
+
+void MergeStatistics::Print(ostream &app) const
+{
+	app << "===== Merge statistics ===============\n";
+
+	app << setprecision(4);
+
+	app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n";
+
+	app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n";
+
+	app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n";
+
+	app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n";
+
+	app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n";
+
+	app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n";
+
+	app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n";
+
+	app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n";
+
+	app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n";
+
+	app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n";
+
+	app << "#EXPECTEDCOST ( expected render cost )\n" << expectedRenderCost << "\n";
+
+	app << "#DEVIATION ( deviation )\n" << deviation << "\n";
+
+	app << "#HEURISTICS ( heuristics )\n" << heuristics << "\n";
+	
+
+	app << "===== END OF BspTree statistics ==========\n";
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.cpp	(revision 508)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.cpp	(revision 508)
@@ -0,0 +1,697 @@
+// ---------------------------------------------------------------------------
+//  Includes for all the program files to see
+// ---------------------------------------------------------------------------
+#include <string.h>
+#include <stdlib.h>
+#include <iostream>
+using namespace std;
+#include <xercesc/util/PlatformUtils.hpp>
+
+// ---------------------------------------------------------------------------
+//  Includes
+// ---------------------------------------------------------------------------
+#include <xercesc/framework/StdInInputSource.hpp>
+#include <xercesc/parsers/SAXParser.hpp>
+#include <xercesc/util/OutOfMemoryException.hpp>
+
+// ---------------------------------------------------------------------------
+//  Includes
+// ---------------------------------------------------------------------------
+#include <xercesc/sax/AttributeList.hpp>
+#include <xercesc/sax/SAXParseException.hpp>
+#include <xercesc/sax/SAXException.hpp>
+
+#include "X3dParser.h"
+
+#include "X3dParserXerces.h"
+#include "Mesh.h"
+#include "SceneGraph.h"
+#include "Triangle3.h"
+#include "ViewCellsManager.h"
+
+// ---------------------------------------------------------------------------
+//  Local data
+//
+//  doNamespaces
+//      Indicates whether namespace processing should be enabled or not.
+//      The default is no, but -n overrides that.
+//
+//  doSchema
+//      Indicates whether schema processing should be enabled or not.
+//      The default is no, but -s overrides that.
+//
+//  schemaFullChecking
+//      Indicates whether full schema constraint checking should be enabled or not.
+//      The default is no, but -s overrides that.
+//
+//  valScheme
+//      Indicates what validation scheme to use. It defaults to 'auto', but
+//      can be set via the -v= command.
+// ---------------------------------------------------------------------------
+static bool     doNamespaces       = false;
+static bool     doSchema           = false;
+static bool     schemaFullChecking = false;
+static SAXParser::ValSchemes    valScheme       = SAXParser::Val_Auto;
+
+
+
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Constructors and Destructor
+// ---------------------------------------------------------------------------
+X3dParseHandlers::X3dParseHandlers(SceneGraphNode *root) :
+  mElementCount(0)
+  , mAttrCount(0)
+  , mCharacterCount(0)
+  , mSpaceCount(0)
+ // , mCurrentObjectId(0)
+{
+  mCurrentNode = root;
+}
+
+X3dParseHandlers::~X3dParseHandlers()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Implementation of the SAX DocumentHandler interface
+// ---------------------------------------------------------------------------
+void X3dParseHandlers::endElement(const XMLCh* const name)
+{
+  StrX lname(name);
+  string element(lname.LocalForm());
+  if (element == "Shape")
+    EndShape();
+}
+
+void
+X3dParseHandlers::EndShape()
+{
+  if (mCurrentMesh->mFaces.size()) {
+    mCurrentMesh->Preprocess();
+    // make an instance of this mesh
+    MeshInstance *mi = new MeshInstance(mCurrentMesh);
+    mCurrentNode->mGeometry.push_back(mi);
+	// set the object id to a unique value
+	//mi->SetId(mCurrentObjectId ++);
+  } else {
+    cout<<"X";
+    delete mCurrentMesh;
+  }
+  mCurrentMesh = NULL;
+}
+
+void
+X3dParseHandlers::StartIndexedFaceSet(
+									  AttributeList&  attributes)
+{
+  int len = attributes.getLength();
+  int i;
+  VertexIndexContainer vertices;
+  
+  for (i=0; i < len; i++) {
+    string attrName(StrX(attributes.getName(i)).LocalForm());
+    if (attrName == "coordIndex") {
+      StrX attrValue(attributes.getValue(i));
+      // handle coordIndex
+      vertices.clear();
+      const char *ptr = attrValue.LocalForm();
+      char *endptr;
+      while(1) {
+	int index = strtol(ptr, &endptr, 10);
+	if (ptr == endptr || index == -1) {
+	  if (vertices.size() > 2) {
+	    Face *face = new Face(vertices);
+	    mCurrentMesh->mFaces.push_back(face);
+	  }
+	  vertices.clear();
+	  if (ptr == endptr)
+	    break;
+	} else {
+	  vertices.push_back(index);
+	}
+	ptr = endptr;
+	  }
+    }
+  }
+}
+
+void
+X3dParseHandlers::StartMaterial(
+				AttributeList&  attributes)
+{
+  int len = attributes.getLength();
+  int i;
+  if (!mCurrentMesh->mMaterial)
+    mCurrentMesh->mMaterial = new Material;
+  for (i=0; i < len; i++) {
+    string attrName(StrX(attributes.getName(i)).LocalForm());
+    StrX attrValue(attributes.getValue(i));
+    const char *ptr = attrValue.LocalForm();
+    if (attrName == "diffuseColor") {
+      float r, g, b;
+      if (sscanf(ptr, "%f %f %f", &r, &g, &b) == 3)
+	mCurrentMesh->mMaterial->mDiffuseColor = RgbColor(r, g, b);
+    }
+  }
+}
+
+void
+X3dParseHandlers::StartCoordinate(
+				  AttributeList&  attributes)
+{
+  int len = attributes.getLength();
+  int i;
+  VertexContainer vertices;
+  for (i=0; i < len; i++) {
+    string attrName(StrX(attributes.getName(i)).LocalForm());
+    if (attrName == "point") {
+      StrX attrValue(attributes.getValue(i));
+      const char *ptr = attrValue.LocalForm();
+      char *endptr;
+      while(1) {
+	float x = (float)strtod(ptr, &endptr);
+	if (ptr == endptr)
+	  break;
+	ptr = endptr;
+	float y = (float)strtod(ptr, &endptr);
+	if (ptr == endptr)
+	  break;
+	ptr = endptr;
+	float z = (float)strtod(ptr, &endptr);
+	if (ptr == endptr)
+	  break;
+	ptr = endptr;
+	if (*ptr == ',')
+	  ptr++;
+	Vector3 v(x, y, z);
+	vertices.push_back(v);
+      }
+      mCurrentMesh->mVertices = vertices;
+    }
+  }
+}
+
+
+void
+X3dParseHandlers::startElement(const XMLCh* const name,
+							   AttributeList&  attributes)
+{
+  StrX lname(name);
+  string element(lname.LocalForm());
+  
+  if (element == "IndexedFaceSet") {
+    // create a new mesh node in the scene graph
+    StartIndexedFaceSet(attributes);
+  }
+
+  if (element == "Shape") {
+    cout<<"+";
+    mCurrentMesh = new Mesh;
+  }
+  
+  if (element == "Coordinate") {
+    if (mCurrentMesh)
+      StartCoordinate(attributes);
+  }
+  
+  if (element == "Material") {
+    StartMaterial(attributes);
+  }
+
+  mElementCount++;
+  mAttrCount += attributes.getLength();
+}
+
+void
+X3dParseHandlers::characters(const XMLCh* const chars,
+			     const unsigned int length)
+{
+  mCharacterCount += length;
+}
+
+void
+X3dParseHandlers::ignorableWhitespace(const XMLCh* const chars,
+				      const unsigned int length)
+{
+  mSpaceCount += length;
+}
+
+void
+X3dParseHandlers::resetDocument()
+{
+  mAttrCount = 0;
+  mCharacterCount = 0;
+  mElementCount = 0;
+  mSpaceCount = 0;
+}
+
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Overrides of the SAX ErrorHandler interface
+// ---------------------------------------------------------------------------
+void
+X3dParseHandlers::error(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nError at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+void
+X3dParseHandlers::fatalError(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nFatal Error at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+void
+X3dParseHandlers::warning(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nWarning at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+
+bool
+X3dParser::ParseFile(const string filename,
+		     SceneGraphNode **root)
+{
+  // Initialize the XML4C system
+  try {
+    XMLPlatformUtils::Initialize();
+  }
+  
+  catch (const XMLException& toCatch)
+    {
+      XERCES_STD_QUALIFIER cerr << "Error during initialization! Message:\n"
+				<< StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl;
+      return false;
+    }
+  
+  
+  //
+  //  Create a SAX parser object. Then, according to what we were told on
+  //  the command line, set the options.
+  //
+  SAXParser* parser = new SAXParser;
+  parser->setValidationScheme(valScheme);
+  parser->setDoNamespaces(doNamespaces);
+  parser->setDoSchema(doSchema);
+  parser->setValidationSchemaFullChecking(schemaFullChecking);
+  
+
+  //
+  //  Create our SAX handler object and install it on the parser, as the
+  //  document and error handler. We are responsible for cleaning them
+  //  up, but since its just stack based here, there's nothing special
+  //  to do.
+  //
+  *root = new SceneGraphNode;
+  X3dParseHandlers handler(*root);
+  parser->setDocumentHandler(&handler);
+  parser->setErrorHandler(&handler);
+  
+  unsigned long duration;
+  int errorCount = 0;
+  // create a faux scope so that 'src' destructor is called before
+  // XMLPlatformUtils::Terminate
+  {
+    //
+    //  Kick off the parse and catch any exceptions. Create a standard
+    //  input input source and tell the parser to parse from that.
+    //
+    //    StdInInputSource src;
+    try
+      {
+	const unsigned long startMillis = XMLPlatformUtils::getCurrentMillis();
+	parser->parse(filename.c_str());
+	const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis();
+	duration = endMillis - startMillis;
+	errorCount = parser->getErrorCount();
+      }
+    catch (const OutOfMemoryException&)
+      {
+	XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
+	errorCount = 2;
+	return false;
+      }
+    catch (const XMLException& e)
+      {
+	XERCES_STD_QUALIFIER cerr << "\nError during parsing: \n"
+				  << StrX(e.getMessage())
+				  << "\n" << XERCES_STD_QUALIFIER endl;
+	errorCount = 1;
+	return false;
+      }
+
+    
+    // Print out the stats that we collected and time taken
+    if (!errorCount) {
+      XERCES_STD_QUALIFIER cout << filename << ": " << duration << " ms ("
+				<< handler.GetElementCount() << " elems, "
+				<< handler.GetAttrCount() << " attrs, "
+				<< handler.GetSpaceCount() << " spaces, "
+				<< handler.GetCharacterCount() << " chars)" << XERCES_STD_QUALIFIER endl;
+    }
+  }
+  
+  //
+  //  Delete the parser itself.  Must be done prior to calling Terminate, below.
+  //
+  delete parser;
+  
+  XMLPlatformUtils::Terminate();
+  
+  if (errorCount > 0)
+    return false;
+  else
+    return true;
+}
+
+
+
+/************************************************************************/
+/*             class X3dViewCellsParseHandlers implementation           */
+/************************************************************************/
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Constructors and Destructor
+// ---------------------------------------------------------------------------
+X3dViewCellsParseHandlers::X3dViewCellsParseHandlers(ViewCellsManager *viewCellsManager, 
+													 float viewCellHeight):
+mElementCount(0), 
+mAttrCount(0), 
+mCharacterCount(0), 
+mSpaceCount(0), 
+mViewCellsManager(viewCellsManager), 
+mViewCellHeight(viewCellHeight)
+{
+}
+
+X3dViewCellsParseHandlers::~X3dViewCellsParseHandlers()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Implementation of the SAX DocumentHandler interface
+// ---------------------------------------------------------------------------
+void X3dViewCellsParseHandlers::endElement(const XMLCh* const name)
+{
+  StrX lname(name);
+  string element(lname.LocalForm());
+  if (element == "Shape")
+    EndShape();
+}
+
+void
+X3dViewCellsParseHandlers::EndShape()
+{
+}
+
+void
+X3dViewCellsParseHandlers::StartIndexedFaceSet(
+				      AttributeList&  attributes)
+{
+	int len = attributes.getLength();
+	int i;
+	// clear previous vertex indices
+	mCurrentVertexIndices.clear();
+	for (i=0; i < len; i++) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+	    
+		if (attrName == "coordIndex") 
+		{
+			StrX attrValue(attributes.getValue(i));
+			
+			// handle coordIndex
+			const char *ptr = attrValue.LocalForm();
+			char *endptr;
+		
+			while (1)
+			{
+				int index = strtol(ptr, &endptr, 10);
+				
+				if (ptr == endptr)
+					break;
+
+				if (index != -1) 
+				{
+					mCurrentVertexIndices.push_back(index);
+				}
+	            
+				ptr = endptr;
+			}
+		}
+	}
+}
+
+
+void
+X3dViewCellsParseHandlers::StartCoordinate(AttributeList&  attributes)
+{
+	int len = attributes.getLength();
+	
+	VertexContainer vertices;
+	int i;
+	for (i=0; i < len; i++) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+		
+		if (attrName == "point") 
+		{
+			StrX attrValue(attributes.getValue(i));
+			
+			const char *ptr = attrValue.LocalForm();
+			
+			char *endptr;
+			
+			while (1) 
+			{
+				float x = (float)strtod(ptr, &endptr);
+                
+				if (ptr == endptr)
+					break;
+				ptr = endptr;
+				
+				float y = (float)(float)strtod(ptr, &endptr);
+
+				
+				if (ptr == endptr)
+					break;
+				ptr = endptr;
+
+				float z = (float)(float)strtod(ptr, &endptr);
+
+				if (ptr == endptr)
+					break;
+
+				ptr = endptr;
+				if (*ptr == ',')
+					ptr++;
+
+				Vector3 v(x, y, z);
+				vertices.push_back(v);				
+			}
+		}
+	}
+
+	for (i = 0; i < mCurrentVertexIndices.size(); i += 3)
+	{
+		Triangle3 baseTri(vertices[mCurrentVertexIndices[i + 0]], 
+						  vertices[mCurrentVertexIndices[i + 1]],
+						  vertices[mCurrentVertexIndices[i + 2]]);
+
+		// create view cell from base triangle
+		mViewCellsManager->AddViewCell(
+			mViewCellsManager->ExtrudeViewCell(baseTri, 
+			mViewCellHeight));
+	}
+}
+
+
+void
+X3dViewCellsParseHandlers::startElement(const XMLCh* const name,
+										AttributeList&  attributes)
+{
+  StrX lname(name);
+  string element(lname.LocalForm());
+  
+  if (element == "IndexedFaceSet") {
+    // create the viewcells from individual triangles
+    StartIndexedFaceSet(attributes);
+  }
+	
+  if (element == "Coordinate") {
+	  // add coordinates to the triangles
+      StartCoordinate(attributes);
+  }
+  // do nothing
+  //if (element == "Shape") {}
+  // ignore material
+  //if (element == "Material") {}
+
+  ++ mElementCount;
+  mAttrCount += attributes.getLength();
+}
+
+void
+X3dViewCellsParseHandlers::characters(const XMLCh* const chars,
+			     const unsigned int length)
+{
+  mCharacterCount += length;
+}
+
+void
+X3dViewCellsParseHandlers::ignorableWhitespace(const XMLCh* const chars,
+				      const unsigned int length)
+{
+  mSpaceCount += length;
+}
+
+void
+X3dViewCellsParseHandlers::resetDocument()
+{
+  mAttrCount = 0;
+  mCharacterCount = 0;
+  mElementCount = 0;
+  mSpaceCount = 0;
+}
+
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Overrides of the SAX ErrorHandler interface
+// ---------------------------------------------------------------------------
+void
+X3dViewCellsParseHandlers::error(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nError at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+void
+X3dViewCellsParseHandlers::fatalError(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nFatal Error at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+void
+X3dViewCellsParseHandlers::warning(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nWarning at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+
+bool
+X3dParser::ParseFile(const string filename, ViewCellsManager &viewCells)
+{
+  // Initialize the XML4C system
+  try {
+    XMLPlatformUtils::Initialize();
+  }
+  
+  catch (const XMLException& toCatch)
+    {
+      XERCES_STD_QUALIFIER cerr << "Error during initialization! Message:\n"
+				<< StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl;
+      return false;
+    }
+  
+  
+  //
+  //  Create a SAX parser object. Then, according to what we were told on
+  //  the command line, set the options.
+  //
+  SAXParser* parser = new SAXParser;
+  parser->setValidationScheme(valScheme);
+  parser->setDoNamespaces(doNamespaces);
+  parser->setDoSchema(doSchema);
+  parser->setValidationSchemaFullChecking(schemaFullChecking);
+  
+
+  //
+  //  Create our SAX handler object and install it on the parser, as the
+  //  document and error handler. We are responsible for cleaning them
+  //  up, but since its just stack based here, there's nothing special
+  //  to do.
+  //
+  X3dViewCellsParseHandlers handler(&viewCells, mViewCellHeight);
+  parser->setDocumentHandler(&handler);
+  parser->setErrorHandler(&handler);
+  
+  unsigned long duration;
+  int errorCount = 0;
+  // create a faux scope so that 'src' destructor is called before
+  // XMLPlatformUtils::Terminate
+  {
+    //
+    //  Kick off the parse and catch any exceptions. Create a standard
+    //  input input source and tell the parser to parse from that.
+    //
+    //    StdInInputSource src;
+    try
+      {
+	const unsigned long startMillis = XMLPlatformUtils::getCurrentMillis();
+	parser->parse(filename.c_str());
+	const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis();
+	duration = endMillis - startMillis;
+	errorCount = parser->getErrorCount();
+      }
+    catch (const OutOfMemoryException&)
+      {
+	XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
+	errorCount = 2;
+	return false;
+      }
+    catch (const XMLException& e)
+      {
+	XERCES_STD_QUALIFIER cerr << "\nError during parsing: \n"
+				  << StrX(e.getMessage())
+				  << "\n" << XERCES_STD_QUALIFIER endl;
+	errorCount = 1;
+	return false;
+      }
+
+    
+    // Print out the stats that we collected and time taken
+    if (!errorCount) {
+      XERCES_STD_QUALIFIER cout << filename << ": " << duration << " ms ("
+				<< handler.GetElementCount() << " elems, "
+				<< handler.GetAttrCount() << " attrs, "
+				<< handler.GetSpaceCount() << " spaces, "
+				<< handler.GetCharacterCount() << " chars)" << XERCES_STD_QUALIFIER endl;
+    }
+  }
+  
+  //
+  //  Delete the parser itself.  Must be done prior to calling Terminate, below.
+  //
+  delete parser;
+  
+  XMLPlatformUtils::Terminate();
+  
+  if (errorCount > 0)
+    return false;
+  else
+    return true;
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Renderer.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Renderer.h	(revision 497)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Renderer.h	(revision 497)
@@ -0,0 +1,32 @@
+#ifndef _Renderer_h__
+#define _Renderer_h__
+
+#include "common.h"
+
+class ViewCellsManager;
+class SceneGraph;
+/** Abstract class used to render the scene.
+*/
+class Renderer
+{
+
+public:
+
+	Renderer();
+	Renderer(SceneGraph *sceneGraph, ViewCellsManager *vcm);
+	
+	~Renderer();
+
+	/** Renders the scene using the current view cell partition.
+	*/
+	virtual bool RenderScene() = 0;
+
+	void SetViewCellsManager(ViewCellsManager *vcm);
+
+protected:
+	ViewCellsManager *mViewCellsManager;
+	SceneGraph *mSceneGraph;
+};
+
+
+#endif // Renderer
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 610)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 610)
@@ -0,0 +1,320 @@
+#ifndef __PVS_H
+#define __PVS_H
+
+#include <map>
+#include <vector>
+
+class KdNode;
+class BspNode;
+class Ray;
+class Intersectable;
+class ViewCellKdNode;
+
+template<typename T>
+struct LtSample {
+    bool operator()(const T a, const T b) const
+    {
+		return a < b;
+	} 
+};
+
+/** Information stored with a PVS entry. Consists of the number
+	the object was seen from the view cell.
+*/
+
+template<typename T> 
+struct PvsData {
+  //  int mVisibleSamples;
+  // sum of probability density of visible sample rays
+  float mSumPdf;
+  PvsData<T>() {}
+  PvsData<T>(const float sumPdf):
+	mSumPdf(sumPdf) {}
+
+  // $$JB in order to return meaningfull values
+  // it assumes that the sum pdf has been normalized somehow!!!
+  float GetVisibility() { return mSumPdf; }
+};
+
+/** Template class representing the Potentially Visible Set (PVS) 
+	mainly from a view cell, but also e.g., from objects.
+*/
+template<typename T>
+class Pvs
+{
+public:
+  Pvs(): /*mSamples(0), */mEntries() {}
+  
+  //int mSamples;
+  
+  /** Compresses PVS lossless or lossy.
+  */
+  int Compress() {return 0;}
+  int GetSize() const {return (int)mEntries.size();}
+  bool Empty() const {return mEntries.empty();}
+
+  /** Normalize the visibility of entries in order to get comparable
+	  results */
+  
+  void NormalizeMaximum();
+  
+  /** Merges pvs of a into this pvs.
+   */
+  void Merge(const Pvs<T> &a);
+  
+  /** Difference of pvs to pvs b.
+	  @returns number of different entries.
+  */
+  int Diff(const Pvs<T> &b);
+  
+  /** Finds sample in PVS.
+	  @returns sample if found, NULL otherwise.
+  */
+  PvsData<T> *Find(T sample);
+
+  bool GetSampleContribution(T sample, const float pdf, float &contribution);
+  
+  /** Adds sample to PVS. 
+	  @contribution contribution of sample (0 or 1)
+	  @returns true if sample was not already in PVS.
+  */
+  bool AddSample(T sample, const float pdf, float &contribution);
+
+  /** Adds sample to PVS.
+	  @returns contribution of sample (0 or 1)
+  */
+  float AddSample(T sample, const float pdf);
+  
+  /** Adds one pvs to another one.
+	  @returns new pvs size
+  */
+  int AddPvs(const Pvs<T> &pvs);
+  /** Subtracts one pvs from another one.
+	  @returns new pvs size
+  */
+  int SubtractPvs(const Pvs<T> &pvs);
+  /** Returns PVS data, i.e., how often it was seen from the view cell, 
+	  and the object itsef.
+  */
+  void GetData(const int index, T &entry, PvsData<T> &data);
+
+  /** Collects the PVS entries and returns them in the vector.
+  */
+  void CollectEntries(std::vector<T> &entries);
+
+  /** Removes sample from PVS if reference count is zero.
+	  @param visibleSampels number of references to be removed
+  */
+  bool RemoveSample(T sample, const float pdf);
+
+  /// Map of PVS entries
+  std::map<T, PvsData<T>, LtSample<T> > mEntries;
+};
+
+
+template <typename T>
+int Pvs<T>::Diff(const Pvs<T> &b)
+{
+	int dif = 0;
+
+	std::map<T, PvsData<T>, LtSample<T> >::const_iterator it;
+
+	for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
+	{
+		PvsData<T> *data = Find((*it).first);		
+		if (!data) ++ dif;
+	}
+
+	return dif;
+}
+
+template <typename T>
+void Pvs<T>::Merge(const Pvs<T> &a)
+{
+	std::map<T, PvsData<T>, LtSample<T> >::const_iterator it;
+
+	for (it = a.mEntries.begin(); it != a.mEntries.end(); ++ it)
+	{
+		PvsData<T> *data = Find((*it).first);
+		
+		if (data)
+			data->mSumPdf += (*it).second.mSumPdf;
+		else
+			mEntries.insert(*it);
+	}
+}
+
+template <typename T>
+PvsData<T> *Pvs<T>::Find(T sample)
+{
+  std::map<T, PvsData<T>, LtSample<T> >::iterator i = mEntries.find(sample);
+  if (i != mEntries.end()) {
+    return &(*i).second;
+  } else
+    return NULL;
+}
+
+template <typename T>
+void Pvs<T>::GetData(const int index,
+					 T &entry,
+					 PvsData<T> &data)
+{
+  std::map<T, PvsData<T>, LtSample<T> >::iterator i = mEntries.begin();
+  for (int k = 0; k != index && i != mEntries.end(); i++, k++);
+
+  entry = (*i).first;
+  data = (*i).second;
+}
+
+template <typename T>
+float
+Pvs<T>::AddSample(T sample, const float pdf)
+{
+  PvsData<T> *data = Find(sample);
+  
+  if (data)  {
+	data->mSumPdf+=pdf;
+	return data->mSumPdf;
+  }
+  else {
+	mEntries[sample] = PvsData<T>(pdf);
+	return pdf;
+  }
+}
+
+template <typename T>
+bool
+Pvs<T>::AddSample(T sample,
+				  const float pdf,
+				  float &contribution)
+{
+  PvsData<T> *data = Find(sample);
+  
+  if (data)  {
+	data->mSumPdf+=pdf;
+	contribution = pdf/data->mSumPdf;
+	return false;
+  }
+  else {
+	mEntries[sample] = PvsData<T>(pdf);
+	contribution = 1.0f;
+	return true;
+  }
+}
+
+template <typename T>
+bool
+Pvs<T>::GetSampleContribution(T sample,
+							  const float pdf,
+							  float &contribution) 
+{
+  PvsData<T> *data = Find(sample);
+  
+  if (data)  {
+	contribution = pdf/(data->mSumPdf + pdf);
+	return false;
+  }
+  else {
+	contribution = 1.0f;
+	return true;
+  }
+}
+
+template <typename T>
+bool Pvs<T>::RemoveSample(T sample,
+						  const float pdf)
+{
+  std::map<T, PvsData<T>, LtSample<T> >::
+	iterator it = mEntries.find(sample);
+  
+  if (it == mEntries.end())
+	return false;
+  
+  PvsData<T> *data = &(*it).second;
+  
+  data->mSumPdf -= pdf;
+  if (data->mSumPdf <= 0.0f)
+	mEntries.erase(it);
+  
+  return true;
+}
+
+template <typename T>
+int Pvs<T>::AddPvs(const Pvs<T> &pvs)
+{
+  std::map<T, PvsData<T>, LtSample<T> >::
+	const_iterator it, it_end = pvs.mEntries.end();
+  
+  float contri;
+  // output PVS of view cell
+  for (it = pvs.mEntries.begin(); it != it_end; ++ it) 
+	AddSample((*it).first, (*it).second.mSumPdf, contri);
+  
+  return GetSize();
+}
+ 
+template <typename T>
+int Pvs<T>::SubtractPvs(const Pvs<T> &pvs)
+{
+  std::map<T, PvsData<T>, LtSample<T> >::
+	const_iterator it, it_end = pvs.mEntries.end();
+  
+  // output PVS of view cell
+  for (it = pvs.mEntries.begin(); it != it_end; ++ it) 
+	RemoveSample((*it).first, (*it).second.mSumPdf);
+  
+  return GetSize();
+}
+
+template <typename T>
+void Pvs<T>::CollectEntries(std::vector<T> &entries)
+{
+	std::map<T, PvsData<T>, LtSample<T> >::
+		const_iterator it, it_end = mEntries.end();
+
+	// output PVS of view cell
+	for (it = mEntries.begin(); it != it_end; ++ it) 
+		entries.push_back((*it)->first);
+}
+
+template <typename T>
+void Pvs<T>::NormalizeMaximum()
+{
+  std::map<T, PvsData<T>, LtSample<T> >::
+	const_iterator it, it_end = mEntries.end();
+
+  float maxPdfSum = -1.0f;
+
+  // output PVS of view cell
+  for (it = mEntries.begin(); it != it_end; ++ it) {
+	float sum = (*it)->second.sumPdf;
+	if (sum > maxSum)
+	  maxSum = sum;
+  }
+
+  maxSum = 1.0f/maxSum;
+
+  for (it = mEntries.begin(); it != it_end; ++ it) {
+	(*it)->second.sumPdf *= maxSum;
+  }
+  
+}
+
+
+/** Class instantiating the Pvs template for kd tree nodes.
+*/
+class KdPvs: public Pvs<KdNode *>
+{
+	int Compress();
+};
+
+typedef std::map<KdNode *, PvsData<KdNode *>, LtSample<KdNode *> > KdPvsMap;
+typedef std::map<Intersectable *, PvsData<Intersectable *>, LtSample<Intersectable *> > ObjectPvsMap;
+typedef PvsData<Intersectable *> ObjectPvsData;
+typedef PvsData<KdNode *> KdPvsData;
+
+typedef Pvs<Intersectable *> ObjectPvs;
+
+
+#endif
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.h	(revision 575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.h	(revision 575)
@@ -0,0 +1,22 @@
+#ifndef __VIEWCELLSDPARSER_H
+#define __VIEWCELLSDPARSER_H
+
+#include "Parser.h"
+#include "Containers.h"
+
+class ViewCellsManager;
+class VspBspTree;
+
+class ViewCellsParser : public Parser
+{
+public:
+  ViewCellsParser():Parser() {}
+  
+  //bool ParseFile(const string filename, ViewCellsManager &viewCells);
+  bool ParseFile(const string filename, 
+				 ViewCellsManager **viewCells,
+				 ObjectContainer *objects);
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Polygon3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Polygon3.h	(revision 574)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Polygon3.h	(revision 574)
@@ -0,0 +1,171 @@
+#ifndef _Polygon3_h__
+#define _Polygon3_h__
+
+
+//#include <iostream>
+//#include <math.h>
+//#include "common.h"
+#include "Containers.h"
+#include "Mesh.h"
+#include <iomanip>
+
+class Polygon3;
+class Plane3;
+class Face;
+class Intersectable;
+class AxisAlignedBox3;
+class Ray;
+//typedef Vertex3 Vector3;
+
+/** Class representing a planar convex polygon in 3d.
+*/
+class Polygon3
+{
+public:
+	enum {BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT};
+
+	/** Default constructor creating an empty polygon.
+	*/
+	Polygon3();
+	/** Constructor creating a polygon from the vertices.
+	*/
+	Polygon3(const VertexContainer &vertices);
+	/** Creates a polygon and stores pointer to parent mesh
+		instance.
+	*/
+	Polygon3(MeshInstance *parent);
+
+	// creates an "infinite" polygon from this plane
+	//Polygon3(Plane3 plane);
+	/** Copies all the vertices of the face.
+	*/
+	Polygon3(Face *face, Mesh *parentMesh);
+	
+	/** Returns supporting plane of this polygon.
+	*/
+	Plane3 GetSupportingPlane() const;
+
+	/** Splits polygon.
+		@param partition the split plane
+		@param front returns the front the front polygon
+		@param back returns the back polygon
+		@param epsilon epsilon where two points are considered equal
+	*/
+	void Split(const Plane3 &partition, 
+			   Polygon3 &front, 
+			   Polygon3 &back,
+			   const float epsilon);// = Limits::Small);
+
+	/** Returns the area of this polygon.
+	*/
+	float GetArea() const;
+
+	/** Classify polygon with respect to the plane.
+	    @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT
+	*/
+	//int ClassifyPlane(const Plane3 &plane) const;
+	
+	/** Classify polygon with respect to the plane.
+	    @param epsilon tolerance value
+		@returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT
+
+	*/
+	int ClassifyPlane(const Plane3 &plane, const float epsilon) const;
+
+	/** Side of the polygon with respect to the plane.
+		@returns 1 if on front side, -1 if on back side, 0 else.
+	*/
+	int Side(const Plane3 &plane, const float epsilon) const;
+
+	/** Scales the polygon about its center
+	*/
+	void Scale(const float scale);
+	
+	/** Computes the center of mass of the polygon
+	 */
+	Vector3 Center() const;
+	/** Checks if the polygon is valid, i.e., not degenerated.
+		@returns true if polygon is valid.
+	*/
+	bool Valid(const float epsilon) const; 
+
+	/** Returns the surface normal.
+	*/
+	Vector3 GetNormal() const;
+
+	/** Casts ray to polygon.
+	*/
+	int CastRay(const Ray &ray, float &t, const float nearestT);
+
+	/** The polygon is converted to triangles.
+	*/
+	void Triangulate(vector<Triangle3> &triangles);
+	/**
+		Adds polygon to mesh
+	*/
+	void AddToMesh(Mesh &mesh);
+	/** 
+		Triangle strip indices are created from this polgon.
+	*/
+	void Triangulate(VertexIndexContainer &indices);
+	
+	/** The piercing rays of the polygon are inherited by the child fragments
+		@parm front_piece the front fragment inheriting the front rays
+		@param back_piece the back fragment inheriting the back rays
+	*/
+	void InheritRays(Polygon3 &front_piece, 
+					 Polygon3 &back_piece) const;
+
+	/** Returns new polygon with reverse orientation.
+	*/
+	Polygon3 *CreateReversePolygon() const;
+
+	/// vertices are connected in counterclockwise order.
+	VertexContainer mVertices;
+
+	/// we can also store materials with polygons
+	Material *mMaterial;
+	
+	/// pointer to the mesh instance this polygon is derived from
+	MeshInstance *mParent;
+
+	/// Rays piercing this polygon
+	RayContainer mPiercingRays;
+
+
+	/** Includes polygons to axis aligned box.
+	*/
+	static void IncludeInBox(const PolygonContainer &polys, AxisAlignedBox3 &box);
+
+	/** Classify polygons with respect to the plane.
+	    @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT
+	*/
+	static int ClassifyPlane(const PolygonContainer &polys, 
+							 const Plane3 &plane,
+							 const float epsilon);
+
+
+	/** Counts the number of different intersectables associated with the polygons.
+	*/
+	static int ParentObjectsSize(const PolygonContainer &polys);
+
+	/** Area of the accumulated polygons.
+	*/
+	static float GetArea(const PolygonContainer &cell);
+};
+
+// Overload << operator for C++-style output
+inline ostream&
+operator<< (ostream &s, const Polygon3 &A)
+{
+	VertexContainer::const_iterator it;
+
+	//s << setprecision(6) << "Polygon:\n";
+	for (it = A.mVertices.begin(); it != A.mVertices.end(); ++it)
+		s << *it << endl;
+	
+	return s;
+}
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Plane3.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Plane3.cpp	(revision 256)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Plane3.cpp	(revision 256)
@@ -0,0 +1,32 @@
+#include "Plane3.h"
+#include "Matrix4x4.h"
+
+
+
+
+bool
+PlaneIntersection(const Plane3 &a, const Plane3 &b, const Plane3 &c, Vector3 &result)
+{
+  Vector3
+    sx(a.mNormal.x, b.mNormal.x, c.mNormal.x),
+    sy(a.mNormal.y, b.mNormal.y, c.mNormal.y),
+    sz(a.mNormal.z, b.mNormal.z, c.mNormal.z),
+    sd(a.mD, b.mD, c.mD);
+
+  Matrix4x4 md(a.mNormal, b.mNormal, c.mNormal), mx, my, mz;
+
+  mx.SetColumns(sd, sy, sz);
+  my.SetColumns(sx, sd, sz);
+  mz.SetColumns(sx, sy, sd);
+  
+  double det = md.Det3x3();
+
+  if (abs(det)<TRASH)
+    return false;
+
+  result.SetValue(mx.Det3x3()/det,
+		  my.Det3x3()/det,
+		  mz.Det3x3()/det);
+  
+  return true;
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.h	(revision 556)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.h	(revision 556)
@@ -0,0 +1,26 @@
+#ifndef __PREPROCESSOR_THREAD_H
+#define __PREPROCESSOR_THREAD_H
+
+#include <QThread>
+
+class Preprocessor;
+
+class PreprocessorThread : public QThread
+{
+  Q_OBJECT
+
+  Preprocessor *mPreprocessor;
+public:
+  PreprocessorThread(Preprocessor *p, QObject *parent = 0);
+  ~PreprocessorThread();
+
+  void Main();
+
+protected:
+  void run() {
+	Main();
+  }
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SceneGraph.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SceneGraph.h	(revision 492)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SceneGraph.h	(revision 492)
@@ -0,0 +1,45 @@
+#ifndef _SceneGraph_H__
+#define _SceneGraph_H__
+
+#include <string>
+using namespace std;
+
+#include "Containers.h"
+#include "AxisAlignedBox3.h"
+
+  
+/** Basic scene graph node, we are interested only in bounding boxes and topology
+    of the scene graph */
+class SceneGraphNode {
+public:
+  ObjectContainer mGeometry;
+  SceneGraphNodeContainer mChildren;
+  AxisAlignedBox3 mBox;
+  void UpdateBox();
+};
+
+
+/** Scene graph class */
+class SceneGraph {
+
+public:
+  SceneGraphNode *mRoot;
+  bool Export(const string filename);
+  
+  int
+  CollectObjects(ObjectContainer *instances);
+  
+  int
+  AssignObjectIds();
+  
+  void
+  GetStatistics(int &intersectables, int &faces) const;
+
+  AxisAlignedBox3 GetBox() const { return mRoot->mBox; }
+  
+protected:
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RenderSimulator.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RenderSimulator.h	(revision 574)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RenderSimulator.h	(revision 574)
@@ -0,0 +1,119 @@
+#ifndef _RenderSimulator_h__
+#define _RenderSimulator_h__
+
+#include "common.h"
+#include "Statistics.h"
+#include "Renderer.h"
+
+
+class SimulationStatistics: public StatisticsBase
+{
+public:
+	/// view cell with the biggest "cost"
+	float maxCost;
+	/// view cell with the minimal "cost"
+    float minCost;
+	/// average render time
+	float avgRenderTime;
+	/// average render time with the overhead when crossing view cells
+	float avgRtWithoutOverhead;
+  
+	//-- options counting only valid view cells
+
+	/// view cell with the biggest "cost"
+	float validMaxCost;
+	/// view cell with the minimal "cost"
+    float validMinCost;
+	/// average render time
+	float validAvgRenderTime;
+	/// average render time with the overhead when crossing view cells
+	float validAvgRtWithoutOverhead;
+
+	void Reset() 
+	{
+		maxCost = 0;
+		minCost = 999999;
+		avgRenderTime = 0;
+		avgRtWithoutOverhead = 0;
+
+		validMaxCost = 0;
+		validMinCost = 999999;
+		validAvgRenderTime = 0;
+		validAvgRtWithoutOverhead = 0;
+	}
+
+	void Print(ostream &app) const;
+
+	friend ostream &operator<<(ostream &s, const SimulationStatistics &stat) 
+	{
+		stat.Print(s);
+		return s;
+	}  
+
+	SimulationStatistics()
+	{
+		Reset();
+	}
+};
+
+/** Simulated rendering using a simple render heuristics. Used to evaluate the 
+	quality of the view cell partition. Evaluates some statistics of the simulation.
+*/
+class RenderSimulator: public Renderer
+{
+
+public:
+	RenderSimulator(ViewCellsManager *viewCellsManager);
+	/** Constructor taking the estimated render cost, 
+		the view cell overhead,
+		and the average move speed of the player into account.
+	*/
+	RenderSimulator(ViewCellsManager *viewCellsManager, 
+					float objRendercost, 
+					float vcOverhead, 
+					float moveSpeed);
+
+	/** Sets estimated render time for a single object in the PVS.
+	*/
+	void SetObjectRenderCost(const float objRenderCost);
+
+	/** Contant overhead for crossing a view cell border.
+	*/
+	void SetVcOverhead(const float vcOverhead);
+
+	/** Average move speed of the player during rendering.
+	*/
+	void SetMoveSpeed(const float moveSpeed);
+
+	/** Returns simulation statistics.
+	*/
+	void GetStatistics(SimulationStatistics &simStats) const;
+
+	/** Simulates rendering of the scene.
+	*/
+	bool RenderScene();
+
+	/** If only valid view space should be rendered.
+	*/
+	void SetRenderOnlyValid(const bool onlyValid);
+
+protected:
+
+	/** Probability for crossing one view cell.
+	*/
+	float GetCrossVcProbability() const;
+
+	/// render time for single object of the PVS
+	float mObjRenderCost;
+	
+	/// const overhead for crossing a view cell border
+	float mVcOverhead;
+
+	/// move speed of player
+	float mMoveSpeed;
+
+	/// Simulation statistics
+	SimulationStatistics mSimulationStatistics;
+};
+
+#endif // RenderSimulator
Index: GTP/trunk/Lib/Vis/Preprocessing/src/MutualVisibility.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/MutualVisibility.h	(revision 501)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/MutualVisibility.h	(revision 501)
@@ -0,0 +1,184 @@
+#ifndef __MUTUAL_VISIBILITY_H
+#define __MUTUAL_VISIBILITY_H
+
+#include "Vector3.h"
+#include "Ray.h"
+
+class Intersectable;
+class AxisAlignedBox3;
+class SceneGraph;
+
+
+struct RaySample {
+  /// true if the sample really intersects both boxes
+  float mMinT;
+  float mMaxT;
+
+  RaySample():mMinT(-1.0f), mMaxT(-1.0f) {}
+  /// intersections of the sample with the scene
+  vector<Ray::Intersection> mIntersections;
+  void SetInvalid() {
+    mMinT = 0.0f;
+    mMaxT = -1.0f;
+  }
+  bool IsValid() const { return mMaxT > 0.0f; }
+  bool IsProcessed() const { return mMinT != mMaxT; }
+};
+
+struct RayShaft {
+public:
+  /// evaluted sampling error
+  float mError;
+  /// depth in recursion
+  int mDepth;
+  /// The source triangle
+  Rectangle3 mSource;
+  /// The target triangle
+  Rectangle3 mTarget;
+  
+  RaySample mSamples[4];
+  
+  void ComputeError();
+  
+  RayShaft() {}
+  
+  RayShaft (
+	    const Rectangle3 &source,
+	    const Rectangle3 &target)
+  {
+    Init(source, target);
+  }
+
+  bool IsValid() const { return
+			   mSamples[0].IsValid() &&
+			   mSamples[1].IsValid() &&
+			   mSamples[2].IsValid() &&
+			   mSamples[3].IsValid();
+  }
+
+  // initial triangle sample
+  void Init(
+	    const Rectangle3 &source,
+	    const Rectangle3 &target);
+  
+  Vector3
+  GetIntersectionPoint(const int rayIndex,
+		       const int depth) const;
+  
+  void GetRay(const int rayIndex,
+	      Vector3 &origin,
+	      Vector3 &direction) const;
+
+  void
+  GetRaySegment(const int i, Ray &ray) const;
+
+};
+
+enum { VISIBLE, INVISIBLE };
+
+  
+class MutualVisibilitySampler {
+public:
+  SceneGraph *mSceneGraph;
+  KdTree *mKdTree;
+  AxisAlignedBox3 mSource;
+  AxisAlignedBox3 mTarget;
+  float mSolidAngleThreshold;
+  bool mUseBoxes;
+
+  MutualVisibilitySampler(
+						  SceneGraph *sceneGraph,
+						  KdTree *kdTree,
+						  const AxisAlignedBox3 &source,
+						  const AxisAlignedBox3 &target,
+						  const float solidAngleThreshold
+						  );
+  int
+  ComputeVisibility();
+
+  void
+  ConstructInitialSamples(const AxisAlignedBox3 &source,
+						  const AxisAlignedBox3 &target,
+						  vector<RayShaft *> &samples
+						  );
+	
+  void
+  ConstructInitialSamples2(
+						   const AxisAlignedBox3 &source,
+						   const AxisAlignedBox3 &target,
+						   vector<RayShaft *> &samples
+						   );
+	
+  void
+  ConstructInitialSamples3(
+						   const AxisAlignedBox3 &source,
+						   const AxisAlignedBox3 &target,
+						   vector<RayShaft *> &samples
+						   );
+	
+  void
+  AddInitialSamples(
+					const Rectangle3 &sourceRect,
+					const Rectangle3 &targetRect,
+					vector<RayShaft *> &samples
+					);
+	
+  void
+  AddInitialSamples2(
+					 const Rectangle3 &sourceRect,
+					 const Rectangle3 &targetRect,
+					 vector<RayShaft *> &samples
+					 );
+	
+  // the split sample method contains a methodology to create new samples
+  // or terminate the sampling
+  bool
+  SplitSample(
+			const RayShaft &source,
+			RayShaft &sample1,
+			RayShaft &sample2
+			);
+  void
+  PerformSplit(
+				const RayShaft &sample,
+				const bool splitSource,
+				const int axis,
+				RayShaft &sample1,
+				RayShaft &sample2
+				 );
+  
+	
+  bool
+  SampleTerminationCriteriaMet(
+								 const RayShaft &sample);
+  
+  float
+  GetSpatialAngle(const RayShaft &sample,
+				  const Vector3 &point
+				 );
+	
+  int
+  CastRays(RayShaft &shaft);
+	
+  void
+  ComputeError(RayShaft &sample);
+  
+  void
+  ExportShafts(vector<RayShaft *> &samples, const bool singleFile);
+
+
+};
+  
+int
+ComputeBoxVisibility(SceneGraph *sceneGraph,
+		     KdTree *kdTree,
+		     const AxisAlignedBox3 &source,
+		     const AxisAlignedBox3 &target,
+		     const float solidAngleThreshold);
+
+
+
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.h	(revision 611)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.h	(revision 611)
@@ -0,0 +1,1027 @@
+#ifndef _ViewCellBsp_H__
+#define _ViewCellBsp_H__
+
+#include "Mesh.h"
+#include "Containers.h"
+#include "Polygon3.h"
+#include <stack>
+#include "Statistics.h"
+#include "VssRay.h"
+#include "ViewCell.h"
+
+
+
+class ViewCell;
+//class BspViewCell;
+class Plane3;
+class BspTree;  
+class BspInterior;
+//class Polygon3;
+class AxisAlignedBox3;
+class Ray;
+class ViewCellsStatistics;
+class ViewCellsManager;
+class ViewCellsTree;
+
+class BspNodeGeometry
+{
+public:
+	BspNodeGeometry()
+	{};  
+
+	// copy constructor copying the polygon array
+	BspNodeGeometry(const BspNodeGeometry &rhs);
+
+	//BspNodeGeometry(const PolygonContainer &polys);
+
+	~BspNodeGeometry();
+
+	/** Returns accumulated area of all polygons.
+	*/
+	float GetArea() const;
+	
+	float GetVolume() const;
+
+	/** Computes new front and back geometry based on the old cell 
+		geometry and a new split plane
+	*/
+	void SplitGeometry(BspNodeGeometry &front,
+					   BspNodeGeometry &back,
+					   const Plane3 &splitPlane,
+                       const AxisAlignedBox3 &box,
+					   const float epsilon) const;
+
+	/** Computes bounding box of the geometry.
+	*/
+	void IncludeInBox(AxisAlignedBox3 &box);
+
+	/** Splits the polygon and returns the part of the polygon inside of the node geometry.
+	*/
+	Polygon3 *SplitPolygon(Polygon3 *poly, const float epsilon) const;
+
+	/** Adds node geometry to mesh.
+		@note the mesh vertices will not be connected
+	*/
+	void AddToMesh(Mesh &mesh);
+
+	/** Computes mass center of bsp node geometry.
+	*/
+	Vector3 CenterOfMass() const;
+
+	/** The polygons the geometry consists of.
+	*/
+	PolygonContainer mPolys;
+};
+
+
+/** Data structure used for optimized ray casting.
+*/
+struct BspRayTraversalData 
+{
+    BspNode *mNode;
+    Vector3 mExitPoint;
+    float mMaxT;
+    
+    BspRayTraversalData() {}
+
+    BspRayTraversalData(BspNode *n, const Vector3 &extp, const float maxt):
+    mNode(n), mExitPoint(extp), mMaxT(maxt) 
+	{}
+
+	BspRayTraversalData(BspNode *n, const Vector3 &extp):
+	mNode(n), mExitPoint(extp)
+	{}
+};
+
+/** Data used for passing ray data down the tree.
+*/
+struct BoundedRay
+{
+	Ray *mRay;
+	float mMinT;
+	float mMaxT;
+		
+	BoundedRay(): mMinT(0), mMaxT(1e6), mRay(NULL)
+	{}
+	BoundedRay(Ray *r, float minT, float maxT):
+	mRay(r), mMinT(minT), mMaxT(maxT)
+	{}
+};
+
+typedef vector<BoundedRay *> BoundedRayContainer;
+
+class BspTreeStatistics: public StatisticsBase
+{
+public:
+	// total number of nodes
+	int nodes;
+	// number of splits
+	int splits[3];
+	
+	// totals number of rays
+	int rays;
+	// maximal reached depth
+	int maxDepth;
+	// minimal depth
+	int minDepth;
+	
+	// max depth nodes
+	int maxDepthNodes;
+	// minimum depth nodes
+	int minDepthNodes;
+	// max depth nodes
+	int minPvsNodes;
+	// nodes with minimum PVS
+	int minRaysNodes;
+	// max ray contribution nodes
+	int maxRayContribNodes;
+	// minimum area nodes
+	int minProbabilityNodes;
+	/// nodes termination because of max cost ratio;
+	int maxCostNodes;
+	// max number of rays per node
+	int maxObjectRefs;
+	// accumulated depth (used to compute average)
+	int accumDepth;
+	// number of initial polygons
+	int polys;
+	/// samples contributing to pvs
+	int contributingSamples;
+	/// sample contributions to pvs
+	int sampleContributions;
+	/// largest pvs
+	int maxPvs;
+	/// number of invalid leaves
+	int invalidLeaves;
+	/// polygon splits 
+	int polySplits;
+	/// accumulated number of rays refs
+	int accumRays;
+
+	// Constructor
+	BspTreeStatistics() 
+	{
+		Reset();
+	}
+
+	int Nodes() const {return nodes;}
+	int Interior() const { return nodes / 2; }
+	int Leaves() const { return (nodes / 2) + 1; }
+	
+	// TODO: computation wrong
+	double AvgDepth() const { return accumDepth / (double)Leaves();}; 
+	double AvgRays() const { return accumRays / (double)Leaves();}; 
+
+	void Reset() 
+	{
+		nodes = 0;
+		for (int i = 0; i < 3; ++ i)
+			splits[i] = 0;
+		
+		maxDepth = 0;
+		minDepth = 99999;
+		polys = 0;
+		accumDepth = 0;
+        
+		maxDepthNodes = 0;
+		minPvsNodes = 0;
+		minRaysNodes = 0;
+		maxRayContribNodes = 0;
+		minProbabilityNodes = 0;
+		maxCostNodes = 0;
+
+		contributingSamples = 0;
+		sampleContributions = 0;
+
+		maxPvs = 0;
+		invalidLeaves = 0;
+		polySplits = 0;
+		accumRays = 0;
+	}
+
+	void Print(ostream &app) const;
+
+	friend ostream &operator<<(ostream &s, const BspTreeStatistics &stat) 
+	{
+		stat.Print(s);
+		return s;
+	} 
+};
+
+
+/**
+    BspNode abstract class serving for interior and leaf node implementation
+*/
+class BspNode 
+{
+	friend class BspTree;
+
+public:
+	BspNode();
+	virtual ~BspNode(){};
+	BspNode(BspInterior *parent);
+
+	/** Determines whether this node is a leaf or not
+	@return true if leaf
+	*/
+	virtual bool IsLeaf() const = 0;
+
+	/** Determines whether this node is a root
+	@return true if root
+	*/
+	virtual bool IsRoot() const;
+
+	/** Returns parent node.
+	*/
+	BspInterior *GetParent();
+
+	/** Sets parent node.
+	*/
+	void SetParent(BspInterior *parent);
+
+	/** Returns true if this node is a sibling of node n.
+	*/
+	bool IsSibling(BspNode *n) const;
+
+	/** returns depth of the node.
+	*/
+	int GetDepth() const;
+
+	/** returns true if the whole subtree is valid
+	*/
+	bool TreeValid() const;
+
+	void SetTreeValid(const bool v);
+
+	//-- mailing options
+
+	void Mail() { mMailbox = sMailId; }
+	static void NewMail() { ++ sMailId; }
+	bool Mailed() const { return mMailbox == sMailId; }
+
+	static int sMailId;
+	int mMailbox;
+
+	int mTimeStamp;
+
+protected:
+
+	/// if this sub tree is a completely valid view space region
+	bool mTreeValid;
+	/// parent of this node
+	BspInterior *mParent;
+};
+
+/** BSP interior node implementation 
+*/
+class BspInterior : public BspNode 
+{
+	friend class BspTree;
+public:
+	/** Standard contructor taking split plane as argument.
+	*/
+	BspInterior(const Plane3 &plane);
+	~BspInterior();
+	/** @return false since it is an interior node 
+	*/
+	bool IsLeaf() const;
+
+	BspNode *GetBack();
+	BspNode *GetFront();
+
+	/** Returns split plane.
+	*/
+	Plane3 GetPlane() const;
+
+	/** Replace front or back child with new child.
+	*/
+	void ReplaceChildLink(BspNode *oldChild, BspNode *newChild);
+	/** Replace front and back child.
+	*/
+	void SetupChildLinks(BspNode *b, BspNode *f);
+
+	friend ostream &operator<<(ostream &s, const BspInterior &A)
+	{
+		return s << A.mPlane;
+	}
+
+protected:
+
+	/// Splitting plane corresponding to this node
+	Plane3 mPlane;
+
+	/// back node
+	BspNode *mBack;
+	/// front node
+	BspNode *mFront;
+};
+
+/** BSP leaf node implementation.
+*/
+class BspLeaf: public BspNode 
+{
+	friend class BspTree;
+
+public:
+	BspLeaf();
+	BspLeaf(ViewCell *viewCell);
+	BspLeaf(BspInterior *parent);
+	BspLeaf(BspInterior *parent, ViewCell *viewCell);
+
+	~BspLeaf();
+
+	/** @return true since it is an interior node 
+	*/
+	bool IsLeaf() const;
+	
+	/** Returns pointer of view cell.
+	*/
+	ViewCell *GetViewCell() const;
+
+	/** Sets pointer to view cell.
+	*/
+	void SetViewCell(ViewCell *viewCell);
+
+	/// Rays piercing this leaf.
+	VssRayContainer mVssRays;
+	
+	/// leaf pvs
+	ObjectPvs *mPvs;
+
+	/// Probability that the view point lies in this leaf
+	float mProbability;
+
+protected:
+	
+	/// if NULL this does not correspond to feasible viewcell
+	ViewCell *mViewCell;
+};
+
+/** Implementation of the view cell BSP tree. 
+*/
+class BspTree 
+{
+	friend class ViewCellsParseHandlers;
+
+public:
+	
+	/** Additional data which is passed down the BSP tree during traversal.
+	*/
+	struct BspTraversalData
+	{  
+		/// the current node
+		BspNode *mNode;
+		/// polygonal data for splitting
+		PolygonContainer *mPolygons;
+		/// current depth
+		int mDepth;
+		/// the view cell associated with this subdivsion
+		ViewCell *mViewCell;
+		/// rays piercing this node
+		BoundedRayContainer *mRays;
+		/// probability of current node
+		float mProbability;
+		/// geometry of node as induced by planes
+		BspNodeGeometry *mGeometry;
+		
+		/// pvs size
+		int mPvs;
+		
+		/** Returns average ray contribution.
+		*/
+		float GetAvgRayContribution() const
+		{
+			return (float)mPvs / ((float)mRays->size() + Limits::Small);
+		}
+
+
+		BspTraversalData():
+		mNode(NULL),
+		mPolygons(NULL),
+		mDepth(0),
+		mViewCell(NULL),
+		mRays(NULL),
+		mPvs(0),
+		mProbability(0.0),
+		mGeometry(NULL)
+		{}
+		
+		BspTraversalData(BspNode *node, 
+						 PolygonContainer *polys, 
+						 const int depth, 
+						 ViewCell *viewCell,
+						 BoundedRayContainer *rays,
+						 int pvs,
+						 float p,
+						 BspNodeGeometry *cell): 
+		mNode(node), 
+		mPolygons(polys), 
+		mDepth(depth), 
+		mViewCell(viewCell),
+		mRays(rays),
+		mPvs(pvs),
+		mProbability(p),
+		mGeometry(cell)
+		{}
+
+
+		float GetCost() const
+		{
+#if 0
+			return mPvs * mProbability;
+#endif
+#if 1
+			return (float) (-mDepth); // for regular grid
+#endif
+#if 0
+			return mProbability;
+#endif
+#if 0
+			return (float)mPvs;
+#endif
+#if 0
+			return (float)mRays->size();
+#endif
+		}
+		
+		friend bool operator<(const BspTraversalData &a, const BspTraversalData &b)
+		{
+			return a.GetCost() < b.GetCost();
+		}
+    };
+	
+	//typedef std::stack<BspTraversalData> BspTraversalStack;
+	typedef std::priority_queue<BspTraversalData> BspTraversalStack;
+
+	/** Default constructor reading the environment file and 
+		creating an empty tree.
+	*/ 
+	BspTree();
+	/** Destroys tree and nodes.
+	*/
+	~BspTree();
+
+	/** Returns detailed statistics of the BSP tree.
+	*/
+	const BspTreeStatistics &GetStatistics() const; 
+  
+	/** Constructs tree using the given list of view cells.
+	    For this type of construction we filter all view cells down the 
+		tree. If there is no polygon left, the last split plane
+ 	    decides inside or outside of the viewcell. A pointer to the 
+		appropriate view cell is stored within each leaf. 
+		Many leafs can point to the same viewcell.
+	*/
+	void Construct(const ViewCellContainer &viewCells);
+
+	/** Constructs tree using the given list of objects. 
+	    @note the objects are not taken as view cells, but the view cells are
+		constructed from the subdivision: Each leaf is taken as one viewcell.
+		@param objects list of objects
+	*/
+	void Construct(const ObjectContainer &objects);
+
+	void Construct(const ObjectContainer &objects,
+				   const RayContainer &sampleRays,
+				   AxisAlignedBox3 *forcedBoundingBox);
+
+	/** Constructs the tree from a given set of rays.
+		@param sampleRays the set of sample rays the construction is based on
+		@param viewCells if not NULL, new view cells are 
+		created in the leafs and stored in the conatainer
+	*/
+	void Construct(const RayContainer &sampleRays,
+				   AxisAlignedBox3 *forcedBoundingBox);
+
+	/** Returns list of BSP leaves.
+	*/
+	void CollectLeaves(vector<BspLeaf *> &leaves) const;
+
+	/** Returns box which bounds the whole tree.
+	*/
+	AxisAlignedBox3 GetBoundingBox()const;
+
+	/** Returns root of BSP tree.
+	*/
+	BspNode *GetRoot() const;
+
+	
+	//bool Export(const string filename);
+
+	/** Collects the leaf view cells of the tree
+		@param viewCells returns the view cells 
+	*/
+	void CollectViewCells(ViewCellContainer &viewCells) const;
+
+	/** A ray is cast possible intersecting the tree.
+		@param the ray that is cast.
+		@returns the number of intersections with objects stored in the tree.
+	*/
+	int	_CastRay(Ray &ray);
+
+
+	int	CastLineSegment(const Vector3 &origin,
+						const Vector3 &termination,
+						ViewCellContainer &viewcells
+						);
+
+	ViewCell *GetViewCell(const Vector3 &point);
+  
+	/// bsp tree construction types
+	enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_SAMPLES};
+
+	/** Returns statistics.
+	*/
+	BspTreeStatistics &GetStat();
+
+	/** finds neighbouring leaves of this tree node.
+	*/
+	int FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors, 
+					  const bool onlyUnmailed) const;
+
+	/** Constructs geometry of view cell returning a BSP node geometry type.
+	*/
+	void ConstructGeometry(BspNode *n, BspNodeGeometry &cell) const;
+	
+	/** Construct geometry of view cell.
+	*/
+	void ConstructGeometry(ViewCell *vc, BspNodeGeometry &geom) const;
+
+			
+	/** Sets pointer to view cells manager.
+	*/
+	void SetViewCellsManager(ViewCellsManager *vcm);
+
+	/** Returns random leaf of BSP tree.
+		@param halfspace defines the halfspace from which the leaf is taken.
+	*/
+	BspLeaf *GetRandomLeaf(const Plane3 &halfspace);
+
+	/** Returns random leaf of BSP tree.
+		@param onlyUnmailed if only unmailed leaves should be returned.
+	*/
+	BspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
+
+
+	/** Returns epsilon of this tree.
+	*/
+	float GetEpsilon() const;
+
+	int CollectMergeCandidates(const vector<BspLeaf *> leaves,
+							   vector<MergeCandidate> &candidates);
+
+	int CollectMergeCandidates(const VssRayContainer &rays,
+					           vector<MergeCandidate> &candidates);
+
+	/** Exports Bsp tree to file.
+	*/
+	bool Export(ofstream &stream);
+
+
+	/** Returns view cell corresponding to 
+		the invalid view space. If it does not exist, it is created.
+	*/
+	BspViewCell *GetOutOfBoundsCell();
+
+	ViewCellsTree *mViewCellsTree;
+	
+protected:
+
+	// --------------------------------------------------------------
+	// For sorting objects
+	// --------------------------------------------------------------
+	struct SortableEntry
+	{
+		enum {POLY_MIN, POLY_MAX};
+    
+		int type;
+		float value;
+		Polygon3 *poly;
+		SortableEntry() {}
+		SortableEntry(const int t, const float v, Polygon3 *poly): 
+		type(t), value(v), poly(poly) {}
+		
+		bool operator<(const SortableEntry &b) const 
+		{
+			return value < b.value;
+		}  
+	};
+
+	void ExportNode(BspNode *node, ofstream &stream);
+
+	/** Evaluates tree stats in the BSP tree leafs.
+	*/
+	void EvaluateLeafStats(const BspTraversalData &data);
+
+	/** Subdivides node with respect to the traversal data.
+	    @param tStack current traversal stack
+		@param tData traversal data also holding node to be subdivided
+		@returns new root of the subtree
+	*/
+	BspNode *Subdivide(BspTraversalStack &tStack, BspTraversalData &tData);
+
+	/** Constructs the tree from the given list of polygons and rays.
+		@param polys stores set of polygons on which subdivision may be based
+		@param rays storesset of rays on which subdivision may be based
+	*/
+	void Construct(PolygonContainer *polys, BoundedRayContainer *rays);
+
+	/** Selects the best possible splitting plane. 
+		@param leaf the leaf to be split
+		@param polys the polygon list on which the split decition is based
+		@param rays ray container on which selection may be based
+		@note the polygons can be reordered in the process
+		@returns the split plane
+	*/
+	Plane3 SelectPlane(BspLeaf *leaf, 
+					   BspTraversalData &data);
+
+	/** Evaluates the contribution of the candidate split plane.
+		
+		@param candidatePlane the candidate split plane
+		@param polys the polygons the split can be based on
+		@param rays the rays the split can be based on
+
+		@returns the cost of the candidate split plane
+	*/
+	float SplitPlaneCost(const Plane3 &candidatePlane,
+						 BspTraversalData &data) const;
+
+	/** Strategies where the effect of the split plane is tested
+	    on all input rays.
+		@returns the cost of the candidate split plane
+	*/
+	float SplitPlaneCost(const Plane3 &candidatePlane,
+						 const PolygonContainer &polys) const;
+
+	/** Strategies where the effect of the split plane is tested
+	    on all input rays.
+
+		@returns the cost of the candidate split plane
+	*/
+	float SplitPlaneCost(const Plane3 &candidatePlane, 
+						 const BoundedRayContainer &rays,
+						 const int pvs,
+						 const float probability,
+						 const BspNodeGeometry &cell) const;
+
+	/** Filters next view cell down the tree and inserts it into the appropriate leaves
+		(i.e., possibly more than one leaf).
+	*/
+	void InsertViewCell(ViewCell *viewCell);
+	/** Inserts polygons down the tree. The polygons are filtered until a leaf is reached,
+		then further subdivided.
+	*/
+	void InsertPolygons(PolygonContainer *polys);
+
+	/** Subdivide leaf.
+		@param leaf the leaf to be subdivided
+		
+		@param polys the polygons to be split
+		@param frontPolys returns the polygons in front of the split plane
+		@param backPolys returns the polygons in the back of the split plane
+		
+		@param rays the polygons to be filtered
+		@param frontRays returns the polygons in front of the split plane
+		@param backRays returns the polygons in the back of the split plane
+
+		@returns the root of the subdivision
+	*/
+
+	BspInterior *SubdivideNode(BspTraversalData &tData,
+							   BspTraversalData &frontData,
+							   BspTraversalData &backData,
+							   PolygonContainer &coincident);
+
+	/** Filters polygons down the tree.
+		@param node the current BSP node
+		@param polys the polygons to be filtered
+		@param frontPolys returns the polygons in front of the split plane
+		@param backPolys returns the polygons in the back of the split plane
+	*/
+	void FilterPolygons(BspInterior *node, 
+						PolygonContainer *polys, 
+						PolygonContainer *frontPolys, 
+						PolygonContainer *backPolys);
+
+	/** Take 3 ray endpoints, where two are minimum and one a maximum
+		point or the other way round.
+	*/
+	Plane3 ChooseCandidatePlane(const BoundedRayContainer &rays) const;
+
+	/** Take plane normal as plane normal and the midpoint of the ray.
+		PROBLEM: does not resemble any point where visibility is likely to change
+	*/
+	Plane3 ChooseCandidatePlane2(const BoundedRayContainer &rays) const;
+
+	/** Fit the plane between the two lines so that the plane has equal shortest 
+		distance to both lines.
+	*/
+	Plane3 ChooseCandidatePlane3(const BoundedRayContainer &rays) const;
+
+	/** Selects the split plane in order to construct a tree with
+		certain characteristics (e.g., balanced tree, least splits, 
+		2.5d aligned)
+		@param polygons container of polygons
+		@param rays bundle of rays on which the split can be based
+	*/
+	Plane3 SelectPlaneHeuristics(BspLeaf *leaf,
+								 BspTraversalData &data);
+
+	/** Extracts the meshes of the objects and adds them to polygons. 
+		Adds object aabb to the aabb of the tree.
+		@param maxPolys the maximal number of objects to be stored as polygons
+		@returns the number of polygons
+	*/
+	int AddToPolygonSoup(const ObjectContainer &objects, 
+						 PolygonContainer &polys, 
+						 int maxObjects = 0,
+						 bool addToBbox = true);
+
+	/** Extracts the meshes of the view cells and and adds them to polygons.
+		Adds view cell aabb to the aabb of the tree.
+		@param maxPolys the maximal number of objects to be stored as polygons
+		@returns the number of polygons
+	*/
+	int AddToPolygonSoup(const ViewCellContainer &viewCells, 
+						 PolygonContainer &polys, 
+						 int maxObjects = 0);
+
+	/** Extract polygons of this mesh and add to polygon container.
+		@param mesh the mesh that drives the polygon construction
+		@param parent the parent intersectable this polygon is constructed from
+		@returns number of polygons
+	*/
+	int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
+
+	/** Helper function which extracts a view cell on the front and the back
+		of the split plane.
+		@param backViewCell returns view cell on the back of the split plane
+		@param frontViewCell returns a view cell on the front of the split plane
+		@param coincident container of polygons coincident to the split plane
+		@param splitPlane the split plane which decides about back and front
+		@param extractBack if a back view cell is extracted
+		@param extractFront if a front view cell is extracted
+	*/
+	void ExtractViewCells(BspTraversalData &frontData,
+						  BspTraversalData &backData, 
+						  const PolygonContainer &coincident,
+						  const Plane3 &splitPlane) const;
+	
+	/** Computes best cost ratio for the suface area heuristics for axis aligned
+		splits. This heuristics minimizes the cost for ray traversal.
+		@param polys the polygons guiding the ratio computation
+		@param box the bounding box of the leaf
+		@param axis the current split axis
+		@param position returns the split position
+		@param objectsBack the number of objects in the back of the split plane
+		@param objectsFront the number of objects in the front of the split plane
+	*/
+	float BestCostRatio(const PolygonContainer &polys,
+						const AxisAlignedBox3 &box,
+						const int axis,
+						float &position,
+						int &objectsBack,
+						int &objectsFront) const;
+	
+	/** Sorts split candidates for surface area heuristics for axis aligned splits.
+		@param polys the input for choosing split candidates
+		@param axis the current split axis
+		@param splitCandidates returns sorted list of split candidates
+	*/
+	void SortSplitCandidates(const PolygonContainer &polys, 
+							 const int axis, 
+							 vector<SortableEntry> &splitCandidates) const;
+
+	/** Selects an axis aligned split plane.
+		Returns true if split is valied
+	*/
+	bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;
+
+	/** Subdivides the rays into front and back rays according to the split plane.
+		
+		@param plane the split plane
+		@param rays contains the rays to be split. The rays are 
+			   distributed into front and back rays.
+		@param frontRays returns rays on the front side of the plane
+		@param backRays returns rays on the back side of the plane
+		
+		@returns the number of splits
+	*/
+	int SplitRays(const Plane3 &plane,
+				  BoundedRayContainer &rays, 
+			      BoundedRayContainer &frontRays, 
+				  BoundedRayContainer &backRays);
+
+
+	/** Extracts the split planes representing the space bounded by node n.
+	*/
+	void ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const;
+
+	/** Adds the object to the pvs of the front and back leaf with a given classification.
+
+		@param obj the object to be added
+		@param cf the ray classification regarding the split plane
+		@param frontPvs returns the PVS of the front partition
+		@param backPvs returns the PVS of the back partition
+	
+	*/
+	void AddObjToPvs(Intersectable *obj, const int cf, int &frontPvs, int &backPvs) const;
+
+	/** Computes PVS size induced by the rays.
+	*/
+	int ComputePvsSize(const BoundedRayContainer &rays) const;
+
+	/** Returns true if tree can be terminated.
+	*/
+	inline bool TerminationCriteriaMet(const BspTraversalData &data) const;
+
+	/** Computes accumulated ray lenght of this rays.
+	*/
+	float AccumulatedRayLength(BoundedRayContainer &rays) const;
+
+	/** Splits polygons with respect to the split plane.
+		@param polys the polygons to be split. the polygons are consumed and
+			   distributed to the containers frontPolys, backPolys, coincident.
+		@param frontPolys returns the polygons in the front of the split plane
+		@param backPolys returns the polygons in the back of the split plane
+		@param coincident returns the polygons coincident to the split plane
+
+		@returns the number of splits	
+	*/
+	int SplitPolygons(const Plane3 &plane,
+					  PolygonContainer &polys, 
+					  PolygonContainer &frontPolys, 
+					  PolygonContainer &backPolys, 
+					  PolygonContainer &coincident) const;
+
+	/** Adds ray sample contributions to the PVS.
+		@param sampleContributions the number contributions of the samples
+		@param contributingSampels the number of contributing rays
+		
+	*/
+	void AddToPvs(BspLeaf *leaf,
+				  const BoundedRayContainer &rays, 
+				  int &sampleContributions,	
+				  int &contributingSamples);
+
+
+	/** Returns view cell corresponding to 
+		the invalid view space. If it does not exist, it is created.
+	*/
+	BspViewCell *GetOrCreateOutOfBoundsCell();
+
+	/// Pointer to the root of the tree.
+	BspNode *mRoot;
+
+	/// Stores statistics during traversal.
+	BspTreeStatistics mStat;
+
+	/// Strategies for choosing next split plane.
+	enum {NO_STRATEGY = 0,
+		  RANDOM_POLYGON = 1, 
+		  AXIS_ALIGNED = 2,
+		  LEAST_SPLITS = 4, 
+		  BALANCED_POLYS = 8,
+		  BALANCED_VIEW_CELLS = 16,
+		  LARGEST_POLY_AREA = 32,
+		  VERTICAL_AXIS = 64,
+		  BLOCKED_RAYS = 128,
+		  LEAST_RAY_SPLITS = 256,
+		  BALANCED_RAYS = 512,
+		  PVS = 1024
+		};
+
+	/// box around the whole view domain
+	AxisAlignedBox3 mBox;
+
+	/// view cell corresponding to unbounded space
+	BspViewCell *mOutOfBoundsCell;
+
+	/// if view cells should be generated or the given view cells should be used.
+	bool mGenerateViewCells;
+
+	/// maximal number of polygons before subdivision termination
+	int mTermMinPolys;
+	/// maximal number of rays before subdivision termination
+	int mTermMinRays;
+	/// maximal possible depth
+	int mTermMaxDepth;
+	/// mininum area
+	float mTermMinProbability;
+	/// mininum PVS
+	int mTermMinPvs;
+
+	/// minimal number of polygons for axis aligned split
+	int mTermMinPolysForAxisAligned;
+	/// minimal number of rays for axis aligned split
+	int mTermMinRaysForAxisAligned;
+	/// minimal number of objects for axis aligned split
+	int mTermMinObjectsForAxisAligned;
+	/// maximal contribution per ray
+	float mTermMaxRayContribution;
+	/// minimal accumulated ray length
+	float mTermMinAccRayLength;
+
+
+	/// strategy to get the best split plane
+	int mSplitPlaneStrategy;
+	/// number of candidates evaluated for the next split plane
+	int mMaxPolyCandidates;
+	/// number of candidates for split planes evaluated using the rays
+	int mMaxRayCandidates;
+	/// maximum tests for split plane evaluation with a single candidate
+	int mMaxTests;
+
+	float mCtDivCi;
+
+	/// axis aligned split criteria
+	float mAxisAlignedCtDivCi;
+	float mSplitBorder;
+	float mMaxCostRatio;
+
+	// factors guiding the split plane heuristics
+	float mVerticalSplitsFactor;
+	float mLargestPolyAreaFactor;
+	float mBlockedRaysFactor;
+	float mLeastRaySplitsFactor;
+	float mBalancedRaysFactor;
+	float mPvsFactor;
+	float mLeastSplitsFactor;
+	float mBalancedPolysFactor;
+	float mBalancedViewCellsFactor;
+
+	/// if area or accumulated ray lenght should be used for PVS heuristics
+	bool mUseAreaForPvs;
+
+	int mMaxViewCells;
+
+	/// epsilon where two points are still considered equal
+	float mEpsilon;
+
+	ViewCellsManager *mViewCellsManager;
+
+	int mTimeStamp;
+
+	float mTotalCost;
+	int mTotalPvsSize;
+
+	//int mSplits;
+	ofstream  mSubdivisionStats;
+
+private:
+	
+	/** Evaluates split plane classification with respect to the plane's 
+		contribution for a balanced tree.
+	*/
+	static const float sLeastPolySplitsTable[4];
+	/** Evaluates split plane classification with respect to the plane's 
+		contribution for a minimum number splits in the tree.
+	*/
+	static const float sBalancedPolysTable[4];
+	/** Evaluates split plane classification with respect to the plane's 
+		contribution for a minimum number of ray splits.
+	*/
+	static const float sLeastRaySplitsTable[5];
+	/** Evaluates split plane classification with respect to the plane's 
+		contribution for balanced rays.
+	*/
+	static const float sBalancedRaysTable[5];
+
+	/// Generates unique ids for PVS criterium
+	static void GenerateUniqueIdsForPvs();
+
+	//-- unique ids for PVS criterium
+	static int sFrontId; 
+	static int sBackId;
+	static int sFrontAndBackId;
+};
+
+struct BspIntersection 
+{
+	// the point of intersection
+	float mT;
+  
+	BspLeaf *mLeaf;
+  
+	BspIntersection(const float t, BspLeaf *l):
+	mT(t), mLeaf(l) {}
+  
+	BspIntersection() {}
+  
+	bool operator<(const BspIntersection &b) const 
+	{
+		return mT < b.mT; 
+	}
+};
+
+struct BspRay 
+{
+	VssRay *vssRay;
+
+	std::vector<BspIntersection> intersections;
+
+	BspRay(VssRay *ray): vssRay(ray) {}
+};
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.h	(revision 542)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.h	(revision 542)
@@ -0,0 +1,523 @@
+#ifndef _AxisAlignedBox3_H__
+#define _AxisAlignedBox3_H__
+
+#include "Rectangle3.h"
+#include "Matrix4x4.h"
+#include "Vector3.h"
+#include "Plane3.h"
+#include "Containers.h"
+
+class Ray;
+class Polygon3;
+class Mesh;
+
+// --------------------------------------------------------
+// CAABox class.
+//  This is a box in 3-space, defined by min and max
+//  corner vectors.  Many useful operations are defined
+//  on this
+// --------------------------------------------------------
+class AxisAlignedBox3
+{
+protected:
+  Vector3 mMin, mMax;
+public:
+  // Constructors.
+  AxisAlignedBox3() { }
+  AxisAlignedBox3(const Vector3 &nMin, const Vector3 &nMax)
+  {
+    mMin = nMin; mMax = nMax;
+  }
+
+  //  AxisAlignedBox3(const Vector3 &center, const float radius):min(center - Vector3(radius)),
+  //						      max(center + Vector3(radius)) {}
+
+  // initialization to the non existing bounding box
+  void Initialize() {
+    mMin = Vector3(MAXFLOAT);
+    mMax = Vector3(-MAXFLOAT);
+  }
+
+  // The center of the box
+  Vector3 Center() const { return 0.5 * (mMin + mMax); }
+  
+  // The diagonal of the box
+  Vector3 Diagonal() const { return (mMax -mMin); }
+
+  float Center(const int axis) const {
+    return  0.5f * (mMin[axis] + mMax[axis]);
+  }
+
+  float Min(const int axis) const {
+    return mMin[axis];
+  }
+
+  float Max(const int axis) const {
+    return  mMax[axis];
+  }
+
+  float Size(const int axis) const {
+    return  Max(axis) - Min(axis);
+  }
+
+  // Read-only const access tomMin and max vectors using references
+  const Vector3& Min() const { return mMin;}
+  const Vector3& Max() const { return mMax;}
+
+  void Enlarge (const Vector3 &v) {
+    mMax += v;
+    mMin -= v;
+  }
+
+
+  void SetMin(const Vector3 &v) {
+    mMin = v;
+  }
+
+  void SetMax(const Vector3 &v) {
+    mMax = v;
+  }
+
+  void SetMin(int axis, const float value) {
+   mMin[axis] = value;
+  }
+
+  void SetMax(int axis, const float value) {
+    mMax[axis] = value;
+  }
+
+  // Decrease box by given splitting plane
+  void Reduce(int axis, int right, float value) {
+    if ( (value >=mMin[axis]) && (value <= mMax[axis]) )
+      if (right)
+				mMin[axis] = value;
+      else
+        mMax[axis] = value;
+  }
+	
+  // the size of the box along all the axes
+  Vector3 Size() const { return mMax - mMin; }
+
+  // Return whether the box is unbounded.  Unbounded boxes appear
+  // when unbounded objects such as quadric surfaces are included.
+  bool Unbounded() const;
+
+  // Expand the axis-aligned box to include the given object.
+  void Include(const Vector3 &newpt);
+  void Include(const Polygon3 &newpoly);
+  void Include(const AxisAlignedBox3 &bbox);
+  void Include(Mesh *mesh);
+  // Expand the axis-aligned box to include given values in particular axis
+  void Include(const int &axis, const float &newBound);
+
+  
+  int
+  Side(const Plane3 &plane) const;
+
+  // Overlap returns 1 if the two axis-aligned boxes overlap .. even weakly
+  friend inline bool Overlap(const AxisAlignedBox3 &, const AxisAlignedBox3 &);
+
+  // Overlap returns 1 if the two axis-aligned boxes overlap .. only strongly
+  friend inline bool OverlapS(const AxisAlignedBox3 &,const AxisAlignedBox3 &);
+
+  // Overlap returns 1 if the two axis-aligned boxes overlap for a given
+  // epsilon. If eps > 0.0, then the boxes has to have the real intersection
+  // box, if eps < 0.0, then the boxes need not intersect really, they
+  // can be at eps distance in the projection
+  friend inline bool Overlap(const AxisAlignedBox3 &,
+			     const AxisAlignedBox3 &,
+			     float eps);
+
+  // Includes returns true if a includes b (completely
+  bool Includes(const AxisAlignedBox3 &b) const;
+
+  virtual int IsInside(const Vector3 &v) const;
+  
+  // Test if the box is really sensefull
+  virtual bool IsCorrect();
+
+  // To answer true requires the box of real volume of non-zero value
+  bool IsSingularOrIncorrect() const;
+
+  // When the box is not of non-zero or negative surface area
+  bool IsCorrectAndNotPoint() const;
+
+  // Returns true when the box degenerates to a point
+  bool IsPoint() const;
+
+  void Scale(const float scale) {
+	Vector3 newSize = Size()*(scale*0.5f);
+	Vector3 center = Center();
+	mMin = center - newSize;
+	mMax = center + newSize;
+  }
+  
+  void
+  GetSqrDistances(const Vector3 &point,
+		  float &minDistance,
+		  float &maxDistance
+		  ) const;
+
+  // returns true, when the sphere specified by the origin and radius
+  // fully contains the box
+  bool IsFullyContainedInSphere(const Vector3 &center, float radius) const;
+
+  // returns true, when the volume of the sphere and volume of the
+  // axis aligned box has no intersection
+  bool HasNoIntersectionWithSphere(const Vector3 &center,
+				   float radius) const;
+
+
+  // Given a sphere described by the center and radius,
+  // the fullowing function returns:
+  //   -1 ... the sphere and the box are completely separate
+  //    0 ... the sphere and the box only partially overlap
+  //    1 ... the sphere contains fully the box
+  //  Note: the case when box fully contains the sphere is not reported
+  //        since it was not required.
+  int MutualPositionWithSphere(const Vector3 &center, float radius) const;
+
+  // Given a cube described by the center and half-size (radius),
+  // the following function returns:
+  //   -1 ... the cube and the box are completely separate
+  //    0 ... the cube and the box only partially overlap
+  //    1 ... the cube contains fully the box
+  int MutualPositionWithCube(const Vector3 &center, float halfSize) const;
+
+
+  Vector3 GetRandomPoint() const {
+    Vector3 size = Size();
+    return mMin + Vector3(RandomValue(0.0f, size.x),
+						  RandomValue(0.0f, size.y),
+						  RandomValue(0.0f, size.z)); 
+  }
+
+
+  Vector3 GetPoint(const Vector3 &p) const {
+    return mMin + p*Size(); 
+  }
+
+  // Returns the smallest axis-aligned box that includes all points
+  // inside the two given boxes.
+  friend inline AxisAlignedBox3 Union(const AxisAlignedBox3 &x,
+			     const AxisAlignedBox3 &y);
+
+  // Returns the intersection of two axis-aligned boxes.
+  friend inline AxisAlignedBox3 Intersect(const AxisAlignedBox3 &x,
+				 const AxisAlignedBox3 &y);
+
+  // Given 4x4 matrix, transform the current box to new one.
+  friend inline AxisAlignedBox3 Transform(const AxisAlignedBox3 &box,
+					  const Matrix4x4 &tform);
+
+  
+  // returns true when two boxes are completely equal
+  friend inline int operator== (const AxisAlignedBox3 &A, const AxisAlignedBox3 &B);
+  
+  virtual float SurfaceArea() const;
+  virtual float GetVolume() const {
+    return (mMax.x - mMin.x) * (mMax.y - mMin.y) * (mMax.z - mMin.z);
+  }
+
+  // Six faces are distuinguished by their name.
+  enum EFaces { ID_Back = 0, ID_Left = 1, ID_Bottom = 2, ID_Front = 3,
+		ID_Right = 4, ID_Top = 5};
+  
+  int
+  ComputeMinMaxT(const Vector3 &origin,
+				 const Vector3 &direction,
+				 float *tmin,
+				 float *tmax) const;
+	
+  // Compute tmin and tmax for a ray, whenever required .. need not pierce box
+  int ComputeMinMaxT(const Ray &ray, float *tmin, float *tmax) const;
+
+  // Compute tmin and tmax for a ray, whenever required .. need not pierce box
+  int ComputeMinMaxT(const Ray &ray,
+					 float *tmin,
+					 float *tmax,
+					 EFaces &entryFace,
+					 EFaces &exitFace) const;
+  
+  // If a ray pierces the box .. returns 1, otherwise 0.
+  // Computes the signed distances for case: tmin < tmax and tmax > 0
+  int GetMinMaxT(const Ray &ray, float *tmin, float *tmax) const;
+  // computes the signed distances for case: tmin < tmax and tmax > 0
+  int GetMinMaxT(const Ray &ray, float *tmin, float *tmax,
+		 EFaces &entryFace, EFaces &exitFace) const;
+  
+  // Writes a brief description of the object, indenting by the given
+  // number of spaces first.
+  virtual void Describe(ostream& app, int ind) const;
+
+  // For edge .. number <0..11> returns two incident vertices
+  void GetEdge(const int edge, Vector3 *a, Vector3 *b) const;
+
+  // Compute the coordinates of one vertex of the box for 0/1 in each axis
+  // 0 .. smaller coordinates, 1 .. large coordinates
+  Vector3 GetVertex(int xAxis, int yAxis, int zAxis) const;
+
+  // Compute the vertex for number N=<0..7>, N = 4*x + 2*y + z, where
+  // x,y,z are either 0 or 1; (0 .. lower coordinate, 1 .. large coordinate)
+  // (xmin,ymin, zmin) .. N = 0, (xmax, ymax, zmax) .. N= 7
+  void GetVertex(const int N, Vector3 &vertex) const;
+
+  Vector3 GetVertex(const int N) const {
+    Vector3 v;
+    GetVertex(N, v);
+    return v;
+  }
+
+  // Returns 1, if the box includes on arbitrary face a given box
+  int IsPiercedByBox(const AxisAlignedBox3 &box, int &axis) const;
+
+
+  int GetFaceVisibilityMask(const Vector3 &position) const;
+  int GetFaceVisibilityMask(const Rectangle3 &rectangle) const;
+
+  Rectangle3 GetFace(const int face) const;
+  
+  // For a given point returns the region, where the point is located
+  // there are 27 regions (0..26) .. determined by the planes embedding in the
+  // sides of the bounding box (0 .. lower the position of the box,
+  // 1 .. inside the box, 2 .. greater than box). The region number is given as
+  // R = 9*x + 3*y + z  ; e.g. region .. inside the box is 13.
+  int GetRegionID(const Vector3 &point) const;
+  
+  // Set the corner point of rectangle on the face of bounding box
+  // given by the index number and the rectangle lying on this face
+  //  void GetFaceRectCorner(const CRectLeaf2D *rect, EFaces faceIndx,
+  //			 const int &cornerIndx, Vector3 &cornerPoint);
+
+  // Project the box to a plane given a normal vector of this plane. Computes
+  // the surface area of projected silhouettes for parallel projection.
+  float ProjectToPlaneSA(const Vector3 &normal) const;
+
+  // Computes projected surface area of the box to a given viewing plane
+  // given a viewpoint. This corresponds the probability, the box will
+  // be hit by the ray .. moreover returns .. the region number (0-26).
+  // the function supposes all the points lie of the box lies in the viewing
+  // frustrum !!! The positive halfspace of viewplane has to contain
+  // viewpoint. "projectionType" == 0 .. perspective projection,
+  // == 1 .. parallel projection.
+  float ProjectToPlaneSA(const Plane3 &viewplane,
+			 const Vector3 &viewpoint,
+			 int *tcase,
+			 const float &maxSA,
+			 int projectionType) const;
+
+  // Computes projected surface area of the box to a given viewing plane
+  // and viewpoint. It clipps the area by all the planes given .. they should
+  // define the viewing frustrum. Variable tclip defines, which planes are
+  // used for clipping, parameter 31 is the most general, clip all the plane.
+  // 1 .. clip left, 2 .. clip top, 4 .. clip right, 8 .. clip bottom,
+  // 16 .. clip supporting plane(its normal towards the viewing frustrum).
+  // "typeProjection" == 0 .. perspective projection,
+  // == 1 .. parallel projection
+  float ProjectToPlaneSA(const Plane3 &viewplane,
+			 const Vector3 &viewpoint,
+			 int *tcase, int &tclip,
+			 const Plane3 &leftPlane,
+			 const Plane3 &topPlane,
+			 const Plane3 &rightPlane,
+			 const Plane3 &bottomPlane,
+			 const Plane3 &suppPlane,
+			 const float &maxSA,
+			 int typeProjection) const;
+
+  // Projects the box to a unit sphere enclosing a given viewpoint and
+  // returns the solid angle of the box projected to a unit sphere
+  float ProjectToSphereSA(const Vector3 &viewpoint, int *tcase) const;
+
+  /** Returns vertex indices of edge.
+  */
+  void GetEdge(const int edge, int  &aIdx, int &bIdx) const;
+
+  /** Computes cross section of plane with box (i.e., bounds box). 
+	  @returns the cross section
+  */
+  Polygon3 *CrossSection(const Plane3 &plane) const;
+
+  /** Computes minimal and maximal t of ray, including the object intersections.
+	  @returns true if ray hits the bounding box.
+  */
+  bool GetRaySegment(const Ray &ray, 
+				float &minT, 
+				float &maxT) const;
+
+  /** If the boxes are intersecting on a common face, this function 
+	  returns the face intersection, false otherwise.
+    
+	  @param neighbour the neighbouring box intersecting with this box.
+  */
+  bool GetIntersectionFace(Rectangle3 &face,
+						   const AxisAlignedBox3 &neighbour) const;
+
+  /** Adds the box faces to the mesh.
+  */
+  void AddBoxToMesh(Mesh *mesh) const;
+
+  void ExtractPolys(PolygonContainer &polys) const;
+
+#define __EXTENT_HACK
+  // get the extent of face
+  float GetExtent(const int &face) const {
+#if defined(__EXTENT_HACK) && defined(__VECTOR_HACK)
+    return mMin[face];
+#else
+    if (face < 3)
+      return mMin[face];
+    else
+      return mMax[face-3];
+#endif
+  }
+
+  // The vertices that form boundaries of the projected bounding box
+  // for all the regions possible, number of regions is 3^3 = 27,
+  // since two parallel sides of bbox forms three disjoint spaces
+  // the vertices are given in anti-clockwise order .. stopped by -1 elem.
+  static const int bvertices[27][9];
+
+  // The list of all faces visible from a given region (except region 13)
+  // the faces are identified by triple: (axis, min-vertex, max-vertex),
+  // that is maximaly three triples are defined. axis = 0 (x-axis),
+  // axis = 1 (y-axis), axis = 2 (z-axis), -1 .. terminator. Is is always
+  // true that: min-vertex < max-vertex for all coordinates excluding axis
+  static const int bfaces[27][10];
+  
+  // The correct corners indexed starting from entry face to exit face
+  // first index determines entry face, second index exit face, and
+  // the two numbers (indx, inc) determines: ind = the index on the exit
+  // face, when starting from the vertex 0 on entry face, 'inc' is
+  // the increment when we go on entry face in order 0,1,2,3 to create
+  // convex shaft with the rectangle on exit face. That is, inc = -1 or 1.
+  static const int pairFaceRects[6][6][2];
+
+  // The vertices that form CLOSEST points with respect to the region
+  // for all the regions possible, number of regions is 3^3 = 27,
+  // since two parallel sides of bbox forms three disjoint spaces.
+  // The vertices are given in anti-clockwise order, stopped by -1 elem,
+  // at most 8 points, at least 1 point.
+  static const int cvertices[27][9];
+  static const int csvertices[27][6];
+
+  // The vertices that form FARTHEST points with respect to the region
+  // for all the regions possible, number of regions is 3^3 = 27,
+  // since two parallel sides of bbox forms three disjoint spaces.
+  // The vertices are given in anti-clockwise order, stopped by -1 elem,
+  // at most 8 points, at least 1 point.
+  static const int fvertices[27][9];  
+  static const int fsvertices[27][9];
+
+  // input and output operator with stream
+  friend ostream& operator<<(ostream &s, const AxisAlignedBox3 &A);
+  friend istream& operator>>(istream &s, AxisAlignedBox3 &A);
+
+protected:
+  // definition of friend functions
+  friend class Ray;
+};
+
+// --------------------------------------------------------------------------
+// Implementation of inline (member) functions
+  
+inline bool
+Overlap(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
+{
+  if (x.mMax.x < y.mMin.x ||
+      x.mMin.x > y.mMax.x ||
+      x.mMax.y < y.mMin.y ||
+      x.mMin.y > y.mMax.y ||
+      x.mMax.z < y.mMin.z ||
+      x.mMin.z > y.mMax.z) {
+    return false;
+  }
+  return true;
+}
+
+inline bool
+OverlapS(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
+{
+  if (x.mMax.x <= y.mMin.x ||
+      x.mMin.x >= y.mMax.x ||
+      x.mMax.y <= y.mMin.y ||
+      x.mMin.y >= y.mMax.y ||
+      x.mMax.z <= y.mMin.z ||
+      x.mMin.z >= y.mMax.z) {
+    return false;
+  }
+  return true;
+}
+
+inline bool
+Overlap(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y, float eps)
+{
+  if ( (x.mMax.x - eps) < y.mMin.x ||
+       (x.mMin.x + eps) > y.mMax.x ||
+       (x.mMax.y - eps) < y.mMin.y ||
+       (x.mMin.y + eps) > y.mMax.y ||
+       (x.mMax.z - eps) < y.mMin.z ||
+       (x.mMin.z + eps) > y.mMax.z ) {
+    return false;
+  }
+  return true;
+}
+
+inline AxisAlignedBox3
+Intersect(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
+{
+  if (x.Unbounded())
+    return y;
+  else
+    if (y.Unbounded())
+      return x;
+  AxisAlignedBox3 ret = x;
+  if (Overlap(ret, y)) {
+    Maximize(ret.mMin, y.mMin);
+    Minimize(ret.mMax, y.mMax);
+    return ret;
+  }
+  else      // Null intersection.
+    return AxisAlignedBox3(Vector3(0), Vector3(0));
+  // return AxisAlignedBox3(Vector3(0), Vector3(-1));
+}
+
+inline AxisAlignedBox3
+Union(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
+{
+  Vector3 min = x.mMin;
+  Vector3 max = x.mMax;
+  Minimize(min, y.mMin);
+  Maximize(max, y.mMax);
+  return AxisAlignedBox3(min, max);
+}
+
+inline AxisAlignedBox3
+Transform(const AxisAlignedBox3 &box, const Matrix4x4 &tform)
+{
+  Vector3 mmin(MAXFLOAT);
+  Vector3 mmax(-MAXFLOAT);
+
+  AxisAlignedBox3 ret(mmin, mmax);
+  ret.Include(tform * Vector3(box.mMin.x, box.mMin.y, box.mMin.z));
+  ret.Include(tform * Vector3(box.mMin.x, box.mMin.y, box.mMax.z));
+  ret.Include(tform * Vector3(box.mMin.x, box.mMax.y, box.mMin.z));
+  ret.Include(tform * Vector3(box.mMin.x, box.mMax.y, box.mMax.z));
+  ret.Include(tform * Vector3(box.mMax.x, box.mMin.y, box.mMin.z));
+  ret.Include(tform * Vector3(box.mMax.x, box.mMin.y, box.mMax.z));
+  ret.Include(tform * Vector3(box.mMax.x, box.mMax.y, box.mMin.z));
+  ret.Include(tform * Vector3(box.mMax.x, box.mMax.y, box.mMax.z));
+  return ret;
+}
+
+
+inline int operator==(const AxisAlignedBox3 &A, const AxisAlignedBox3 &B)
+{
+  return (A.mMin == B.mMin) && (A.mMax == B.mMax);
+}
+
+  
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/UnigraphicsParser.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/UnigraphicsParser.cpp	(revision 340)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/UnigraphicsParser.cpp	(revision 340)
@@ -0,0 +1,180 @@
+#include  <stdlib.h>
+#include <iostream>
+#include <list>
+#include <map>
+using namespace std;
+
+#include "Vector3.h"
+#include "Mesh.h"
+#include "SceneGraph.h"
+
+#include "UnigraphicsParser.h"
+#include "Material.h"
+#include "Environment.h"
+
+
+
+struct ltstr
+{
+  bool operator()(const string s1, const string s2) const
+  {
+    return s1 < s2;
+  }
+};
+
+
+bool
+UnigraphicsParser::ParseFile(const string filename,
+			     SceneGraphNode **proot)
+{
+  
+  map<string, Vector3, ltstr> vht; // hash table for vectors
+  map<string, Vector3, ltstr> cht; // hash table for colors
+  
+  FILE         *file;
+  char str[80];
+  Face     *face;
+  //Vector3  *vptr;
+  
+  float x,y,z;
+  int i;
+  
+  
+  if ((file = fopen(filename.c_str(),"rt")) == NULL)
+    return false;
+
+  SceneGraphNode *root = new SceneGraphNode;
+  Mesh *currentMesh = new Mesh;
+
+  int meshGrouping;
+  environment->GetIntValue("Unigraphics.meshGrouping",
+			   meshGrouping);
+  
+  while(fscanf(file,"%s",str)!=EOF) {
+    switch (str[0]) {
+      
+    case 'c':
+      if (strcmp(str,"c_rgb")==0)
+	{
+	  cout<<"c";
+	  cout.flush();
+	  /* vertex */
+	  fscanf(file,"%s",str); // label
+	  fscanf(file,"%f %f %f",&x,&y,&z);
+	  
+	  cht[str] = Vector3(x,y,z); // swap the file coordinates
+	}
+      break;
+      
+      
+    case 'v':            // is it v ?
+      cout<<".";
+      cout.flush();
+      /* vertex */
+      fscanf(file,"%s",str); // label
+      fscanf(file,"%f %f %f",&x,&y,&z);
+      
+      vht[str] = Vector3(x,z,-y); // swap the file coordinates
+      //         vptr = new Vector3C(x,y,z); // swap the file coordinates
+      break;
+      
+    case 'f': {
+      cout<<"+";
+      vector<Vector3> vertices;
+      vector<int> vertexIndices;
+
+      /* face */
+      fscanf(file,"%s",str); // label may  be ?
+      if (str[0]!='(')
+	fscanf(file,"%s",str);
+      
+      i = 0;                              // index of the vertex
+      
+      
+      map<string, Vector3, ltstr>::const_iterator c = vht.find(&str[1]);
+      
+      if (c == vht.end()) {
+	cout<<"error reading file : "<<
+	  filename<<" ---missing vertex:"<<str<<endl; exit(1);
+      }
+      
+      vertices.push_back((*c).second);
+      
+      fscanf(file,"%s",str);      // get the vertex label
+      
+      while(str[0]!=')') {
+	
+	c = vht.find(str);
+	
+	if (c == vht.end())
+	  {
+	    cout<<"error reading file : "<<filename<<" -- missing vertex\n";
+	    exit(1);  }
+	
+	vertices.push_back((*c).second);
+	fscanf(file,"%s",str);   // get the next vertex label
+      }
+
+      // add vertices to the mesh vertex list
+      int index = (int)currentMesh->mVertices.size();
+      for (i=0; i < vertices.size(); i++, index++) {
+	currentMesh->mVertices.push_back(vertices[i]);
+	vertexIndices.push_back(index);
+      }
+      
+      face = new Face(vertexIndices);
+      
+      fscanf(file,"%s",str);   // get the next vertex label
+      
+      if (str[0]!=';') {
+	c = cht.find(str);
+	if (currentMesh->mMaterial == NULL) {
+	  Material *mat = new Material;
+	  if (c != cht.end()) {
+	    mat->mDiffuseColor = RgbColor((*c).second.x, (*c).second.y, (*c).second.z);
+	    currentMesh->mMaterial = mat;
+	  }
+	  else
+	    *mat = RandomMaterial();
+	  currentMesh->mMaterial = mat;
+	}
+      }
+      
+      currentMesh->AddFace(face);
+      if (meshGrouping != 0 &&
+					currentMesh->mFaces.size() >=  meshGrouping) {
+				currentMesh->Preprocess();
+				// make an instance of this mesh
+				MeshInstance *mi = new MeshInstance(currentMesh);
+				root->mGeometry.push_back(mi);	
+				currentMesh = new Mesh;
+      }
+    }
+    break;
+    }      /* end face */
+    
+    // get the rest of the line
+    fgets(str,80,file);
+  }
+  
+  if (currentMesh->mVertices.size()) {
+    currentMesh->Preprocess();
+    MeshInstance *mi = new MeshInstance(currentMesh);
+    root->mGeometry.push_back(mi);
+  }
+  
+  fclose(file);
+  
+  *proot = root;
+
+  return true;
+}
+
+
+
+
+
+
+
+
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Halton.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Halton.h	(revision 497)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Halton.h	(revision 497)
@@ -0,0 +1,135 @@
+#ifndef __HALTON_H
+#define __HALTON_H
+
+#include <iostream>
+using namespace std;
+
+class Halton2 {
+  static float _invBases[2];
+  float _prev[2];
+  
+  float halton(float baseRec, float prev) const {
+	float r = 1 - prev - 1e-10f;
+	if (baseRec < r)
+	  return prev + baseRec;
+	float h = baseRec;
+	float hh;
+	do {
+	  hh = h;
+	  h *= baseRec;
+	} while (h >= r);
+	return prev + hh + h - 1;
+  }
+  
+public:
+  
+  void Reset() {
+	_prev[0] =_prev[1] = 0;
+  }
+  
+  Halton2() {
+	_invBases[0] = 1.0f/2;
+	_invBases[1] = 1.0f/3;
+	Reset();
+  }
+  
+  void
+  GetNext(float &a, float &b) {
+	a = halton(_invBases[0], _prev[0]);
+	b = halton(_invBases[1], _prev[1]);
+	_prev[0] = a;
+	_prev[1] = b;
+  }
+};
+
+
+/**
+ * Assert whether the argument is a prime number.
+ * @param number the number to be checked
+ */
+inline bool IsPrime(const int number) {
+  bool isIt = true;
+  for(int i = 2; i < number; i++) {
+	if(number % i == 0) {
+	  isIt = false;
+	  break;
+	}
+  }
+	if(number == 2) {
+	  isIt = false;
+	}
+	return isIt;
+}
+
+/**
+ * Find the nth prime number.
+ * @param index the ordinal position in the sequence
+ */
+inline int FindPrime(const int index) {
+  if(index < 1) {
+	cerr<<"FindPrime: The argument must be non-negative."<<endl;
+	return -1;
+  }
+  int prime = 1;
+  int found = 1;
+  while(found != index) {
+	prime += 2;
+	  if(IsPrime(prime) == true) {
+		found++;
+	  }
+  }
+  return prime;
+}
+
+struct HaltonSequence {
+public:
+  int index;
+
+  HaltonSequence():index(1) {}
+
+  void Reset() {
+	index = 1;
+  }
+
+  void GenerateNext() {
+	index++;
+  }
+  
+  /**
+   * Returns the nth number in the sequence, taken from a specified dimension.
+   * @param index the ordinal position in the sequence
+   * @param dimension the dimension
+   */
+
+  double GetNumber(const int dimension)  {
+	int base = FindPrime(dimension);
+	if(base == 1) {
+	  base++;  //The first dimension uses base 2.
+	} 
+	double remainder;
+	double output = 0.0;
+	double fraction = 1.0 / (double)base;
+	int N1 = 0;
+	int copyOfIndex = index;
+	if((base >= 2) && (index >= 1)) {
+	// changed by matt
+	//if(base >= 2 & index >= 1) {
+	  while(copyOfIndex > 0) {
+		N1 = (copyOfIndex / base);
+		remainder = copyOfIndex % base;
+		output += fraction * remainder;
+		copyOfIndex = (int)(copyOfIndex / base);
+		fraction /= (double)base;
+	  } 
+	  return output;
+	}
+	else {
+	  cerr<<"Error generating Halton sequence."<<endl;
+	  exit(1);
+	}
+  }
+};
+
+extern Halton2 halton2;
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Vector3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Vector3.h	(revision 492)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Vector3.h	(revision 492)
@@ -0,0 +1,489 @@
+#ifndef _Vector3_h__
+#define _Vector3_h__
+
+#include <iostream>
+using namespace std;
+#include <math.h>
+#include "common.h"
+
+
+
+// Forward-declare some other classes.
+class Matrix4x4;
+class Vector2;
+
+// HACK of returning vector components as array fields.
+// NOT guarrantied to work with some strange variable allignment !
+#define __VECTOR_HACK
+
+class Vector3
+{
+public:
+  float x, y, z;
+
+  // for compatibility with pascal's code
+  void  setX(float q) { x=q; }
+  void  setY(float q) { y=q; }
+  void  setZ(float q) { z=q; }
+  float getX() const { return x; }
+  float getY() const { return y; }
+  float getZ() const { return z; }
+
+  // constructors
+  Vector3() { }
+
+  Vector3(float X, float Y, float Z) { x = X; y = Y; z = Z; }
+  Vector3(float X) { x = y = z = X; }
+  Vector3(const Vector3 &v) { x = v.x; y = v.y; z = v.z; }
+
+  // Functions to get at the vector components
+  float& operator[] (int inx) {
+#ifndef __VECTOR_HACK
+    if (inx == 0)
+      return x;
+    else
+      if (inx == 1)
+	return y;
+    else
+      return z;
+#else
+    return (&x)[inx];
+#endif
+    
+  }
+
+#ifdef __VECTOR_HACK
+  operator const float*() const { return (const float*) this; }
+#endif
+
+  const float& operator[] (int inx) const {
+#ifndef __VECTOR_HACK
+    if (inx == 0)
+      return x;
+    else
+      if (inx == 1)
+	return y;
+      else
+	return z;
+#else
+    return *(&x+inx);
+#endif
+  }
+
+  void ExtractVerts(float *px, float *py, int which) const;
+  
+  void SetValue(const float &a, const float &b, const float &c)
+  {  x=a; y=b; z=c; }
+
+  void SetValue(const float a) { x = y = z = a; }
+  
+  // returns the axis, where the vector has the largest value
+  int DrivingAxis(void) const;
+
+  // returns the axis, where the vector has the smallest value
+  int TinyAxis(void) const;
+
+  inline float MaxComponent(void) const {
+     // return (x > y && x > z) ? x : ((y > z) ? y : z);
+     return (x > y) ? ( (x > z) ? x : z) : ( (y > z) ? y : z);
+   }
+ 
+   inline Vector3 Abs(void) const {
+     return Vector3(fabs(x), fabs(y), fabs(z));
+   }
+
+  // normalizes the vector of unit size corresponding to given vector
+  inline void Normalize();
+  
+  /**
+    ===> Using ArbitraryNormal() for constructing coord systems 
+    ===> is obsoleted by RightHandedBase() method (<JK> 12/20/03).   
+
+     Return an arbitrary normal to `v'.
+     In fact it tries v x (0,0,1) an if the result is too small,
+     it definitely does v x (0,1,0). It will always work for
+     non-degenareted vector and is much faster than to use
+     TangentVectors.
+
+     @param v(in) The vector we want to find normal for.
+     @return The normal vector to v.
+  */
+  friend inline Vector3 ArbitraryNormal(const Vector3 &v); 
+
+  /**
+    Find a right handed coordinate system with (*this) being
+    the z-axis. For a right-handed system, U x V = (*this) holds.
+    This implementation is here to avoid inconsistence and confusion
+    when construction coordinate systems using ArbitraryNormal():
+    In fact:
+      V = ArbitraryNormal(N);
+      U = CrossProd(V,N);
+    constructs a right-handed coordinate system as well, BUT:
+    1) bugs can be introduced if one mistakenly constructs a 
+       left handed sytems e.g. by doing
+       U = ArbitraryNormal(N);
+       V = CrossProd(U,N);
+    2) this implementation gives non-negative base vectors
+       for (*this)==(0,0,1) |  (0,1,0) | (1,0,0), which is
+       good for debugging and is not the case with the implementation
+       using ArbitraryNormal()
+
+    ===> Using ArbitraryNormal() for constructing coord systems 
+	     is obsoleted by this method (<JK> 12/20/03).   
+  */
+  void RightHandedBase(Vector3& U, Vector3& V) const;
+
+  /// Transforms a vector to the global coordinate frame.
+  /**
+    Given a local coordinate frame (U,V,N) (i.e. U,V,N are 
+    the x,y,z axes of the local coordinate system) and
+    a vector 'loc' in the local coordiante system, this
+    function returns a the coordinates of the same vector
+    in global frame (i.e. frame (1,0,0), (0,1,0), (0,0,1).
+  */
+  friend inline Vector3 ToGlobalFrame(const Vector3& loc,
+	  const Vector3& U,
+	  const Vector3& V,
+	  const Vector3& N);
+  
+  /// Transforms a vector to a local coordinate frame.
+  /**
+    Given a local coordinate frame (U,V,N) (i.e. U,V,N are 
+    the x,y,z axes of the local coordinate system) and
+    a vector 'loc' in the global coordiante system, this
+    function returns a the coordinates of the same vector
+    in the local frame.
+  */
+  friend inline Vector3 ToLocalFrame(const Vector3& loc,
+	  const Vector3& U,
+	  const Vector3& V,
+	  const Vector3& N);
+
+  /// the magnitude=size of the vector
+  friend inline float Magnitude(const Vector3 &v);
+  /// the squared magnitude of the vector .. for efficiency in some cases
+  friend inline float SqrMagnitude(const Vector3 &v);
+  /// Magnitude(v1-v2)
+  friend inline float Distance(const Vector3 &v1, const Vector3 &v2);
+  /// SqrMagnitude(v1-v2)
+  friend inline float SqrDistance(const Vector3 &v1, const Vector3 &v2);
+
+  // creates the vector of unit size corresponding to given vector
+  friend inline Vector3 Normalize(const Vector3 &A);
+
+  // Rotate a normal vector.
+  friend Vector3 PlaneRotate(const Matrix4x4 &, const Vector3 &);
+
+  // construct view vectors .. DirAt is the main viewing direction
+  // Viewer is the coordinates of viewer location, UpL is the vector.
+  friend void ViewVectors(const Vector3 &DirAt, const Vector3 &Viewer,
+	                  const Vector3 &UpL, Vector3 &ViewV,
+			  Vector3 &ViewU, Vector3 &ViewN );
+
+  // Given the intersection point `P', you have available normal `N'
+  // of unit length. Let us suppose the incoming ray has direction `D'.
+  // Then we can construct such two vectors `U' and `V' that
+  // `U',`N', and `D' are coplanar, and `V' is perpendicular
+  // to the vectors `N','D', and `V'. Then 'N', 'U', and 'V' create
+  // the orthonormal base in space R3.
+  friend void TangentVectors(Vector3 &U, Vector3 &V, // output
+			     const Vector3 &normal, // input
+			     const Vector3 &dirIncoming);
+  // Unary operators
+  Vector3 operator+ () const;
+  Vector3 operator- () const;
+
+  // Assignment operators
+  Vector3& operator+= (const Vector3 &A);
+  Vector3& operator-= (const Vector3 &A);
+  Vector3& operator*= (const Vector3 &A);
+  Vector3& operator*= (float A);
+  Vector3& operator/= (float A);
+
+  // Binary operators
+  friend inline Vector3 operator+ (const Vector3 &A, const Vector3 &B);
+  friend inline Vector3 operator- (const Vector3 &A, const Vector3 &B);
+  friend inline Vector3 operator* (const Vector3 &A, const Vector3 &B);
+  friend inline Vector3 operator* (const Vector3 &A, float B);
+  friend inline Vector3 operator* (float A, const Vector3 &B);
+  friend Vector3 operator* (const Matrix4x4 &, const Vector3 &);
+  friend inline Vector3 operator/ (const Vector3 &A, const Vector3 &B);
+
+  friend inline int operator< (const Vector3 &A, const Vector3 &B);
+  friend inline int operator<= (const Vector3 &A, const Vector3 &B);
+
+  friend inline Vector3 operator/ (const Vector3 &A, float B);
+  friend inline int operator== (const Vector3 &A, const Vector3 &B);
+  friend inline float DotProd(const Vector3 &A, const Vector3 &B);
+  friend inline Vector3 CrossProd (const Vector3 &A, const Vector3 &B);
+
+  friend ostream& operator<< (ostream &s, const Vector3 &A);
+  friend istream& operator>> (istream &s, Vector3 &A);
+    
+  friend void Minimize(Vector3 &min, const Vector3 &candidate);
+  friend void Maximize(Vector3 &max, const Vector3 &candidate);
+
+  friend inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2, float thr);
+  friend inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2);
+
+  friend Vector3 UniformRandomVector(const Vector3 &normal);
+  friend Vector3 UniformRandomVector();
+  
+
+};
+
+inline Vector3
+ArbitraryNormal(const Vector3 &N)
+{
+  float dist2 = N.x * N.x + N.y * N.y;
+  if (dist2 > 0.0001) {
+    float inv_size = 1.0f/sqrtf(dist2);
+    return Vector3(N.y * inv_size, -N.x * inv_size, 0); // N x (0,0,1)
+  }
+  float inv_size = 1.0f/sqrtf(N.z * N.z + N.x * N.x);
+  return Vector3(-N.z * inv_size, 0, N.x * inv_size); // N x (0,1,0)
+}
+
+
+inline Vector3
+ToGlobalFrame(const Vector3 &loc,
+	      const Vector3 &U,
+	      const Vector3 &V,
+	      const Vector3 &N)
+{
+  return loc.x * U + loc.y * V + loc.z * N;
+}
+
+inline Vector3
+ToLocalFrame(const Vector3 &loc,
+	     const Vector3 &U,
+	     const Vector3 &V,
+	     const Vector3 &N)
+{
+  return Vector3( loc.x * U.x + loc.y * U.y + loc.z * U.z,
+		    loc.x * V.x + loc.y * V.y + loc.z * V.z,
+		    loc.x * N.x + loc.y * N.y + loc.z * N.z);
+}
+
+inline float
+Magnitude(const Vector3 &v) 
+{
+  return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
+}
+
+inline float
+SqrMagnitude(const Vector3 &v) 
+{
+  return v.x * v.x + v.y * v.y + v.z * v.z;
+}
+
+inline float
+Distance(const Vector3 &v1, const Vector3 &v2)
+{
+  return sqrtf(sqr(v1.x-v2.x) + sqr(v1.y-v2.y) + sqr(v1.z-v2.z));
+}
+
+inline float
+SqrDistance(const Vector3 &v1, const Vector3 &v2)
+{
+  return sqr(v1.x-v2.x)+sqr(v1.y-v2.y)+sqr(v1.z-v2.z);
+}
+
+inline Vector3
+Normalize(const Vector3 &A)
+{
+  return A * (1.0f/Magnitude(A));
+}
+
+inline float
+DotProd(const Vector3 &A, const Vector3 &B)
+{
+  return A.x * B.x + A.y * B.y + A.z * B.z;
+}
+
+// angle between two vectors with respect to a surface normal in the
+// range [0 .. 2 * pi]
+inline float
+Angle(const Vector3 &A, const Vector3 &B, const Vector3 &norm)
+{
+	Vector3 cross = CrossProd(A, B);
+
+	float signedAngle;
+
+	if (DotProd(cross, norm) > 0)
+		signedAngle = atan2(-Magnitude(CrossProd(A, B)), DotProd(A, B));
+	else
+		signedAngle = atan2(Magnitude(CrossProd(A, B)), DotProd(A, B));
+
+	if (signedAngle < 0)
+		return 2 * PI + signedAngle;
+
+	return signedAngle;
+}
+
+inline Vector3
+Vector3::operator+() const
+{
+  return *this;
+}
+
+inline Vector3
+Vector3::operator-() const
+{
+  return Vector3(-x, -y, -z);
+}
+
+inline Vector3&
+Vector3::operator+=(const Vector3 &A)
+{
+  x += A.x;  y += A.y;  z += A.z;
+  return *this;
+}
+
+inline Vector3&
+Vector3::operator-=(const Vector3 &A)
+{
+  x -= A.x;  y -= A.y;  z -= A.z;
+  return *this;
+}
+
+inline Vector3&
+Vector3::operator*= (float A)
+{
+  x *= A;  y *= A;  z *= A;
+  return *this;
+}
+
+inline Vector3&
+Vector3::operator/=(float A)
+{
+  float a = 1.0f/A;
+  x *= a;  y *= a;  z *= a;
+  return *this;
+}
+
+inline Vector3&
+Vector3::operator*= (const Vector3 &A)
+{
+  x *= A.x;  y *= A.y;  z *= A.z;
+  return *this;
+}
+
+inline Vector3
+operator+ (const Vector3 &A, const Vector3 &B)
+{
+  return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);
+}
+
+inline Vector3
+operator- (const Vector3 &A, const Vector3 &B)
+{
+  return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);
+}
+
+inline Vector3
+operator* (const Vector3 &A, const Vector3 &B)
+{
+  return Vector3(A.x * B.x, A.y * B.y, A.z * B.z);
+}
+
+inline Vector3
+operator* (const Vector3 &A, float B)
+{
+  return Vector3(A.x * B, A.y * B, A.z * B);
+}
+
+inline Vector3
+operator* (float A, const Vector3 &B)
+{
+  return Vector3(B.x * A, B.y * A, B.z * A);
+}
+
+inline Vector3
+operator/ (const Vector3 &A, const Vector3 &B)
+{
+  return Vector3(A.x / B.x, A.y / B.y, A.z / B.z);
+}
+
+inline Vector3
+operator/ (const Vector3 &A, float B)
+{
+  float b = 1.0f / B;
+  return Vector3(A.x * b, A.y * b, A.z * b);
+}
+
+inline int
+operator< (const Vector3 &A, const Vector3 &B)
+{
+  return A.x < B.x && A.y < B.y && A.z < B.z;
+}
+
+inline int
+operator<= (const Vector3 &A, const Vector3 &B)
+{
+  return A.x <= B.x && A.y <= B.y && A.z <= B.z;
+}
+
+// Might replace floating-point == with comparisons of
+// magnitudes, if needed.
+inline int operator== (const Vector3 &A, const Vector3 &B)
+{
+  return (A.x == B.x) && (A.y == B.y) && (A.z == B.z);
+}
+
+inline Vector3
+CrossProd (const Vector3 &A, const Vector3 &B)
+{
+  return Vector3(A.y * B.z - A.z * B.y,
+		 A.z * B.x - A.x * B.z,
+		 A.x * B.y - A.y * B.x);
+}
+
+inline void
+Vector3::Normalize()
+{
+  float sqrmag = x * x + y * y + z * z;
+  if (sqrmag > 0.0f)
+    (*this) *= 1.0f / sqrtf(sqrmag);
+}
+
+
+// Overload << operator for C++-style output
+inline ostream&
+operator<< (ostream &s, const Vector3 &A)
+{
+  return s << "(" << A.x << ", " << A.y << ", " << A.z << ")";
+}
+
+// Overload >> operator for C++-style input
+inline istream&
+operator>> (istream &s, Vector3 &A)
+{
+  char a;
+  // read "(x, y, z)"
+  return s >> a >> A.x >> a >> A.y >> a >> A.z >> a;
+}
+
+inline int
+EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2, float thr)
+{
+  if ( fabsf(v1.x-v2.x) > thr )
+    return false;
+  if ( fabsf(v1.y-v2.y) > thr )
+    return false;
+  if ( fabsf(v1.z-v2.z) > thr )
+    return false;
+  return true;
+}
+
+inline int
+EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2)
+{
+  return EpsilonEqualV3(v1, v2, Limits::Small);
+}
+
+
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RssTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RssTree.h	(revision 569)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RssTree.h	(revision 569)
@@ -0,0 +1,1083 @@
+// ================================================================
+// $Id$
+// ****************************************************************
+// 
+// Initial coding by
+/**
+   @author Jiri Bittner
+*/
+
+#ifndef __RSSTREE_H__
+#define __RSSTREE_H__
+
+// Standard headers
+#include <iomanip>
+#include <vector>
+#include <functional>
+#include <stack>
+
+
+// User headers
+#include "VssRay.h"
+#include "AxisAlignedBox3.h"
+#include "Halton.h"
+#include "Beam.h"
+#include "Statistics.h"
+#include "Ray.h"
+
+#include "Containers.h"
+
+#define USE_KDNODE_VECTORS 1
+#define _RSS_STATISTICS
+#define _RSS_TRAVERSAL_STATISTICS
+
+
+// --------------------------------------------------------------
+// Static statistics for kd-tree search
+// --------------------------------------------------------------
+class RssStatistics :
+  public StatisticsBase
+{
+public:  
+  // total number of nodes
+  int nodes;
+  // number of leaves
+  int leaves;
+  // number of splits along each of the axes
+  int splits[7];
+  // totals number of rays
+  int rays;
+  // initial size of the pvs
+  int initialPvsSize;
+  // total number of query domains
+  int queryDomains;
+  // total number of ray references
+  int rayRefs;
+
+  // max depth nodes
+  int maxDepthNodes;
+  // max depth nodes
+  int minPvsNodes;
+  int minRaysNodes;
+  // max ray contribution nodes
+  int maxRayContribNodes;
+  // max depth nodes
+  int minSizeNodes;
+  int maxCostRatioNodes;
+
+  // max number of rays per node
+  int maxRayRefs;
+  // number of dynamically added ray refs
+  int addedRayRefs;
+  // number of dynamically removed ray refs
+  int removedRayRefs;
+
+
+
+  // dynamically updated values
+  float avgPvsSize;
+  float avgRays;
+  float avgRayContribution;
+  float avgPvsEntropy;
+  float avgRayLengthEntropy;
+  float avgImportance;
+
+  float avgWeightedRayContribution;
+
+  // Constructor
+  RssStatistics() {
+    Reset();
+  }
+
+  int Nodes() const {return nodes;}
+  int Interior() const { return nodes/2; }
+  int Leaves() const { return Nodes() - Interior(); }
+
+  void Reset() {
+    nodes = 0;
+    for (int i=0; i<7; i++)
+      splits[i] = 0;
+    rays = queryDomains = 0;
+    rayRefs = 0;
+    maxDepthNodes = 0;
+    minPvsNodes = 0;
+    minRaysNodes = 0;
+    maxRayRefs = 0;
+    addedRayRefs = removedRayRefs = 0;
+	initialPvsSize = 0;
+	maxRayContribNodes = 0;
+	minSizeNodes = 0;
+	maxCostRatioNodes = 0;
+  }
+
+  
+  void
+  Print(ostream &app) const;
+
+  friend ostream &operator<<(ostream &s, const RssStatistics &stat) {
+    stat.Print(s);
+    return s;
+  }
+  
+};
+
+
+
+
+class RssTreeInterior;
+
+
+// --------------------------------------------------------------
+// KD-tree node - abstract class
+// --------------------------------------------------------------
+class RssTreeNode
+{
+public:
+
+  struct RayInfo
+  {
+	// pointer to the actual ray
+	VssRay *mRay;
+	
+	RayInfo():mRay(NULL) {}
+	
+	RayInfo(VssRay *r):mRay(r)
+	{}
+	
+	enum {
+	  SOURCE_RAY = 0,
+	  TERMINATION_RAY,
+	  PASSING_RAY,
+	  CONTAINED_RAY
+	};
+	
+	int GetRayClass() const {
+	  return SOURCE_RAY;
+	}
+	
+	friend bool operator<(const RayInfo &a, const RayInfo &b) {
+	  return a.mRay < b.mRay;
+	}
+
+#define USE_ORIGIN 0
+	
+	Vector3 GetOrigin() const {
+#if USE_ORIGIN
+	  return mRay->GetOrigin();
+#else
+	  return mRay->GetTermination();
+#endif
+	}
+
+	Vector3 GetTermination() const {
+#if USE_ORIGIN
+	  return mRay->GetTermination();
+#else
+	  return mRay->GetOrigin();
+#endif
+	}
+
+	float GetOrigin(const int axis) const {
+#if USE_ORIGIN
+	  return mRay->GetOrigin(axis);
+#else
+	  return mRay->GetTermination(axis);
+#endif
+	}
+
+	Vector3 GetDir() const {
+#if USE_ORIGIN
+	  return mRay->GetDir();
+#else
+	  return -mRay->GetDir();
+#endif
+	}
+
+	float GetDirParametrization(const int axis) const {
+#if USE_ORIGIN
+	  return mRay->GetDirParametrization(axis);
+#else
+	  return mRay->GetOpositeDirParametrization(axis);
+#endif
+	}
+
+	
+// 	Vector3 GetTermination() const {
+// 	  return mRay->GetOrigin();
+// 	}
+	
+// 	float GetTermination(const int axis) const {
+// 	  return mRay->GetTermination(axis);
+// 	}
+
+	Intersectable *GetObject() const {
+#if USE_ORIGIN
+	  return mRay->mTerminationObject;
+#else
+	  return mRay->mOriginObject;
+#endif
+	}
+	
+	Intersectable *GetSourceObject() const {
+#if USE_ORIGIN
+	  return mRay->mOriginObject;
+#else
+	  return mRay->mTerminationObject;
+#endif
+	}
+
+	//	Vector3 Extrap(const float t) const {
+	//	  return mRay->Extrap(t);
+	//	}
+	
+	int
+	ComputeRaySide(const int axis,
+				   const float position
+				   ) const {
+	  
+	  // only compare the side of the origin
+	  float rpos = (axis < 3) ? GetOrigin(axis) : GetDirParametrization(axis - 3);
+	  return (rpos <= position) ? -1 : 1;
+	}
+
+	static bool GreaterWeightedPvsContribution(const RayInfo &a,
+											   const RayInfo &b) {
+	  return a.mRay->mWeightedPvsContribution > b.mRay->mWeightedPvsContribution;
+	}
+
+	static float Distance(const RayInfo &a,
+						 const RayInfo &b)
+	{
+	  if (a.mRay->mTerminationObject == b.mRay->mTerminationObject)
+		return MAX_FLOAT;
+	  
+	  return Min(a.mRay->SqrDistance(b.GetTermination()),
+				 b.mRay->SqrDistance(a.GetTermination()));
+	}
+
+	
+	static float SqrDistance5D(const RayInfo &a,
+							   const RayInfo &b,
+							   const Vector3 &spatialDerivative,
+							   const Vector3 &directionalDerivative
+							   )
+	{
+	  Vector3 spatialDiff = b.GetOrigin() - a.GetOrigin();
+	  Vector3 directionalDiff = b.GetDir() - a.GetDir();
+	  
+	  return DotProd(spatialDiff, spatialDerivative) +
+		DotProd(directionalDiff, directionalDerivative);
+	}
+
+	
+  };
+
+  struct SilhouetteRays {
+	RayInfo *a;
+	RayInfo *b;
+	SilhouetteRays() {}
+	SilhouetteRays(RayInfo *_a, RayInfo *_b):a(_a), b(_b) {
+	}
+  };
+  
+  typedef vector<RayInfo> RayInfoContainer;
+	
+  enum { EInterior, ELeaf };
+
+  /////////////////////////////////
+  // The actual data goes here
+  
+  // link to the parent
+  RssTreeInterior *parent;
+
+  enum {SPLIT_X=0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
+  
+  // splitting axis
+  char axis;
+	
+  // depth
+  unsigned char depth;
+  
+  //  short depth;
+  //
+  /////////////////////////////////
+
+
+  // the bbox of the node
+  AxisAlignedBox3 bbox;
+  
+  // the bbox of the node
+  AxisAlignedBox3 dirBBox;
+
+  
+  inline RssTreeNode(RssTreeInterior *p);
+
+  
+  virtual ~RssTreeNode() {};
+  virtual int Type() const  = 0;
+  
+
+  bool IsLeaf() const { return axis == -1; }
+  
+  virtual void Print(ostream &s) const = 0;
+
+  virtual int GetAccessTime() {
+    return 0x7FFFFFF;
+  }
+
+  
+	
+};
+
+// --------------------------------------------------------------
+// KD-tree node - interior node
+// --------------------------------------------------------------
+class RssTreeInterior :
+  public RssTreeNode
+{
+public:
+  // plane in local modelling coordinates
+  float position;
+
+  // pointers to children
+  RssTreeNode *back, *front;
+
+
+  // data for caching
+  long accesses;
+  long lastAccessTime;
+  
+  RssTreeInterior(RssTreeInterior *p):RssTreeNode(p),
+									  back(NULL),
+									  front(NULL),
+									  accesses(0),
+									  lastAccessTime(-1)
+  { }
+
+  virtual int GetAccessTime() {
+    return lastAccessTime;
+  }
+
+  void SetupChildLinks(RssTreeNode *b, RssTreeNode *f) {
+    back = b;
+    front = f;
+    b->parent = f->parent = this;
+  }
+
+  void ReplaceChildLink(RssTreeNode *oldChild, RssTreeNode *newChild) {
+    if (back == oldChild)
+      back = newChild;
+    else
+      front = newChild;
+  }
+
+  virtual int Type() const  { return EInterior; }
+  
+  virtual ~RssTreeInterior() {
+    if (back)
+      delete back;
+    if (front)
+      delete front;
+  }
+  
+  virtual void Print(ostream &s) const {
+    if (axis == 0)
+      s<<"x ";
+    else
+      if (axis == 1)
+		s<<"y ";
+      else
+		s<<"z ";
+    s<<position<<" ";
+    back->Print(s);
+    front->Print(s);
+  }
+
+  
+	
+  int ComputeRaySide(const
+					 RayInfo &rayData
+					 ) {
+	return rayData.ComputeRaySide(axis, position);
+  }
+
+};
+
+
+// --------------------------------------------------------------
+// KD-tree node - leaf node
+// --------------------------------------------------------------
+class RssTreeLeaf :
+  public RssTreeNode
+{
+private:
+  int mPvsSize;
+public:
+  static int mailID;
+  int mailbox;
+  
+  RayInfoContainer rays;
+  int mTotalRays;
+	
+  bool mValidPvs;
+  float mImportance;
+  
+  HaltonSequence halton;
+
+  Beam mBeam;
+  
+  RssTreeLeaf(RssTreeInterior *p,
+			  const int nRays
+			  ):RssTreeNode(p), rays(), mPvsSize(0), mTotalRays(0), mValidPvs(false) {
+    rays.reserve(nRays);
+  }
+  
+  virtual ~RssTreeLeaf() { }
+
+  virtual int Type() const  { return ELeaf; }
+
+  virtual void Print(ostream &s) const {
+    s<<
+	  "L: rays="<<(int)rays.size()<<
+	  " pvs="<<mPvsSize<<" importance="<<mImportance<<endl;
+  };
+  
+  void AddRay(const RayInfo &data) {
+	mValidPvs = false;
+    rays.push_back(data);
+	mTotalRays++;
+	data.mRay->Ref();
+  }
+	
+  int GetPvsSize() const {
+	return mPvsSize;
+  }
+
+  void SetPvsSize(const int s) {
+	mPvsSize = s;
+	mValidPvs = true;
+  }
+
+
+  float
+  ComputePvsEntropy() const;
+  
+  float
+  ComputeRayLengthEntropy() const;
+  
+  float
+  ComputeRayTerminationEntropy() const;
+  
+
+  float
+  ComputeEntropyImportance() const;
+  
+  float
+  ComputeRayContributionImportance() const;
+
+  void Mail() { mailbox = mailID; }
+  static void NewMail() { mailID++; }
+  bool Mailed() const { return mailbox == mailID; }
+  
+  bool Mailed(const int mail) {
+    return mailbox >= mailID + mail;
+  }
+
+  float GetAvgRayContribution() const {
+	return GetPvsSize()/((float)rays.size() + Limits::Small);
+  }
+
+  float GetImportance() const;
+  
+  float GetSqrRayContribution() const {
+	return sqr(GetPvsSize()/((float)rays.size() + Limits::Small));
+  }
+  
+  // comparator for the 
+  struct less_contribution : public
+  binary_function<const RssTreeLeaf *, const RssTreeLeaf *, bool> {
+	
+	bool operator()(const RssTreeLeaf * a, const RssTreeLeaf *b) {
+	  return a->GetAvgRayContribution() < b->GetAvgRayContribution();
+	}
+  };
+  
+  struct greater_contribution : public
+  binary_function<const RssTreeLeaf *, const RssTreeLeaf *, bool> {
+	
+	bool operator()(const RssTreeLeaf * a, const RssTreeLeaf *b) {
+	  return a->GetAvgRayContribution() > b->GetAvgRayContribution();
+	}
+  };
+  
+  friend bool GreaterContribution(const RssTreeLeaf * a, const RssTreeLeaf *b) {
+	return a->GetAvgRayContribution() > b->GetAvgRayContribution();
+  }
+
+  
+};
+
+// Inline functions
+inline
+RssTreeNode::RssTreeNode(RssTreeInterior *p):
+  parent(p), axis(-1), depth(p ? p->depth + 1 : 0) {}
+
+
+
+// ---------------------------------------------------------------
+// Main LSDS search class
+// ---------------------------------------------------------------
+class RssTree
+{
+  struct TraversalData
+  {  
+    RssTreeNode *node;
+    AxisAlignedBox3 bbox;
+    int depth;
+    float priority;
+    
+    TraversalData() {}
+
+    TraversalData(RssTreeNode *n, const float p):
+      node(n), priority(p)
+    {}
+
+    TraversalData(RssTreeNode *n,
+				  const AxisAlignedBox3 &b,
+				  const int d):
+      node(n), bbox(b), depth(d) {}
+    
+		
+    // comparator for the 
+    struct less_priority : public
+    binary_function<const TraversalData, const TraversalData, bool> {
+			
+      bool operator()(const TraversalData a, const TraversalData b) {
+		return a.priority < b.priority;
+      }
+      
+    };
+
+    //    ~TraversalData() {}
+    //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
+    
+    friend bool operator<(const TraversalData &a,
+						  const TraversalData &b) {
+      //      return a.node->queries.size() < b.node->queries.size();
+      RssTreeLeaf *leafa = (RssTreeLeaf *) a.node;
+      RssTreeLeaf *leafb = (RssTreeLeaf *) b.node;
+#if 0
+	  return
+		leafa->rays.size()*a.bbox.GetVolume()
+		<
+		leafb->rays.size()*b.bbox.GetVolume();
+#endif
+#if 0
+	  return
+		leafa->GetPvsSize()*a.bbox.GetVolume()
+		<
+		leafb->GetPvsSize()*b.bbox.GetVolume();
+#endif
+#if 0
+	  return
+		leafa->GetPvsSize()
+		<
+		leafb->GetPvsSize();
+#endif
+#if 0
+	  return
+		leafa->GetPvsSize()/(leafa->rays.size()+1)
+		>
+		leafb->GetPvsSize()/(leafb->rays.size()+1);
+#endif
+#if 1
+	  return
+		leafa->GetPvsSize()*leafa->rays.size()
+		<
+		leafb->GetPvsSize()*leafb->rays.size();
+#endif
+    }
+  };
+  
+  // simplified data for ray traversal only...
+
+  struct RayTraversalData {
+    
+    RssTreeNode::RayInfo rayData;
+    RssTreeNode *node;
+    
+    RayTraversalData() {}
+    RayTraversalData(RssTreeNode *n,
+					 const RssTreeNode::RayInfo &data):
+      rayData(data), node(n) {}
+  };
+	
+public:
+  /////////////////////////////
+  // The core pointer
+  vector<RssTreeNode *> mRoots;
+  
+  
+  
+  /////////////////////////////
+  // Basic properties
+
+  // total number of nodes of the tree
+  int nodes;
+
+  // axis aligned bounding box of the scene
+  AxisAlignedBox3 bbox;
+
+  // axis aligned bounding box of directions
+  AxisAlignedBox3 dirBBox;
+
+  // forced bounding box for from viewcell visibility
+  //  AxisAlignedBox3 *mForcedBoundingBox;
+
+  /////////////////////////////
+  // Construction parameters
+
+  // epsilon used for the construction
+  float epsilon;
+
+  // ratio between traversal and intersection costs
+  float ct_div_ci;
+  // max depth of the tree
+  int termMaxDepth;
+  // minimal ratio of the volume of the cell and the query volume
+  float termMinSize;
+
+  // minimal pvs per node to still get subdivided
+  int termMinPvs;
+
+  // minimal ray number per node to still get subdivided
+  int termMinRays;
+	
+  // maximal cost ration to subdivide a node
+  float termMaxCostRatio;
+	
+  // maximal contribution per ray to subdivide the node
+  float termMaxRayContribution;
+
+  // randomized construction
+  bool randomize;
+
+  // use a root per object in the tree
+  bool mPerObjectTree;
+  
+  // type of the splitting to use fo rthe tree construction
+  enum {ESplitRegular, ESplitHeuristic, ESplitHybrid };
+  int splitType;
+
+  bool mSplitUseOnlyDrivingAxis;
+  
+
+  // interleave directional and spatial splits based on their costs
+  // if false directional splits are only performed after spatial splits
+  bool mInterleaveDirSplits;
+
+  // depth at which directional splits are performed if mInterleaveDirSplits is false
+  int mDirSplitDepth;
+
+  // maximal number of rays maintained in the rss tree
+  int mMaxRays;
+  
+  // maximal size of the box on which the refdir splitting can be performed
+  // (relative to the scene bbox
+  float refDirBoxMaxSize;
+  
+  // maximum alovable memory in MB
+  float maxTotalMemory;
+
+  // maximum alovable memory for static kd tree in MB
+  float maxStaticMemory;
+
+  // this is used during the construction depending
+  // on the type of the tree and queries...
+  float maxMemory;
+
+
+  // minimal acess time for collapse
+  int accessTimeThreshold;
+
+  // minimal depth at which to perform collapse
+  int minCollapseDepth;
+
+  bool mImportanceBasedCost;
+
+  // sampling pass
+  int mCurrentPass;
+  
+  // reusable array of split candidates
+  vector<SortableEntry> *splitCandidates;
+  /////////////////////////////
+
+  RssStatistics stat;
+	
+  
+  RssTree();
+  virtual ~RssTree();
+
+  virtual void
+  Construct(
+			ObjectContainer &objects,
+			VssRayContainer &rays
+			//			AxisAlignedBox3 *forcedBoundingBox = NULL
+			);
+	
+  // incemental construction
+  virtual void UpdateRays(VssRayContainer &remove,
+						  VssRayContainer &add
+						  );
+
+  virtual void AddRays(
+					   VssRayContainer &add
+					   )
+  {
+	VssRayContainer remove;
+	UpdateRays(remove, add);
+  }
+
+  
+	
+  RssTreeNode *
+  Locate(const Vector3 &v);
+	
+  RssTreeNode *
+  SubdivideNode(RssTreeLeaf *leaf,
+				const AxisAlignedBox3 &box,
+				AxisAlignedBox3 &backBox,
+				AxisAlignedBox3 &frontBox
+				);
+	
+  RssTreeNode *
+  Subdivide(const TraversalData &tdata);
+	
+
+  void
+  SortSplitCandidates(
+					  RssTreeLeaf *node,
+					  const int axis
+					  );
+	
+  
+  // return memory usage in MB
+  float GetMemUsage() const {
+    return 
+      (sizeof(RssTree) +
+       stat.Leaves()*sizeof(RssTreeLeaf) +
+       stat.Interior()*sizeof(RssTreeInterior) +
+       stat.rayRefs*sizeof(RssTreeNode::RayInfo))/(1024.0f*1024.0f);
+  }
+	
+  float GetRayMemUsage() const {
+    return 
+      stat.rays*(sizeof(VssRay))/(1024.0f*1024.0f);
+  }
+  
+  struct SplitInfo {
+	
+	int axis;
+	float position;
+	float costRatio;
+	
+	int rays;
+	int raysBack;
+	int raysFront;
+
+	int pvs;
+	int pvsBack;
+	int pvsFront;
+
+	float contribution;
+	float contributionBack;
+	float contributionFront;
+
+	int viewCells;
+	int viewCellsBack;
+	int viewCellsFront;
+
+	float volume;
+	float volumeBack;
+	float volumeFront;
+	
+  };
+  
+  void
+  BestCostRatio(
+				RssTreeLeaf *node,
+				SplitInfo &info
+// 				int &axis,
+// 				float &position,
+// 				int &raysBack,
+// 				int &raysFront,
+// 				int &pvsBack,
+// 				int &pvsFront
+				);
+	
+  
+  void
+  EvalCostRatio(
+				RssTreeLeaf *node,
+				SplitInfo &info
+// 				const int axis,
+// 				const float position,
+// 				int &raysBack,
+// 				int &raysFront,
+// 				int &pvsBack,
+// 				int &pvsFront
+				);
+
+  void
+  EvalCostRatioHeuristic(
+						 RssTreeLeaf *node,
+						 SplitInfo &info
+// 						 const int axis,
+// 						 float &position,
+// 						 int &raysBack,
+// 						 int &raysFront,
+// 						 int &pvsBack,
+// 						 int &pvsFront
+						 );
+
+  int
+  SelectPlane(RssTreeLeaf *leaf,
+			  const AxisAlignedBox3 &box,
+			  SplitInfo &info
+			  );
+  
+  void
+  GetCostRatio(
+			   RssTreeLeaf *leaf,
+			   SplitInfo &info
+			   // 			   const int axis,
+			   // 			   const float position,
+			   // 			   const int raysBack,
+			   // 			   const int raysFront,
+			   // 			   const int pvsBack,
+			   // 			   const int pvsFront
+			   );
+  
+  AxisAlignedBox3 GetBBox(const RssTreeNode *node) const {
+	return node->bbox;
+
+//     if (node->parent == NULL)
+//       return bbox;
+
+//     if (!node->IsLeaf())
+//       return ((RssTreeInterior *)node)->bbox;
+
+//     if (node->parent->axis >= 3)
+//       return node->parent->bbox;
+      
+//     AxisAlignedBox3 box(node->parent->bbox);
+//     if (node->parent->front == node)
+//       box.SetMin(node->parent->axis, node->parent->position);
+//     else
+//       box.SetMax(node->parent->axis, node->parent->position);
+//     return box;
+  }
+
+  AxisAlignedBox3 GetShrankedBBox(const RssTreeNode *node) const;
+
+  AxisAlignedBox3 GetDirBBox(const RssTreeNode *node) const {
+	return node->dirBBox;
+//     if (node->parent == NULL)
+//       return dirBBox;
+    
+//     if (!node->IsLeaf() )
+//       return ((RssTreeInterior *)node)->dirBBox;
+
+//     if (node->parent->axis < 3)
+//       return node->parent->dirBBox;
+    
+//     AxisAlignedBox3 dBBox(node->parent->dirBBox);
+
+//     if (node->parent->front == node)
+//       dBBox.SetMin(node->parent->axis - 3, node->parent->position);
+//     else
+//       dBBox.SetMax(node->parent->axis - 3, node->parent->position);
+//     return dBBox;
+  }
+  
+  int
+  ReleaseMemory(const int time);
+
+  int
+  CollapseSubtree(RssTreeNode *node, const int time);
+
+  void
+  CountAccess(RssTreeInterior *node, const long time) {
+    node->accesses++;
+    node->lastAccessTime = time;
+  }
+
+  RssTreeNode *
+  SubdivideLeaf(
+				RssTreeLeaf *leaf
+				);
+
+  void
+  RemoveRay(VssRay *ray,
+			vector<RssTreeLeaf *> *affectedLeaves,
+			const bool removeAllScheduledRays
+			);
+
+  //  void
+  //  AddRay(VssRay *ray);
+  void
+  AddRay(RssTreeNode::RayInfo &info);
+  
+  void
+  TraverseInternalNode(
+					   RayTraversalData &data,
+					   stack<RayTraversalData> &tstack);
+
+  void
+  EvaluateLeafStats(const TraversalData &data);
+
+
+  int
+  GetRootPvsSize() const {
+	return GetPvsSize(bbox);
+  }
+  
+  int
+  GetPvsSize(const AxisAlignedBox3 &box) const;
+
+  int
+  CollectPvs(const AxisAlignedBox3 &box,
+			 ObjectContainer &pvs
+			 ) const;
+
+  int
+  CollectRootPvs(
+				 ObjectContainer &pvs
+				 ) const
+  {
+	return CollectPvs(bbox, pvs);
+  }
+  
+	
+  void
+  UpdateTreeStatistics();
+
+
+  int
+  GenerateRays(const float ratioPerLeaf,
+			   SimpleRayContainer &rays);
+
+  int
+  GenerateRays(const int numberOfRays,
+			   const int numberOfLeaves,
+			   SimpleRayContainer &rays);
+		
+  float
+  GetAvgPvsSize();
+
+  int
+  UpdateSubdivision();
+
+  bool
+  TerminationCriteriaSatisfied(RssTreeLeaf *leaf);
+
+  void
+  CollectLeaves(vector<RssTreeLeaf *> &leaves);
+
+  bool
+  ClipRay(
+		  RssTreeNode::RayInfo &rayInfo,
+		  const AxisAlignedBox3 &box
+		  );
+
+  RssTreeNode *GetRoot(Intersectable *object = NULL) const;
+
+  bool
+  ValidLeaf(RssTreeLeaf *leaf) const;
+
+  void
+  GenerateLeafRays(RssTreeLeaf *leaf,
+				   const int numberOfRays,
+				   SimpleRayContainer &rays);
+
+
+  void
+  PickEdgeRays(RssTreeLeaf *leaf,
+			   int &r1,
+			   int &r2
+			   );
+
+    int
+  CollectRays(VssRayContainer &rays,
+			  const int number);
+
+  int
+  CollectRays(VssRayContainer &rays
+			  );
+
+  void
+  UpdatePvsSize(RssTreeLeaf *leaf);
+
+  void
+  ComputeImportance(RssTreeLeaf *leaf);
+  
+  void
+  SetPass(const int p) {
+	mCurrentPass = p;
+  }
+  
+  void GetRayContribution(const RssTreeNode::RayInfo &info,
+						  float &weight,
+						  float &contribution);
+
+  float
+  GetSampleWeight(const int pass);
+
+  int
+  RemoveInteriorRays(
+					 RssTreeLeaf *leaf
+					 );
+
+  bool
+  IsRayConvexCombination(const RssTreeNode::RayInfo &ray,
+						 const RssTreeNode::RayInfo &r1,
+						 const RssTreeNode::RayInfo &r2,
+						 const RssTreeNode::RayInfo &r3);
+
+  int
+  PruneRays(RssTreeLeaf *leaf,
+			const float contributionThreshold);
+  int
+  PruneRaysRandom(RssTreeLeaf *leaf,
+				  const float ratio);
+
+  int
+  PruneRaysContribution(RssTreeLeaf *leaf,
+						const float ratio);
+
+  int
+  PruneRays(
+			const int desired
+			);
+  
+
+  void
+  FindSilhouetteRays(RssTreeLeaf *leaf,
+					 vector<RssTreeLeaf::SilhouetteRays> &rays
+					 );
+
+  void
+  PushRoots(priority_queue<TraversalData> &stack) const;
+
+  void
+  PushRoots(stack<RssTreeNode *> &st) const;
+
+  void
+  PushRoots(stack<RayTraversalData> &st, RssTreeNode::RayInfo &info) const;
+
+
+};
+
+
+#endif // __LSDS_KDTREE_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Makefile
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Makefile	(revision 589)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Makefile	(revision 589)
@@ -0,0 +1,133 @@
+#############################################################################
+# Makefile for building: preprocessor
+# Generated by qmake (2.00a) (Qt 4.1.0) on: so 4. II 09:57:31 2006
+# Project:  preprocessor.pro
+# Template: app
+# Command: qmake -win32 -o Makefile preprocessor.pro
+#############################################################################
+
+first: release
+install: release-install
+uninstall: release-uninstall
+MAKEFILE      = Makefile
+QMAKE         = qmake
+DEL_FILE      = del
+CHK_DIR_EXISTS= if not exist
+MKDIR         = mkdir
+COPY          = copy /y
+COPY_FILE     = $(COPY)
+COPY_DIR      = xcopy /s /q /y /i
+INSTALL_FILE  = $(COPY_FILE)
+INSTALL_DIR   = $(COPY_DIR)
+DEL_FILE      = del
+SYMLINK       = 
+DEL_DIR       = rmdir
+MOVE          = move
+CHK_DIR_EXISTS= if not exist
+MKDIR         = mkdir
+SUBTARGETS    =  \
+		release \
+		debug
+
+release: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release
+release-make_default: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release 
+release-make_first: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release first
+release-all: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release all
+release-clean: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release clean
+release-distclean: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release distclean
+release-install: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release install
+release-uninstall: $(MAKEFILE).Release FORCE
+	$(MAKE) -f $(MAKEFILE).Release uninstall
+debug: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug
+debug-make_default: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug 
+debug-make_first: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug first
+debug-all: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug all
+debug-clean: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug clean
+debug-distclean: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug distclean
+debug-install: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug install
+debug-uninstall: $(MAKEFILE).Debug FORCE
+	$(MAKE) -f $(MAKEFILE).Debug uninstall
+
+Makefile: preprocessor.pro  D:/Qt/4.1.0/mkspecs/win32-msvc.net\qmake.conf D:/Qt/4.1.0/mkspecs/qconfig.pri \
+		D:\Qt\4.1.0\mkspecs\features\qt_config.prf \
+		D:\Qt\4.1.0\mkspecs\features\exclusive_builds.prf \
+		D:\Qt\4.1.0\mkspecs\features\default_pre.prf \
+		D:\Qt\4.1.0\mkspecs\features\win32\default_pre.prf \
+		D:\Qt\4.1.0\mkspecs\features\release.prf \
+		D:\Qt\4.1.0\mkspecs\features\debug_and_release.prf \
+		D:\Qt\4.1.0\mkspecs\features\default_post.prf \
+		D:\Qt\4.1.0\mkspecs\features\qt.prf \
+		D:\Qt\4.1.0\mkspecs\features\win32\opengl.prf \
+		D:\Qt\4.1.0\mkspecs\features\moc.prf \
+		D:\Qt\4.1.0\mkspecs\features\win32\thread.prf \
+		D:\Qt\4.1.0\mkspecs\features\warn_off.prf \
+		D:\Qt\4.1.0\mkspecs\features\win32\console.prf \
+		D:\Qt\4.1.0\mkspecs\features\win32\rtti.prf \
+		D:\Qt\4.1.0\mkspecs\features\win32\exceptions.prf \
+		D:\Qt\4.1.0\mkspecs\features\win32\stl.prf \
+		D:\Qt\4.1.0\mkspecs\features\shared.prf \
+		D:\Qt\4.1.0\mkspecs\features\resources.prf \
+		D:\Qt\4.1.0\mkspecs\features\uic.prf
+	$(QMAKE) -win32 -o Makefile preprocessor.pro
+D:/Qt/4.1.0/mkspecs/qconfig.pri:
+D:\Qt\4.1.0\mkspecs\features\qt_config.prf:
+D:\Qt\4.1.0\mkspecs\features\exclusive_builds.prf:
+D:\Qt\4.1.0\mkspecs\features\default_pre.prf:
+D:\Qt\4.1.0\mkspecs\features\win32\default_pre.prf:
+D:\Qt\4.1.0\mkspecs\features\release.prf:
+D:\Qt\4.1.0\mkspecs\features\debug_and_release.prf:
+D:\Qt\4.1.0\mkspecs\features\default_post.prf:
+D:\Qt\4.1.0\mkspecs\features\qt.prf:
+D:\Qt\4.1.0\mkspecs\features\win32\opengl.prf:
+D:\Qt\4.1.0\mkspecs\features\moc.prf:
+D:\Qt\4.1.0\mkspecs\features\win32\thread.prf:
+D:\Qt\4.1.0\mkspecs\features\warn_off.prf:
+D:\Qt\4.1.0\mkspecs\features\win32\console.prf:
+D:\Qt\4.1.0\mkspecs\features\win32\rtti.prf:
+D:\Qt\4.1.0\mkspecs\features\win32\exceptions.prf:
+D:\Qt\4.1.0\mkspecs\features\win32\stl.prf:
+D:\Qt\4.1.0\mkspecs\features\shared.prf:
+D:\Qt\4.1.0\mkspecs\features\resources.prf:
+D:\Qt\4.1.0\mkspecs\features\uic.prf:
+qmake: qmake_all FORCE
+	@$(QMAKE) -win32 -o Makefile preprocessor.pro
+
+qmake_all: FORCE
+
+make_default: release-make_default debug-make_default FORCE
+make_first: release-make_first debug-make_first FORCE
+all: release-all debug-all FORCE
+clean: release-clean debug-clean FORCE
+	-$(DEL_FILE) preprocessor.exp
+distclean: release-distclean debug-distclean FORCE
+	-$(DEL_FILE) Makefile
+
+release-mocclean: $(MAKEFILE).Release
+	$(MAKE) -f $(MAKEFILE).Release mocclean
+debug-mocclean: $(MAKEFILE).Debug
+	$(MAKE) -f $(MAKEFILE).Debug mocclean
+mocclean: release-mocclean debug-mocclean
+
+release-mocables: $(MAKEFILE).Release
+	$(MAKE) -f $(MAKEFILE).Release mocables
+debug-mocables: $(MAKEFILE).Debug
+	$(MAKE) -f $(MAKEFILE).Debug mocables
+mocables: release-mocables debug-mocables
+FORCE:
+
+$(MAKEFILE).Release: Makefile
+$(MAKEFILE).Debug: Makefile
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Camera.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Camera.h	(revision 492)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Camera.h	(revision 492)
@@ -0,0 +1,76 @@
+#ifndef __CAMERA_H
+#define __CAMERA_H
+
+#include "Vector3.h"
+#include "AxisAlignedBox3.h"
+
+class KdTree;
+class SceneGraph;
+
+class Camera
+{
+public:
+  Vector3 mPosition;
+  Vector3 mDirection;
+  /** up vector takes into account the FOV at a unit distance from the origin */
+  Vector3 mUp;
+  /** right vector takes into account the FOV at a unit distance from the origin */
+  Vector3 mRight;
+
+  float mFovy;
+  int mWidth;
+  int mHeight;
+  
+  Camera() {
+    mWidth = 1400;
+    mHeight = 1000;
+    mFovy = 60.0f*(float)M_PI/180.0f;
+  }
+  
+  void Precompute() {
+    mDirection.Normalize();
+    Vector3 side = CrossProd(Vector3(0,1,0), mDirection);
+    mUp = Normalize(CrossProd(side, mDirection));
+    mRight = Normalize(CrossProd(mDirection, mUp));
+    float k = tan(mFovy/2);
+    mUp *= k;
+    mRight *= k*mWidth/mHeight;
+  }
+
+  void SetPosition(const Vector3 &pos) {
+    mPosition = pos;
+    Precompute();
+  }
+
+	void SetDirection(const Vector3 &dir) {
+    mDirection = dir;
+    Precompute();
+  }
+
+  void LookInBox(const AxisAlignedBox3 &box)
+  {
+    mDirection = Vector3(0,0,1); 
+    mPosition = box.Center();
+    Precompute();
+  }
+    
+
+  void LookAtBox(const AxisAlignedBox3 &box)
+  {
+    mDirection = box.Max() - box.Min();
+    mPosition = box.Min() - mDirection;
+    Precompute();
+  }
+  
+  bool
+  SnapImage(string filename,
+			KdTree *tree,
+			SceneGraph *sceneGraph
+			);
+
+  void SetupRay(Ray &ray, const int x, const int y);
+
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 610)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 610)
@@ -0,0 +1,846 @@
+#ifndef _ViewCellsManager_H__
+#define _ViewCellsManager_H__
+
+#include "Ray.h"
+#include "VssRay.h"
+#include "Containers.h"
+#include "ViewCell.h"
+#include "ViewCellBsp.h"
+
+class ViewCell;
+class Intersectable;
+class RenderSimulator;
+class Renderer;
+class Mesh;
+struct Triangle3;
+class SimulationStatistics;
+class BspTree;
+class KdTree;
+class VspKdTree;
+class VspBspTree;
+class KdNode;
+class KdLeaf;
+class VspKdTree;
+class AxisAlignedBox3;
+class BspLeaf;
+class ViewCellsStatistics;
+class Exporter;
+class Beam;
+class Preprocessor;
+class ViewCellsTree;
+class MergeCandidate;
+
+struct BspRay;
+
+/**
+	Manages different higher order operations on the view cells.
+*/
+class ViewCellsManager
+{
+
+public:
+  struct PvsStatistics {
+	int minPvs;
+	int maxPvs;
+	float avgPvs;
+	int viewcells;
+  };
+  
+  /// view cell container types
+  enum {BSP, KD, VSP_KD, VSP_BSP};
+  
+	/** Constructor taking the initial and construction samples.
+		@param initialSamples the maximal number of samples used for creating the hierarchy
+		of view cells
+		@param constructionSamples the maximal number of samples used for construction
+	*/
+	ViewCellsManager(const int initialSamples, const int constructionSamples);
+
+	ViewCellsManager();
+
+	virtual ~ViewCellsManager();
+
+	/** Constructs view cells container taking a preprocessor
+		@returns the output rays (if not null)
+	*/ 
+	int Construct(Preprocessor *preprocessor, VssRayContainer *outRays = NULL);
+
+	/** Constructs view cell container with a given number of samples.
+	*/
+	virtual int ConstructSubdivision(const ObjectContainer &objects, 
+						  const VssRayContainer &rays) = 0;
+
+	/** Computes sample contributions of the rays to the view cells PVS.
+	
+		@param rays bundle of rays used to find intersections with view cells and 
+		adding the contribution
+		@param addRays true if rays should be added to the PVSs of the viewcells they
+		intersect 
+		@param storeViewCells true if view cells should be stored in the ray
+	*/
+  float ComputeSampleContributions(const VssRayContainer &rays,
+								   const bool addContributions,
+								   const bool storeViewCells);
+
+  /** Add sample contributions to the viewcells they intersect */
+  void AddSampleContributions(const VssRayContainer &rays);
+  
+
+	/** Computes sample contribution of a simgle ray to the view cells PVS.
+		@param ray finds intersections with view cells and holds the contribution
+		@param castRay true if ray should be cast to gain the information, false if ray
+		is already holding the information and need not be recast.
+	  
+		@returns number of sample contributions
+	*/
+	virtual float ComputeSampleContributions(VssRay &ray, 
+											 const bool addRays, 
+											 const bool storeViewCells);
+
+	virtual void AddSampleContributions(VssRay &ray);
+
+	/** Prints out statistics of the view cells.
+	*/
+	virtual void PrintStatistics(ostream &s) const;
+
+	/** Post processes view cells givemŽa number of rays.
+	*/
+	virtual int PostProcess(const ObjectContainer &objects, 
+							const VssRayContainer &rays) = 0;
+
+	/** Show visualization of the view cells.
+	*/
+	virtual void Visualize(const ObjectContainer &objects,
+						   const VssRayContainer &sampleRays) = 0;
+
+	/** type of the view cell container.
+	*/
+	virtual int GetType() const = 0;
+
+	/** Load the input viewcells. The input viewcells should be given as a collection
+		of meshes. Each mesh is assume to form a bounded polyhedron defining the interior of
+		the viewcell. The method then builds a BSP tree of these view cells.
+		
+		@param filename file to load
+		@return true on success
+    */
+    virtual bool LoadViewCellsGeometry(const string filename);
+
+	
+	/** Constructs view cell from base triangle. The ViewCell is extruded along the normal vector.
+		@param the base triangle
+		@param the height of the newly created view cell
+	*/
+	ViewCell *ExtrudeViewCell(const Triangle3 &baseTri, const float height) const;
+
+	/** Merges two view cells.
+		@note the piercing rays of the front and back will be ordered	
+		@returns new view cell based on the merging.
+	*/
+	ViewCellInterior *MergeViewCells(ViewCell *front, ViewCell *back) const;
+
+	/** Merges a container of view cells.
+		@returns new view cell based on the merging.
+	*/
+	ViewCellInterior *MergeViewCells(ViewCellContainer &children) const;
+	
+	/** Generates view cell of type specified by this manager
+	*/
+	virtual ViewCell *GenerateViewCell(Mesh *mesh = NULL) const = 0;
+
+	/** Adds a new view cell to the list of predefined view cells.
+	*/
+	void AddViewCell(ViewCell *viewCell);
+
+	/** Derive view cells from objects.
+	*/
+	void DeriveViewCells(const ObjectContainer &objects, 
+						 ViewCellContainer &viewCells, 
+						 const int maxViewCells) const;
+
+	/** Sets maximal number of samples used for the 
+		construction of the view cells.
+	*/
+	void SetVisualizationSamples(const int visSamples);
+
+	/** Sets maximal number of samples used for the construction of the view cells.
+	*/
+	void SetConstructionSamples(const int constructionSamples);
+
+	/** Sets maximal number of samples used for the visualization of the view cells.
+	*/
+	void SetInitialSamples(const int initialSamples);
+
+	/** Sets maximal number of samples used for the post processing of the view cells.
+	*/
+	void SetPostProcessSamples(const int postProcessingSamples);
+
+	/** See set.
+	*/
+	int GetVisualizationSamples() const;
+
+	/** See set.
+	*/
+	int GetConstructionSamples() const;
+
+	/** See set.
+	*/
+	int GetPostProcessSamples() const;
+
+	/** Returns true if view cells wer already constructed.
+	*/
+	virtual bool ViewCellsConstructed() const = 0;
+
+	/** cast line segment to get a list of unique viewcells which are intersected
+		by this line segment 
+	*/
+  
+	virtual int CastLineSegment(const Vector3 &origin,
+							  const Vector3 &termination,
+							  ViewCellContainer &viewcells
+							  ) = 0;
+
+	virtual void GetPvsStatistics(PvsStatistics &stat);
+
+	/** Get a viewcell containing the specified point */
+	virtual ViewCell *GetViewCell(const Vector3 &point) const = 0;
+  
+	virtual void PrintPvsStatistics(ostream &s);
+
+	/** Returns probability that view point lies in one view cell.
+	*/
+	virtual float GetProbability(ViewCell *viewCell) = 0;
+
+	/** Returns render cost of a single view cell given the render cost of an object.
+	*/
+	float GetRendercost(ViewCell *viewCell, float objRendercost) const;
+
+	/** Returns container of loaded / generated view cells.
+	*/
+	ViewCellContainer &GetViewCells();
+
+	/** Helper function used to split ray sets uniformly 
+		into one that is currently used and the other that 
+		is saved for later processing.
+		@param sourceRays the input ray set
+		@param maxSize the maximal number of rays that will be used
+		@param usedRays returns the used ray set
+		@param savedRays if not null, returns the saved ray set
+	*/
+	void GetRaySets(const VssRayContainer &sourceRays,
+					const int maxSize,
+					VssRayContainer &usedRays, 
+					VssRayContainer *savedRays = NULL) const;
+	
+	/** Returns accumulated area of all view cells.
+	*/
+	float GetAccVcArea();
+
+	/** Returns area of one view cell.
+	*/
+	virtual float GetArea(ViewCell *viewCell) const;
+
+	/** Returns volume of view cell.
+	*/
+	virtual float GetVolume(ViewCell *viewCell) const;
+
+	/** Sets the current renderer mainly for view cells statistics.
+	*/
+	void SetRenderer(Renderer *renderer);
+
+	/** Computes a (random) view point in the valid view space.
+		@returns true if valid view point was found
+	*/
+	virtual bool GetViewPoint(Vector3 &viewPoint) const;
+
+	/** Returns true if this view point is in the valid view space.
+	*/
+	virtual bool ViewPointValid(const Vector3 &viewPoint) const;
+
+	/** Sets a view space boundary.
+	*/
+	void SetViewSpaceBox(const AxisAlignedBox3 &box);
+
+	AxisAlignedBox3 GetViewSpaceBox() const;
+
+	/** Creates mesh for this view cell.
+	*/
+	virtual void CreateMesh(ViewCell *vc) = NULL;
+
+	/** Writes view cells to disc.
+	*/
+	virtual bool ExportViewCells(const string filename);
+
+	/** Casts beam to collect view cells.
+	*/
+	virtual int CastBeam(Beam &beam);
+
+	/** Checks if view cell is considered as valid.
+	*/
+	virtual bool CheckValidity(ViewCell *vc, 
+							   int minPvsSize, 
+							   int maxPvsSize) const;
+
+	
+	/** Sets validity of view cell
+	*/
+	virtual void SetValidity(ViewCell *vc, 
+							 int minPvsSize, 
+							 int maxPvsSize) const;
+
+  /** sets validy of all viewcells */
+  	virtual void SetValidity(
+							 int minPvsSize, 
+							 int maxPvsSize) const;
+
+
+	/** set valid viewcells in the range of pvs. sorts the viewcells
+	  according to the pvs and then pickups those in the ranges */
+
+    
+	void SetValidityPercentage(const float minValid,	const float maxValid);
+
+    int CountValidViewcells() const;
+
+	/** Returns maximal allowed pvs size.
+	*/
+	int GetMaxPvsSize() const;
+
+	/** Returns maximal allowed pvs size.
+	*/
+	int GetMinPvsSize() const;
+
+	/** Returns maximal ratio. i.e., currentPVs / maxPvs,
+		where pvs is still considered valid.
+	*/
+	float GetMaxPvsRatio() const;
+
+	/** Exports view cell geometry.
+	*/
+	virtual void ExportViewCellGeometry(Exporter *exporter, 
+										ViewCell *vc,
+										const Plane3 *cuttingPlane = NULL) const = 0;
+
+	virtual void FinalizeViewCells(const bool createMesh);
+
+
+	/** Loads view cells from file. The view cells manager is created with 
+		respect to the loaded view cells.
+
+		@returns the view cells manager if loading was successful, false otherwise
+	*/
+	static ViewCellsManager *LoadViewCells(const string filename, 
+										   ObjectContainer *objects);
+
+	/** Evaluates statistics values on view cells.
+	*/
+	void EvaluateRenderStatistics(float &totalRenderCost,
+								  float &expectedRenderCost,
+								  float &deviation,
+								  float &variance,
+								  int &totalPvs,
+								  float &avgRenderCost);
+
+
+	/** Returns hierarchy of the view cells.
+	*/
+	ViewCellsTree *GetViewCellsTree();
+
+	virtual void CollectMergeCandidates(const VssRayContainer &rays, 
+										vector<MergeCandidate> &candidates) = 0;
+
+	void CollectViewCells(const int n);
+
+
+	virtual void CreateMergeHierarchy() {};
+	
+	virtual bool EqualToSpatialNode(ViewCell *viewCell) const { return false;}
+
+
+protected:
+
+
+	/**
+		if the view cells tree was already constructed or not.
+	*/
+	bool ViewCellsTreeConstructed() const;
+
+	int CastPassSamples(const int samplesPerPass, 
+						const int sampleType, 
+						VssRayContainer &vssRays) const;
+
+	void ParseEnvironment();
+
+	/** Creates unique view cell ids.
+	*/
+	void CreateUniqueViewCellIds();
+
+	/** Finalizes, i.e., creates mesh, volume, area etc. for the view cell.
+	*/
+	virtual void Finalize(ViewCell *viewCell, const bool createMesh);
+
+	/** Recollects view cells and resets statistics.
+	*/
+	void ResetViewCells();
+	
+	/** Collects the view cells in the view cell container.
+	*/
+	virtual void CollectViewCells() = 0;
+	
+	/** Evaluates view cells statistics and stores it in
+		mViewCellsStatistics.
+	*/
+	void EvaluateViewCellsStats();
+
+	//-- helper functions for view cell visualization
+
+	/** Exports the view cell partition.
+	*/
+	void ExportViewCellsForViz(Exporter *exporter) const;
+
+	/** Sets exporter color.
+	*/
+	virtual void ExportColor(Exporter *exporter, ViewCell *vc) const = 0;
+
+
+	virtual float GetViewSpaceVolume();
+	
+	/** Creates meshes from the view cells.
+	*/
+	void CreateViewCellMeshes();
+
+
+	/** Takes different measures to prepares the view cells after loading them from disc.
+	*/
+	virtual void PrepareLoadedViewCells() {};
+
+
+	void CreateCuttingPlane();
+
+	Plane3 mCuttingPlane;
+	bool mUseCuttingPlaneForViz;
+
+
+	/// Renders the view cells.
+	Renderer *mRenderer;
+
+	/// Loaded view cells
+	ViewCellContainer mViewCells;
+
+	ViewCellsTree *mViewCellsTree;
+
+	/// maximum number of samples taken for construction of the view cells
+	int mConstructionSamples;
+	int mSamplesPerPass;
+	int mInitialSamples;
+	int mPostProcessSamples;
+	int mVisualizationSamples;
+
+	float mTotalAreaValid;
+	float mTotalArea;
+
+	int mMaxPvsSize;
+	int mMinPvsSize;
+	float mMaxPvsRatio;
+
+	int mNumActiveViewCells;
+	bool mCompressViewCells;
+
+	ViewCellsStatistics mViewCellsStats;
+	/// the scene bounding box
+	AxisAlignedBox3 mViewSpaceBox;
+	/// holds the view cell meshes
+	MeshContainer mMeshContainer;
+	/// if view cells should be exported
+	bool mExportViewCells;
+
+	//bool mMarchTree);
+	bool mOnlyValidViewCells;
+
+	/// if rays should be used to collect merge candidates
+	bool mUseRaysForMerge;
+	
+	bool mMergeViewCells;
+	
+	//-- visualization options
+	
+	/// color code for view cells
+	int mColorCode;
+	bool mExportGeometry;
+	bool mExportRays;
+
+	bool mViewCellsFinished;
+};
+
+
+
+/**
+	Manages different higher order operations on the view cells.
+*/
+class BspViewCellsManager: public ViewCellsManager
+{
+
+public:
+	/** Constructor taking the bsp tree and the number of samples
+		used to construct the bsp tree.
+	*/
+	BspViewCellsManager(BspTree *tree);
+
+	~BspViewCellsManager();
+
+	int ConstructSubdivision(const ObjectContainer &objects, 
+				  const VssRayContainer &rays);
+
+	int PostProcess(const ObjectContainer &objects, 
+					const VssRayContainer &rays);
+
+	void Visualize(const ObjectContainer &objects,
+				   const VssRayContainer &sampleRays);
+
+	int GetType() const;
+	
+	ViewCell *GenerateViewCell(Mesh *mesh = NULL) const;
+
+	bool ViewCellsConstructed() const;
+
+	//void PrintStatistics(ostream &s) const;
+
+	int CastLineSegment(const Vector3 &origin,
+						const Vector3 &termination,
+						ViewCellContainer &viewcells);
+	
+	float GetProbability(ViewCell *viewCell);
+	
+
+	/** Get a viewcell containing the specified point */
+	ViewCell *GetViewCell(const Vector3 &point) const;
+
+	void CreateMesh(ViewCell *vc);
+
+	void ExportViewCellGeometry(Exporter *exporter, 
+								ViewCell *vc, 
+								const Plane3 *cuttingPlane = NULL) const;
+	
+	void CollectMergeCandidates(const VssRayContainer &rays, 
+								vector<MergeCandidate> &candidates);
+
+	void Finalize(ViewCell *viewCell, const bool createMesh);
+
+	bool ExportViewCells(const string filename);
+
+	void CreateMergeHierarchy();
+
+
+protected:
+
+	struct TraversalData
+	{  
+		ViewCellInterior *mParentViewCell;
+		BspNode *mNode;
+		
+
+		TraversalData() {}
+		TraversalData(BspNode *node, ViewCellInterior *vc):
+			 mNode(node), mParentViewCell(vc)
+		{}
+   
+		bool operator<(const TraversalData &b) const 
+		{
+			return mNode->mTimeStamp < b.mNode->mTimeStamp;
+		}
+	};
+
+	typedef priority_queue<TraversalData> TraversalQueue;
+
+	/** HACK
+	*/
+	void AddCurrentViewCellsToHierarchy();
+
+	void CollectViewCells();
+
+	void ExportColor(Exporter *exporter, ViewCell *vc) const;
+	
+
+
+	/// the BSP tree.
+	BspTree *mBspTree;
+	
+	vector<BspRay *> mBspRays;
+
+private:
+
+	/** Exports visualization of the BSP splits.
+	*/
+	void ExportSplits(const ObjectContainer &objects);
+
+	/** Exports visualization of the BSP PVS.
+	*/
+	void ExportBspPvs(const ObjectContainer &objects);
+
+};
+
+/**
+	Manages different higher order operations on the KD type view cells.
+*/
+class KdViewCellsManager: public ViewCellsManager
+{
+
+public:
+
+	KdViewCellsManager(KdTree *tree);
+
+	int ConstructSubdivision(const ObjectContainer &objects, 
+				  const VssRayContainer &rays);
+
+	int CastLineSegment(const Vector3 &origin,
+						const Vector3 &termination,
+						ViewCellContainer &viewcells);
+
+	int PostProcess(const ObjectContainer &objects, 
+					const VssRayContainer &rays);
+
+	void Visualize(const ObjectContainer &objects,
+				   const VssRayContainer &sampleRays);
+
+	int GetType() const;
+
+	bool ViewCellsConstructed() const;
+
+	ViewCell *GenerateViewCell(Mesh *mesh) const;
+
+	/** Prints out statistics of this approach.
+	*/
+	//  virtual void PrintStatistics(ostream &s) const;
+	ViewCell *GetViewCell(const Vector3 &point) const { return NULL; }
+
+	float GetProbability(ViewCell *viewCell);
+	
+
+	void CreateMesh(ViewCell *vc);
+
+	void ExportViewCellGeometry(Exporter *exporter, 
+								ViewCell *vc,
+								const Plane3 *cuttingPlane = NULL) const;
+
+	void CollectMergeCandidates(const VssRayContainer &rays, 
+								vector<MergeCandidate> &candidates);
+
+protected:
+
+	/** Collects view cells from a hierarchy.
+	*/
+	void CollectViewCells();
+
+	KdNode *GetNodeForPvs(KdLeaf *leaf);
+
+	void ExportColor(Exporter *exporter, ViewCell *vc) const;
+
+
+	/// the BSP tree.
+	KdTree *mKdTree;
+
+	/// depth of the KD tree nodes with represent the view cells
+	int mKdPvsDepth;
+};
+
+/**
+	Manages different higher order operations on the view cells 
+	for vsp kd tree view cells.
+*/
+class VspKdViewCellsManager: public ViewCellsManager
+{
+
+public:
+
+	VspKdViewCellsManager(VspKdTree *vspKdTree);
+
+	int ConstructSubdivision(const ObjectContainer &objects, 
+				  const VssRayContainer &rays);
+
+
+	int PostProcess(const ObjectContainer &objects, 
+					const VssRayContainer &rays);
+
+	void Visualize(const ObjectContainer &objects,
+				   const VssRayContainer &sampleRays);
+
+	int GetType() const;
+	
+	bool ViewCellsConstructed() const;
+
+	//virtual void PrintStatistics(ostream &s) const;
+
+	ViewCell *GenerateViewCell(Mesh *mesh) const;
+
+
+    int CastLineSegment(const Vector3 &origin,
+						const Vector3 &termination,
+						ViewCellContainer &viewcells);
+
+	ViewCell *GetViewCell(const Vector3 &point) const { return NULL; }
+
+	float GetProbability(ViewCell *viewCell);
+
+
+	void CreateMesh(ViewCell *vc);
+
+	void ExportViewCellGeometry(Exporter *exporter, 
+								ViewCell *vc,
+								const Plane3 *cuttingPlane = NULL) const;
+
+	void CollectMergeCandidates(const VssRayContainer &rays, vector<MergeCandidate> &candidates);
+
+protected:
+
+	void ExportLeaves(const ObjectContainer &objects,
+					  const VssRayContainer &sampleRays);
+
+	void CollectViewCells();
+
+	void ExportColor(Exporter *exporter, ViewCell *vc) const;
+
+
+
+	/// the BSP tree.
+	VspKdTree *mVspKdTree;
+};
+
+
+
+/**
+	Manages different higher order operations on the view cells.
+*/
+class VspBspViewCellsManager: public ViewCellsManager
+{
+
+public:
+
+	VspBspViewCellsManager(VspBspTree *tree);
+	~VspBspViewCellsManager();
+
+	int ConstructSubdivision(const ObjectContainer &objects, 
+				  const VssRayContainer &rays);
+
+	int PostProcess(const ObjectContainer &objects, 
+					const VssRayContainer &rays);
+
+	void Visualize(const ObjectContainer &objects,
+				   const VssRayContainer &sampleRays);
+
+	int GetType() const;
+	
+	ViewCell *GenerateViewCell(Mesh *mesh = NULL) const;
+
+	bool ViewCellsConstructed() const;
+
+	
+	int CastLineSegment(const Vector3 &origin,
+						const Vector3 &termination,
+						ViewCellContainer &viewcells);
+
+	float GetProbability(ViewCell *viewCell);
+	
+	ViewCell *GetViewCell(const Vector3 &point) const;
+
+	bool GetViewPoint(Vector3 &viewPoint) const;
+
+	bool ViewPointValid(const Vector3 &viewPoint) const;
+
+	void CreateMesh(ViewCell *vc);
+
+	//bool LoadViewCellsGeometry(const string filename, ObjectContainer *objects);
+	bool ExportViewCells(const string filename);
+
+	int CastBeam(Beam &beam);
+
+	void ExportViewCellGeometry(Exporter *exporter, 
+								ViewCell *vc,
+								const Plane3 *cuttingPlane = NULL) const;
+
+	//float GetVolume(ViewCell *viewCell) const;
+
+	void Finalize(ViewCell *viewCell, const bool createMesh);
+
+	void CollectMergeCandidates(const VssRayContainer &rays, vector<MergeCandidate> &candidates);
+
+	bool EqualToSpatialNode(ViewCell *viewCell) const;
+
+protected:
+
+	struct TraversalData
+	{  
+		ViewCellInterior *mParentViewCell;
+		BspNode *mNode;
+		
+
+		TraversalData() {}
+		TraversalData(BspNode *node, ViewCellInterior *vc):
+			 mNode(node), mParentViewCell(vc)
+		{}
+   
+		bool operator<(const TraversalData &b) const 
+		{
+			return mNode->mTimeStamp < b.mNode->mTimeStamp;
+		}
+	};
+
+	typedef priority_queue<TraversalData> TraversalQueue;
+
+	/** Returns node of the spatial hierarchy corresponding to the view cell
+		if such a node exists.
+	*/
+	BspNode *GetSpatialNode(ViewCell *viewCell) const;
+
+	/** HACK
+	*/
+	void AddCurrentViewCellsToHierarchy();
+
+	/** Merges the view cells.
+	*/
+	void MergeViewCells(const VssRayContainer &rays, 
+						const ObjectContainer &objects);
+	
+	void RefineViewCells(const VssRayContainer &rays, const ObjectContainer &objects);
+
+	void CollectViewCells();
+
+	/** Returns maximal depth difference of view cell 
+		leaves in tree.
+	*/
+	int GetMaxTreeDiff(ViewCell *vc) const;
+	
+
+	void ExportColor(Exporter *exporter, ViewCell *vc) const;
+
+	void PrepareLoadedViewCells();
+
+	void CreateMergeHierarchy();
+	/// the view space partition BSP tree.
+	VspBspTree *mVspBspTree;
+
+
+private:
+
+	/** Exports visualization of the BSP splits.
+	*/
+	void ExportSplits(const ObjectContainer &objects, 
+					  const VssRayContainer &rays);
+
+	/** Exports visualization of the BSP PVS.
+	*/
+	void ExportBspPvs(const ObjectContainer &objects,
+					  const VssRayContainer &rays);
+
+};
+
+
+class ViewCellsManagerFactory
+{
+
+public:
+
+	ViewCellsManager *Create(const string mName);
+
+};
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 612)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 612)
@@ -0,0 +1,3150 @@
+#include <stack>
+#include <time.h>
+#include <iomanip>
+
+#include "Plane3.h"
+#include "VspBspTree.h"
+#include "Mesh.h"
+#include "common.h"
+#include "ViewCell.h"
+#include "Environment.h"
+#include "Polygon3.h"
+#include "Ray.h"
+#include "AxisAlignedBox3.h"
+#include "Exporter.h"
+#include "Plane3.h"
+#include "ViewCellBsp.h"
+#include "ViewCellsManager.h"
+#include "Beam.h"
+
+
+//-- static members
+
+/** Evaluates split plane classification with respect to the plane's
+	contribution for a minimum number of ray splits.
+*/
+const float VspBspTree::sLeastRaySplitsTable[] = {0, 0, 1, 1, 0};
+/** Evaluates split plane classification with respect to the plane's
+	contribution for  balanced rays.
+*/
+const float VspBspTree::sBalancedRaysTable[] = {1, -1, 0, 0, 0};
+
+
+int VspBspTree::sFrontId = 0;
+int VspBspTree::sBackId = 0;
+int VspBspTree::sFrontAndBackId = 0;
+
+
+
+
+// pvs penalty can be different from pvs size
+inline float EvalPvsPenalty(const int pvs, 
+							const int lower,
+							const int upper)
+{
+	// clamp to minmax values
+	if (pvs < lower)
+		return (float)lower;
+	if (pvs > upper)
+		return (float)upper;
+
+	return (float)pvs;
+}
+
+
+
+
+/******************************************************************************/
+/*                       class VspBspTree implementation                      */
+/******************************************************************************/
+
+
+VspBspTree::VspBspTree():
+mRoot(NULL),
+mUseAreaForPvs(false),
+mCostNormalizer(Limits::Small),
+mViewCellsManager(NULL),
+mOutOfBoundsCell(NULL),
+mStoreRays(false),
+mRenderCostWeight(0.5),
+mUseRandomAxis(false),
+mTimeStamp(0)
+{
+	bool randomize = false;
+	environment->GetBoolValue("VspBspTree.Construction.randomize", randomize);
+	if (randomize)
+		Randomize(); // initialise random generator for heuristics
+
+	//-- termination criteria for autopartition
+	environment->GetIntValue("VspBspTree.Termination.maxDepth", mTermMaxDepth);
+	environment->GetIntValue("VspBspTree.Termination.minPvs", mTermMinPvs);
+	environment->GetIntValue("VspBspTree.Termination.minRays", mTermMinRays);
+	environment->GetFloatValue("VspBspTree.Termination.minProbability", mTermMinProbability);
+	environment->GetFloatValue("VspBspTree.Termination.maxRayContribution", mTermMaxRayContribution);
+	environment->GetFloatValue("VspBspTree.Termination.minAccRayLenght", mTermMinAccRayLength);
+	environment->GetFloatValue("VspBspTree.Termination.maxCostRatio", mTermMaxCostRatio);
+	environment->GetIntValue("VspBspTree.Termination.missTolerance", mTermMissTolerance);
+	environment->GetIntValue("VspBspTree.Termination.maxViewCells", mMaxViewCells);
+	//-- max cost ratio for early tree termination
+	environment->GetFloatValue("VspBspTree.Termination.maxCostRatio", mTermMaxCostRatio);
+
+	// HACK
+	mTermMinPolygons = 25;
+
+	//-- factors for bsp tree split plane heuristics
+	environment->GetFloatValue("VspBspTree.Factor.balancedRays", mBalancedRaysFactor);
+	environment->GetFloatValue("VspBspTree.Factor.pvs", mPvsFactor);
+	environment->GetFloatValue("VspBspTree.Termination.ct_div_ci", mCtDivCi);
+
+
+	//-- partition criteria
+	environment->GetIntValue("VspBspTree.maxPolyCandidates", mMaxPolyCandidates);
+	environment->GetIntValue("VspBspTree.maxRayCandidates", mMaxRayCandidates);
+	environment->GetIntValue("VspBspTree.splitPlaneStrategy", mSplitPlaneStrategy);
+
+	environment->GetFloatValue("VspBspTree.Construction.epsilon", mEpsilon);
+	environment->GetIntValue("VspBspTree.maxTests", mMaxTests);
+
+	// if only the driving axis is used for axis aligned split
+	environment->GetBoolValue("VspBspTree.splitUseOnlyDrivingAxis", mOnlyDrivingAxis);
+	
+	//-- termination criteria for axis aligned split
+	environment->GetFloatValue("VspBspTree.Termination.AxisAligned.maxRayContribution", 
+		mTermMaxRayContriForAxisAligned);
+	environment->GetIntValue("VspBspTree.Termination.AxisAligned.minRays",
+		mTermMinRaysForAxisAligned);
+
+	//environment->GetFloatValue("VspBspTree.maxTotalMemory", mMaxTotalMemory);
+	environment->GetFloatValue("VspBspTree.maxStaticMemory", mMaxMemory);
+
+	environment->GetFloatValue("VspBspTree.Construction.renderCostWeight", mRenderCostWeight);
+
+	environment->GetBoolValue("VspBspTree.usePolygonSplitIfAvailable", mUsePolygonSplitIfAvailable);
+
+	mSubdivisionStats.open("subdivisionStats.log");
+
+	environment->GetBoolValue("VspBspTree.useCostHeuristics", mUseCostHeuristics);
+
+
+	//-- debug output
+
+	Debug << "******* VSP BSP options ******** " << endl;
+    Debug << "max depth: " << mTermMaxDepth << endl;
+	Debug << "min PVS: " << mTermMinPvs << endl;
+	Debug << "min probabiliy: " << mTermMinProbability << endl;
+	Debug << "min rays: " << mTermMinRays << endl;
+	Debug << "max ray contri: " << mTermMaxRayContribution << endl;
+	//Debug << "VSP BSP mininam accumulated ray lenght: ", mTermMinAccRayLength) << endl;
+	Debug << "max cost ratio: " << mTermMaxCostRatio << endl;
+	Debug << "miss tolerance: " << mTermMissTolerance << endl;
+	Debug << "max view cells: " << mMaxViewCells << endl;
+	Debug << "max polygon candidates: " << mMaxPolyCandidates << endl;
+	Debug << "max plane candidates: " << mMaxRayCandidates << endl;
+	Debug << "randomize: " << randomize << endl;
+
+	Debug << "using area for pvs: " << mUseAreaForPvs << endl;
+	Debug << "render cost weight: " << mRenderCostWeight << endl;
+	Debug << "Split plane strategy: ";
+
+	if (mSplitPlaneStrategy & RANDOM_POLYGON)
+	{
+		Debug << "random polygon ";
+	}
+	if (mSplitPlaneStrategy & AXIS_ALIGNED)
+	{
+		Debug << "axis aligned ";
+	}
+	if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
+	{
+		mCostNormalizer += mLeastRaySplitsFactor;
+		Debug << "least ray splits ";
+	}
+	if (mSplitPlaneStrategy & BALANCED_RAYS)
+	{
+		mCostNormalizer += mBalancedRaysFactor;
+		Debug << "balanced rays ";
+	}
+	if (mSplitPlaneStrategy & PVS)
+	{
+		mCostNormalizer += mPvsFactor;
+		Debug << "pvs";
+	}
+
+
+	mSplitCandidates = new vector<SortableEntry>;
+
+	Debug << endl;
+}
+
+
+BspViewCell *VspBspTree::GetOutOfBoundsCell()
+{
+	return mOutOfBoundsCell;
+}
+
+
+BspViewCell *VspBspTree::GetOrCreateOutOfBoundsCell()
+{
+	if (!mOutOfBoundsCell)
+	{
+		mOutOfBoundsCell = new BspViewCell();
+		mOutOfBoundsCell->SetId(-1);
+		mOutOfBoundsCell->SetValid(false);
+	}
+
+	return mOutOfBoundsCell;
+}
+
+
+const BspTreeStatistics &VspBspTree::GetStatistics() const
+{
+	return mBspStats;
+}
+
+
+VspBspTree::~VspBspTree()
+{
+	DEL_PTR(mRoot);
+	DEL_PTR(mSplitCandidates);
+}
+
+
+int VspBspTree::AddMeshToPolygons(Mesh *mesh,
+								  PolygonContainer &polys,
+								  MeshInstance *parent)
+{
+	FaceContainer::const_iterator fi;
+
+	// copy the face data to polygons
+	for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi)
+	{
+		Polygon3 *poly = new Polygon3((*fi), mesh);
+
+		if (poly->Valid(mEpsilon))
+		{
+			poly->mParent = parent; // set parent intersectable
+			polys.push_back(poly);
+		}
+		else
+			DEL_PTR(poly);
+	}
+	return (int)mesh->mFaces.size();
+}
+
+
+int VspBspTree::AddToPolygonSoup(const ViewCellContainer &viewCells,
+							  PolygonContainer &polys,
+							  int maxObjects)
+{
+	int limit = (maxObjects > 0) ?
+		Min((int)viewCells.size(), maxObjects) : (int)viewCells.size();
+
+	int polysSize = 0;
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		if (viewCells[i]->GetMesh()) // copy the mesh data to polygons
+		{
+			mBox.Include(viewCells[i]->GetBox()); // add to BSP tree aabb
+			polysSize +=
+				AddMeshToPolygons(viewCells[i]->GetMesh(),
+								  polys,
+								  viewCells[i]);
+		}
+	}
+
+	return polysSize;
+}
+
+
+int VspBspTree::AddToPolygonSoup(const ObjectContainer &objects,
+								 PolygonContainer &polys,
+								 int maxObjects)
+{
+	int limit = (maxObjects > 0) ?
+		Min((int)objects.size(), maxObjects) : (int)objects.size();
+
+	for (int i = 0; i < limit; ++i)
+	{
+		Intersectable *object = objects[i];//*it;
+		Mesh *mesh = NULL;
+
+		switch (object->Type()) // extract the meshes
+		{
+		case Intersectable::MESH_INSTANCE:
+			mesh = dynamic_cast<MeshInstance *>(object)->GetMesh();
+			break;
+		case Intersectable::VIEW_CELL:
+			mesh = dynamic_cast<ViewCell *>(object)->GetMesh();
+			break;
+			// TODO: handle transformed mesh instances
+		default:
+			Debug << "intersectable type not supported" << endl;
+			break;
+		}
+
+        if (mesh) // copy the mesh data to polygons
+		{
+			mBox.Include(object->GetBox()); // add to BSP tree aabb
+			AddMeshToPolygons(mesh, polys, NULL);
+		}
+	}
+
+	return (int)polys.size();
+}
+
+
+void VspBspTree::Construct(const VssRayContainer &sampleRays,
+						   AxisAlignedBox3 *forcedBoundingBox)
+{
+	mBspStats.nodes = 1;
+	mBox.Initialize(); 	// initialise BSP tree bounding box
+
+	if (forcedBoundingBox)
+		mBox = *forcedBoundingBox;
+	
+	PolygonContainer polys;
+	RayInfoContainer *rays = new RayInfoContainer();
+
+	VssRayContainer::const_iterator rit, rit_end = sampleRays.end();
+
+	long startTime = GetTime();
+
+	cout << "Extracting polygons from rays ... ";
+
+	Intersectable::NewMail();
+
+	int numObj = 0;
+
+	//-- extract polygons intersected by the rays
+	for (rit = sampleRays.begin(); rit != rit_end; ++ rit)
+	{
+		VssRay *ray = *rit;
+
+		if ((mBox.IsInside(ray->mTermination) || !forcedBoundingBox) &&
+			ray->mTerminationObject && 
+			!ray->mTerminationObject->Mailed())
+		{
+			ray->mTerminationObject->Mail();
+			MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mTerminationObject);
+			AddMeshToPolygons(obj->GetMesh(), polys, obj);
+			++ numObj;
+			//-- compute bounding box
+			if (!forcedBoundingBox)
+				mBox.Include(ray->mTermination);
+		}
+
+		if ((mBox.IsInside(ray->mOrigin) || !forcedBoundingBox) &&
+			ray->mOriginObject && 
+			!ray->mOriginObject->Mailed())
+		{
+			ray->mOriginObject->Mail();
+			MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->mOriginObject);
+			AddMeshToPolygons(obj->GetMesh(), polys, obj);
+			++ numObj;
+
+			//-- compute bounding box
+			if (!forcedBoundingBox)
+				mBox.Include(ray->mOrigin);
+		}
+	}
+	
+	Debug << "maximal pvs (i.e., pvs still considered as valid) : " << mViewCellsManager->GetMaxPvsSize() << endl;
+
+	//-- store rays
+	for (rit = sampleRays.begin(); rit != rit_end; ++ rit)
+	{
+		VssRay *ray = *rit;
+
+		float minT, maxT;
+
+		static Ray hray;
+		hray.Init(*ray);
+
+		// TODO: not very efficient to implictly cast between rays types
+		if (mBox.GetRaySegment(hray, minT, maxT))
+		{
+			float len = ray->Length();
+
+			if (!len)
+				len = Limits::Small;
+
+			rays->push_back(RayInfo(ray, minT / len, maxT / len));
+		}
+	}
+
+	// normalize
+	if (mUseAreaForPvs)
+		mTermMinProbability *= mBox.SurfaceArea(); 
+	else 
+		mTermMinProbability *= mBox.GetVolume();
+
+	mBspStats.polys = (int)polys.size();
+
+	cout << "finished" << endl;
+
+	Debug << "\nPolygon extraction: " << (int)polys.size() << " polys extracted from "
+		  << (int)sampleRays.size() << " rays in "
+		  << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl << endl;
+
+	Construct(polys, rays);
+
+	// clean up polygons
+	CLEAR_CONTAINER(polys);
+}
+
+
+// TODO: return memory usage in MB
+float VspBspTree::GetMemUsage(/*const VspBspTraversalQueue &tstack*/) const
+{
+	return
+		(sizeof(VspBspTree) +
+		 (float)mBspStats.Leaves() * sizeof(BspLeaf) + 
+		 // the nodes in the stack is the minimal additional number of leaves
+		 //(float)tstack.size() * sizeof(BspLeaf) +
+		 mBspStats.Interior() * sizeof(BspInterior) +
+		 mBspStats.accumRays * sizeof(RayInfo)) / (1024.0f * 1024.0f);
+}
+
+
+
+void VspBspTree::Construct(const PolygonContainer &polys, RayInfoContainer *rays)
+{
+	VspBspTraversalQueue tQueue;
+
+	mRoot = new BspLeaf();
+
+	// constrruct root node geometry
+	BspNodeGeometry *geom = new BspNodeGeometry();
+	ConstructGeometry(mRoot, *geom);
+
+	const float prop = mUseAreaForPvs ? geom->GetArea() : geom->GetVolume();
+
+	VspBspTraversalData tData(mRoot,
+							  new PolygonContainer(polys),
+							  0,
+							  rays,
+                              ComputePvsSize(*rays),
+							  prop,
+							  geom);
+#if OCTREE_HACK
+tData.mAxis = 0;
+#endif
+	// first node is kd node, i.e. an axis aligned box
+	if (1)
+        tData.mIsKdNode = true;
+	else
+		tData.mIsKdNode = false;
+
+	tQueue.push(tData);
+
+
+	mTotalCost = tData.mPvs * tData.mProbability / mBox.GetVolume();
+	mTotalPvsSize = tData.mPvs;
+	
+	mSubdivisionStats 
+			<< "#ViewCells\n1\n" <<  endl
+			<< "#RenderCostDecrease\n0\n" << endl 
+			<< "#TotalRenderCost\n" << mTotalCost << endl
+			<< "#AvgRenderCost\n" << mTotalPvsSize << endl;
+
+	Debug << "total cost: " << mTotalCost << endl;
+	
+	
+	mBspStats.Start();
+	cout << "Contructing vsp bsp tree ... \n";
+
+	long startTime = GetTime();	
+	int nLeaves = 0;
+	int nViewCells = 0;
+
+	// used for intermediate time measurements and progress
+	long interTime = GetTime();	
+
+	mOutOfMemory = false;
+
+	mCreatedViewCells = 0;
+	
+	while (!tQueue.empty())
+	{
+		tData = tQueue.top();
+	    tQueue.pop();		
+
+		if (0 && !mOutOfMemory)
+		{
+			float mem = GetMemUsage();
+
+			if (mem > mMaxMemory)
+			{
+				mOutOfMemory = true;
+				Debug << "memory limit reached: " << mem << endl;
+			}
+		}
+
+		// subdivide leaf node
+		BspNode *r = Subdivide(tQueue, tData);
+
+		if (r == mRoot)
+			Debug << "VSP BSP tree construction time spent at root: "
+				  << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
+
+		if (mBspStats.Leaves() == nLeaves)
+		{
+			nLeaves += 500;
+
+			cout << "leaves=" << mBspStats.Leaves() << endl;
+			Debug << "needed "
+				  << TimeDiff(interTime, GetTime())*1e-3 
+				  << " secs to create 500 view cells" << endl;
+			interTime = GetTime();
+		}
+
+		if (mCreatedViewCells == nViewCells)
+		{
+			nViewCells += 500;
+
+			cout << "generated " << mCreatedViewCells << " viewcells" << endl;
+		}
+	}
+
+	Debug << "Used Memory: " << GetMemUsage() << " MB" << endl << endl;
+	cout << "finished\n";
+
+	mBspStats.Stop();
+}
+
+
+bool VspBspTree::TerminationCriteriaMet(const VspBspTraversalData &data) const
+{
+	return
+		(((int)data.mRays->size() <= mTermMinRays) ||
+		 (data.mPvs <= mTermMinPvs)   ||
+		 (data.mProbability <= mTermMinProbability) ||
+		 (mBspStats.Leaves() >= mMaxViewCells) ||
+#if 0
+		 (((int)data.mPolygons->size() <= mTermMinPolygons) && !data.mPolygons->empty())||
+#endif
+		 (data.GetAvgRayContribution() > mTermMaxRayContribution) ||
+		 (data.mDepth >= mTermMaxDepth));
+}
+
+
+BspNode *VspBspTree::Subdivide(VspBspTraversalQueue &tQueue,
+							   VspBspTraversalData &tData)
+{
+	BspNode *newNode = tData.mNode;
+
+	if (!mOutOfMemory && !TerminationCriteriaMet(tData))
+	{
+		PolygonContainer coincident;
+
+		VspBspTraversalData tFrontData;
+		VspBspTraversalData tBackData;
+
+#if OCTREE_HACK
+		//Debug << "new axis:" << (tData.mAxis + 1) % 3 << endl;
+		tFrontData.mAxis = (tData.mAxis + 1) % 3;
+		tBackData.mAxis = (tData.mAxis + 1) % 3;
+#endif
+		// create new interior node and two leaf nodes
+		// or return leaf as it is (if maxCostRatio missed)
+		newNode = SubdivideNode(tData, tFrontData, tBackData, coincident);
+
+		if (!newNode->IsLeaf()) //-- continue subdivision
+		{
+			if (1)
+			{
+				float cFront = (float)tFrontData.mPvs * tFrontData.mProbability;
+				float cBack = (float)tBackData.mPvs * tBackData.mProbability;
+				float cData = (float)tData.mPvs * tData.mProbability;;
+
+                float costDecr = 
+					(cFront + cBack - cData) / mBox.GetVolume();
+
+				mTotalCost += costDecr;
+				mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs;
+
+				mSubdivisionStats 
+						<< "#ViewCells\n" << mBspStats.Leaves() << endl
+						<< "#RenderCostDecrease\n" << -costDecr << endl 
+						<< "#TotalRenderCost\n" << mTotalCost << endl
+						<< "#AvgRenderCost\n" << mTotalPvsSize / mBspStats.Leaves() << endl;
+			}
+
+			// push the children on the stack
+			tQueue.push(tFrontData);
+			tQueue.push(tBackData);
+
+			// delete old leaf node
+			DEL_PTR(tData.mNode);
+		}
+	}
+
+	//-- terminate traversal and create new view cell
+	if (newNode->IsLeaf())
+	{
+		BspLeaf *leaf = dynamic_cast<BspLeaf *>(newNode);
+		BspViewCell *viewCell = new BspViewCell();
+		
+		leaf->SetViewCell(viewCell);
+	
+		//-- update pvs
+		int conSamp = 0;
+		float sampCon = 0.0f;
+		AddToPvs(leaf, *tData.mRays, sampCon, conSamp);
+
+		mBspStats.contributingSamples += conSamp;
+		mBspStats.sampleContributions +=(int) sampCon;
+
+		//-- store additional info
+		if (mStoreRays)
+		{
+			RayInfoContainer::const_iterator it, it_end = tData.mRays->end();
+			for (it = tData.mRays->begin(); it != it_end; ++ it)
+				leaf->mVssRays.push_back((*it).mRay);
+		}
+
+		// should I check here?
+		if (0 && !mViewCellsManager->CheckValidity(viewCell, 0, mViewCellsManager->GetMaxPvsSize()))
+		{
+			viewCell->SetValid(false);
+			leaf->SetTreeValid(false);
+			PropagateUpValidity(leaf);
+
+			++ mBspStats.invalidLeaves;
+		}
+		
+        viewCell->mLeaf = leaf;
+
+		if (mUseAreaForPvs)
+			viewCell->SetArea(tData.mProbability);
+		else
+			viewCell->SetVolume(tData.mProbability);
+
+		leaf->mProbability = tData.mProbability;
+
+		EvaluateLeafStats(tData);		
+	}
+
+	//-- cleanup
+	tData.Clear();
+
+	return newNode;
+}
+
+
+BspNode *VspBspTree::SubdivideNode(VspBspTraversalData &tData,
+								   VspBspTraversalData &frontData,
+								   VspBspTraversalData &backData,
+								   PolygonContainer &coincident)
+{
+	BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode);
+	
+	// select subdivision plane
+	Plane3 splitPlane;
+	
+	int maxCostMisses = tData.mMaxCostMisses;
+
+	int splitAxis;
+
+	const bool success = 
+		SelectPlane(splitPlane, leaf, tData, frontData, backData, splitAxis);
+
+	if (!success)
+	{
+		++ maxCostMisses;
+
+		if (maxCostMisses > mTermMissTolerance)
+		{
+			// terminate branch because of max cost
+			++ mBspStats.maxCostNodes;
+            return leaf;
+		}
+	}
+
+	//! error also computed if cost ratio is missed
+	if (splitAxis < 3)
+		++ mBspStats.splits[splitAxis];
+	else
+		++ mBspStats.polySplits;
+
+	mBspStats.nodes += 2;
+
+	//-- subdivide further
+	BspInterior *interior = new BspInterior(splitPlane);
+
+#ifdef _DEBUG
+	Debug << interior << endl;
+#endif
+
+	//-- the front and back traversal data is filled with the new values
+	frontData.mDepth = tData.mDepth + 1;
+	frontData.mPolygons = new PolygonContainer();
+	frontData.mRays = new RayInfoContainer();
+	
+	backData.mDepth = tData.mDepth + 1;
+	backData.mPolygons = new PolygonContainer();
+	backData.mRays = new RayInfoContainer();
+	
+	// subdivide rays
+	SplitRays(interior->GetPlane(),
+			  *tData.mRays,
+			  *frontData.mRays,
+			  *backData.mRays);
+
+	// subdivide polygons
+	SplitPolygons(interior->GetPlane(),
+				  *tData.mPolygons,
+	              *frontData.mPolygons,
+				  *backData.mPolygons,
+				  coincident);
+
+
+	// how often was max cost ratio missed in this branch?
+	frontData.mMaxCostMisses = maxCostMisses;
+	backData.mMaxCostMisses = maxCostMisses;
+
+	// compute pvs
+	frontData.mPvs = ComputePvsSize(*frontData.mRays);
+	backData.mPvs = ComputePvsSize(*backData.mRays);
+
+	// split front and back node geometry and compute area
+	
+	// if geometry was not already computed
+	if (!frontData.mGeometry && !backData.mGeometry)
+	{
+		frontData.mGeometry = new BspNodeGeometry();
+		backData.mGeometry = new BspNodeGeometry();
+
+		tData.mGeometry->SplitGeometry(*frontData.mGeometry,
+									   *backData.mGeometry,
+									   interior->GetPlane(),
+									   mBox,
+									   mEpsilon);
+		
+		if (mUseAreaForPvs)
+		{
+			frontData.mProbability = frontData.mGeometry->GetArea();
+			backData.mProbability = backData.mGeometry->GetArea();
+		}
+		else
+		{
+			frontData.mProbability = frontData.mGeometry->GetVolume();
+			backData.mProbability =  tData.mProbability - frontData.mProbability;
+		}
+	}
+	
+
+	//-- create front and back leaf
+
+	BspInterior *parent = leaf->GetParent();
+
+	// replace a link from node's parent
+	if (parent)
+	{
+		parent->ReplaceChildLink(leaf, interior);
+		interior->SetParent(parent);
+	}
+	else // new root
+	{
+		mRoot = interior;
+	}
+
+	// and setup child links
+	interior->SetupChildLinks(new BspLeaf(interior), new BspLeaf(interior));
+
+	frontData.mNode = interior->GetFront();
+	backData.mNode = interior->GetBack();
+
+	frontData.mNode->mTimeStamp = mTimeStamp;
+	backData.mNode->mTimeStamp = mTimeStamp ++;
+
+	//DEL_PTR(leaf);
+	return interior;
+}
+
+
+void VspBspTree::AddToPvs(BspLeaf *leaf,
+						  const RayInfoContainer &rays,
+						  float &sampleContributions,
+						  int &contributingSamples)
+{
+  sampleContributions = 0;
+  contributingSamples = 0;
+  
+  RayInfoContainer::const_iterator it, it_end = rays.end();
+  
+  ViewCell *vc = leaf->GetViewCell();
+  
+  // add contributions from samples to the PVS
+  for (it = rays.begin(); it != it_end; ++ it)
+	{
+	  float sc = 0.0f;
+	  VssRay *ray = (*it).mRay;
+	  bool madeContrib = false;
+	  float contribution;
+	  if (ray->mTerminationObject) {
+		if (vc->GetPvs().AddSample(ray->mTerminationObject, ray->mPdf, contribution))
+		  madeContrib = true;
+		sc += contribution;
+	  }
+	  
+	  if (ray->mOriginObject) {
+		if (vc->GetPvs().AddSample(ray->mOriginObject, ray->mPdf, contribution))
+		  madeContrib = true;
+		sc += contribution;
+	  }
+	  
+	  sampleContributions += sc;
+	  if (madeContrib)
+		  ++ contributingSamples;
+		
+	  //leaf->mVssRays.push_back(ray);
+	}
+}
+
+
+void VspBspTree::SortSplitCandidates(const RayInfoContainer &rays, const int axis)
+{
+	mSplitCandidates->clear();
+
+	int requestedSize = 2 * (int)(rays.size());
+	// creates a sorted split candidates array
+	if (mSplitCandidates->capacity() > 500000 &&
+		requestedSize < (int)(mSplitCandidates->capacity()  / 10) )
+	{
+    	delete mSplitCandidates;
+   		mSplitCandidates = new vector<SortableEntry>;
+	}
+
+	mSplitCandidates->reserve(requestedSize);
+
+	// insert all queries
+	for (RayInfoContainer::const_iterator ri = rays.begin(); ri < rays.end(); ++ ri)
+	{
+		const bool positive = (*ri).mRay->HasPosDir(axis);
+		mSplitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMin : SortableEntry::ERayMax,
+												  (*ri).ExtrapOrigin(axis), (*ri).mRay));
+
+		mSplitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMax : SortableEntry::ERayMin,
+												  (*ri).ExtrapTermination(axis), (*ri).mRay));
+	}
+
+	stable_sort(mSplitCandidates->begin(), mSplitCandidates->end());
+}
+
+
+float VspBspTree::BestCostRatioHeuristics(const RayInfoContainer &rays,
+										  const AxisAlignedBox3 &box,
+										  const int pvsSize,
+										  const int &axis,
+                                          float &position)
+{
+	SortSplitCandidates(rays, axis);
+
+	// go through the lists, count the number of objects left and right
+	// and evaluate the following cost funcion:
+	// C = ct_div_ci  + (ql*rl + qr*rr)/queries
+
+	int pvsl = 0, pvsr = pvsSize;
+
+	int pvsBack = pvsl;
+	int pvsFront = pvsr;
+
+	float minBox = box.Min(axis);
+	float maxBox = box.Max(axis);
+	float sizeBox = maxBox - minBox;
+
+	float minBand = minBox + 0.1f * (maxBox - minBox);
+	float maxBand = minBox + 0.9f * (maxBox - minBox);
+
+	float sum = (float)pvsSize * sizeBox;
+	float minSum = 1e20f;
+
+	Intersectable::NewMail();
+
+   	RayInfoContainer::const_iterator ri, ri_end = rays.end();
+
+	// set all object as belonging to the front pvs
+	for(ri = rays.begin(); ri != ri_end; ++ ri)
+	{
+		Intersectable *oObject = (*ri).mRay->mOriginObject;
+		Intersectable *tObject = (*ri).mRay->mTerminationObject;
+
+		if (oObject)
+		{
+			if (!oObject->Mailed())
+			{
+				oObject->Mail();
+				oObject->mCounter = 1;
+			}
+			else
+			{
+				++ oObject->mCounter;
+			}
+		}
+		if (tObject)
+		{
+			if (!tObject->Mailed())
+			{
+				tObject->Mail();
+				tObject->mCounter = 1;
+			}
+			else
+			{
+				++ tObject->mCounter;
+			}
+		}
+	}
+
+	Intersectable::NewMail();
+
+	vector<SortableEntry>::const_iterator ci, ci_end = mSplitCandidates->end();
+
+	for (ci = mSplitCandidates->begin(); ci < ci_end; ++ ci)
+	{
+		VssRay *ray;
+		ray = (*ci).ray;
+		
+		Intersectable *oObject = ray->mOriginObject;
+		Intersectable *tObject = ray->mTerminationObject;
+		
+
+		switch ((*ci).type)
+		{
+			case SortableEntry::ERayMin:
+				{
+					if (oObject && !oObject->Mailed())
+					{
+						oObject->Mail();
+						++ pvsl;
+					}
+					if (tObject && !tObject->Mailed())
+					{
+						tObject->Mail();
+						++ pvsl;
+					}
+					break;
+				}
+			case SortableEntry::ERayMax:
+				{
+					if (oObject)
+					{
+						if (-- oObject->mCounter == 0)
+							-- pvsr;
+					}
+
+					if (tObject)
+					{
+						if (-- tObject->mCounter == 0)
+							-- pvsr;
+					}
+
+					break;
+				}
+		}
+
+		// Note: sufficient to compare size of bounding boxes of front and back side?
+		if ((*ci).value > minBand && (*ci).value < maxBand)
+		{
+			sum = pvsl * ((*ci).value - minBox) + pvsr * (maxBox - (*ci).value);
+
+			//  cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl;
+			// cout<<"cost= "<<sum<<endl;
+
+			if (sum < minSum)
+			{
+				minSum = sum;
+				position = (*ci).value;
+
+				pvsBack = pvsl;
+				pvsFront = pvsr;
+			}
+		}
+	}
+
+	// -- compute cost
+
+	const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize();
+	const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize();
+
+	const float pOverall = sizeBox;
+
+	const float pBack = position - minBox;
+	const float pFront = maxBox - position;
+	
+	const float penaltyOld = EvalPvsPenalty(pvsSize, lowerPvsLimit, upperPvsLimit);
+    const float penaltyFront = EvalPvsPenalty(pvsFront, lowerPvsLimit, upperPvsLimit);
+	const float penaltyBack = EvalPvsPenalty(pvsBack, lowerPvsLimit, upperPvsLimit);
+	
+	const float oldRenderCost = penaltyOld * pOverall;
+	const float newRenderCost = penaltyFront * pFront + penaltyBack * pBack;
+
+	float ratio = mPvsFactor * newRenderCost / (oldRenderCost + Limits::Small);
+
+	//Debug << "costRatio=" << ratio << " pos=" << position << " t=" << (position - minBox) / (maxBox - minBox)
+	//     <<"\t q=(" << queriesBack << "," << queriesFront << ")\t r=(" << raysBack << "," << raysFront << ")" << endl;
+
+	return ratio;
+}
+
+
+float VspBspTree::SelectAxisAlignedPlane(Plane3 &plane,
+										 const VspBspTraversalData &tData,
+										 int &axis,
+										 BspNodeGeometry **frontGeom,
+										 BspNodeGeometry **backGeom,
+										 float &pFront,
+										 float &pBack,
+										 const bool useKdSplit)
+{
+	float nPosition[3];
+	float nCostRatio[3];
+	float nProbFront[3];
+	float nProbBack[3];
+
+	BspNodeGeometry *nFrontGeom[3];
+	BspNodeGeometry *nBackGeom[3];
+
+	for (int i = 0; i < 3; ++ i)
+	{
+		nFrontGeom[i] = NULL;
+		nBackGeom[i] = NULL;
+	}
+
+	int bestAxis = -1;
+
+	// create bounding box of node geometry
+	AxisAlignedBox3 box;
+	box.Initialize();
+	
+	//TODO: for kd split geometry already is box => only take minmax vertices
+	if (1)
+	{
+		PolygonContainer::const_iterator it, it_end = tData.mGeometry->mPolys.end();
+
+		for(it = tData.mGeometry->mPolys.begin(); it < it_end; ++ it)
+			box.Include(*(*it));
+	}
+	else
+	{
+		RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end();
+
+		for(ri = tData.mRays->begin(); ri < ri_end; ++ ri)
+			box.Include((*ri).ExtrapTermination());
+	}
+#if OCTREE_HACK
+	//Debug << "choosing axis:" << tData.mAxis << endl;
+	const int sAxis = tData.mAxis;
+#else
+	const int sAxis = mUseRandomAxis ? Random(3) : box.Size().DrivingAxis();
+#endif
+	for (axis = 0; axis < 3; ++ axis)
+	{
+		if (!mOnlyDrivingAxis || (axis == sAxis))
+		{
+			if (!mUseCostHeuristics)
+			{
+				nFrontGeom[axis] = new BspNodeGeometry();
+				nBackGeom[axis] = new BspNodeGeometry();
+
+				nPosition[axis] = (box.Min()[axis] + box.Max()[axis]) * 0.5f;
+				Vector3 normal(0,0,0); normal[axis] = 1.0f;
+
+				// allows faster split because we have axis aligned kd tree boxes
+				if (useKdSplit)
+				{
+					nCostRatio[axis] = EvalAxisAlignedSplitCost(tData,
+																box,
+																axis,
+																nPosition[axis],
+																nProbFront[axis], 
+																nProbBack[axis]);
+					
+					Vector3 pos;
+					
+					pos = box.Max(); pos[axis] = nPosition[axis];
+					AxisAlignedBox3 bBox(box.Min(), pos);
+					bBox.ExtractPolys(nBackGeom[axis]->mPolys);
+					
+					pos = box.Min(); pos[axis] = nPosition[axis];
+					AxisAlignedBox3 fBox(pos, box.Max());
+					fBox.ExtractPolys(nFrontGeom[axis]->mPolys);
+				}
+				else
+				{
+					nCostRatio[axis] = 
+						EvalSplitPlaneCost(Plane3(normal, nPosition[axis]), 
+										   tData, *nFrontGeom[axis], *nBackGeom[axis],
+										   nProbFront[axis], nProbBack[axis]);
+				}
+			}
+			else
+			{
+				nCostRatio[axis] =
+					BestCostRatioHeuristics(*tData.mRays,
+										    box,
+											tData.mPvs,
+											axis,
+											nPosition[axis]);
+			}
+
+			if (bestAxis == -1)
+			{
+				bestAxis = axis;
+			}
+			else if (nCostRatio[axis] < nCostRatio[bestAxis])
+			{
+				bestAxis = axis;
+			}
+
+		}
+	}
+
+	//-- assign values
+	axis = bestAxis;
+	pFront = nProbFront[bestAxis];
+	pBack = nProbBack[bestAxis];
+
+	// assign best split nodes geometry 
+	*frontGeom = nFrontGeom[bestAxis];
+	*backGeom = nBackGeom[bestAxis];
+
+	// and delete other geometry
+	DEL_PTR(nFrontGeom[(bestAxis + 1) % 3]);
+	DEL_PTR(nBackGeom[(bestAxis + 2) % 3]);
+
+	//-- split plane
+    Vector3 normal(0,0,0); normal[bestAxis] = 1;
+	plane = Plane3(normal, nPosition[bestAxis]);
+
+	return nCostRatio[bestAxis];
+}
+
+
+bool VspBspTree::SelectPlane(Plane3 &bestPlane,
+							 BspLeaf *leaf,
+							 VspBspTraversalData &data,
+							 VspBspTraversalData &frontData,
+							 VspBspTraversalData &backData,
+							 int &splitAxis)
+{
+	// simplest strategy: just take next polygon
+	if (mSplitPlaneStrategy & RANDOM_POLYGON)
+	{
+        if (!data.mPolygons->empty())
+		{
+			const int randIdx = 
+				(int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1));
+			Polygon3 *nextPoly = (*data.mPolygons)[randIdx];
+
+			bestPlane = nextPoly->GetSupportingPlane();
+			return true;
+		}
+	}
+
+	//-- use heuristics to find appropriate plane
+
+	// intermediate plane
+	Plane3 plane;
+	float lowestCost = MAX_FLOAT;
+	
+	// decides if the first few splits should be only axisAligned
+	const bool onlyAxisAligned  = 
+		(mSplitPlaneStrategy & AXIS_ALIGNED) &&
+		((int)data.mRays->size() > mTermMinRaysForAxisAligned) &&
+		((int)data.GetAvgRayContribution() < mTermMaxRayContriForAxisAligned);
+	
+	const int limit = onlyAxisAligned ? 0 : 
+		Min((int)data.mPolygons->size(), mMaxPolyCandidates);
+
+	float candidateCost;
+
+	int maxIdx = (int)data.mPolygons->size();
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		// the already taken candidates are stored behind maxIdx
+		// => assure that no index is taken twice
+		const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx));
+		Polygon3 *poly = (*data.mPolygons)[candidateIdx];
+
+		// swap candidate to the end to avoid testing same plane
+		std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]);
+		//Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)];
+
+		// evaluate current candidate
+		BspNodeGeometry fGeom, bGeom;
+		float fArea, bArea;
+		plane = poly->GetSupportingPlane();
+		candidateCost = EvalSplitPlaneCost(plane, data, fGeom, bGeom, fArea, bArea);
+		
+		if (candidateCost < lowestCost)
+		{
+			bestPlane = plane;
+			lowestCost = candidateCost;
+		}
+	}
+
+	// cost ratio miss
+	if (mUsePolygonSplitIfAvailable && !data.mPolygons->empty())
+	{
+		frontData.mIsKdNode = backData.mIsKdNode = false;
+		if (lowestCost > mTermMaxCostRatio)
+			return false;
+
+		return true;
+	}
+
+	//-- evaluate axis aligned splits
+	int axis;
+	BspNodeGeometry *fGeom, *bGeom;
+	float pFront, pBack;
+
+	candidateCost = SelectAxisAlignedPlane(plane, 
+										   data, 
+										   axis,
+										   &fGeom, 
+										   &bGeom, 
+										   pFront, 
+										   pBack,
+										   data.mIsKdNode);	 
+
+	splitAxis = 3;
+
+	if (candidateCost < lowestCost)
+	{	
+		bestPlane = plane;
+		lowestCost = candidateCost;
+		splitAxis = axis;
+		// assign already computed values
+		// we can do this because we always save the
+		// computed values from the axis aligned splits		
+		if (fGeom && bGeom)
+		{
+			frontData.mGeometry = fGeom;
+			backData.mGeometry = bGeom;
+	
+			frontData.mProbability = pFront;
+			backData.mProbability = pBack;
+		}
+	}
+	else
+	{
+		DEL_PTR(fGeom);
+		DEL_PTR(bGeom);
+	}
+
+	frontData.mIsKdNode = backData.mIsKdNode = 
+		(data.mIsKdNode && splitAxis < 3);
+
+#ifdef _DEBUG
+	Debug << "plane lowest cost: " << lowestCost << endl;
+#endif
+
+	// cost ratio miss
+	if (lowestCost > mTermMaxCostRatio)
+	{
+		return false;
+	}
+
+	return true;
+}
+
+
+Plane3 VspBspTree::ChooseCandidatePlane(const RayInfoContainer &rays) const
+{
+	const int candidateIdx = (int)RandomValue(0, (Real)((int)rays.size() - 1));
+
+	const Vector3 minPt = rays[candidateIdx].ExtrapOrigin();
+	const Vector3 maxPt = rays[candidateIdx].ExtrapTermination();
+
+	const Vector3 pt = (maxPt + minPt) * 0.5;
+	const Vector3 normal = Normalize(rays[candidateIdx].mRay->GetDir());
+
+	return Plane3(normal, pt);
+}
+
+
+Plane3 VspBspTree::ChooseCandidatePlane2(const RayInfoContainer &rays) const
+{
+	Vector3 pt[3];
+
+	int idx[3];
+	int cmaxT = 0;
+	int cminT = 0;
+	bool chooseMin = false;
+
+	for (int j = 0; j < 3; ++ j)
+	{
+		idx[j] = (int)RandomValue(0, (Real)((int)rays.size() * 2 - 1));
+
+		if (idx[j] >= (int)rays.size())
+		{
+			idx[j] -= (int)rays.size();
+
+			chooseMin = (cminT < 2);
+		}
+		else
+			chooseMin = (cmaxT < 2);
+
+		RayInfo rayInf = rays[idx[j]];
+		pt[j] = chooseMin ? rayInf.ExtrapOrigin() : rayInf.ExtrapTermination();
+	}
+
+	return Plane3(pt[0], pt[1], pt[2]);
+}
+
+
+Plane3 VspBspTree::ChooseCandidatePlane3(const RayInfoContainer &rays) const
+{
+	Vector3 pt[3];
+
+	int idx1 = (int)RandomValue(0, (Real)((int)rays.size() - 1));
+	int idx2 = (int)RandomValue(0, (Real)((int)rays.size() - 1));
+
+	// check if rays different
+	if (idx1 == idx2)
+		idx2 = (idx2 + 1) % (int)rays.size();
+
+	const RayInfo ray1 = rays[idx1];
+	const RayInfo ray2 = rays[idx2];
+
+	// normal vector of the plane parallel to both lines
+	const Vector3 norm = Normalize(CrossProd(ray1.mRay->GetDir(), ray2.mRay->GetDir()));
+
+	// vector from line 1 to line 2
+	const Vector3 vd = ray2.ExtrapOrigin() - ray1.ExtrapOrigin();
+
+	// project vector on normal to get distance
+	const float dist = DotProd(vd, norm);
+
+	// point on plane lies halfway between the two planes
+	const Vector3 planePt = ray1.ExtrapOrigin() + norm * dist * 0.5;
+
+	return Plane3(norm, planePt);
+}
+
+
+inline void VspBspTree::GenerateUniqueIdsForPvs()
+{
+	Intersectable::NewMail(); sBackId = Intersectable::sMailId;
+	Intersectable::NewMail(); sFrontId = Intersectable::sMailId;
+	Intersectable::NewMail(); sFrontAndBackId = Intersectable::sMailId;
+}
+
+
+float VspBspTree::EvalSplitPlaneCost(const Plane3 &candidatePlane,
+									 const VspBspTraversalData &data,
+									 BspNodeGeometry &geomFront,
+									 BspNodeGeometry &geomBack,
+									 float &pFront,
+									 float &pBack) const
+{
+	float cost = 0;
+
+	float sumBalancedRays = 0;
+	float sumRaySplits = 0;
+
+	int pvsFront = 0;
+	int pvsBack = 0;
+
+	// probability that view point lies in back / front node
+	float pOverall = 0;
+	pFront = 0;
+	pBack = 0;
+
+	int raysFront = 0;
+	int raysBack = 0;
+	int totalPvs = 0;
+
+	int limit;
+	bool useRand;
+
+	// choose test rays randomly if too much
+	if ((int)data.mRays->size() > mMaxTests)
+	{
+		useRand = true;
+		limit = mMaxTests;
+	}
+	else
+	{
+		useRand = false;
+		limit = (int)data.mRays->size();
+	}
+	
+	for (int i = 0; i < limit; ++ i)
+	{
+		const int testIdx = useRand ? 
+			(int)RandomValue(0, (Real)((int)data.mRays->size() - 1)) : i;
+		RayInfo rayInf = (*data.mRays)[testIdx];
+
+		float t;
+		VssRay *ray = rayInf.mRay;
+		const int cf = rayInf.ComputeRayIntersection(candidatePlane, t);
+
+        if (0)
+		{
+			if (cf >= 0)
+				++ raysFront;
+			if (cf <= 0)
+				++ raysBack;
+		}
+
+		if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
+		{
+			sumBalancedRays += cf;
+		}
+
+		if (mSplitPlaneStrategy & BALANCED_RAYS)
+		{
+			if (cf == 0)
+				++ sumRaySplits;
+		}
+
+		if (mSplitPlaneStrategy & PVS)
+		{
+			// find front and back pvs for origing and termination object
+			AddObjToPvs(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs);
+			AddObjToPvs(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs);
+		}
+	}
+
+	const float raysSize = (float)data.mRays->size() + Limits::Small;
+
+	if (mSplitPlaneStrategy & PVS)
+	{
+		// create unique ids for pvs heuristics
+		GenerateUniqueIdsForPvs();
+
+		// construct child geometry with regard to the candidate split plane
+		data.mGeometry->SplitGeometry(geomFront,
+									  geomBack,
+									  candidatePlane,
+									  mBox,
+									  mEpsilon);
+
+		pOverall = data.mProbability;
+
+		if (!mUseAreaForPvs) // use front and back cell areas to approximate volume
+		{
+			pFront = geomFront.GetVolume();
+			pBack = pOverall - pFront;
+		}
+		else
+		{
+			pFront = geomFront.GetArea();
+			pBack = geomBack.GetArea();
+		}
+	}
+
+
+	if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
+		cost += mLeastRaySplitsFactor * sumRaySplits / raysSize;
+
+	if (mSplitPlaneStrategy & BALANCED_RAYS)
+		cost += mBalancedRaysFactor * fabs(sumBalancedRays) / raysSize;
+
+	// -- pvs rendering heuristics
+	if (mSplitPlaneStrategy & PVS)
+	{
+		const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize();
+		const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize();
+
+		// only render cost heuristics or combined with standard deviation
+		const float penaltyOld = EvalPvsPenalty(totalPvs, lowerPvsLimit, upperPvsLimit);
+        const float penaltyFront = EvalPvsPenalty(pvsFront, lowerPvsLimit, upperPvsLimit);
+		const float penaltyBack = EvalPvsPenalty(pvsBack, lowerPvsLimit, upperPvsLimit);
+			
+		const float oldRenderCost = pOverall * penaltyOld;
+		const float newRenderCost = penaltyFront * pFront + penaltyBack * pBack;
+
+		float oldCost, newCost;
+
+		// only render cost
+		if (1)
+		{
+			oldCost = oldRenderCost;
+			newCost = newRenderCost;
+		}
+		else // also considering standard deviation
+		{
+			// standard deviation is difference of back and front pvs
+			const float expectedCost = 0.5f * (penaltyFront + penaltyBack);
+
+			const float newDeviation = 0.5f * 
+				fabs(penaltyFront - expectedCost) + fabs(penaltyBack - expectedCost);
+
+			const float oldDeviation = penaltyOld;
+
+			newCost = mRenderCostWeight * newRenderCost + (1.0f - mRenderCostWeight) * newDeviation;
+			oldCost = mRenderCostWeight * oldRenderCost + (1.0f - mRenderCostWeight) * oldDeviation;
+		}
+
+		cost += mPvsFactor * newCost / (oldCost + Limits::Small);
+		
+	}
+
+#ifdef _DEBUG
+  	Debug << "totalpvs: " << data.mPvs << " ptotal: " << pOverall
+  		  << " frontpvs: " << pvsFront << " pFront: " << pFront
+  		  << " backpvs: " << pvsBack << " pBack: " << pBack << endl << endl;
+	Debug << "cost: " << cost << endl;
+#endif
+
+	
+	// normalize cost by sum of linear factors
+	if(0)
+		return cost / (float)mCostNormalizer;
+	else
+		return cost;
+}
+
+
+float VspBspTree::EvalAxisAlignedSplitCost(const VspBspTraversalData &data,
+										   const AxisAlignedBox3 &box,
+										   const int axis,
+										   const float &position,										  
+										   float &pFront,
+										   float &pBack) const
+{
+	int pvsTotal = 0;
+	int pvsFront = 0;
+	int pvsBack = 0;
+	
+	// create unique ids for pvs heuristics
+	GenerateUniqueIdsForPvs();
+
+	const int pvsSize = data.mPvs;
+
+	RayInfoContainer::const_iterator rit, rit_end = data.mRays->end();
+
+	// this is the main ray classification loop!
+	for(rit = data.mRays->begin(); rit != rit_end; ++ rit)
+	{
+		//if (!(*rit).mRay->IsActive())	continue;
+
+		// determine the side of this ray with respect to the plane
+		float t;
+		const int side = (*rit).ComputeRayIntersection(axis, position, t);
+	
+		AddObjToPvs((*rit).mRay->mTerminationObject, side, pvsFront, pvsBack, pvsTotal);
+		AddObjToPvs((*rit).mRay->mOriginObject, side, pvsFront, pvsBack, pvsTotal);
+	}
+
+	//-- pvs heuristics
+	float pOverall;
+
+	//-- compute heurstics
+	//   we take simplified computation for mid split
+		
+	pOverall = data.mProbability;
+
+	if (!mUseAreaForPvs)
+	{   // volume
+		pBack = pFront = pOverall * 0.5f;
+		
+#if 0
+		// box length substitute for probability
+		const float minBox = box.Min(axis);
+		const float maxBox = box.Max(axis);
+
+		pBack = position - minBox;
+		pFront = maxBox - position;
+		pOverall = maxBox - minBox;
+#endif
+	}
+	else //-- area substitute for probability
+	{
+		const int axis2 = (axis + 1) % 3;
+		const int axis3 = (axis + 2) % 3;
+
+		const float faceArea = 
+			(box.Max(axis2) - box.Min(axis2)) *
+			(box.Max(axis3) - box.Min(axis3));
+
+		pBack = pFront = pOverall * 0.5f + faceArea;
+	}
+
+#ifdef _DEBUG
+	Debug << axis << " " << pvsSize << " " << pvsBack << " " << pvsFront << endl;
+	Debug << pFront << " " << pBack << " " << pOverall << endl;
+#endif
+
+	
+	const float newCost = pvsBack * pBack + pvsFront * pFront;
+	const float oldCost = (float)pvsSize * pOverall + Limits::Small;
+
+	return  (mCtDivCi + newCost) / oldCost;
+}
+
+
+void VspBspTree::AddObjToPvs(Intersectable *obj,
+							 const int cf,
+							 int &frontPvs,
+							 int &backPvs,
+							 int &totalPvs) const
+{
+	if (!obj)
+		return;
+	
+	if ((obj->mMailbox != sFrontId) &&
+		(obj->mMailbox != sBackId) &&
+		(obj->mMailbox != sFrontAndBackId))
+	{
+		++ totalPvs;
+	}
+
+	// TODO: does this really belong to no pvs?
+	//if (cf == Ray::COINCIDENT) return;
+
+	// object belongs to both PVS
+	if (cf >= 0)
+	{
+		if ((obj->mMailbox != sFrontId) &&
+			(obj->mMailbox != sFrontAndBackId))
+		{
+			++ frontPvs;
+		
+			if (obj->mMailbox == sBackId)
+				obj->mMailbox = sFrontAndBackId;
+			else
+				obj->mMailbox = sFrontId;
+		}
+	}
+
+	if (cf <= 0)
+	{
+		if ((obj->mMailbox != sBackId) &&
+			(obj->mMailbox != sFrontAndBackId))
+		{
+			++ backPvs;
+		
+			if (obj->mMailbox == sFrontId)
+				obj->mMailbox = sFrontAndBackId;
+			else
+				obj->mMailbox = sBackId;
+		}
+	}
+}
+
+
+void VspBspTree::CollectLeaves(vector<BspLeaf *> &leaves, 
+							   const bool onlyUnmailed,
+							   const int maxPvsSize) const
+{
+	stack<BspNode *> nodeStack;
+	nodeStack.push(mRoot);
+
+	while (!nodeStack.empty())
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+		
+		if (node->IsLeaf())
+		{
+			// test if this leaf is in valid view space
+			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+			if (leaf->TreeValid() && 
+				(!onlyUnmailed || !leaf->Mailed()) &&
+				((maxPvsSize < 0) || (leaf->GetViewCell()->GetPvs().GetSize() <= maxPvsSize)))
+			{
+				leaves.push_back(leaf);
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			nodeStack.push(interior->GetBack());
+			nodeStack.push(interior->GetFront());
+		}
+	}
+}
+
+
+AxisAlignedBox3 VspBspTree::GetBoundingBox() const
+{
+	return mBox;
+}
+
+
+BspNode *VspBspTree::GetRoot() const
+{
+	return mRoot;
+}
+
+
+void VspBspTree::EvaluateLeafStats(const VspBspTraversalData &data)
+{
+	// the node became a leaf -> evaluate stats for leafs
+	BspLeaf *leaf = dynamic_cast<BspLeaf *>(data.mNode);
+
+	// store maximal and minimal depth
+	if (data.mDepth > mBspStats.maxDepth)
+		mBspStats.maxDepth = data.mDepth;
+
+	if (data.mPvs > mBspStats.maxPvs)
+		mBspStats.maxPvs = data.mPvs;
+	
+	if (data.mDepth < mBspStats.minDepth)
+		mBspStats.minDepth = data.mDepth;
+
+	if (data.mDepth >= mTermMaxDepth)
+		++ mBspStats.maxDepthNodes;
+
+	// accumulate rays to compute rays /  leaf
+	mBspStats.accumRays += (int)data.mRays->size();
+
+	if (data.mPvs < mTermMinPvs)
+		++ mBspStats.minPvsNodes;
+
+	if ((int)data.mRays->size() < mTermMinRays)
+		++ mBspStats.minRaysNodes;
+
+	if (data.GetAvgRayContribution() > mTermMaxRayContribution)
+		++ mBspStats.maxRayContribNodes;
+
+	if (data.mProbability <= mTermMinProbability)
+		++ mBspStats.minProbabilityNodes;
+	
+	// accumulate depth to compute average depth
+	mBspStats.accumDepth += data.mDepth;
+
+	++ mCreatedViewCells;
+#ifdef _DEBUG
+	Debug << "BSP stats: "
+		  << "Depth: " << data.mDepth << " (max: " << mTermMaxDepth << "), "
+		  << "PVS: " << data.mPvs << " (min: " << mTermMinPvs << "), "
+	  //		  << "Area: " << data.mProbability << " (min: " << mTermMinProbability << "), "
+		  << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), "
+		  << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "=, "
+		  << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl;
+#endif
+}
+
+
+int VspBspTree::CastRay(Ray &ray)
+{
+	int hits = 0;
+
+	stack<BspRayTraversalData> tQueue;
+
+	float maxt, mint;
+
+	if (!mBox.GetRaySegment(ray, mint, maxt))
+		return 0;
+
+	Intersectable::NewMail();
+	ViewCell::NewMail();
+	Vector3 entp = ray.Extrap(mint);
+	Vector3 extp = ray.Extrap(maxt);
+
+	BspNode *node = mRoot;
+	BspNode *farChild = NULL;
+
+	while (1)
+	{
+		if (!node->IsLeaf())
+		{
+			BspInterior *in = dynamic_cast<BspInterior *>(node);
+
+			Plane3 splitPlane = in->GetPlane();
+			const int entSide = splitPlane.Side(entp);
+			const int extSide = splitPlane.Side(extp);
+
+			if (entSide < 0)
+			{
+				node = in->GetBack();
+
+				if(extSide <= 0) // plane does not split ray => no far child
+					continue;
+
+				farChild = in->GetFront(); // plane splits ray
+
+			} else if (entSide > 0)
+			{
+				node = in->GetFront();
+
+				if (extSide >= 0) // plane does not split ray => no far child
+					continue;
+
+				farChild = in->GetBack(); // plane splits ray
+			}
+			else // ray and plane are coincident
+			{
+				// WHAT TO DO IN THIS CASE ?
+				//break;
+				node = in->GetFront();
+				continue;
+			}
+
+			// push data for far child
+			tQueue.push(BspRayTraversalData(farChild, extp, maxt));
+
+			// find intersection of ray segment with plane
+			float t;
+			extp = splitPlane.FindIntersection(ray.GetLoc(), extp, &t);
+			maxt *= t;
+
+		} else // reached leaf => intersection with view cell
+		{
+			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+
+			if (!leaf->GetViewCell()->Mailed())
+			{
+				//ray.bspIntersections.push_back(Ray::VspBspIntersection(maxt, leaf));
+				leaf->GetViewCell()->Mail();
+				++ hits;
+			}
+
+   			//-- fetch the next far child from the stack
+			if (tQueue.empty())
+				break;
+
+			entp = extp;
+			mint = maxt; // NOTE: need this?
+
+			if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f)
+				break;
+
+			BspRayTraversalData &s = tQueue.top();
+
+			node = s.mNode;
+			extp = s.mExitPoint;
+			maxt = s.mMaxT;
+
+			tQueue.pop();
+		}
+	}
+
+	return hits;
+}
+
+
+void VspBspTree::CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const
+{
+	ViewCell::NewMail();
+	
+	CollectViewCells(mRoot, onlyValid, viewCells, true);
+}
+
+
+void VspBspTree::CollapseViewCells()
+{
+// TODO
+#if VC_HISTORY
+	stack<BspNode *> nodeStack;
+
+	if (!mRoot)
+		return;
+
+	nodeStack.push(mRoot);
+	
+	while (!nodeStack.empty()) 
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+		
+		if (node->IsLeaf())
+        {
+			BspViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->GetViewCell();
+
+			if (!viewCell->GetValid())
+			{
+				BspViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->GetViewCell();
+	
+				ViewCellContainer leaves;
+				mViewCellsTree->CollectLeaves(viewCell, leaves);
+
+				ViewCellContainer::const_iterator it, it_end = leaves.end();
+
+				for (it = leaves.begin(); it != it_end; ++ it)
+				{
+					BspLeaf *l = dynamic_cast<BspViewCell *>(*it)->mLeaf;
+					l->SetViewCell(GetOrCreateOutOfBoundsCell());
+					++ mBspStats.invalidLeaves;
+				}
+
+				// add to unbounded view cell
+				GetOrCreateOutOfBoundsCell()->GetPvs().AddPvs(viewCell->GetPvs());
+				DEL_PTR(viewCell);
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+		
+			nodeStack.push(interior->GetFront());
+			nodeStack.push(interior->GetBack());
+		}
+	}
+
+	Debug << "invalid leaves: " << mBspStats.invalidLeaves << endl;
+#endif
+}
+
+
+void VspBspTree::ValidateTree()
+{
+	stack<BspNode *> nodeStack;
+
+	if (!mRoot)
+		return;
+
+	nodeStack.push(mRoot);
+	
+	mBspStats.invalidLeaves = 0;
+	while (!nodeStack.empty()) 
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+		
+		if (node->IsLeaf())
+		{
+			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+
+			if (!leaf->GetViewCell()->GetValid())
+				++ mBspStats.invalidLeaves;
+
+			// validity flags don't match => repair
+			if (leaf->GetViewCell()->GetValid() != leaf->TreeValid())
+			{
+				leaf->SetTreeValid(leaf->GetViewCell()->GetValid());
+				PropagateUpValidity(leaf);
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+		
+			nodeStack.push(interior->GetFront());
+			nodeStack.push(interior->GetBack());
+		}
+	}
+
+	Debug << "invalid leaves: " << mBspStats.invalidLeaves << endl;
+}
+
+
+
+void VspBspTree::CollectViewCells(BspNode *root,
+								  bool onlyValid,
+								  ViewCellContainer &viewCells,
+								  bool onlyUnmailed) const
+{
+	stack<BspNode *> nodeStack;
+
+	if (!root)
+		return;
+
+	nodeStack.push(root);
+	
+	while (!nodeStack.empty()) 
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+		
+		if (node->IsLeaf())
+		{
+			if (!onlyValid || node->TreeValid())
+			{
+				ViewCell *viewCell = 
+					mViewCellsTree->GetActiveViewCell(dynamic_cast<BspLeaf *>(node)->GetViewCell());
+						
+				if (!onlyUnmailed || !viewCell->Mailed()) 
+				{
+					viewCell->Mail();
+					viewCells.push_back(viewCell);
+				}
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+		
+			nodeStack.push(interior->GetFront());
+			nodeStack.push(interior->GetBack());
+		}
+	}
+
+}
+
+
+float VspBspTree::AccumulatedRayLength(const RayInfoContainer &rays) const
+{
+	float len = 0;
+
+	RayInfoContainer::const_iterator it, it_end = rays.end();
+
+	for (it = rays.begin(); it != it_end; ++ it)
+		len += (*it).SegmentLength();
+
+	return len;
+}
+
+
+int VspBspTree::SplitRays(const Plane3 &plane,
+						  RayInfoContainer &rays,
+						  RayInfoContainer &frontRays,
+						  RayInfoContainer &backRays)
+{
+	int splits = 0;
+
+	RayInfoContainer::const_iterator it, it_end = rays.end();
+
+	for (it = rays.begin(); it != it_end; ++ it)
+	{
+		RayInfo bRay = *it;
+		
+		VssRay *ray = bRay.mRay;
+		float t;
+
+		// get classification and receive new t
+		const int cf = bRay.ComputeRayIntersection(plane, t);
+
+		switch (cf)
+		{
+		case -1:
+			backRays.push_back(bRay);
+			break;
+		case 1:
+			frontRays.push_back(bRay);
+			break;
+		case 0:
+			{
+				//-- split ray
+				//-- test if start point behind or in front of plane
+				const int side = plane.Side(bRay.ExtrapOrigin());
+
+				if (side <= 0)
+				{
+					backRays.push_back(RayInfo(ray, bRay.GetMinT(), t));
+					frontRays.push_back(RayInfo(ray, t, bRay.GetMaxT()));
+				}
+				else
+				{
+					frontRays.push_back(RayInfo(ray, bRay.GetMinT(), t));
+					backRays.push_back(RayInfo(ray, t, bRay.GetMaxT()));
+				}
+			}
+			break;
+		default:
+			Debug << "Should not come here" << endl;
+			break;
+		}
+	}
+
+	return splits;
+}
+
+
+void VspBspTree::ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const
+{
+	BspNode *lastNode;
+
+	do
+	{
+		lastNode = n;
+
+		// want to get planes defining geometry of this node => don't take
+		// split plane of node itself
+		n = n->GetParent();
+
+		if (n)
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(n);
+			Plane3 halfSpace = dynamic_cast<BspInterior *>(interior)->GetPlane();
+
+            if (interior->GetFront() != lastNode)
+				halfSpace.ReverseOrientation();
+
+			halfSpaces.push_back(halfSpace);
+		}
+	}
+	while (n);
+}
+
+
+void VspBspTree::ConstructGeometry(BspNode *n,
+								   BspNodeGeometry &geom) const
+{
+	vector<Plane3> halfSpaces;
+	ExtractHalfSpaces(n, halfSpaces);
+
+	PolygonContainer candidatePolys;
+
+	// bounded planes are added to the polygons (reverse polygons
+	// as they have to be outfacing
+	for (int i = 0; i < (int)halfSpaces.size(); ++ i)
+	{
+		Polygon3 *p = GetBoundingBox().CrossSection(halfSpaces[i]);
+
+		if (p->Valid(mEpsilon))
+		{
+			candidatePolys.push_back(p->CreateReversePolygon());
+			DEL_PTR(p);
+		}
+	}
+
+	// add faces of bounding box (also could be faces of the cell)
+	for (int i = 0; i < 6; ++ i)
+	{
+		VertexContainer vertices;
+
+		for (int j = 0; j < 4; ++ j)
+			vertices.push_back(mBox.GetFace(i).mVertices[j]);
+
+		candidatePolys.push_back(new Polygon3(vertices));
+	}
+
+	for (int i = 0; i < (int)candidatePolys.size(); ++ i)
+	{
+		// polygon is split by all other planes
+		for (int j = 0; (j < (int)halfSpaces.size()) && candidatePolys[i]; ++ j)
+		{
+			if (i == j) // polygon and plane are coincident
+				continue;
+
+			VertexContainer splitPts;
+			Polygon3 *frontPoly, *backPoly;
+
+			const int cf =
+				candidatePolys[i]->ClassifyPlane(halfSpaces[j],
+												 mEpsilon);
+
+			switch (cf)
+			{
+				case Polygon3::SPLIT:
+					frontPoly = new Polygon3();
+					backPoly = new Polygon3();
+
+					candidatePolys[i]->Split(halfSpaces[j],
+											 *frontPoly,
+											 *backPoly,
+											 mEpsilon);
+
+					DEL_PTR(candidatePolys[i]);
+
+					if (frontPoly->Valid(mEpsilon))
+						candidatePolys[i] = frontPoly;
+					else
+						DEL_PTR(frontPoly);
+
+					DEL_PTR(backPoly);
+					break;
+				case Polygon3::BACK_SIDE:
+					DEL_PTR(candidatePolys[i]);
+					break;
+				// just take polygon as it is
+				case Polygon3::FRONT_SIDE:
+				case Polygon3::COINCIDENT:
+				default:
+					break;
+			}
+		}
+
+		if (candidatePolys[i])
+			geom.mPolys.push_back(candidatePolys[i]);
+	}
+}
+
+
+void VspBspTree::ConstructGeometry(ViewCell *vc, 
+								   BspNodeGeometry &vcGeom) const
+{
+	ViewCellContainer leaves;
+	
+	mViewCellsTree->CollectLeaves(vc, leaves);
+
+	ViewCellContainer::const_iterator it, it_end = leaves.end();
+
+	for (it = leaves.begin(); it != it_end; ++ it)
+	{
+		BspLeaf *l = dynamic_cast<BspViewCell *>(*it)->mLeaf;
+		
+		ConstructGeometry(l, vcGeom);
+	}
+}
+
+
+typedef pair<BspNode *, BspNodeGeometry *> bspNodePair;
+
+
+int VspBspTree::FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors,
+							  const bool onlyUnmailed) const
+{
+	stack<bspNodePair> nodeStack;
+	
+	BspNodeGeometry nodeGeom;
+	ConstructGeometry(n, nodeGeom);
+	
+	// split planes from the root to this node
+	// needed to verify that we found neighbor leaf
+	// TODO: really needed?
+	vector<Plane3> halfSpaces;
+	ExtractHalfSpaces(n, halfSpaces);
+
+
+	BspNodeGeometry *rgeom = new BspNodeGeometry();
+	ConstructGeometry(mRoot, *rgeom);
+
+	nodeStack.push(bspNodePair(mRoot, rgeom));
+
+	while (!nodeStack.empty())
+	{
+		BspNode *node = nodeStack.top().first;
+		BspNodeGeometry *geom = nodeStack.top().second;
+	
+		nodeStack.pop();
+
+		if (node->IsLeaf())
+		{
+			// test if this leaf is in valid view space
+			if (node->TreeValid() &&
+				(node != n) && 
+				(!onlyUnmailed || !node->Mailed()))
+			{
+				bool isAdjacent = true;
+
+				if (1)
+				{
+					// test all planes of current node if still adjacent
+					for (int i = 0; (i < halfSpaces.size()) && isAdjacent; ++ i)
+					{
+						const int cf =
+							Polygon3::ClassifyPlane(geom->mPolys,
+													halfSpaces[i],
+													mEpsilon);
+
+						if (cf == Polygon3::BACK_SIDE)
+						{
+							isAdjacent = false;
+						}
+					}
+				}
+				else
+				{
+					// TODO: why is this wrong??
+					// test all planes of current node if still adjacent
+					for (int i = 0; (i < (int)nodeGeom.mPolys.size()) && isAdjacent; ++ i)
+					{
+						Polygon3 *poly = nodeGeom.mPolys[i];
+
+						const int cf =
+							Polygon3::ClassifyPlane(geom->mPolys,
+													poly->GetSupportingPlane(),
+													mEpsilon);
+
+						if (cf == Polygon3::BACK_SIDE)
+						{
+							isAdjacent = false;
+						}
+					}
+				}
+				// neighbor was found
+				if (isAdjacent)
+				{	
+					neighbors.push_back(dynamic_cast<BspLeaf *>(node));
+				}
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			const int cf = Polygon3::ClassifyPlane(nodeGeom.mPolys,
+												   interior->GetPlane(),
+												   mEpsilon);
+			
+			BspNode *front = interior->GetFront();
+			BspNode *back = interior->GetBack();
+            
+			BspNodeGeometry *fGeom = new BspNodeGeometry();
+			BspNodeGeometry *bGeom = new BspNodeGeometry();
+
+			geom->SplitGeometry(*fGeom,
+								*bGeom,
+								interior->GetPlane(),
+								mBox,
+								mEpsilon);
+		
+			if (cf == Polygon3::FRONT_SIDE)
+			{
+				nodeStack.push(bspNodePair(interior->GetFront(), fGeom));
+				DEL_PTR(bGeom);
+			}
+			else
+			{
+				if (cf == Polygon3::BACK_SIDE)
+				{
+					nodeStack.push(bspNodePair(interior->GetBack(), bGeom));
+					DEL_PTR(fGeom);
+				}
+				else
+				{	// random decision
+					nodeStack.push(bspNodePair(front, fGeom));
+					nodeStack.push(bspNodePair(back, bGeom));
+				}
+			}
+		}
+	
+		DEL_PTR(geom);
+	}
+
+	return (int)neighbors.size();
+}
+
+
+
+int VspBspTree::FindApproximateNeighbors(BspNode *n, vector<BspLeaf *> &neighbors,
+										 const bool onlyUnmailed) const
+{
+	stack<bspNodePair> nodeStack;
+	
+	BspNodeGeometry nodeGeom;
+	ConstructGeometry(n, nodeGeom);
+	
+	// split planes from the root to this node
+	// needed to verify that we found neighbor leaf
+	// TODO: really needed?
+	vector<Plane3> halfSpaces;
+	ExtractHalfSpaces(n, halfSpaces);
+
+
+	BspNodeGeometry *rgeom = new BspNodeGeometry();
+	ConstructGeometry(mRoot, *rgeom);
+
+	nodeStack.push(bspNodePair(mRoot, rgeom));
+
+	while (!nodeStack.empty())
+	{
+		BspNode *node = nodeStack.top().first;
+		BspNodeGeometry *geom = nodeStack.top().second;
+	
+		nodeStack.pop();
+
+		if (node->IsLeaf())
+		{
+			// test if this leaf is in valid view space
+			if (node->TreeValid() &&
+				(node != n) && 
+				(!onlyUnmailed || !node->Mailed()))
+			{
+				bool isAdjacent = true;
+
+				// neighbor was found
+				if (isAdjacent)
+				{	
+					neighbors.push_back(dynamic_cast<BspLeaf *>(node));
+				}
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			const int cf = Polygon3::ClassifyPlane(nodeGeom.mPolys,
+												   interior->GetPlane(),
+												   mEpsilon);
+			
+			BspNode *front = interior->GetFront();
+			BspNode *back = interior->GetBack();
+            
+			BspNodeGeometry *fGeom = new BspNodeGeometry();
+			BspNodeGeometry *bGeom = new BspNodeGeometry();
+
+			geom->SplitGeometry(*fGeom,
+								*bGeom,
+								interior->GetPlane(),
+								mBox,
+								mEpsilon);
+		
+			if (cf == Polygon3::FRONT_SIDE)
+			{
+				nodeStack.push(bspNodePair(interior->GetFront(), fGeom));
+				DEL_PTR(bGeom);
+			}
+			else
+			{
+				if (cf == Polygon3::BACK_SIDE)
+				{
+					nodeStack.push(bspNodePair(interior->GetBack(), bGeom));
+					DEL_PTR(fGeom);
+				}
+				else
+				{	// random decision
+					nodeStack.push(bspNodePair(front, fGeom));
+					nodeStack.push(bspNodePair(back, bGeom));
+				}
+			}
+		}
+	
+		DEL_PTR(geom);
+	}
+
+	return (int)neighbors.size();
+}
+
+
+
+BspLeaf *VspBspTree::GetRandomLeaf(const Plane3 &halfspace)
+{
+    stack<BspNode *> nodeStack;
+  	nodeStack.push(mRoot);
+
+	int mask = rand();
+
+	while (!nodeStack.empty())
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+
+		if (node->IsLeaf())
+		{
+			return dynamic_cast<BspLeaf *>(node);
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+			BspNode *next;
+			BspNodeGeometry geom;
+
+			// todo: not very efficient: constructs full cell everytime
+			ConstructGeometry(interior, geom);
+
+			const int cf = 
+				Polygon3::ClassifyPlane(geom.mPolys, halfspace, mEpsilon);
+
+			if (cf == Polygon3::BACK_SIDE)
+				next = interior->GetFront();
+			else
+				if (cf == Polygon3::FRONT_SIDE)
+					next = interior->GetFront();
+			else
+			{
+				// random decision
+				if (mask & 1)
+					next = interior->GetBack();
+				else
+					next = interior->GetFront();
+				mask = mask >> 1;
+			}
+
+			nodeStack.push(next);
+		}
+	}
+
+	return NULL;
+}
+
+BspLeaf *VspBspTree::GetRandomLeaf(const bool onlyUnmailed)
+{
+	stack<BspNode *> nodeStack;
+
+	nodeStack.push(mRoot);
+
+	int mask = rand();
+
+	while (!nodeStack.empty())
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+
+		if (node->IsLeaf())
+		{
+			if ( (!onlyUnmailed || !node->Mailed()) )
+				return dynamic_cast<BspLeaf *>(node);
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			// random decision
+			if (mask & 1)
+				nodeStack.push(interior->GetBack());
+			else
+				nodeStack.push(interior->GetFront());
+
+			mask = mask >> 1;
+		}
+	}
+
+	return NULL;
+}
+
+int VspBspTree::ComputePvsSize(const RayInfoContainer &rays) const
+{
+	int pvsSize = 0;
+
+	RayInfoContainer::const_iterator rit, rit_end = rays.end();
+
+	Intersectable::NewMail();
+
+	for (rit = rays.begin(); rit != rays.end(); ++ rit)
+	{
+		VssRay *ray = (*rit).mRay;
+
+		if (ray->mOriginObject)
+		{
+			if (!ray->mOriginObject->Mailed())
+			{
+				ray->mOriginObject->Mail();
+				++ pvsSize;
+			}
+		}
+		if (ray->mTerminationObject)
+		{
+			if (!ray->mTerminationObject->Mailed())
+			{
+				ray->mTerminationObject->Mail();
+				++ pvsSize;
+			}
+		}
+	}
+
+	return pvsSize;
+}
+
+float VspBspTree::GetEpsilon() const
+{
+	return mEpsilon;
+}
+
+
+int VspBspTree::SplitPolygons(const Plane3 &plane,
+							  PolygonContainer &polys,
+							  PolygonContainer &frontPolys,
+							  PolygonContainer &backPolys,
+							  PolygonContainer &coincident) const
+{
+	int splits = 0;
+
+	PolygonContainer::const_iterator it, it_end = polys.end();
+
+	for (it = polys.begin(); it != polys.end(); ++ it)	
+	{
+		Polygon3 *poly = *it;
+
+		// classify polygon
+		const int cf = poly->ClassifyPlane(plane, mEpsilon);
+
+		switch (cf)
+		{
+			case Polygon3::COINCIDENT:
+				coincident.push_back(poly);
+				break;
+			case Polygon3::FRONT_SIDE:
+				frontPolys.push_back(poly);
+				break;
+			case Polygon3::BACK_SIDE:
+				backPolys.push_back(poly);
+				break;
+			case Polygon3::SPLIT:
+				backPolys.push_back(poly);
+				frontPolys.push_back(poly);
+				++ splits;
+				break;
+			default:
+                Debug << "SHOULD NEVER COME HERE\n";
+				break;
+		}
+	}
+
+	return splits;
+}
+
+
+int VspBspTree::CastLineSegment(const Vector3 &origin,
+								const Vector3 &termination,
+								vector<ViewCell *> &viewcells)
+{
+	int hits = 0;
+	stack<BspRayTraversalData> tQueue;
+
+	float mint = 0.0f, maxt = 1.0f;
+
+	Intersectable::NewMail();
+	ViewCell::NewMail();
+
+	Vector3 entp = origin;
+	Vector3 extp = termination;
+
+	BspNode *node = mRoot;
+	BspNode *farChild = NULL;
+
+	float t;
+	while (1)
+	{
+		if (!node->IsLeaf())
+		{
+			BspInterior *in = dynamic_cast<BspInterior *>(node);
+
+			Plane3 splitPlane = in->GetPlane();
+			
+			const int entSide = splitPlane.Side(entp);
+			const int extSide = splitPlane.Side(extp);
+
+			if (entSide < 0) 
+			{
+			  node = in->GetBack();
+			  // plane does not split ray => no far child
+			  if (extSide <= 0) 
+				continue;
+			  
+			  farChild = in->GetFront(); // plane splits ray
+			} 
+			else if (entSide > 0)
+			{
+			  node = in->GetFront();
+
+			  if (extSide >= 0) // plane does not split ray => no far child
+				continue;
+
+				farChild = in->GetBack(); // plane splits ray
+			}
+			else // ray end point on plane
+			{	// NOTE: what to do if ray is coincident with plane?
+				if (extSide < 0)
+					node = in->GetBack();
+				else 
+					node = in->GetFront();
+								
+				continue; // no far child
+			}
+
+			// push data for far child
+			tQueue.push(BspRayTraversalData(farChild, extp));
+
+			// find intersection of ray segment with plane
+			extp = splitPlane.FindIntersection(origin, extp, &t);
+		} 
+		else
+		{
+			// reached leaf => intersection with view cell
+			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+
+			ViewCell *viewCell = mViewCellsTree->GetActiveViewCell(leaf->GetViewCell());
+			if (!viewCell->Mailed())
+			{
+				viewcells.push_back(viewCell);
+				viewCell->Mail();
+				++ hits;
+			}
+
+			//-- fetch the next far child from the stack
+			if (tQueue.empty())
+				break;
+
+			entp = extp;
+			
+			BspRayTraversalData &s = tQueue.top();
+
+			node = s.mNode;
+			extp = s.mExitPoint;
+
+			tQueue.pop();
+		}
+	}
+
+	return hits;
+}
+
+
+
+
+int VspBspTree::TreeDistance(BspNode *n1, BspNode *n2) const
+{
+	std::deque<BspNode *> path1;
+	BspNode *p1 = n1;
+
+	// create path from node 1 to root
+	while (p1)
+	{
+		if (p1 == n2) // second node on path
+			return (int)path1.size();
+
+		path1.push_front(p1);
+		p1 = p1->GetParent();
+	}
+
+	int depth = n2->GetDepth();
+	int d = depth;
+
+	BspNode *p2 = n2;
+
+	// compare with same depth
+	while (1)
+	{
+		if ((d < (int)path1.size()) && (p2 == path1[d]))
+			return (depth - d) + ((int)path1.size() - 1 - d);
+
+		-- d;
+		p2 = p2->GetParent();
+	}
+
+	return 0; // never come here
+}
+
+
+BspNode *VspBspTree::CollapseTree(BspNode *node, int &collapsed)
+{
+// TODO
+#if VC_HISTORY
+	if (node->IsLeaf())
+		return node;
+
+	BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+	BspNode *front = CollapseTree(interior->GetFront(), collapsed);
+	BspNode *back = CollapseTree(interior->GetBack(), collapsed);
+
+	if (front->IsLeaf() && back->IsLeaf())
+	{
+		BspLeaf *frontLeaf = dynamic_cast<BspLeaf *>(front);
+		BspLeaf *backLeaf = dynamic_cast<BspLeaf *>(back);
+
+		//-- collapse tree
+		if (frontLeaf->GetViewCell() == backLeaf->GetViewCell())
+		{
+			BspViewCell *vc = frontLeaf->GetViewCell();
+
+			BspLeaf *leaf = new BspLeaf(interior->GetParent(), vc);
+			leaf->SetTreeValid(frontLeaf->TreeValid());
+
+			// replace a link from node's parent
+			if (leaf->GetParent())
+				leaf->GetParent()->ReplaceChildLink(node, leaf);
+			else
+				mRoot = leaf;
+
+			++ collapsed;
+			delete interior;
+
+			return leaf;
+		}
+	}
+#endif
+	return node;
+}
+
+
+int VspBspTree::CollapseTree()
+{
+	int collapsed = 0;
+	//TODO
+#if VC_HISTORY
+	(void)CollapseTree(mRoot, collapsed);
+
+	// revalidate leaves
+	RepairViewCellsLeafLists();
+#endif
+	return collapsed;
+}
+
+
+void VspBspTree::RepairViewCellsLeafLists()
+{
+// TODO
+#if VC_HISTORY
+	// list not valid anymore => clear
+	stack<BspNode *> nodeStack;
+	nodeStack.push(mRoot);
+
+	ViewCell::NewMail();
+
+	while (!nodeStack.empty())
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+
+		if (node->IsLeaf())
+		{
+			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+
+			BspViewCell *viewCell = leaf->GetViewCell();
+
+			if (!viewCell->Mailed())
+			{
+				viewCell->mLeaves.clear();
+				viewCell->Mail();
+			}
+	
+			viewCell->mLeaves.push_back(leaf);
+
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			nodeStack.push(interior->GetFront());
+			nodeStack.push(interior->GetBack());
+		}
+	}
+// TODO
+#endif
+}
+
+
+typedef pair<BspNode *, BspNodeGeometry *> bspNodePair;
+
+
+int VspBspTree::CastBeam(Beam &beam)
+{
+    stack<bspNodePair> nodeStack;
+	BspNodeGeometry *rgeom = new BspNodeGeometry();
+	ConstructGeometry(mRoot, *rgeom);
+
+	nodeStack.push(bspNodePair(mRoot, rgeom));
+  
+	ViewCell::NewMail();
+
+	while (!nodeStack.empty()) 
+	{
+		BspNode *node = nodeStack.top().first;
+		BspNodeGeometry *geom = nodeStack.top().second;
+		nodeStack.pop();
+		
+		AxisAlignedBox3 box;
+		box.Initialize();
+		geom->IncludeInBox(box);
+
+		const int side = beam.ComputeIntersection(box);
+		
+		switch (side) 
+		{
+		case -1:
+			CollectViewCells(node, true, beam.mViewCells, true);
+			break;
+		case 0:
+			
+			if (node->IsLeaf())
+			{
+				BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+			
+				if (!leaf->GetViewCell()->Mailed() && leaf->TreeValid())
+				{
+					leaf->GetViewCell()->Mail();
+					beam.mViewCells.push_back(leaf->GetViewCell());
+				}
+			}
+			else 
+			{
+				BspInterior *interior = dynamic_cast<BspInterior *>(node);
+			
+				BspNode *first = interior->GetFront();
+				BspNode *second = interior->GetBack();
+            
+				BspNodeGeometry *firstGeom = new BspNodeGeometry();
+				BspNodeGeometry *secondGeom = new BspNodeGeometry();
+
+				geom->SplitGeometry(*firstGeom,
+									*secondGeom,
+									interior->GetPlane(),
+									mBox,
+									mEpsilon);
+
+				// decide on the order of the nodes
+				if (DotProd(beam.mPlanes[0].mNormal, 
+					interior->GetPlane().mNormal) > 0)
+				{
+					swap(first, second);
+					swap(firstGeom, secondGeom);
+				}
+
+				nodeStack.push(bspNodePair(first, firstGeom));
+				nodeStack.push(bspNodePair(second, secondGeom));
+			}
+			
+			break;
+		default:
+			// default: cull
+			break;
+		}
+		
+		DEL_PTR(geom);
+		
+	}
+
+	return (int)beam.mViewCells.size();
+}
+
+
+void VspBspTree::SetViewCellsManager(ViewCellsManager *vcm)
+{
+	mViewCellsManager = vcm;
+}
+
+
+int VspBspTree::CollectMergeCandidates(const vector<BspLeaf *> leaves,
+									   vector<MergeCandidate> &candidates)
+{
+	BspLeaf::NewMail();
+	
+	vector<BspLeaf *>::const_iterator it, it_end = leaves.end();
+
+	int numCandidates = 0;
+
+	// find merge candidates and push them into queue
+	for (it = leaves.begin(); it != it_end; ++ it)
+	{
+		BspLeaf *leaf = *it;
+		
+		// the same leaves must not be part of two merge candidates
+		leaf->Mail();
+		vector<BspLeaf *> neighbors;
+		FindNeighbors(leaf, neighbors, true);
+		//FindApproximateNeighbors(leaf, neighbors, true);
+		vector<BspLeaf *>::const_iterator nit, nit_end = neighbors.end();
+
+		// TODO: test if at least one ray goes from one leaf to the other
+		for (nit = neighbors.begin(); nit != nit_end; ++ nit)
+		{
+			if ((*nit)->GetViewCell() != leaf->GetViewCell())
+			{
+				MergeCandidate mc(leaf->GetViewCell(), (*nit)->GetViewCell());
+				candidates.push_back(mc);
+
+				++ numCandidates;
+				if ((numCandidates % 1000) == 0)
+				{
+					cout << "collected " << numCandidates << " merge candidates" << endl;
+				}
+			}
+		}
+	}
+
+	Debug << "merge queue: " << (int)candidates.size() << endl;
+	Debug << "leaves in queue: " << numCandidates << endl;
+	
+
+	return (int)leaves.size();
+}
+
+
+int VspBspTree::CollectMergeCandidates(const VssRayContainer &rays, 
+									   vector<MergeCandidate> &candidates)
+{
+	ViewCell::NewMail();
+	long startTime = GetTime();
+	
+	map<BspLeaf *, vector<BspLeaf*> > neighborMap;
+	ViewCellContainer::const_iterator iit;
+
+	int numLeaves = 0;
+	
+	BspLeaf::NewMail();
+
+	for (int i = 0; i < (int)rays.size(); ++ i)
+	{  
+		VssRay *ray = rays[i];
+	
+		// traverse leaves stored in the rays and compare and 
+		// merge consecutive leaves (i.e., the neighbors in the tree)
+		if (ray->mViewCells.size() < 2)
+			continue;
+//TODO viewcellhierarchy
+		iit = ray->mViewCells.begin();
+		BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*(iit ++));
+		BspLeaf *leaf = bspVc->mLeaf;
+		
+		// traverse intersections 
+		// consecutive leaves are neighbors => add them to queue
+		for (; iit != ray->mViewCells.end(); ++ iit)
+		{
+			// next pair
+			BspLeaf *prevLeaf = leaf;
+			bspVc = dynamic_cast<BspViewCell *>(*iit);
+            leaf = bspVc->mLeaf;
+
+			// view space not valid or same view cell
+			if (!leaf->TreeValid() || !prevLeaf->TreeValid() ||
+				(leaf->GetViewCell() == prevLeaf->GetViewCell()))
+				continue;
+
+           	vector<BspLeaf *> &neighbors = neighborMap[leaf];
+			
+			bool found = false;
+
+			// both leaves inserted in queue already =>
+			// look if double pair already exists
+			if (leaf->Mailed() && prevLeaf->Mailed())
+			{
+				vector<BspLeaf *>::const_iterator it, it_end = neighbors.end();
+				
+                for (it = neighbors.begin(); !found && (it != it_end); ++ it)
+					if (*it == prevLeaf)
+						found = true; // already in queue
+			}
+		
+			if (!found)
+			{
+				// this pair is not in map yet
+				// => insert into the neighbor map and the queue
+				neighbors.push_back(prevLeaf);
+				neighborMap[prevLeaf].push_back(leaf);
+
+				leaf->Mail();
+				prevLeaf->Mail();
+		
+				MergeCandidate mc(leaf->GetViewCell(), prevLeaf->GetViewCell());
+				
+				candidates.push_back(mc);
+
+				if (((int)candidates.size() % 1000) == 0)
+				{
+					cout << "collected " << (int)candidates.size() << " merge candidates" << endl;
+				}
+			}
+        }
+	}
+
+	Debug << "neighbormap size: " << (int)neighborMap.size() << endl;
+	Debug << "merge queue: " << (int)candidates.size() << endl;
+	Debug << "leaves in queue: " << numLeaves << endl;
+
+
+	//-- collect the leaves which haven't been found by ray casting
+	if (0)
+	{
+		cout << "finding additional merge candidates using geometry" << endl;
+		vector<BspLeaf *> leaves;
+		CollectLeaves(leaves, true);
+		Debug << "found " << (int)leaves.size() << " new leaves" << endl << endl;
+		CollectMergeCandidates(leaves, candidates);
+	}
+
+	return numLeaves;
+}
+
+
+
+
+ViewCell *VspBspTree::GetViewCell(const Vector3 &point)
+{
+  if (mRoot == NULL)
+	return NULL;
+  
+  stack<BspNode *> nodeStack;
+  nodeStack.push(mRoot);
+  
+  ViewCell *viewcell = NULL;
+  
+  while (!nodeStack.empty())  {
+	BspNode *node = nodeStack.top();
+	nodeStack.pop();
+	
+	if (node->IsLeaf()) {
+	  viewcell = dynamic_cast<BspLeaf *>(node)->GetViewCell();
+	  break;
+	} else {
+	  
+	  BspInterior *interior = dynamic_cast<BspInterior *>(node);
+		
+	  // random decision
+	  if (interior->GetPlane().Side(point) < 0)
+		nodeStack.push(interior->GetBack());
+	  else
+		nodeStack.push(interior->GetFront());
+	}
+  }
+  
+  return viewcell;
+}
+
+
+bool VspBspTree::ViewPointValid(const Vector3 &viewPoint) const
+{
+	BspNode *node = mRoot;
+
+	while (1)
+	{
+		// early exit
+		if (node->TreeValid())
+			return true;
+
+		if (node->IsLeaf())
+			return false;
+			
+		BspInterior *in = dynamic_cast<BspInterior *>(node);
+					
+		if (in->GetPlane().Side(viewPoint) <= 0) 
+		{
+			node = in->GetBack();
+		} 
+		else
+		{
+			node = in->GetFront();
+		}
+	}
+
+	// should never come here
+	return false;
+}
+
+
+void VspBspTree::PropagateUpValidity(BspNode *node)
+{
+	const bool isValid = node->TreeValid();
+
+	// propagative up invalid flag until only invalid nodes exist over this node
+	if (!isValid)
+	{
+		while (!node->IsRoot() && node->GetParent()->TreeValid())
+		{
+			node = node->GetParent();
+			node->SetTreeValid(false);
+		}
+	}
+	else
+	{
+		// propagative up valid flag until one of the subtrees is invalid
+		while (!node->IsRoot() && !node->TreeValid())
+		{
+            node = node->GetParent();
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+			
+			// the parent is valid iff both leaves are valid
+			node->SetTreeValid(interior->GetBack()->TreeValid() && 
+							   interior->GetFront()->TreeValid());
+		}
+	}
+}
+
+
+bool VspBspTree::Export(ofstream &stream)
+{
+	ExportNode(mRoot, stream);
+
+	return true;
+}
+
+
+void VspBspTree::ExportNode(BspNode *node, ofstream &stream)
+{
+	if (node->IsLeaf())
+	{
+		BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+		ViewCell *viewCell = mViewCellsTree->GetActiveViewCell(leaf->GetViewCell());
+
+		int id = -1;
+		if (viewCell != mOutOfBoundsCell)
+			id = viewCell->GetId();
+
+		stream << "<Leaf viewCellId=\"" << id << "\" />" << endl;
+	}
+	else
+	{
+		BspInterior *interior = dynamic_cast<BspInterior *>(node);
+	
+		Plane3 plane = interior->GetPlane();
+		stream << "<Interior plane=\"" << plane.mNormal.x << " " 
+			   << plane.mNormal.y << " " << plane.mNormal.z << " " 
+			   << plane.mD << "\">" << endl;
+
+		ExportNode(interior->GetBack(), stream);
+		ExportNode(interior->GetFront(), stream);
+
+		stream << "</Interior>" << endl;
+	}
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Ray.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Ray.h	(revision 563)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Ray.h	(revision 563)
@@ -0,0 +1,335 @@
+#ifndef __RAY_H__
+#define __RAY_H__
+
+#include <vector>
+#include "Matrix4x4.h"
+#include "Vector3.h"
+//#include "ViewCellBsp.h"
+
+// forward declarations
+class Plane3;
+class Intersectable;
+class KdLeaf;
+class MeshInstance;
+class ViewCell;
+class BspLeaf;
+class VssRay;
+
+
+// -------------------------------------------------------------------
+// CRay class.  A ray is defined by a location and a direction.
+// The direction is always normalized (length == 1).
+// -------------------------------------------------------------------
+
+class Ray
+{
+public:
+  enum RayType { LOCAL_RAY, GLOBAL_RAY, LINE_SEGMENT };
+	
+  enum { NO_INTERSECTION=0, INTERSECTION_OUT_OF_LIMITS, INTERSECTION };
+
+  /// if ray is on back (front) side of plane, or goes from the 
+  /// front (back) to the back (front)
+  enum {FRONT, BACK, BACK_FRONT, FRONT_BACK, COINCIDENT};
+	
+  struct Intersection {
+    // the point of intersection
+    float mT;
+
+    // can be either mesh or a viewcell
+    Intersectable *mObject;
+		
+    // the face of the intersectable
+    int mFace;
+
+    Intersection(const float t,
+				 Intersectable *object,
+				 const int face):mT(t), mObject(object), mFace(face) {}
+		
+				 Intersection(): mT(0), mObject(NULL), mFace(0) {}
+		
+    bool operator<(
+				   const Intersection &b) const {
+
+      return 
+				mT
+				<
+				b.mT;
+    }
+    
+  };
+
+
+  // I should have some abstract cell data type !!! here
+  // corresponds to the spatial elementary cell
+  /** intersection with the source object if any */
+  Intersection sourceObject;
+  
+  vector<Intersection> intersections;
+ // vector<BspIntersection> bspIntersections;
+  vector<KdLeaf *> kdLeaves;
+  vector<Intersectable *> testedObjects;
+
+  // various flags
+  enum {STORE_KDLEAVES=1, STORE_BSP_INTERSECTIONS=2, STORE_TESTED_OBJECTS=4, CULL_BACKFACES=8};
+  int mFlags;
+
+	
+  // constructors
+  Ray(const Vector3 &wherefrom,
+      const Vector3 &whichdir,
+      const int _type):mFlags(CULL_BACKFACES) {
+    loc = wherefrom;
+    if (_type == LINE_SEGMENT)
+      dir = whichdir;
+    else
+      dir = Normalize(whichdir);
+    mType = _type;
+    depth = 0;
+		Init();
+  }
+  // dummy constructor
+  Ray() {}
+
+  /** Construct ray from a vss ray.
+  */
+  Ray(const VssRay &vssRay) {
+	Init(vssRay);
+	mFlags |= CULL_BACKFACES;
+  }
+
+  void Clear() {
+	intersections.clear();
+	kdLeaves.clear();
+	testedObjects.clear();
+	//	bspIntersections.clear();
+  }
+
+  void Init(const VssRay &vssRay);
+
+  Intersectable *GetIntersectionObject(const int i) const {
+    return intersections[i].mObject;
+  }
+  
+  Vector3 GetIntersectionPoint(const int i) const {
+    return Extrap(intersections[i].mT);
+  }
+  
+  // Inititalize the ray again when already constructed
+  void Init(const Vector3 &wherefrom,
+			const Vector3 &whichdir,
+			const int _type, 
+			bool dirNormalized = false) {
+    loc = wherefrom;
+    dir = (dirNormalized || _type == LINE_SEGMENT) ? whichdir: Normalize(whichdir) ;
+    mType = _type;
+    depth = 0;
+    Init();
+  }
+
+  // --------------------------------------------------------
+  // Extrapolate ray given a signed distance, returns a point
+  // --------------------------------------------------------
+  Vector3 Extrap(float t) const {
+    return loc + dir * t;
+  }
+
+  // -----------------------------------
+  // Return parameter given point on ray
+  // -----------------------------------
+  float Interp(Vector3 &x) const {
+    for (int i = 0; i < 3; i++)
+      if (Abs(dir[i]) > Limits::Small)
+	return (x[i] - loc[i]) / dir[i];
+    return 0;
+  }
+
+  // -----------------------------------
+  // Reflects direction of reflection for the ray, 
+  // given the normal to the surface.
+  // -----------------------------------
+  Vector3 ReflectRay(const Vector3 &N) const {
+    return N * 2.0 * DotProd(N, -dir) + dir;
+  }
+  void ReflectRay(Vector3 &result, const Vector3 &N) const {
+    result =  N * 2.0 * DotProd(N, -dir) + dir;
+  }
+
+  // Computes the inverted direction of the ray, used optionally by
+  // a ray traversal algorithm.
+  void ComputeInvertedDir() const;
+
+  // Given the matrix 4x4, transforms the ray to another space
+  void ApplyTransform(const Matrix4x4 &tform) {
+    loc = tform * loc;
+    dir = RotateOnly(tform, dir);
+    // note that normalization to the unit size of the direction
+    // is NOT computed -- this is what we want.
+    Precompute();
+  }
+
+  // returns ID of this ray (use for mailboxes)
+  int GetId() const { return ID; }
+
+  // returns the transfrom ID of the ray (use for ray transformations)
+  int GetTransformID() const { return transfID; }
+
+  // copy the transform ID from an input ray
+  void CopyTransformID(const Ray &ray) { transfID = ray.transfID; }
+  
+  // set unique ID for a given ray - always avoid setting to zero
+  void SetId() {
+    if ((ID = ++genID) == 0)
+      ID = ++genID;
+    transfID = ID;
+  }
+  // set ID to explicit value - it can be even 0 for rays transformed
+  // to the canonical object space to supress the mailbox failure.
+  void SetId(int newID) {
+    ID = newID;
+    // note that transfID is not changed!
+  }
+
+
+  // the object on which the ray starts at
+  const Intersection* GetStartObject() const { return &intersections[0]; }
+  const Intersection* GetStopObject() const { return &intersections[intersections.size()-1]; }
+  
+  
+  void SetLoc(const Vector3 &l);
+  Vector3& GetLoc() { return loc; }
+  Vector3  GetLoc() const { return loc; }
+
+  float  GetLoc(const int axis) const { return loc[axis]; }
+
+  void SetDir(const Vector3 &ndir) { dir = ndir;} 
+  Vector3& GetDir() { return dir; }
+  Vector3  GetDir() const { return dir; }
+  float  GetDir(const int axis) const { return dir[axis]; }
+
+  int GetType() const { return mType; }
+  
+  // make such operation to slightly change the ray direction
+  // in case any component of ray direction is zero.
+  void CorrectZeroComponents();
+
+  // the depth of the ray - primary rays are in the depth 0
+  int GetDepth() const { return depth;}
+  void SetDepth(int newDepth) { depth = newDepth;}
+  
+  /** Classifies ray with respect to the plane.
+  */
+  int ClassifyPlane(const Plane3 &plane, 
+					const float minT, 
+					const float maxT,
+					Vector3 &entP,
+					Vector3 &extP) const;
+
+private:
+  Vector3 loc, dir;		// Describes ray origin and vector
+  
+  // The inverted direction of the ray components. It is computed optionally
+  // by the ray traversal algorithm using function ComputeInvertedDir();
+  mutable Vector3 invDir;
+
+  // Type of the ray: primary, shadow, dummy etc., see ERayType above
+  int mType;
+ 
+  
+  // unique ID of a ray for the use in the mailboxes
+  int ID;
+  
+  // unique ID of a ray for the use with a transformations - this one
+  // never can be changed that allows the nesting of transformations
+  // and caching the transformed rays correctly
+  int transfID;
+  
+  // the ID generator fo each ray instantiated
+  static int genID;  
+
+  // When ray shot from the source(camera/light), this number is equal
+  // to the number of bounces of the ray, also called the depth of the
+  // ray (primary ray has its depth zero)
+  int depth;
+
+	
+	
+  void Init();
+
+  // precompute some values that are necessary
+  void Precompute();
+
+  friend class AxisAlignedBox3;
+  friend class Plane3;
+
+  // for CKDR GEMS
+  friend float DistanceToXPlane(const Vector3 &vec, const Ray &ray);
+  friend float DistanceToYPlane(const Vector3 &vec, const Ray &ray);
+  friend float DistanceToZPlane(const Vector3 &vec, const Ray &ray);
+  friend int MakeIntersectLine(const Plane3 &p, const Plane3 &q, Ray &ray);
+
+	friend ostream &operator<<(ostream &s, const Ray &r) {
+		return s<<"Ray:loc="<<r.loc<<" dir="<<r.dir;
+	}
+};
+
+
+class PassingRaySet {
+public:
+  enum { Resolution = 2 };
+  int mDirectionalContributions[3*Resolution*Resolution];
+  int mRays;
+  int mContributions;
+
+	PassingRaySet() {
+    Reset();
+  }
+
+	void
+  Reset();
+  
+  void AddRay(const Ray &ray, const int contributions);
+	void AddRay2(const Ray &ray,
+							 const int objects,
+							 const int viewcells);
+
+  int GetEntryIndex(const Vector3 &direction) const;
+
+  friend ostream &operator<<(ostream &s, const PassingRaySet &set);
+
+};
+
+struct SimpleRay
+{
+  Vector3 mOrigin;
+  Vector3 mDirection;
+  float mPdf;
+
+  SimpleRay() {}
+  SimpleRay(const Vector3 &o, const Vector3 &d, const float p=1.0f):
+	mOrigin(o), mDirection(d), mPdf(p) {}
+};
+
+class SimpleRayContainer : public vector<SimpleRay>
+{
+public:
+  
+  float mSumPdf;
+  
+  SimpleRayContainer():vector<SimpleRay>(), mSumPdf(0.0f) {}
+  
+  void NormalizePdf() {
+	iterator it = begin();
+	float c = 1.0f/mSumPdf;
+	for (; it != end(); it++)
+	  (*it).mPdf*=c;
+  }
+
+  void AddRay(const SimpleRay &ray) {
+	push_back(ray);
+	mSumPdf += ray.mPdf;
+  }
+};
+
+#endif 
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VssTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VssTree.h	(revision 466)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VssTree.h	(revision 466)
@@ -0,0 +1,932 @@
+// ================================================================
+// $Id$
+// ****************************************************************
+// 
+// Initial coding by
+/**
+   @author Jiri Bittner
+*/
+
+#ifndef __VSSTREE_H__
+#define __VSSTREE_H__
+
+// Standard headers
+#include <iomanip>
+#include <vector>
+#include <functional>
+#include <stack>
+
+
+// User headers
+#include "VssRay.h"
+#include "AxisAlignedBox3.h"
+
+
+#define USE_KDNODE_VECTORS 1
+#define _RSS_STATISTICS
+#define _RSS_TRAVERSAL_STATISTICS
+
+
+#include "Statistics.h"
+#include "Ray.h"
+
+// --------------------------------------------------------------
+// Static statistics for kd-tree search
+// --------------------------------------------------------------
+class VssStatistics :
+  public StatisticsBase
+{
+public:  
+  // total number of nodes
+  int nodes;
+  // number of splits along each of the axes
+  int splits[7];
+  // totals number of rays
+  int rays;
+  // initial size of the pvs
+  int initialPvsSize;
+  // total number of query domains
+  int queryDomains;
+  // total number of ray references
+  int rayRefs;
+
+  // max depth nodes
+  int maxDepthNodes;
+  // max depth nodes
+  int minPvsNodes;
+  int minRaysNodes;
+  // max ray contribution nodes
+  int maxRayContribNodes;
+  // max depth nodes
+  int minSizeNodes;
+  int maxCostRatioNodes;
+
+  // max number of rays per node
+  int maxRayRefs;
+  // number of dynamically added ray refs
+  int addedRayRefs;
+  // number of dynamically removed ray refs
+  int removedRayRefs;
+  
+  // Constructor
+  VssStatistics() {
+    Reset();
+  }
+
+  int Nodes() const {return nodes;}
+  int Interior() const { return nodes/2; }
+  int Leaves() const { return (nodes/2) + 1; }
+
+  void Reset() {
+    nodes = 0;
+    for (int i=0; i<7; i++)
+      splits[i] = 0;
+    rays = queryDomains = 0;
+    rayRefs = 0;
+    maxDepthNodes = 0;
+    minPvsNodes = 0;
+    minRaysNodes = 0;
+    maxRayRefs = 0;
+    addedRayRefs = removedRayRefs = 0;
+	initialPvsSize = 0;
+	maxRayContribNodes = 0;
+	minSizeNodes = 0;
+	maxCostRatioNodes = 0;
+  }
+
+  
+  void
+  Print(ostream &app) const;
+
+  friend ostream &operator<<(ostream &s, const VssStatistics &stat) {
+    stat.Print(s);
+    return s;
+  }
+  
+};
+
+
+
+
+class VssTreeInterior;
+
+
+// --------------------------------------------------------------
+// KD-tree node - abstract class
+// --------------------------------------------------------------
+class VssTreeNode
+{
+public:
+
+#define USE_FIXEDPOINT_T 0
+
+  struct RayInfo
+  {
+	// pointer to the actual ray
+	VssRay *mRay;
+	
+	// endpoints  - do we need them?
+#if USE_FIXEDPOINT_T
+	short mMinT, mMaxT;
+#else
+	float mMinT, mMaxT;
+#endif
+	
+	RayInfo():mRay(NULL) {}
+	
+	RayInfo(VssRay *r):mRay(r), mMinT(0),
+#if USE_FIXEDPOINT_T
+#define FIXEDPOINT_ONE 0x7FFE
+					   //			  mMaxT(0xFFFF)
+					   mMaxT(FIXEDPOINT_ONE)
+#else
+	  mMaxT(1.0f)
+#endif
+	{}
+	
+	RayInfo(VssRay *r,
+			const float _min,
+			const float _max
+			):mRay(r) {
+	  SetMinT(_min);
+	  SetMaxT(_max);
+	}
+	
+	RayInfo(VssRay *r,
+			const short _min,
+			const float _max
+			):mRay(r), mMinT(_min) {
+	  SetMaxT(_max);
+	}
+	
+	RayInfo(VssRay *r,
+			const float _min,
+			const short _max
+			):mRay(r), mMaxT(_max) {
+	  SetMinT(_min);
+	}
+
+	enum {
+	  SOURCE_RAY = 0,
+	  TERMINATION_RAY,
+	  PASSING_RAY,
+	  CONTAINED_RAY
+	};
+	
+	int GetRayClass() const {
+		
+	  bool startsBefore = GetMinT() > 0.0f;
+	  bool terminatesAfter = GetMaxT() < 1.0f;
+		
+	  if (startsBefore && terminatesAfter)
+		return PASSING_RAY;
+
+	  if (!startsBefore && !terminatesAfter)
+		return CONTAINED_RAY;
+		
+	  if (!startsBefore)
+		return SOURCE_RAY;
+		
+	  return TERMINATION_RAY;
+	}
+	
+	friend bool operator<(const RayInfo &a, const RayInfo &b) {
+	  return a.mRay < b.mRay;
+	}
+  
+	
+	float ExtrapOrigin(const int axis) const {
+	  return mRay->GetOrigin(axis) + GetMinT()*mRay->GetDir(axis);
+	}
+	
+	float ExtrapTermination(const int axis) const {
+	  return mRay->GetOrigin(axis) + GetMaxT()*mRay->GetDir(axis);
+	}
+
+	Vector3 Extrap(const float t) const {
+	  return mRay->Extrap(t);
+	}
+	
+#if USE_FIXEDPOINT_T
+	float GetMinT () const { return mMinT/(float)(FIXEDPOINT_ONE); }
+	float GetMaxT () const { return mMaxT/(float)(FIXEDPOINT_ONE); }
+	
+	void SetMinT (const float t) {
+	  mMinT = (short) (t*(float)(FIXEDPOINT_ONE));
+	}
+	
+	void SetMaxT (const float t) {
+	  mMaxT = (short) (t*(float)(FIXEDPOINT_ONE));
+	  mMaxT++;
+	  //      if (mMaxT!=0xFFFF)
+	  //	mMaxT++;
+	}
+#else
+	float GetMinT () const { return mMinT; }
+	float GetMaxT () const { return mMaxT; }
+	
+	void SetMinT (const float t) { mMinT = t; }
+	void SetMaxT (const float t) { mMaxT = t; }
+#endif 
+
+
+	int ComputeRayIntersection(const int axis,
+							   const float position,
+							   float &t
+							   ) const {
+		
+#if 1
+	  // intersect the ray with the plane
+	  float denom = mRay->GetDir(axis);
+    
+	  if (fabs(denom) < 1e-20)
+		//if (denom == 0.0f)
+		return (mRay->GetOrigin(axis) > position) ? 1 : -1;
+    
+	  t = (position - mRay->GetOrigin(axis))/denom;
+
+	  if (t < GetMinT())
+		return (denom > 0) ? 1 : -1;
+
+	  if (t > GetMaxT())
+		return (denom > 0) ? -1 : 1;
+
+	  return 0;
+#else
+	  // subbdivision based only on the origin
+	  t = 0;
+	  float rpos = mRay->GetOrigin(axis);
+	  return (rpos < position) ? -1 : 1;
+
+#endif
+	}
+
+
+  };
+
+
+  typedef vector<RayInfo> RayInfoContainer;
+	
+  enum { EInterior, ELeaf };
+
+  /////////////////////////////////
+  // The actual data goes here
+  
+  // link to the parent
+  VssTreeInterior *parent;
+
+  enum {SPLIT_X=0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
+  
+  // splitting axis
+  char axis;
+	
+  // depth
+  unsigned char depth;
+  
+  //  short depth;
+  //
+  /////////////////////////////////
+  
+  inline VssTreeNode(VssTreeInterior *p);
+
+  
+  virtual ~VssTreeNode() {};
+  virtual int Type() const  = 0;
+  
+
+  bool IsLeaf() const { return axis == -1; }
+  
+  virtual void Print(ostream &s) const = 0;
+
+  virtual int GetAccessTime() {
+    return 0x7FFFFFF;
+  }
+
+  
+	
+};
+
+// --------------------------------------------------------------
+// KD-tree node - interior node
+// --------------------------------------------------------------
+class VssTreeInterior :
+  public VssTreeNode
+{
+public:
+  // plane in local modelling coordinates
+  float position;
+
+  // pointers to children
+  VssTreeNode *back, *front;
+
+  // the bbox of the node
+  AxisAlignedBox3 bbox;
+
+  // the bbox of the node
+  AxisAlignedBox3 dirBBox;
+  
+  // data for caching
+  long accesses;
+  long lastAccessTime;
+  
+  VssTreeInterior(VssTreeInterior *p):VssTreeNode(p),
+									  back(NULL),
+									  front(NULL),
+									  accesses(0),
+									  lastAccessTime(-1)
+  { }
+
+  virtual int GetAccessTime() {
+    return lastAccessTime;
+  }
+
+  void SetupChildLinks(VssTreeNode *b, VssTreeNode *f) {
+    back = b;
+    front = f;
+    b->parent = f->parent = this;
+  }
+
+  void ReplaceChildLink(VssTreeNode *oldChild, VssTreeNode *newChild) {
+    if (back == oldChild)
+      back = newChild;
+    else
+      front = newChild;
+  }
+
+  virtual int Type() const  { return EInterior; }
+  
+  virtual ~VssTreeInterior() {
+    if (back)
+      delete back;
+    if (front)
+      delete front;
+  }
+  
+  virtual void Print(ostream &s) const {
+    if (axis == 0)
+      s<<"x ";
+    else
+      if (axis == 1)
+		s<<"y ";
+      else
+		s<<"z ";
+    s<<position<<" ";
+    back->Print(s);
+    front->Print(s);
+  }
+
+  
+	
+  int ComputeRayIntersection(const RayInfo &rayData,
+							 float &t
+							 ) {
+	return rayData.ComputeRayIntersection(axis, position, t);
+  }
+
+};
+
+
+// --------------------------------------------------------------
+// KD-tree node - leaf node
+// --------------------------------------------------------------
+class VssTreeLeaf :
+  public VssTreeNode
+{
+private:
+  int mPvsSize;
+public:
+  static int mailID;
+  int mailbox;
+  
+  RayInfoContainer rays;
+  int mPassingRays;
+	
+  bool mValidPvs;
+  float mEntropyImportance;
+  
+	
+  VssTreeLeaf(VssTreeInterior *p,
+			  const int nRays
+			  ):VssTreeNode(p), rays(), mPvsSize(0), mPassingRays(0), mValidPvs(false) {
+    rays.reserve(nRays);
+  }
+  
+  virtual ~VssTreeLeaf() { }
+
+  virtual int Type() const  { return ELeaf; }
+
+  virtual void Print(ostream &s) const {
+    s<<endl<<"L: r="<<(int)rays.size()<<endl;
+  };
+  
+  void AddRay(const RayInfo &data) {
+	mValidPvs = false;
+    rays.push_back(data);
+    data.mRay->Ref();
+	if (data.GetRayClass() == RayInfo::PASSING_RAY)
+	  mPassingRays++;
+  }
+	
+  int GetPvsSize() const {
+	return mPvsSize;
+  }
+
+  void SetPvsSize(const int s) {
+	mPvsSize = s;
+	mValidPvs = true;
+  }
+
+  void
+  UpdatePvsSize();
+
+  float
+  ComputePvsEntropy();
+  
+  float
+  ComputeRayLengthEntropy();
+  
+  float
+  ComputeRayTerminationEntropy();
+  
+  void
+  ComputeEntropyImportance();
+
+  void Mail() { mailbox = mailID; }
+  static void NewMail() { mailID++; }
+  bool Mailed() const { return mailbox == mailID; }
+  
+  bool Mailed(const int mail) {
+    return mailbox >= mailID + mail;
+  }
+
+  float GetAvgRayContribution() const {
+	return GetPvsSize()/((float)rays.size() + Limits::Small);
+  }
+
+  float GetImportance() const;
+  
+  float GetSqrRayContribution() const {
+	return sqr(GetPvsSize()/((float)rays.size() + Limits::Small));
+  }
+  
+  // comparator for the 
+  struct less_contribution : public
+  binary_function<const VssTreeLeaf *, const VssTreeLeaf *, bool> {
+	
+	bool operator()(const VssTreeLeaf * a, const VssTreeLeaf *b) {
+	  return a->GetAvgRayContribution() < b->GetAvgRayContribution();
+	}
+  };
+  
+  struct greater_contribution : public
+  binary_function<const VssTreeLeaf *, const VssTreeLeaf *, bool> {
+	
+	bool operator()(const VssTreeLeaf * a, const VssTreeLeaf *b) {
+	  return a->GetAvgRayContribution() > b->GetAvgRayContribution();
+	}
+  };
+  
+  friend bool GreaterContribution(const VssTreeLeaf * a, const VssTreeLeaf *b) {
+	return a->GetAvgRayContribution() > b->GetAvgRayContribution();
+  }
+  
+};
+
+// Inline functions
+inline
+VssTreeNode::VssTreeNode(VssTreeInterior *p):
+  parent(p), axis(-1), depth(p ? p->depth + 1 : 0) {}
+
+
+
+// ---------------------------------------------------------------
+// Main LSDS search class
+// ---------------------------------------------------------------
+class VssTree
+{
+  struct TraversalData
+  {  
+    VssTreeNode *node;
+    AxisAlignedBox3 bbox;
+    int depth;
+    float priority;
+    
+    TraversalData() {}
+
+    TraversalData(VssTreeNode *n, const float p):
+      node(n), priority(p)
+    {}
+
+    TraversalData(VssTreeNode *n,
+				  const AxisAlignedBox3 &b,
+				  const int d):
+      node(n), bbox(b), depth(d) {}
+    
+		
+    // comparator for the 
+    struct less_priority : public
+    binary_function<const TraversalData, const TraversalData, bool> {
+			
+      bool operator()(const TraversalData a, const TraversalData b) {
+		return a.priority < b.priority;
+      }
+      
+    };
+
+    //    ~TraversalData() {}
+    //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
+    
+    friend bool operator<(const TraversalData &a,
+						  const TraversalData &b) {
+      //      return a.node->queries.size() < b.node->queries.size();
+      VssTreeLeaf *leafa = (VssTreeLeaf *) a.node;
+      VssTreeLeaf *leafb = (VssTreeLeaf *) b.node;
+#if 0
+	  return
+		leafa->rays.size()*a.bbox.GetVolume()
+		<
+		leafb->rays.size()*b.bbox.GetVolume();
+#endif
+#if 0
+	  return
+		leafa->GetPvsSize()*a.bbox.GetVolume()
+		<
+		leafb->GetPvsSize()*b.bbox.GetVolume();
+#endif
+#if 0
+	  return
+		leafa->GetPvsSize()
+		<
+		leafb->GetPvsSize();
+#endif
+#if 0
+	  return
+		leafa->GetPvsSize()/(leafa->rays.size()+1)
+		>
+		leafb->GetPvsSize()/(leafb->rays.size()+1);
+#endif
+#if 1
+	  return
+		leafa->GetPvsSize()*leafa->rays.size()
+		<
+		leafb->GetPvsSize()*leafb->rays.size();
+#endif
+    }
+  };
+  
+  // simplified data for ray traversal only...
+
+  struct RayTraversalData {
+    
+    VssTreeNode::RayInfo rayData;
+    VssTreeNode *node;
+    
+    RayTraversalData() {}
+    RayTraversalData(VssTreeNode *n,
+					 const VssTreeNode::RayInfo &data):
+      rayData(data), node(n) {}
+  };
+	
+public:
+  /////////////////////////////
+  // The core pointer
+  VssTreeNode *root;
+  
+  /////////////////////////////
+  // Basic properties
+
+  // total number of nodes of the tree
+  int nodes;
+  // axis aligned bounding box of the scene
+  AxisAlignedBox3 bbox;
+
+  // axis aligned bounding box of directions
+  AxisAlignedBox3 dirBBox;
+  
+  /////////////////////////////
+  // Construction parameters
+
+  // epsilon used for the construction
+  float epsilon;
+
+  // ratio between traversal and intersection costs
+  float ct_div_ci;
+  // max depth of the tree
+  int termMaxDepth;
+  // minimal ratio of the volume of the cell and the query volume
+  float termMinSize;
+
+  // minimal pvs per node to still get subdivided
+  int termMinPvs;
+
+  // minimal ray number per node to still get subdivided
+  int termMinRays;
+	
+  // maximal cost ration to subdivide a node
+  float termMaxCostRatio;
+	
+  // maximal contribution per ray to subdivide the node
+  float termMaxRayContribution;
+
+	
+  // randomized construction
+  bool randomize;
+  
+  // type of the splitting to use fo rthe tree construction
+  enum {ESplitRegular, ESplitHeuristic, ESplitHybrid };
+  int splitType;
+
+  bool mSplitUseOnlyDrivingAxis;
+  
+  // use ray space subdivision instead of view space subdivision
+  bool mUseRss;
+
+  // interleave directional and spatial splits based on their costs
+  // if false directional splits are only performed after spatial splits
+  bool mInterleaveDirSplits;
+
+  // depth at which directional splits are performed if mInterleaveDirSplits is false
+  int mDirSplitDepth;
+  
+  // maximal size of the box on which the refdir splitting can be performed
+  // (relative to the scene bbox
+  float refDirBoxMaxSize;
+  
+  // maximum alovable memory in MB
+  float maxTotalMemory;
+
+  // maximum alovable memory for static kd tree in MB
+  float maxStaticMemory;
+
+  // this is used during the construction depending
+  // on the type of the tree and queries...
+  float maxMemory;
+
+
+  // minimal acess time for collapse
+  int accessTimeThreshold;
+
+  // minimal depth at which to perform collapse
+  int minCollapseDepth;
+
+  
+  // reusable array of split candidates
+  vector<SortableEntry> *splitCandidates;
+  /////////////////////////////
+
+  VssStatistics stat;
+	
+  
+  VssTree();
+  virtual ~VssTree();
+
+  virtual void
+  Construct(
+			VssRayContainer &rays,
+			AxisAlignedBox3 *forcedBoundingBox = NULL
+			);
+	
+  // incemental construction
+  virtual void UpdateRays(VssRayContainer &remove,
+						  VssRayContainer &add
+						  );
+
+  virtual void AddRays(
+					   VssRayContainer &add
+					   )
+  {
+	VssRayContainer remove;
+	UpdateRays(remove, add);
+  }
+
+  
+	
+  VssTreeNode *
+  Locate(const Vector3 &v);
+	
+  VssTreeNode *
+  SubdivideNode(VssTreeLeaf *leaf,
+				const AxisAlignedBox3 &box,
+				AxisAlignedBox3 &backBox,
+				AxisAlignedBox3 &frontBox
+				);
+	
+  VssTreeNode *
+  Subdivide(const TraversalData &tdata);
+	
+  int
+  SelectPlane(VssTreeLeaf *leaf,
+			  const AxisAlignedBox3 &box,
+			  float &position,
+			  int &raysBack,
+			  int &raysFront,
+			  int &pvsBack,
+			  int &pvsFront
+			  );
+
+  void
+  SortSplitCandidates(
+					  VssTreeLeaf *node,
+					  const int axis
+					  );
+	
+  
+  // return memory usage in MB
+  float GetMemUsage() const {
+    return 
+      (sizeof(VssTree) +
+       stat.Leaves()*sizeof(VssTreeLeaf) +
+       stat.Interior()*sizeof(VssTreeInterior) +
+       stat.rayRefs*sizeof(VssTreeNode::RayInfo))/(1024.0f*1024.0f);
+  }
+	
+  float GetRayMemUsage() const {
+    return 
+      stat.rays*(sizeof(VssRay))/(1024.0f*1024.0f);
+  }
+  
+
+  float
+  BestCostRatio(
+				VssTreeLeaf *node,
+				int &axis,
+				float &position,
+				int &raysBack,
+				int &raysFront,
+				int &pvsBack,
+				int &pvsFront
+				);
+	
+  float
+  EvalCostRatio(
+				VssTreeLeaf *node,
+				const int axis,
+				const float position,
+				int &raysBack,
+				int &raysFront,
+				int &pvsBack,
+				int &pvsFront
+				);
+
+  float
+  EvalCostRatioHeuristic(
+						 VssTreeLeaf *node,
+						 const int axis,
+						 float &position,
+						 int &raysBack,
+						 int &raysFront,
+						 int &pvsBack,
+						 int &pvsFront
+						 );
+
+  float
+  GetCostRatio(
+			   VssTreeLeaf *leaf,
+			   const int axis,
+			   const float position,
+			   const int raysBack,
+			   const int raysFront,
+			   const int pvsBack,
+			   const int pvsFront
+			   );
+
+  AxisAlignedBox3 GetBBox(const VssTreeNode *node) const {
+    if (node->parent == NULL)
+      return bbox;
+
+    if (!node->IsLeaf())
+      return ((VssTreeInterior *)node)->bbox;
+
+    if (node->parent->axis >= 3)
+      return node->parent->bbox;
+      
+    AxisAlignedBox3 box(node->parent->bbox);
+    if (node->parent->front == node)
+      box.SetMin(node->parent->axis, node->parent->position);
+    else
+      box.SetMax(node->parent->axis, node->parent->position);
+    return box;
+  }
+
+  AxisAlignedBox3 GetDirBBox(const VssTreeNode *node) const {
+
+    if (node->parent == NULL)
+      return dirBBox;
+    
+    if (!node->IsLeaf() )
+      return ((VssTreeInterior *)node)->dirBBox;
+
+    if (node->parent->axis < 3)
+      return node->parent->dirBBox;
+    
+    AxisAlignedBox3 dBBox(node->parent->dirBBox);
+
+    if (node->parent->front == node)
+      dBBox.SetMin(node->parent->axis - 3, node->parent->position);
+    else
+      dBBox.SetMax(node->parent->axis - 3, node->parent->position);
+    return dBBox;
+  }
+  
+  int
+  ReleaseMemory(const int time);
+
+  int
+  CollapseSubtree(VssTreeNode *node, const int time);
+
+  void
+  CountAccess(VssTreeInterior *node, const long time) {
+    node->accesses++;
+    node->lastAccessTime = time;
+  }
+
+  VssTreeNode *
+  SubdivideLeaf(
+				VssTreeLeaf *leaf
+				);
+
+  void
+  RemoveRay(VssRay *ray,
+			vector<VssTreeLeaf *> *affectedLeaves,
+			const bool removeAllScheduledRays
+			);
+
+  //  void
+  //  AddRay(VssRay *ray);
+  void
+  AddRay(VssTreeNode::RayInfo &info);
+  
+  void
+  TraverseInternalNode(
+					   RayTraversalData &data,
+					   stack<RayTraversalData> &tstack);
+
+  void
+  EvaluateLeafStats(const TraversalData &data);
+
+
+  int
+  GetRootPvsSize() const {
+	return GetPvsSize(bbox);
+  }
+  
+  int
+  GetPvsSize(const AxisAlignedBox3 &box) const;
+
+  void
+  GetRayContributionStatistics(
+							   float &minRayContribution,
+							   float &maxRayContribution,
+							   float &avgRayContribution
+							   );
+
+  int
+  GenerateRays(const float ratioPerLeaf,
+			   SimpleRayContainer &rays);
+
+  int
+  GenerateRays(const int numberOfRays,
+			   const int numberOfLeaves,
+			   SimpleRayContainer &rays);
+		
+  float
+  GetAvgPvsSize();
+
+  int
+  UpdateSubdivision();
+
+  bool
+  TerminationCriteriaSatisfied(VssTreeLeaf *leaf);
+
+  void
+  CollectLeaves(vector<VssTreeLeaf *> &leaves);
+
+  bool
+  ClipRay(
+		  VssTreeNode::RayInfo &rayInfo,
+		  const AxisAlignedBox3 &box
+		  );
+
+  VssTreeNode *GetRoot() const { return root; }
+
+  bool
+  ValidLeaf(VssTreeLeaf *leaf) const;
+
+  void
+  GenerateLeafRays(VssTreeLeaf *leaf,
+				   const int numberOfRays,
+				   SimpleRayContainer &rays);
+
+  int
+  CollectRays(VssRayContainer &rays,
+			  const int number);
+
+  int
+  CollectRays(VssRayContainer &rays
+			  );
+  
+};
+
+
+#endif // __LSDS_KDTREE_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/gzstream.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/gzstream.h	(revision 372)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/gzstream.h	(revision 372)
@@ -0,0 +1,146 @@
+// ============================================================================
+// gzstream, C++ iostream classes wrapping the zlib compression library.
+// Copyright (C) 2001  Deepak Bandyopadhyay, Lutz Kettner
+//
+// 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, or (at your option) any later version.
+//
+// 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
+// ============================================================================
+//
+// File          : gzstream.h
+// Revision      : $Revision: 1.1 $
+// Revision_date : $Date: 2004/02/16 14:46:00 $
+// Author(s)     : Deepak Bandyopadhyay, Lutz Kettner
+// 
+// Standard streambuf implementation following Nicolai Josuttis, "The 
+// Standard C++ Library".
+// ============================================================================
+
+#ifndef GZSTREAM_H
+#define GZSTREAM_H 1
+
+#include <zlib.h>
+
+// standard C++ with new header file names and std:: namespace
+#include <iostream>
+#include <fstream>
+using namespace std;
+
+#ifdef GZSTREAM_NAMESPACE
+namespace GZSTREAM_NAMESPACE {
+#endif
+
+// ----------------------------------------------------------------------------
+// Internal classes to implement gzstream. See below for user classes.
+// ----------------------------------------------------------------------------
+
+   // size of data buff
+#define gzbufferSize  303   
+
+
+
+//  #define STREAMBUF std::streambuf 
+//  #define ISTREAM std::istream
+//  #define OSTREAM std::ostream
+
+#define STREAMBUF streambuf 
+#define ISTREAM istream
+#define OSTREAM ostream
+
+class gzstreambuf : public STREAMBUF {
+
+private:
+    // totals 512 bytes under g++ for igzstream at the end.
+
+    gzFile           file;               // file handle for compressed file
+    char             buffer[gzbufferSize]; // data buffer
+    char             opened;             // open/close state of stream
+    int              mode;               // I/O mode
+
+    int flush_buffer();
+public:
+    gzstreambuf() : opened(0) {
+        setp( buffer, buffer + (gzbufferSize-1));
+        setg( buffer + 4,     // beginning of putback area
+              buffer + 4,     // read position
+              buffer + 4);    // end position      
+        // ASSERT: both input & output capabilities will not be used together
+    }
+    int is_open() { return opened; }
+    gzstreambuf* open( const char* name, int open_mode);
+    gzstreambuf* close();
+    ~gzstreambuf() { close(); }
+  
+    virtual int     overflow( int c = EOF);
+    virtual int     underflow();
+    virtual int     sync();
+
+};
+
+class gzstreambase : virtual public ios {
+
+protected:
+    gzstreambuf buf;
+public:
+  gzstreambase() { init(&buf); }
+  gzstreambase( const char* name, int open_mode);
+  ~gzstreambase();
+  void open( const char* name, int open_mode);
+  void close();
+  gzstreambuf* rdbuf() { return &buf; }
+};
+
+// ----------------------------------------------------------------------------
+// User classes. Use igzstream and ogzstream analogously to ifstream and
+// ofstream respectively. They read and write files based on the gz* 
+// function interface of the zlib. Files are compatible with gzip compression.
+// ----------------------------------------------------------------------------
+
+  
+
+  class igzstream : public gzstreambase, public ISTREAM {
+  
+  public:
+    igzstream() : gzstreambase(), ISTREAM( &buf )  {} 
+    
+    igzstream( const char* name, int open_mode = std::ios::in)
+      : gzstreambase( name, open_mode), ISTREAM( &buf) {}
+    
+    gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
+    
+    void open( const char* name, int open_mode = std::ios::in) {
+      gzstreambase::open( name, open_mode);
+    }
+  };
+  
+class ogzstream : public gzstreambase, public OSTREAM {
+  
+public:
+  ogzstream() : OSTREAM( &buf) {}
+  ogzstream( const char* name, int mode = std::ios::out)
+    : gzstreambase( name, mode), OSTREAM( &buf) {}  
+  gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
+  void open( const char* name, int open_mode = std::ios::out) {
+    gzstreambase::open( name, open_mode);
+  }
+  
+};
+
+#ifdef GZSTREAM_NAMESPACE
+} // namespace GZSTREAM_NAMESPACE
+#endif
+
+#endif // GZSTREAM_H
+// ============================================================================
+// EOF //
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Parser.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Parser.h	(revision 508)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Parser.h	(revision 508)
@@ -0,0 +1,21 @@
+#ifndef __PARSER_H
+#define __PARSER_H
+
+#include <string>
+using namespace std;
+
+class SceneGraphNode;
+
+
+
+class Parser
+{
+public:
+  Parser() {}
+
+  virtual bool ParseFile(const string filename, SceneGraphNode **root) {return false;};
+	
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.h	(revision 492)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.h	(revision 492)
@@ -0,0 +1,244 @@
+#ifndef _Mesh_H__
+#define _Mesh_H__
+
+#include <vector>
+using namespace std;
+#include "Intersectable.h"
+#include "Plane3.h"
+#include "Matrix4x4.h"
+#include "AxisAlignedBox3.h"
+#include "Material.h"
+
+struct Triangle3;
+class MeshInstance;
+class MeshKdTree;
+
+/// default vertex container for Mesh
+typedef std::vector<Vector3> VertexContainer;
+
+/// vertex index container
+typedef std::vector<int> VertexIndexContainer;
+
+
+/** Patch used as an element of the mesh */
+class Face {
+public:
+  Face(): mVertexIndices() {}
+  Face(const int a, const int b, const int c):mVertexIndices(3) {
+    mVertexIndices[0] = a;
+    mVertexIndices[1] = b;
+    mVertexIndices[2] = c;
+  }
+
+  Face(const int a, const int b, const int c, const int d): 
+  mVertexIndices(4) {
+    mVertexIndices[0] = a;
+    mVertexIndices[1] = b;
+    mVertexIndices[2] = c;
+    mVertexIndices[3] = d;
+  }
+
+  Face(const VertexIndexContainer &vertices):mVertexIndices(vertices) {}
+  
+  /// list of vertex pointers
+  VertexIndexContainer mVertexIndices;  
+};
+
+/// default patch container for Mesh
+typedef std::vector<Face *> FaceContainer;
+
+/** Mesh containing polygonal patches */
+class Mesh {
+
+public:
+
+  /// Default constructor
+  Mesh():mVertices(), mFaces(), mMaterial(NULL), mKdTree(NULL) {}
+  
+  /// Constructor with container preallocation
+  Mesh(const int vertices,
+       const int faces):
+    mFaces(),
+    mMaterial(NULL),
+    mKdTree(NULL),
+    mVertices(),
+    mIsConvex(false),
+    mIsWatertight(false)
+  {
+    mVertices.reserve(vertices);
+    mFaces.reserve(faces);
+  }
+  
+  ~Mesh() {
+    for (int i=0; i < mFaces.size(); i++)
+      delete mFaces[i];
+  }
+
+  void AddTriangle(const Triangle3 &triangle);
+  void AddRectangle(const Rectangle3 &triangle);
+
+	void Cleanup();
+	bool
+	ValidateFace(const int face);
+
+  void AddFace(Face *face) 
+  {
+    mFaces.push_back(face);
+  }
+  
+  void Preprocess();
+
+  /** Axis aligned bounding box of the mesh in local mesh coordinates */
+  AxisAlignedBox3 mBox;
+  
+  /** Vertices forming the mesh */
+  VertexContainer mVertices;
+  
+  /** Patches forming the mesh */
+  FaceContainer mFaces;
+  
+  /** Global mesh material */
+  Material *mMaterial;
+  
+  /** true if the mesh is a convex mesh */
+  bool mIsConvex;
+
+  /** true if the mesh is a convex mesh */
+  bool mIsWatertight;
+
+  MeshKdTree *mKdTree;
+  
+  int
+  CastRay(
+					Ray &ray,
+					MeshInstance *instance
+					);
+	
+  int
+  CastRayToSelectedFaces(
+												 Ray &ray,
+												 const vector<int> &faces,
+												 Intersectable *instance
+												 );
+	
+  int
+  CastRayToFace(
+								const int faceIndex,
+								Ray &ray,
+								float &nearestT,
+								int &nearestFace,
+								Intersectable *instance
+								);
+	
+  
+  int
+  RayFaceIntersection(const int faceIndex,
+											const Ray &ray,
+											float &t,
+											const float nearestT
+											);
+  
+  Plane3 GetFacePlane(const int faceIndex);
+
+  AxisAlignedBox3 GetFaceBox(const int faceIndex);
+
+  int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal);
+
+  int
+  GetRandomVisibleSurfacePoint(Vector3 &point,
+							   Vector3 &normal,
+							   const Vector3 &viewpoint,
+							   const int maxTries
+							   );
+  
+  virtual ostream &Describe(ostream &s) {
+	return s<<"Mesh #vertices="<<(int)mVertices.size()<<" #faces="<<(int)mFaces.size();
+  }
+  
+
+};
+
+
+class MeshInstance : public Intersectable {
+protected:
+  Mesh *mMesh;
+  
+public:
+  MeshInstance(Mesh *mesh):Intersectable(), mMesh(mesh)
+  {
+  }
+
+  int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal);
+
+	int
+	GetRandomVisibleSurfacePoint(Vector3 &point,
+															 Vector3 &normal,
+															 const Vector3 &viewpoint,
+															 const int maxTries
+															 );
+
+
+  Mesh *GetMesh() { return mMesh; }
+
+  virtual AxisAlignedBox3 GetBox() {
+    return mMesh->mBox;
+  }
+
+  virtual int
+  CastRay(
+	  Ray &ray
+	  );
+
+  virtual bool IsConvex() { return mMesh->mIsConvex; }
+  virtual bool IsWatertight() { return mMesh->mIsWatertight; }
+  virtual float IntersectionComplexity() {  return (float)mMesh->mFaces.size(); }
+
+	virtual int NumberOfFaces() const {  return (int)mMesh->mFaces.size(); }
+
+  virtual int Type() const { return MESH_INSTANCE; }
+
+  virtual int
+  CastRay(
+	  Ray &ray,
+	  const vector<int> &faces
+	  );
+
+
+	virtual ostream &Describe(ostream &s) {
+		s<<"MeshInstance Id="<<GetId();
+		return mMesh->Describe(s);
+	}
+	
+};
+
+
+class TransformedMeshInstance : public MeshInstance
+{
+public:
+  TransformedMeshInstance(Mesh *mesh):MeshInstance(mesh)
+  {
+    mWorldTransform = IdentityMatrix();
+  }
+  
+  virtual AxisAlignedBox3 GetBox() {
+    return Transform(mMesh->mBox,
+		     mWorldTransform);
+  }
+  
+  virtual int
+  CastRay(
+	  Ray &ray
+	  );
+
+  virtual int Type() const { return TRANSFORMED_MESH_INSTANCE; }
+
+  int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal);
+
+private:
+  Matrix4x4 mWorldTransform;
+  
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Tetrahedron3.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Tetrahedron3.cpp	(revision 544)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Tetrahedron3.cpp	(revision 544)
@@ -0,0 +1,27 @@
+#include "Tetrahedron3.h"
+
+
+float Tetrahedron3::GetArea() const
+{
+	float area = 0;
+	for (int i = 0; i < 4; ++ i)
+		area += GetTriangle(i).GetArea();
+
+	return area;
+}
+
+
+float Tetrahedron3::GetVolume() const
+{
+	const Vector3 a = mVertices[2] - mVertices[1];
+	const Vector3 b = mVertices[3] - mVertices[1];
+	const Vector3 c = mVertices[4] - mVertices[1];
+
+	return (1.0f / 6.0f) * fabs(DotProd(a, CrossProd(b, c)));
+}
+
+
+bool Tetrahedron3::Valid() const
+{
+	return true;
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 612)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 612)
@@ -0,0 +1,2025 @@
+// ================================================================
+// $Id: environ.cpp,v 1.1 2004/02/16 14:45:59 bittner Exp $
+//
+// environ.cpp
+//     Implementation of the environment operations, ie. reading
+//     environment file, reading command line parameters etc.
+//
+
+//#define _DEBUG_PARAMS
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fstream>
+
+#include "gzstream.h"
+#include "common.h"
+#include "Environment.h"
+#include "Vector3.h"
+
+  
+Environment *environment = NULL;
+
+Environment::~Environment()
+{
+  int i, j;
+
+  // delete the params structure
+  for (i = 0; i < numParams; i++) {
+    for (j = 0; j < paramRows; j++)
+      if (params[i][j] != NULL)
+	delete[] params[i][j];
+    if (params[i] != NULL)
+      delete[] params[i];
+  }
+
+  if (params != NULL)
+    delete[] params;
+  
+  // delete the options structure
+  if (options != NULL)
+    delete[] options;
+  
+  if (optionalParams != NULL)
+    delete optionalParams;
+}
+
+bool
+Environment::CheckForSwitch(const int argc,
+							char **argv,
+							const char swtch) const
+{
+  for (int i = 1; i < argc; i++)
+    if ((argv[i][0] == '-') && (argv[i][1] == swtch))
+      return true;
+  return false;
+}
+
+bool
+Environment::CheckType(const char *value,
+			const EOptType type) const
+{
+  char *s, *t, *u;
+
+  switch (type) {
+    case optInt: {
+      strtol(value, &t, 10);
+      if (value + strlen(value) != t)
+        return false;
+      else
+        return true;
+    }
+    case optFloat: {
+      strtod(value, &t);
+      if (value + strlen(value) != t)
+        return false;
+      else
+        return true;
+    }
+    case optBool: {
+      if (!strcasecmp(value, "true") ||
+          !strcasecmp(value, "false") ||
+          !strcasecmp(value, "YES") ||
+          !strcasecmp(value, "NO") ||
+          !strcmp(value, "+") ||
+          !strcmp(value, "-") ||
+          !strcasecmp(value, "ON") ||
+          !strcasecmp(value, "OFF"))
+        return true;
+      return false;
+    }
+    case optVector:{
+      strtod(value, &s);
+      if (*s == ' ' || *s == '\t') {
+        while (*s == ' ' || *s == '\t')
+          s++;
+        if (*s != ',')
+          s--;
+      }
+      if ((*s != ',' && *s != ' ' && *s != '\t') || value == s)
+        return false;
+      t = s;
+      strtod(s + 1, &u);
+      if (*u == ' ' || *u == '\t') {
+        while (*u == ' ' || *u == '\t')
+          u++;
+        if (*u != ',')
+          u--;
+      }
+      if ((*u != ',' && *s != ' ' && *s != '\t') || t == u)
+        return false;
+      t = u;
+      strtod(u + 1, &s);
+      if (t == s || value + strlen(value) != s)
+        return false;
+      return true;
+    }
+    case optString: {
+      return true;
+    }
+    default: {
+      Debug << "Internal error: Unknown type of option.\n" << flush;
+      exit(1);
+    }
+  }
+  return false;
+}
+
+void
+Environment::ReadCmdlineParams(const int argc,
+							   char **argv,
+							   const char *optParams)
+{
+  int i;
+
+  // Make sure we are called for the first time
+  if (optionalParams != NULL)
+    return;
+
+  numParams = (int)strlen(optParams) + 1;
+  optionalParams = new char[numParams];
+  strcpy(optionalParams, optParams);
+
+  // First, count all non-optional parameters on the command line
+  for (i = 1; i < argc; i++)
+    if (argv[i][0] != '-')
+      paramRows++;
+
+  // if there is no non-optional parameter add a default one...
+  if (paramRows == 0)
+    paramRows = 1;
+  
+  // allocate and initialize the table for parameters
+  params = new char **[numParams];
+  for (i = 0; i < numParams; i++) {
+    params[i] = new char *[paramRows];
+    for (int j = 0; j < paramRows; j++)
+      params[i][j] = NULL;
+  }
+  // Now read all non-optional and optional parameters into the table
+  curRow = -1;
+  for (i = 1; i < argc; i++) {
+    if (argv[i][0] != '-') {
+      // non-optional parameter encountered
+      curRow++;
+      params[0][curRow] = new char[strlen(argv[i]) + 1];
+      strcpy(params[0][curRow], argv[i]);
+    }
+    else {
+      // option encountered
+      char *t = strchr(optionalParams, argv[i][1]);
+      if (t != NULL) {
+        // this option is optional parameter
+        int index = t - optionalParams + 1;
+        if (curRow < 0) {
+          // it's a global parameter
+          for (int j = 0; j < paramRows; j++) {
+            params[index][j] = new char[strlen(argv[i] + 2) + 1];
+            strcpy(params[index][j], argv[i] + 2);
+          }
+        }
+        else {
+          // it's a scene parameter
+          if (params[index][curRow] != NULL) {
+            delete[] params[index][curRow];
+          }
+          params[index][curRow] = new char[strlen(argv[i] + 2) + 1];
+          strcpy(params[index][curRow], argv[i] + 2);
+        }
+      }
+    }
+  }
+  curRow = 0;
+
+#ifdef _DEBUG_PARAMS
+  // write out the parameter table
+  cerr << "Parameter table for " << numParams << " columns and "
+       << paramRows << " rows:\n";
+  for (int j = 0; j < paramRows; j++) {
+    for (i = 0; i < numParams; i++) {
+      if (params[i][j] != NULL)
+        cerr << params[i][j];
+      else
+        cerr << "NULL";
+      cerr << "\t";
+    }
+    cerr << "\n";
+  }
+  cerr << "Params done.\n" << flush;
+#endif // _DEBUG_PARAMS
+}
+
+bool
+Environment::GetParam(const char name,
+		       const int index,
+		       char *value) const
+{
+  int column;
+
+  if (index >= paramRows || index < 0)
+    return false;
+  if (name == ' ')
+    column = 0;
+  else {
+    char *t = strchr(optionalParams, name);
+
+    if (t == NULL)
+      return false;
+    column = t - optionalParams + 1;
+  }
+
+  if (params[column][index] == NULL)
+    return false;
+  //  value = new char[strlen(params[column][index]) + 1];
+  strcpy(value, params[column][index]);
+  return true;
+}
+
+void
+Environment::RegisterOption(const char *name,
+			     const EOptType type,
+			     const char *abbrev,
+			     const char *defValue)
+{
+  int i;
+
+  // make sure this option was not yet registered
+  for (i = 0; i < numOptions; i++)
+    if (!strcmp(name, options[i].name)) {
+      Debug << "Error: Option " << name << " registered twice.\n";
+      exit(1);
+    }
+  // make sure we have enough room in memory
+  if (numOptions >= maxOptions) {
+    Debug << "Error: Too many options. Try enlarge the maxOptions "
+	  << "definition.\n";
+    exit(1);
+  }
+
+  // make sure the abbreviation doesn't start with 'D'
+  if (abbrev != NULL && (abbrev[0] == 'D' )) {
+    Debug << "Internal error: reserved switch " << abbrev
+         << " used as an abbreviation.\n";
+    exit(1);
+  }
+  // new option
+  options[numOptions].type = type;
+  options[numOptions].name = strdup(name);
+  // assign abbreviation, if requested
+  if (abbrev != NULL) {
+    options[numOptions].abbrev = strdup(abbrev);
+  }
+  // assign default value, if requested
+  if (defValue != NULL) {
+    options[numOptions].defaultValue = strdup(defValue);
+    if (!CheckType(defValue, type)) {
+      Debug << "Internal error: Inconsistent type and default value in option "
+           << name << ".\n";
+      exit(1);
+    }
+  }
+  // new option registered
+  numOptions++;
+}
+
+bool
+Environment::OptionPresent(const char *name) const
+{
+  bool found = false;
+  int i;
+
+  for (i = 0; i < numOptions; i++)
+    if (!strcmp(options[i].name, name)) {
+      found = true;
+      break;
+    }
+  if (!found) {
+    Debug << "Internal error: Option " << name << " not registered.\n" << flush;
+    exit(1);
+  }
+  if (options[i].value != NULL || options[i].defaultValue != NULL)
+    return true;
+  else
+    return false;
+}
+
+int
+Environment::FindOption(const char *name,
+			const bool isFatal) const
+{
+  int i;
+  bool found = false;
+  // is this option registered ?
+  for (i = 0; i < numOptions; i++)
+    if (!strcmp(options[i].name, name)) {
+      found = true;
+      break;
+    }
+  if (!found) {
+    // no registration found
+    Debug << "Internal error: Required option " << name
+	  << " not registered.\n" << flush;
+    exit(1);
+  }
+  if (options[i].value == NULL && options[i].defaultValue == NULL)
+    // this option was not initialised to some value
+    if (isFatal) {
+      Debug << "Error: Required option " << name << " not found.\n" << flush;
+      exit(1);
+    }
+    else {
+      Debug << "Error: Required option " << name << " not found.\n" << flush;
+      return -1;
+    }
+  return i;
+}
+
+bool
+Environment::GetIntValue(const char *name,
+			 int &value,
+			 const bool isFatal) const
+{
+  int i = FindOption(name, isFatal);
+
+  if (i<0)
+    return false;
+
+  if (options[i].value != NULL) {
+    // option was explicitly specified
+    value = strtol(options[i].value, NULL, 10);
+  } else {
+    // option was not read, so use the default
+    value = strtol(options[i].defaultValue, NULL, 10);
+  }
+
+  return true;
+}
+
+bool
+Environment::GetDoubleValue(const char *name,
+			    double &value,
+			    const bool isFatal) const
+{
+  int i = FindOption(name, isFatal);
+
+  if (i<0)
+    return false;
+
+  if (options[i].value != NULL) {
+    // option was explicitly specified
+    value = strtod(options[i].value, NULL);
+  } else {
+    // option was not read, so use the default
+    value = strtod(options[i].defaultValue, NULL);
+  }
+  return true;
+}
+
+bool
+Environment::GetRealValue(const char *name,
+			  Real &value,
+			  const bool isFatal) const
+{
+  int i = FindOption(name, isFatal);
+  
+  if (i<0)
+    return false;
+
+  if (options[i].value != NULL) {
+    // option was explicitly specified
+    value = (Real)strtod(options[i].value, NULL);
+  } else {
+    // option was not read, so use the default
+    value = (Real)strtod(options[i].defaultValue, NULL);
+  }
+  return true;
+}
+
+bool
+Environment::GetFloatValue(const char *name,
+			   float &value,
+			   const bool isFatal) const
+{
+  int i = FindOption(name, isFatal);
+
+  if (i<0)
+    return false;
+
+  if (options[i].value != NULL) {
+    // option was explicitly specified
+    value = (float)strtod(options[i].value, NULL);
+  } else {
+    // option was not read, so use the default
+    value = (float)strtod(options[i].defaultValue, NULL);
+  }
+  return true;
+}
+
+bool
+Environment::GetBool(const char *name,
+		     const bool isFatal) const
+{
+  bool ret;
+  if (GetBoolValue(name, ret, isFatal))
+    return ret;
+  else
+    return false;
+}
+
+bool
+Environment::ParseBool(const char *name) const
+{
+
+  bool value = true;
+  
+  if (!strcasecmp(name, "false") ||
+      !strcasecmp(name, "NO") ||
+      !strcmp(name, "-") ||
+      !strcasecmp(name, "OFF"))
+    value = false;
+  
+  return value;
+}
+
+void
+Environment::ParseVector(const char *name, Vector3 &v) const
+{
+  // option was not read, so use the default
+  char *s, *t;
+  
+  v.x = (Real)strtod(name, &s);
+  v.y = (Real)strtod(s + 1, &t);
+  v.z = (Real)strtod(t + 1, NULL);
+
+}
+
+bool
+Environment::GetBoolValue(const char *name,
+			   bool &value,
+			   const bool isFatal) const
+{
+  int i = FindOption(name, isFatal);
+
+  if (i<0)
+    return false;
+
+  
+  if (options[i].value != NULL) 
+    value = ParseBool(options[i].value);
+  else
+    value = ParseBool(options[i].defaultValue);
+
+  return true;
+}
+
+bool
+Environment::GetVectorValue(const char *name,
+			    Vector3 &v,
+			    const bool isFatal) const
+{
+  int i = FindOption(name, isFatal);
+  if (i<0)
+    return false;
+
+  if (options[i].value != NULL) 
+
+    
+  if (options[i].value != NULL) {
+    ParseVector(options[i].value, v);
+  }
+  else {
+    ParseVector(options[i].defaultValue, v);
+  }
+  return true;
+}
+
+bool
+Environment::GetStringValue(const char *name,
+			    char *value,
+			    const bool isFatal) const
+{
+  int i = FindOption(name, isFatal);
+
+  if (i<0)
+    return false;
+
+  
+  if (options[i].value != NULL) {
+    // option was not read, so use the default
+    strcpy(value, options[i].value);
+  }
+  else {
+    // option was explicitly specified
+    strcpy(value, options[i].defaultValue);
+  }
+  return true;
+}
+
+void
+Environment::SetInt(const char *name, const int value)
+{
+
+  int i = FindOption(name);
+  if (i<0)
+    return;
+
+  if (options[i].type == optInt) {
+    delete options[i].value;
+    options[i].value = new char[16];
+    sprintf(options[i].value, "%.15d", value);
+  }
+  else {
+    Debug << "Internal error: Trying to set non-integer option " << name
+	  << " to integral value.\n" << flush;
+    exit(1);
+  }
+}
+
+void
+Environment::SetFloat(const char *name, const Real value)
+{
+  int i = FindOption(name);
+  if (i<0)
+    return;
+
+  if (options[i].type == optFloat) {
+    delete options[i].value;
+    options[i].value = new char[25];
+    sprintf(options[i].value, "%.15e", value);
+  }
+  else {
+    Debug << "Internal error: Trying to set non-Real option " << name
+	  << " to Real value.\n" << flush;
+    exit(1);
+  }
+}
+
+void
+Environment::SetBool(const char *name, const bool value)
+{
+  int i = FindOption(name);
+  if (i<0)
+    return;
+
+  if (options[i].type == optBool) {
+    delete options[i].value;
+    options[i].value = new char[6];
+    if (value)
+      sprintf(options[i].value, "true");
+    else
+      sprintf(options[i].value, "false");
+  }
+  else {
+    Debug << "Internal error: Trying to set non-bool option " << name
+	  << " to boolean value.\n" << flush;
+    exit(1);
+  }
+}
+
+void
+Environment::SetVector(const char *name,
+		       const Vector3 &v)
+{
+  int i = FindOption(name);
+  if (i<0)
+    return;
+
+  if (options[i].type == optVector) {
+    delete options[i].value;
+    options[i].value = new char[128];
+    sprintf(options[i].value, "%.15e,%.15e,%.15e", v.x, v.y, v.z);
+  }
+  else {
+    Debug << "Internal error: Trying to set non-vector option " << name
+	  << " to vector value.\n" << flush;
+    exit(1);
+  }
+}
+
+void
+Environment::SetString(const char *name, const char *value)
+{
+  int i = FindOption(name);
+  if (i<0)
+    return;
+
+  if (options[i].type == optString) {
+    delete options[i].value;
+    options[i].value = strdup(value);
+  }
+  else {
+    Debug << "Internal error: Trying to set non-string option " << name
+	  << " to string value.\n" << flush;
+    exit(1);
+  }
+}
+
+void
+Environment::ParseCmdline(const int argc,
+						  char **argv,
+						  const int index)
+{
+  int curIndex = -1;
+
+  for (int i = 1; i < argc; i++) {
+    // if this parameter is non-optional, skip it and increment the counter
+    if (argv[i][0] != '-') {
+      curIndex++;
+      continue;
+    }
+    // make sure to skip all non-optional parameters
+    char *t = strchr(optionalParams, argv[i][1]);
+    if (t != NULL)
+      continue;
+
+    // if we are in the scope of the current parameter, parse it
+    if (curIndex == -1 || curIndex == index) {
+      if (argv[i][1] == 'D') {
+        // it's a full name definition
+        bool found = false;
+        int j;
+
+        char *t = strchr(argv[i] + 2, '=');
+        if (t == NULL) {
+          Debug << "Error: Missing '=' in option. "
+		<< "Syntax is -D<name>=<value>.\n" << flush;
+          exit(1);
+        }
+        for (j = 0; j < numOptions; j++)
+          if (!strncmp(options[j].name, argv[i] + 2, t - argv[i] - 2) &&
+              (unsigned)(t - argv[i] - 2) == strlen(options[j].name)) {
+            found = true;
+            break;
+          }
+        if (!found) {
+          Debug << "Warning: Unregistered option " << argv[i] << ".\n" << flush;
+	  //  exit(1);
+        }
+	if (found) {
+	  if (!CheckType(t + 1, options[j].type)) {
+	    Debug << "Error: invalid type of value " << t + 1 << " in option "
+		  << options[j].name << ".\n";
+	    exit(1);
+	  }
+	  if (options[j].value != NULL)
+	    delete options[j].value;
+	  options[j].value = strdup(t + 1);
+	}
+      }
+      else {
+        // it's an abbreviation
+        bool found = false;
+        int j;
+	
+        for (j = 0; j < numOptions; j++)
+          if (options[j].abbrev != NULL &&
+              !strncmp(options[j].abbrev, argv[i] + 1, strlen(options[j].abbrev))) {
+            found = true;
+            break;
+          }
+        if (!found) {
+          Debug << "Warning: Unregistered option " << argv[i] << ".\n" << flush;
+	  //          exit(1);
+        }
+	if (found) {
+	  if (!CheckType(argv[i] + 1 + strlen(options[j].abbrev), options[j].type)) {
+	    Debug << "Error: invalid type of value "
+		  << argv[i] + 1 + strlen(options[j].abbrev) << "in option "
+		  << options[j].name << ".\n";
+	    exit(1);
+	  }
+	  if (options[j].value != NULL)
+	    delete options[j].value;
+	  options[j].value = strdup(argv[i] + 1 + strlen(options[j].abbrev));
+	}
+      }
+    }
+  }
+#ifdef _DEBUG_PARAMS
+  // write out the options table
+  cerr << "Options table for " << numOptions << " options:\n";
+  for (int j = 0; j < numOptions; j++) {
+    cerr << options[j];
+    cerr << "\n";
+  }
+  cerr << "Options done.\n" << flush;
+#endif // _DEBUG_PARAMS
+}
+
+
+char *
+Environment::ParseString(char *buffer, char *string) const
+{
+  char *s = buffer;
+  char *t = string + strlen(string);
+
+  // skip leading whitespaces
+  while (*s == ' ' || *s == '\t')
+    s++;
+  if (*s == '\0')
+    return NULL;
+  while ((*s >= 'a' && *s <= 'z') ||
+         (*s >= 'A' && *s <= 'Z') ||
+         (*s >= '0' && *s <= '9') ||
+         *s == '_')
+    *t++ = *s++;
+  *t = '\0';
+  // skip trailing whitespaces
+  while (*s == ' ' || *s == '\t')
+    s++;
+  return s;
+}
+
+const char code[] = "JIDHipewhfdhyd74387hHO&{WK:DOKQEIDKJPQ*H#@USX:#FWCQ*EJMQAHPQP(@G#RD";
+
+void
+Environment::DecodeString(char *buff, int max)
+{
+  buff[max] = 0;
+  char *p = buff;
+  const char *cp = code; 
+  for (; *p; p++) {
+    if (*p != '\n')
+      *p = *p ^ *cp;
+    ++cp;
+    if (*cp == 0)
+      cp = code;
+  }
+}
+
+void
+Environment::CodeString(char *buff, int max)
+{
+  buff[max] = 0;
+  char *p = buff;
+  const char *cp = code; 
+  for (; *p; p++) {
+    if (*p != '\n')
+      *p = *p ^ *cp;
+    ++cp;
+    if (*cp == 0)
+      cp = code;
+  }
+}
+
+void
+Environment::SaveCodedFile(char *filenameText,
+			    char *filenameCoded)
+{
+  ifstream envStream(filenameText);
+  
+  // some error had occured
+  if (envStream.fail()) {
+    cerr << "Error: Can't open file " << filenameText << " for reading (err. "
+         << envStream.rdstate() << ").\n";
+    return;
+  }
+  char buff[256];
+  envStream.getline(buff, 255);
+  buff[8] = 0;
+  if (strcmp(buff, "CGX_CF10") == 0)
+    return;
+
+  ofstream cStream(filenameCoded);
+  cStream<<"CGX_CF10";
+  
+  // main loop
+  for (;;) {
+    // read in one line
+    envStream.getline(buff, 255);
+    if (!envStream)
+      break;
+    CodeString(buff, 255);
+    cStream<<buff;
+  }
+  
+}
+
+bool
+Environment::ReadEnvFile(const char *envFilename)
+{
+  char buff[MaxStringLength], name[MaxStringLength];
+  char *s, *t;
+  int i, line = 0;
+  bool found;
+  igzstream envStream(envFilename);
+
+  // some error had occured
+  if (envStream.fail()) {
+    cerr << "Error: Can't open file " << envFilename << " for reading (err. "
+         << envStream.rdstate() << ").\n";
+    return false;
+  }
+  
+  name[0] = '\0';
+
+//    bool coded;
+//    envStream.getline(buff, 255);
+//    buff[8] = 0;
+//    if (strcmp(buff, "CGX_CF10") == 0) 
+//      coded = true;
+//    else {
+//      coded = false;
+//      envStream.Rewind();
+//    }
+  
+  // main loop
+  for (;;) {
+    // read in one line
+    envStream.getline(buff, 255);
+    
+    if (!envStream)
+      break;
+
+//      if (coded)
+//        DecodeString(buff, 255);
+
+    line++;
+    // get rid of comments
+    s = strchr(buff, '#');
+    if (s != NULL)
+      *s = '\0';
+
+    // get one identifier
+    s = ParseString(buff, name);
+    // parse line
+    while (s != NULL) {
+      // it's a group name - make the full name
+      if (*s == '{') {
+        strcat(name, ".");
+        s++;
+        s = ParseString(s, name);
+        continue;
+      }
+      // end of group
+      if (*s == '}') {
+        if (strlen(name) == 0) {
+          cerr << "Error: unpaired } in " << envFilename << " (line "
+               << line << ").\n";
+          envStream.close();
+          return false;
+        }
+        name[strlen(name) - 1] = '\0';
+        t = strrchr(name, '.');
+        if (t == NULL)
+          name[0] = '\0';
+        else
+          *(t + 1) = '\0';
+        s++;
+        s = ParseString(s, name);
+        continue;
+      }
+      // find variable name in the table
+      found = false;
+      for (i = 0; i < numOptions; i++)
+        if (!strcmp(name, options[i].name)) {
+          found = true;
+          break;
+        }
+      if (!found) {
+        cerr << "Warning: unknown option " << name << " in environment file "
+             << envFilename << " (line " << line << ").\n";
+      } else
+	switch (options[i].type) {
+        case optInt: {
+          strtol(s, &t, 10);
+          if (t == s || (*t != ' ' && *t != '\t' &&
+                         *t != '\0' && *t != '}')) {
+            cerr << "Error: Mismatch in int variable " << name << " in "
+                 << "environment file " << envFilename << " (line "
+                 << line << ").\n";
+            envStream.close();
+            return false;
+          }
+          if (options[i].value != NULL)
+            delete options[i].value;
+          options[i].value = new char[t - s + 1];
+          strncpy(options[i].value, s, t - s);
+          options[i].value[t - s] = '\0';
+          s = t;
+          break;
+        }
+        case optFloat: {
+          strtod(s, &t);
+          if (t == s || (*t != ' ' && *t != '\t' &&
+                         *t != '\0' && *t != '}')) {
+            cerr << "Error: Mismatch in Real variable " << name << " in "
+                 << "environment file " << envFilename << " (line "
+                 << line << ").\n";
+            envStream.close();
+            return false;
+          }
+          if (options[i].value != NULL)
+            delete options[i].value;
+          options[i].value = new char[t - s + 1];
+          strncpy(options[i].value, s, t - s);
+          options[i].value[t - s] = '\0';
+          s = t;
+          break;
+        }
+        case optBool: {
+          t = s;
+          while ((*t >= 'a' && *t <= 'z') ||
+                 (*t >= 'A' && *t <= 'Z') ||
+                 *t == '+' || *t == '-')
+            t++;
+          if (((!strncasecmp(s, "true", t - s)  && t - s == 4) ||
+               (!strncasecmp(s, "false", t - s) && t - s == 5) ||
+               (!strncasecmp(s, "YES", t -s)    && t - s == 3) ||
+               (!strncasecmp(s, "NO", t - s)    && t - s == 2) ||
+               (!strncasecmp(s, "ON", t - s)    && t - s == 2) ||
+               (!strncasecmp(s, "OFF", t - s)   && t - s == 3) ||
+               (t - s == 1 && (*s == '+' || *s == '-'))) &&
+              (*t == ' ' || *t == '\t' || *t == '\0' || *t == '}')) {
+            if (options[i].value != NULL)
+              delete options[i].value;
+            options[i].value = new char[t - s + 1];
+            strncpy(options[i].value, s, t - s);
+            options[i].value[t - s] = '\0';
+            s = t;
+          }
+          else {
+            cerr << "Error: Mismatch in bool variable " << name << " in "
+                 << "environment file " << envFilename << " (line "
+                 << line << ").\n";
+            envStream.close();
+            return false;
+          }
+          break;
+        }
+        case optVector:{
+          strtod(s, &t);
+          if (*t == ' ' || *t == '\t') {
+            while (*t == ' ' || *t == '\t')
+              t++;
+            if (*t != ',')
+              t--;
+          }
+          if (t == s || (*t != ' ' && *t != '\t' && *t != ',')) {
+            cerr << "Error: Mismatch in vector variable " << name << " in "
+                 << "environment file " << envFilename << " (line "
+                 << line << ").\n";
+            envStream.close();
+            return false;
+          }
+          char *u;
+          strtod(t, &u);
+          t = u;
+          if (*t == ' ' || *t == '\t') {
+            while (*t == ' ' || *t == '\t')
+              t++;
+            if (*t != ',')
+              t--;
+          }
+          if (t == s || (*t != ' ' && *t != '\t' && *t != ',')) {
+            cerr << "Error: Mismatch in vector variable " << name << " in "
+                 << "environment file " << envFilename << " (line "
+                 << line << ").\n";
+            envStream.close();
+            return false;
+          }
+          strtod(t, &u);
+          t = u;
+          if (t == s || (*t != ' ' && *t != '\t' &&
+                         *t != '\0' && *t != '}')) {
+            cerr << "Error: Mismatch in vector variable " << name << " in "
+                 << "environment file " << envFilename << " (line "
+                 << line << ").\n";
+            envStream.close();
+            return false;
+          }
+          if (options[i].value != NULL)
+            delete options[i].value;
+          options[i].value = new char[t - s + 1];
+          strncpy(options[i].value, s, t - s);
+          options[i].value[t - s] = '\0';
+          s = t;
+          break;
+        }
+        case optString: {
+          if (options[i].value != NULL)
+            delete options[i].value;
+          options[i].value = new char[strlen(s) + 1];
+          strcpy(options[i].value, s);
+          s += strlen(s);
+          break;
+        }
+        default: {
+          Debug << "Internal error: Unknown type of option.\n" << flush;
+          exit(1);
+        }
+      }
+      // prepare the variable name for next pass
+      t = strrchr(name, '.');
+      if (t == NULL)
+        name[0] = '\0';
+      else
+        *(t + 1) = '\0';
+      // get next identifier
+      s = ParseString(s, name);
+    }
+  }
+  envStream.close();
+  return true;
+}
+
+void
+Environment::PrintUsage(ostream &s) const
+{
+  // Print out all environment variable names
+  s << "Registered options:\n";
+  for (int j = 0; j < numOptions; j++)
+    s << options[j] << "\n";
+  s << flush;
+}
+
+
+Environment::Environment()
+{
+  optionalParams = NULL;
+  paramRows = 0;
+  numParams = 0;
+  params = NULL;
+  maxOptions = 500;
+
+  
+// this is maximal nuber of options.
+  numOptions = 0;
+
+  options = new COption[maxOptions];
+
+  if (options == NULL ) {
+    Debug << "Error: Memory allocation failed.\n";
+    exit(1);
+  }
+  
+  // register all basic options
+
+  RegisterOption("Limits.threshold", optFloat, NULL, "0.01");
+  RegisterOption("Limits.small", optFloat, NULL, "1e-6");
+  RegisterOption("Limits.infinity", optFloat, NULL, "1e6");
+
+
+  RegisterOption("Scene.filename",
+				 optString,
+				 "scene_filename=",
+				 "atlanta2.x3d");
+
+  RegisterOption("Unigraphics.meshGrouping",
+				 optInt,
+				 "unigraphics_mesh_grouping=",
+				 "0");
+  
+
+  RegisterOption("KdTree.Termination.minCost",
+				 optInt,
+				 "kd_term_min_cost=",
+				 "10");
+  
+  RegisterOption("KdTree.Termination.maxDepth",
+				 optInt,
+				 "kd_term_max_depth=",
+				 "20");
+
+  RegisterOption("KdTree.Termination.maxCostRatio",
+				 optFloat,
+				 "kd_term_max_cost_ratio=",
+				 "1.5");
+
+  RegisterOption("KdTree.Termination.ct_div_ci",
+				 optFloat,
+				 "kd_term_ct_div_ci=",
+				 "1.0");
+
+  RegisterOption("KdTree.splitMethod",
+				 optString,
+				 "kd_split_method=",
+				 "spatialMedian");
+
+  RegisterOption("KdTree.splitBorder",
+		 optFloat,
+		 "kd_split_border=",
+		 "0.1");
+
+  RegisterOption("KdTree.sahUseFaces",
+		 optBool,
+		 "kd_sah_use_faces=",
+		 "true");
+
+
+  RegisterOption("MeshKdTree.Termination.minCost",
+		 optInt,
+		 "kd_term_min_cost=",
+		 "10");
+  
+  RegisterOption("MeshKdTree.Termination.maxDepth",
+		 optInt,
+		 "kd_term_max_depth=",
+		 "20");
+
+  RegisterOption("MeshKdTree.Termination.maxCostRatio",
+		 optFloat,
+		 "kd_term_max_cost_ratio=",
+		 "1.5");
+
+  RegisterOption("MeshKdTree.Termination.ct_div_ci",
+		 optFloat,
+		 "kd_term_ct_div_ci=",
+		 "1.0");
+
+  RegisterOption("MeshKdTree.splitMethod",
+		 optString,
+		 "kd_split_method=",
+		 "spatialMedian");
+
+  RegisterOption("MeshKdTree.splitBorder",
+		 optFloat,
+		 "kd_split_border=",
+		 "0.1");
+
+  RegisterOption("SamplingPreprocessor.totalSamples",
+		 optInt,
+		 "total_samples=",
+		 "1000000");
+
+  RegisterOption("SamplingPreprocessor.samplesPerPass",
+		 optInt,
+		 "samples_per_pass=",
+		 "10");
+
+  RegisterOption("VssPreprocessor.initialSamples",
+				 optInt,
+				 "initial_samples=",
+				 "100000");
+  
+  RegisterOption("VssPreprocessor.testBeamSampling", optBool, "beam_sampling", "false");
+
+  RegisterOption("VssPreprocessor.vssSamples",
+				 optInt,
+				 "vss_samples=",
+				 "1000000");
+	
+  RegisterOption("VssPreprocessor.vssSamplesPerPass",
+				 optInt,
+				 "vss_samples_per_pass=",
+				 "1000");
+  
+  RegisterOption("VssPreprocessor.samplesPerPass",
+				 optInt,
+				 "samples_per_pass=",
+				 "100000");
+
+
+
+  RegisterOption("VssPreprocessor.useImportanceSampling",
+				 optBool,
+				 "vss_use_importance=",
+				 "true");
+
+   RegisterOption("VssPreprocessor.loadInitialSamples",
+	  optBool,
+	  "-vss_load_loadInitialSamples=",
+	  "false");
+
+   RegisterOption("VssPreprocessor.storeInitialSamples",
+	  optBool,
+	  "-vss_store_storedInitialSamples=",
+	  "false");
+   
+
+    RegisterOption("VssPreprocessor.useViewSpaceBox",
+	  optBool,
+	  "-vss_use_viewspace_box=",
+	  "false");
+   
+
+  /************************************************************************************/
+  /*                         View cells related options                               */
+  /************************************************************************************/
+
+
+	RegisterOption("ViewCells.type",
+			optString,
+			"view_cells_type",
+			"bspTree");
+
+	RegisterOption("ViewCells.active",
+					optInt,
+					"1000");
+
+	RegisterOption("ViewCells.Construction.samples",
+					optInt,
+					"view_cells_construction_samples=",
+					"5000000");
+
+	RegisterOption("ViewCells.Construction.samplesPerPass",
+					optInt,
+					"view_cells_construction_samples_per_pass=",
+					"500000");
+
+	RegisterOption("ViewCells.PostProcess.samples",
+					optInt,
+					"view_cells_postprocess_samples=",
+					"200000");
+
+	RegisterOption("ViewCells.Visualization.samples",
+					optInt,
+					"view_cells_visualization_samples=",
+					"20000");
+
+	RegisterOption("ViewCells.loadFromFile",
+					optBool,
+					"view_cells_load_from_file",
+					"false");
+
+	RegisterOption("ViewCells.PostProcess.refine",
+					optBool,
+					"view_cells_refine",
+					"false");
+
+
+	RegisterOption("ViewCells.PostProcess.compress",
+					optBool,
+					"view_cells_compress",
+					"false");
+
+	RegisterOption("ViewCells.exportToFile",
+					optBool,
+					"view_cells_export_to_file",
+					"false");
+
+	RegisterOption("ViewCells.maxViewCells",
+			optInt,
+			"view_cells_max_view_cells=",
+			"0");
+
+	RegisterOption("ViewCells.maxPvsRatio",
+					optFloat,
+					"view_cells_max_pvs_ratio=",
+					"0.1");
+
+	RegisterOption("ViewCells.filename",
+			optString,
+			"view_cells_filename=",
+			"atlanta_viewcells_large.x3d");
+
+	RegisterOption("ViewCells.height",
+			optFloat,
+			"view_cells_height=",
+			"5.0");
+
+	RegisterOption("ViewCells.Visualization.colorCode",
+		optString,
+		"-view_cells_visualization_color_code",
+		"PVS");
+
+	RegisterOption("ViewCells.Visualization.exportRays",
+		optBool,
+		"-view_cells_delayed_construction",
+		"false");
+
+	
+
+	RegisterOption("ViewCells.Visualization.exportGeometry",
+		optBool,
+		"-view_cells_visualization_export_geometry",
+		"false");
+
+	RegisterOption("ViewCells.pruneEmptyViewCells",
+		optBool,
+		"-view_cells_prune_empty_view_cells",
+		"false");
+
+	RegisterOption("ViewCells.processOnlyValidViewCells",
+		optBool,
+		"-view_cells_process_only_valid_view_cells",
+		"false");
+	
+	
+	RegisterOption("ViewCells.PostProcess.maxCostRatio",
+			optFloat,
+			"-view_cells_post_process_max_cost_ratio=",
+			"0.9");
+
+	
+	RegisterOption("ViewCells.PostProcess.renderCostWeight",
+			optFloat,
+			"-view_cells_post_process_render_cost_weight",
+			"0.5");
+
+	
+	RegisterOption("ViewCells.PostProcess.avgCostMaxDeviation",
+			optFloat,
+			"-vsp_bsp_avgcost_max_deviations",
+			"0.5");
+
+	RegisterOption("ViewCells.PostProcess.maxMergesPerPass", 
+		optInt, 
+		"vsp_bsp_term_max_merges_per_pass=", 
+		"500");
+
+	RegisterOption("ViewCells.PostProcess.minViewCells", 
+		optInt, 
+		"vsp_bsp_term_post_process_min_view_cells=", 
+		"1000");
+
+	RegisterOption("ViewCells.PostProcess.useRaysForMerge", 
+		optBool,
+		"view_cells_post_process_use_rays_for_merge=", 
+		"false");
+	
+	RegisterOption("ViewCells.PostProcess.merge", 
+		optBool,
+		"view_cells_post_merge=", 
+		"true");
+
+	RegisterOption("ViewCells.Visualization.exportMergedViewCells",
+		optBool, 
+		"view_cells_viz_export_merged_viewcells=", 
+		"false");
+
+	RegisterOption("ViewCells.maxStaticMemory", 
+		optFloat, 
+		"view_cells_max_static_mem=", 
+		"8.0");
+
+	RegisterOption("ViewCells.Visualization.useCuttingPlane",
+		optBool, 
+		"view_cells_viz_use_cutting_plane=", 
+		"false");
+
+	
+	RegisterOption("ViewCells.Visualization.cuttingPlaneAxis",
+		optInt, 
+		"view_cells_viz_cutting_plane_axis=", 
+		"0");
+
+
+	/************************************************************************************/
+	/*                         Render simulation related options                        */
+	/************************************************************************************/
+
+
+	RegisterOption("Simulation.objRenderCost",
+			optFloat,
+			"simulation_obj_render_cost",
+			"1.0");
+
+	RegisterOption("Simulation.vcOverhead",
+			optFloat,
+			"simulation_vc_overhead",
+			"0.05");
+
+	RegisterOption("Simulation.moveSpeed",
+			optFloat,
+			"simulation_moveSpeed",
+			"1.0");
+
+
+
+
+	/************************************************************************************/
+	/*                         Bsp tree related options                                 */
+	/************************************************************************************/
+
+
+	RegisterOption("BspTree.Construction.input",
+		optString,
+		"bsp_construction_input=",
+		"fromViewCells");
+
+	RegisterOption("BspTree.Construction.samples",
+		optInt,
+		"bsp_construction_samples=",
+		"100000");
+
+	RegisterOption("BspTree.Construction.epsilon",
+		optFloat,
+		"bsp_construction_side_tolerance=",
+		"0.002");
+
+	RegisterOption("BspTree.Termination.minPolygons",
+			optInt,
+			"bsp_term_min_polygons=",
+			"5");
+
+	RegisterOption("BspTree.Termination.minPvs",
+			optInt,
+			"bsp_term_min_pvs=",
+			"20");
+
+	RegisterOption("BspTree.Termination.minProbability",
+			optFloat,
+			"bsp_term_min_probability=",
+			"0.001");
+
+	RegisterOption("BspTree.Termination.maxRayContribution",
+			optFloat,
+			"bsp_term_ray_contribution=",
+			"0.005");
+
+	RegisterOption("BspTree.Termination.minAccRayLenght",
+			optFloat,
+			"bsp_term_min_acc_ray_length=",
+			"50");
+
+	RegisterOption("BspTree.Termination.minRays",
+			optInt,
+			"bsp_term_min_rays=",
+			"-1");
+
+	RegisterOption("BspTree.Termination.ct_div_ci",
+			optFloat,
+			"bsp_term_ct_div_ci=",
+			"0.0");
+
+	RegisterOption("BspTree.Termination.maxDepth",
+			optInt,
+			"bsp_term_max_depth=",
+			"100");
+
+	RegisterOption("BspTree.Termination.maxCostRatio",
+			optFloat,
+			"bsp_term_axis_aligned_max_cost_ratio=",
+			"1.5");
+
+	RegisterOption("BspTree.Termination.AxisAligned.ct_div_ci",
+			optFloat,
+			"bsp_term_axis_aligned_ct_div_ci=",
+			"0.5");
+
+	RegisterOption("BspTree.AxisAligned.splitBorder",
+			optFloat,
+			"bsp__axis_aligned_split_border=",
+			"0.1");
+
+	RegisterOption("BspTree.Termination.AxisAligned.minPolys",
+			optInt,
+			"bsp_term_axis_aligned_max_polygons=",
+			"50");
+
+	RegisterOption("BspTree.Termination.AxisAligned.minObjects",
+			optInt,
+			"bsp_term_min_objects=",
+			"3");
+
+	RegisterOption("BspTree.Termination.AxisAligned.minRays",
+			optInt,
+			"bsp_term_axis_aligned_min_rays=",
+			"-1");
+
+	RegisterOption("BspTree.splitPlaneStrategy",
+			optString,
+			"bsp_split_method=",
+			"leastSplits");
+
+	RegisterOption("BspTree.maxPolyCandidates",
+		optInt,
+		"bsp_max_poly_candidates=",
+		"20");
+
+	RegisterOption("BspTree.maxRayCandidates",
+		optInt,
+		"bsp_max_plane_candidates=",
+		"20");
+
+	RegisterOption("BspTree.maxTests",
+		optInt,
+		"bsp_max_tests=",
+		"5000");
+
+	RegisterOption("BspTree.Termination.maxViewCells",
+		optInt,
+		"bsp_max_view_cells=",
+		"5000");
+
+	RegisterOption("BspTree.Visualization.exportSplits",
+		optBool,
+		"bsp_visualization.export_splits",
+		"false");
+
+	RegisterOption("BspTree.Factor.verticalSplits", optFloat, "bsp_factor_vertical=", "1.0");
+	RegisterOption("BspTree.Factor.largestPolyArea", optFloat, "bsp_factor_largest_poly=", "1.0");
+	RegisterOption("BspTree.Factor.blockedRays", optFloat, "bsp_factor_blocked=", "1.0");
+	RegisterOption("BspTree.Factor.leastSplits", optFloat, "bsp_factor_least_splits=", "1.0");
+	RegisterOption("BspTree.Factor.balancedPolys", optFloat, "bsp_factor_balanced_polys=", "1.0");
+	RegisterOption("BspTree.Factor.balancedViewCells", optFloat, "bsp_factor_balanced_view_cells=", "1.0");
+	RegisterOption("BspTree.Factor.leastRaySplits", optFloat, "bsp_factor_least_ray_splits=", "1.0");
+	RegisterOption("BspTree.Factor.balancedRays", optFloat, "bsp_factor_balanced_rays=", "1.0");
+	RegisterOption("BspTree.Factor.pvs", optFloat, "bsp_factor_pvs=", "1.0");
+
+	/************************************************************************************/
+	/*                         Preprocessor related options                             */
+	/************************************************************************************/
+
+	RegisterOption("Preprocessor.type",
+					optString,
+					"preprocessor=",
+					"sampling");
+
+	RegisterOption("Preprocessor.samplesFilename",
+					optString,
+					"-preprocessor_samples_filename=",
+					"rays.out");
+
+	RegisterOption("Preprocessor.useGlRenderer",
+					optBool,
+					"useGlRenderer",
+					"false");
+
+	RegisterOption("Preprocessor.pvsRenderErrorSamples",
+				   optInt,
+				   "pvsRenderErrorSamples=",
+				   "10000");
+
+	RegisterOption("Preprocessor.useGlDebugger",
+					optBool,
+					"useGlDebugger",
+					"false");
+
+	RegisterOption("Preprocessor.detectEmptyViewSpace",
+				   optBool,
+				   "detectEmptyViewSpace",
+				   "false");
+	
+	RegisterOption("Preprocessor.quitOnFinish",
+				   optBool,
+				   "quitOnFinish",
+				   "true");
+
+	/**************************************************************************************/
+	/*                  View space partition KD tree related options                      */
+	/**************************************************************************************/
+
+	RegisterOption("VspKdTree.Construction.samples",
+					optInt,
+					"vsp_kd_construction_samples=",
+					"100000");
+
+	RegisterOption("VspKdTree.Termination.maxDepth", 
+		optInt, 
+		"vsp_term_maxdepth=", "30");
+
+	RegisterOption("VspKdTree.Termination.minPvs", 
+		optInt, 
+		"vsp_minpvs=", 
+		"1");
+
+	RegisterOption("VspKdTree.Termination.minRays", 
+		optInt, 
+		"vsp_term_minrays=", 
+		"10");
+
+	RegisterOption("VspKdTree.Termination.minSize", 
+		optFloat, 
+		"vsp_term_minsize=", 
+		"0.001");
+
+	RegisterOption("VspKdTree.Termination.maxCostRatio", 
+		optFloat, 
+		"vsp_term_maxcost=",
+		"0.95");
+
+	RegisterOption("VspKdTree.Termination.maxRayContribution", 
+		optFloat, 
+		"vsp_term_max_ray_contrib=", 
+		"0.5");
+
+	RegisterOption("VspKdTree.epsilon", 
+		optFloat, 
+		"kd_eps=", 
+		"1e-6");
+
+	RegisterOption("VspKdTree.ct_div_ci", 
+		optFloat, 
+		"vsp_ctdivci=", "1.0");
+
+	RegisterOption("VspKdTree.splitType", 
+		optString, 
+		"split=", 
+		"queries");
+
+	RegisterOption("VspKdTree.splitAxis", 
+		optString, 
+		"split=", 
+		"drivingAxis");
+
+	RegisterOption("VspKdTree.splitUseOnlyDrivingAxis", 
+		optBool, 
+		"vsp_kd_splitdriving=", 
+		"false");
+
+	RegisterOption("VspKdTree.numberOfEndPointDomains", 
+		optInt, 
+		"endpoints=", 
+		"10000");
+
+	RegisterOption("VspKdTree.maxTotalMemory", 
+		optFloat, 
+		"vsp_max_total_mem=", 
+		"60.0");
+
+	RegisterOption("VspKdTree.maxStaticMemory", 
+		optFloat, 
+		"vsp_max_static_mem=", 
+		"8.0");
+
+	RegisterOption("VspKdTree.queryType", 
+		optString, 
+		"qtype=", 
+		"static");
+
+	RegisterOption("VspKdTree.queryPosWeight", 
+		optFloat, 
+		"vsp_kd_qposweight=", 
+		"0.0");
+
+	RegisterOption("VspKdTree.accessTimeThreshold", 
+		optInt, 
+		"vsp_kd_accesstime=", 
+		"1000");
+
+	RegisterOption("VspKdTree.minCollapseDepth", 
+		optInt, 
+		"vsp_kd_min_colldepth=", 
+		"4");
+
+	RegisterOption("VspKdTree.PostProcess.maxCostRatio",
+			optFloat,
+			"vsp_kd_post_process_max_cost_ratio=",
+			"0.9");
+
+	RegisterOption("VspKdTree.PostProcess.minViewCells", 
+		optInt, 
+		"vsp_kd_term_post_process_min_view_cells=", 
+		"1000");
+
+	RegisterOption("VspKdTree.Termination.maxViewCells", 
+		optInt, 
+		"vsp_kd_term_post_process_min_view_cells=", 
+		"300");
+
+	RegisterOption("VspKdTree.PostProcess.maxPvsSize", 
+		optInt, 
+		"vsp_kd_term_post_process_max_pvs_size=", 
+		"100");
+
+	RegisterOption("VspKdTree.Termination.missTolerance",
+			optInt,
+			"-vsp_kd_term_miss_tolerance=",
+			"4");
+
+	/************************************************************************************/
+	/*                   VSS Preprocessor cells related options                         */
+	/************************************************************************************/
+
+	RegisterOption("VssTree.maxDepth", optInt, "kd_depth=", "12");
+	RegisterOption("VssTree.minPvs", optInt, "kd_minpvs=", "1");
+	RegisterOption("VssTree.minRays", optInt, "kd_minrays=", "10");
+	RegisterOption("VssTree.maxCostRatio", optFloat, "maxcost=", "0.95");
+	RegisterOption("VssTree.maxRayContribution", optFloat, "maxraycontrib=", "0.5");
+
+	RegisterOption("VssTree.epsilon", optFloat, "kd_eps=", "1e-6");
+	RegisterOption("VssTree.ct_div_ci", optFloat, "kd_ctdivci=", "1.0");
+	RegisterOption("VssTree.randomize", optBool, "randomize", "false");
+	RegisterOption("VssTree.splitType", optString, "split=", "queries");
+	RegisterOption("VssTree.splitUseOnlyDrivingAxis", optBool, "splitdriving=", "false");
+	RegisterOption("VssTree.useRss", optBool, "rss=", "false");
+	RegisterOption("VssTree.numberOfEndPointDomains", optInt, "endpoints=", "10000");
+
+	RegisterOption("VssTree.minSize", optFloat, "minsize=", "0.001");
+
+	RegisterOption("VssTree.maxTotalMemory", optFloat, "mem=", "60.0");
+	RegisterOption("VssTree.maxStaticMemory", optFloat, "statmem=", "8.0");
+
+	RegisterOption("VssTree.queryType", optString, "qtype=", "static");
+
+	
+	
+	RegisterOption("VssTree.queryPosWeight", optFloat, "qposweight=", "0.0");
+	RegisterOption("VssTree.useRefDirSplits", optBool, "refdir", "false");
+	RegisterOption("VssTree.refDirAngle", optFloat, "refangle=", "10");
+	RegisterOption("VssTree.refDirBoxMaxSize", optFloat, "refboxsize=", "0.1");
+	RegisterOption("VssTree.accessTimeThreshold", optInt, "accesstime=", "1000");
+	RegisterOption("VssTree.minCollapseDepth", optInt, "colldepth=", "4");
+
+	RegisterOption("VssTree.interleaveDirSplits", optBool, "interleavedirsplits", "true");
+	RegisterOption("VssTree.dirSplitDepth", optInt, "dirsplidepth=", "10");
+
+
+	RegisterOption("RssPreprocessor.initialSamples",
+									optInt,
+									"initial_samples=",
+									"100000");
+
+	RegisterOption("RssPreprocessor.vssSamples",
+					optInt,
+					"rss_vss_samples=",
+					"1000000");
+
+	RegisterOption("RssPreprocessor.vssSamplesPerPass",
+					optInt,
+					"rss_vss_samples_per_pass=",
+					"1000");
+
+	RegisterOption("RssPreprocessor.samplesPerPass",
+					optInt,
+					"rss_samples_per_pass=",
+					"100000");
+
+	RegisterOption("RssPreprocessor.useImportanceSampling",
+					optBool,
+					"rss_use_importance",
+					"true");
+
+	RegisterOption("RssPreprocessor.objectBasedSampling",
+					optBool,
+					"rss_object_based_sampling",
+					"true");
+
+	RegisterOption("RssPreprocessor.directionalSampling",
+					optBool,
+					"rss_directional_sampling",
+					"false");
+
+	RegisterOption("RssTree.maxDepth", optInt, "kd_depth=", "12");
+	RegisterOption("RssTree.minPvs", optInt, "kd_minpvs=", "1");
+	RegisterOption("RssTree.minRays", optInt, "kd_minrays=", "10");
+	RegisterOption("RssTree.maxCostRatio", optFloat, "maxcost=", "0.95");
+	RegisterOption("RssTree.maxRayContribution", optFloat, "maxraycontrib=", "0.5");
+
+	RegisterOption("RssTree.epsilon", optFloat, "kd_eps=", "1e-6");
+	RegisterOption("RssTree.ct_div_ci", optFloat, "kd_ctdivci=", "1.0");
+	RegisterOption("RssTree.randomize", optBool, "randomize", "false");
+	RegisterOption("RssTree.splitType", optString, "split=", "queries");
+	RegisterOption("RssTree.splitUseOnlyDrivingAxis", optBool, "splitdriving=", "false");
+
+	RegisterOption("RssTree.numberOfEndPointDomains", optInt, "endpoints=", "10000");
+
+	RegisterOption("RssTree.minSize", optFloat, "minsize=", "0.001");
+
+	RegisterOption("RssTree.maxTotalMemory", optFloat, "mem=", "60.0");
+	RegisterOption("RssTree.maxStaticMemory", optFloat, "statmem=", "8.0");
+
+	RegisterOption("RssTree.queryType", optString, "qtype=", "static");
+
+	RegisterOption("RssTree.queryPosWeight", optFloat, "qposweight=", "0.0");
+	RegisterOption("RssTree.useRefDirSplits", optBool, "refdir", "false");
+	RegisterOption("RssTree.refDirAngle", optFloat, "refangle=", "10");
+	RegisterOption("RssTree.refDirBoxMaxSize", optFloat, "refboxsize=", "0.1");
+	RegisterOption("RssTree.accessTimeThreshold", optInt, "accesstime=", "1000");
+	RegisterOption("RssTree.minCollapseDepth", optInt, "colldepth=", "4");
+
+	RegisterOption("RssTree.interleaveDirSplits", optBool, "interleavedirsplits", "true");
+	RegisterOption("RssTree.dirSplitDepth", optInt, "dirsplidepth=", "10");
+	RegisterOption("RssTree.importanceBasedCost", optBool, "importance_based_cost", "true");
+	RegisterOption("RssTree.maxRays", optInt, "rss_max_rays=", "2000000");
+
+	RegisterOption("RssTree.perObjectTree", optBool, "rss_per_object_tree", "false");
+
+	RegisterOption("RssPreprocessor.Export.pvs", optBool, "rss_export_pvs", "false");
+	RegisterOption("RssPreprocessor.Export.rssTree", optBool, "rss_export_rss_tree", "false");
+	RegisterOption("RssPreprocessor.Export.rays", optBool, "rss_export_rays", "false");
+	RegisterOption("RssPreprocessor.Export.numRays", optInt, "rss_export_num_rays=", "5000");
+	RegisterOption("RssPreprocessor.useViewcells", optBool, "rss_use_viewcells", "false");
+	RegisterOption("RssPreprocessor.updateSubdivision",
+				   optBool,
+				   "rss_update_subdivision",
+				   "false");
+
+
+/************************************************************************************/
+/*               View space partition BSP tree related options                      */
+/************************************************************************************/
+
+
+	RegisterOption("RssPreprocessor.loadInitialSamples",
+					optBool,
+					"vss_load_loadInitialSamples=",
+					"false");
+
+	RegisterOption("RssPreprocessor.storeInitialSamples",
+					optBool,
+					"vss_store_storeInitialSamples=",
+					"false");
+
+
+/************************************************************************************/
+/*               View space partition BSP tree related options                      */
+/************************************************************************************/
+
+
+	RegisterOption("VspBspTree.Termination.minPolygons",
+					optInt,
+					"vsp_bsp_term_min_polygons=",
+					"5");
+
+	RegisterOption("VspBspTree.Termination.minPvs",
+					optInt,
+					"vsp_bsp_term_min_pvs=",
+					"20");
+	RegisterOption("VspBspTree.Termination.minProbability",
+					optFloat,
+					"vsp_bsp_term_min_probability=",
+					"0.001");
+
+	RegisterOption("VspBspTree.Termination.maxRayContribution",
+					optFloat,
+					"vsp_bsp_term_ray_contribution=",
+					"0.005");
+
+	RegisterOption("VspBspTree.Termination.minAccRayLenght",
+					optFloat,
+					"vsp_bsp_term_min_acc_ray_length=",
+					"50");
+
+	RegisterOption("VspBspTree.Termination.minRays",
+					optInt,
+					"vsp_bsp_term_min_rays=",
+					"-1");
+
+	RegisterOption("VspBspTree.Termination.ct_div_ci",
+					optFloat,
+					"vsp_bsp_term_ct_div_ci=",
+					"0.0");
+
+	RegisterOption("VspBspTree.Termination.maxDepth",
+					optInt,
+					"vsp_bsp_term_max_depth=",
+					"100");
+
+	RegisterOption("VspBspTree.Termination.AxisAligned.maxCostRatio",
+		optFloat,
+		"-vsp_bsp_term_axis_aligned_max_cost_ratio=",
+		"1.5");
+
+	RegisterOption("VspBspTree.useCostHeuristics",
+		optBool,
+		"-vsp_bsp_use_cost_heuristics=",
+		"false");
+
+	RegisterOption("VspBspTree.Termination.maxViewCells",
+		optInt,
+		"-vsp_bsp_term_max_view_cells=",
+		"1000");
+
+	RegisterOption("VspBspTree.Termination.maxCostRatio",
+		optFloat,
+		"-vsp_bsp_term_max_cost_ratio=",
+		"1.5");
+
+	RegisterOption("VspBspTree.Termination.missTolerance",
+					optInt,
+					"vsp_bsp_term_miss_tolerance=",
+					"4");
+	RegisterOption("VspBspTree.splitPlaneStrategy",
+					optString,
+					"vsp_bsp_split_method=",
+					"leastSplits");
+
+	RegisterOption("VspBspTree.maxPolyCandidates",
+					optInt,
+					"vsp_bsp_max_poly_candidates=",
+					"20");
+	RegisterOption("VspBspTree.maxRayCandidates",
+					optInt,
+					"vsp_bsp_max_plane_candidates=",
+					"20");
+
+	RegisterOption("VspBspTree.maxTests",
+					optInt,
+					"vsp_bsp_max_tests=",
+					"5000");
+
+	RegisterOption("VspBspTree.Construction.samples",
+					optInt,
+					"bsp_construction_samples=",
+					"100000");
+
+	RegisterOption("VspBspTree.Construction.epsilon",
+					optFloat,
+					"vsp_bsp_construction_side_tolerance=",
+					"0.002");
+
+	RegisterOption("VspBspTree.Visualization.exportSplits",
+					optBool,
+					"vsp_bsp_visualization.export_splits",
+					"false");
+
+	RegisterOption("VspBspTree.splitUseOnlyDrivingAxis", 
+					optBool, 
+					"vsp_bsp_splitdriving=", 
+					"false");
+
+	RegisterOption("VspBspTree.usePolygonSplitIfAvailable",
+					optBool,
+                    "vsp_bsp_usePolygonSplitIfAvailable=",
+					"false");
+
+	RegisterOption("VspBspTree.Termination.AxisAligned.minRays",
+			optInt,
+			"bsp_term_axis_aligned_min_rays=",
+			"100");
+	
+	RegisterOption("VspBspTree.Termination.AxisAligned.maxRayContribution",
+			optFloat,
+			"bsp_term_axis_aligned_min_rays=",
+			"0.1");
+
+	RegisterOption("VspBspTree.Factor.leastRaySplits", optFloat, "-vsp_bsp_factor_least_ray_splits=", "1.0");
+	RegisterOption("VspBspTree.Factor.balancedRays", optFloat, "-vsp_bsp_factor_balanced_rays=", "1.0");
+	RegisterOption("VspBspTree.Factor.pvs", optFloat, "-vsp_bsp_factor_pvs=", "1.0");
+
+
+	RegisterOption("VspBspTree.Construction.renderCostWeight",
+			optFloat,
+			"-vsp_bsp_post_process_render_cost_weight",
+			"0.5");
+
+
+	RegisterOption("VspBspTree.Construction.randomize", 
+		optBool, 
+		"vsp_bsp_construction_randomize=", 
+		"false");
+
+	
+	RegisterOption("VspBspTree.maxTotalMemory", 
+		optFloat, 
+		"vsp_bsp_max_total_mem=", 
+		"60.0");
+
+	RegisterOption("VspBspTree.maxStaticMemory", 
+		optFloat, 
+		"vsp_bsp_max_static_mem=", 
+		"8.0");
+
+	
+	
+
+	//////////////////////////////////////////////////////////////////////////////////
+}
+
+void
+Environment::SetStaticOptions()
+{
+  
+  // get Global option values
+  GetRealValue("Limits.threshold", Limits::Threshold);
+  GetRealValue("Limits.small", Limits::Small);
+  GetRealValue("Limits.infinity", Limits::Infinity);
+
+
+}
+
+void
+Environment::Parse(const int argc, char **argv, bool useExePath)
+{
+  
+  // Read the names of the scene, environment and output files
+  ReadCmdlineParams(argc, argv, "");
+
+  char *envFilename = new char[128];
+
+  char filename[64];
+
+  // Get the environment file name
+  if (!GetParam(' ', 0, filename)) {
+    // user didn't specified environment file explicitly, so
+    strcpy(filename, "default.env");
+  }
+  
+  if (useExePath) {
+    char *path = GetPath(argv[0]);
+    if (*path != 0)
+      sprintf(envFilename, "%s/%s", path, filename);
+    else
+      strcpy(envFilename, filename);
+    
+    delete path;
+  }
+  else
+    strcpy(envFilename, filename);
+
+  
+  // Now it's time to read in environment file.
+  if (!ReadEnvFile(envFilename)) {
+    // error - bad input file name specified ?
+    cerr<<"Error parsing environment file "<<envFilename<<endl;
+  }
+  delete envFilename;
+
+  // Parse the command line; options given on the command line subsume
+  // stuff specified in the input environment file.
+  ParseCmdline(argc, argv, 0);
+
+  SetStaticOptions();
+
+  // Check for request for help
+  if (CheckForSwitch(argc, argv, '?')) {
+    PrintUsage(cout);
+    exit(0);
+  }
+
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Beam.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Beam.h	(revision 542)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Beam.h	(revision 542)
@@ -0,0 +1,117 @@
+#ifndef __BEAM_H
+#define __BEAM_H
+
+#include <vector>
+#include "AxisAlignedBox3.h"
+#include "Statistics.h"
+
+using namespace std;
+
+class KdNode;
+class Intersectable;
+class Mesh;
+
+// the values need for rss tree update computed already inside the glrendererbuffer
+// not all of them need to be computed
+class BeamSampleStatistics: public StatisticsBase
+{
+public:
+	enum {COMPUTE_PVS_SIZE, COMPUTE_RAY_CONTRIBUTIONS, COMPUTE_PVS_ENTROPY};
+	int flags;
+
+	BeamSampleStatistics(): flags(COMPUTE_RAY_CONTRIBUTIONS) 
+	{
+		Reset();
+	}
+	
+	float pvsSize;
+	float rays;
+	float rayContributions;
+	float pvsEntropy;
+	float rayLengthEntropy;
+	float importance;
+	
+	float weightedRayContribution;
+
+	void Reset() 
+	{
+		pvsSize = 0;
+		rays = 0;
+		rayContributions = 0;
+		pvsEntropy = 0;
+		rayLengthEntropy = 0;
+		importance = 0;
+	}
+
+	void Print(ostream &app) const;
+
+	friend ostream &operator<<(ostream &s, const BeamSampleStatistics &stat) 
+	{
+		stat.Print(s);
+		return s;
+	}  
+};
+
+  
+class Beam {
+  
+public:			
+  enum {STORE_KD_NODES=1, STORE_OBJECTS=2, STORE_VIEW_CELLS, VALID=8};
+  int mFlags;
+  
+  // list of nodes intersected by the frustum
+  vector<KdNode *> mKdNodes;
+  // list of objects intersected by the frustum
+  ObjectContainer mObjects;
+  // view cells intersected by frustum
+  ViewCellContainer mViewCells;
+
+  // spatial box
+  AxisAlignedBox3 mBox;
+  // directional box (it is actually a 2D box - only x and y ranges are valid)
+  // directional parametrization according to VssRay::GetDirParametrization
+  AxisAlignedBox3 mDirBox;
+
+  vector<Plane3> mPlanes;
+
+  Mesh *mMesh;
+    
+  /** Constructs a beam from a spatial and a directional box.
+  */
+  void Construct(const AxisAlignedBox3 &box,
+		 	     const AxisAlignedBox3 &dBox);
+  
+  /** Computes parameters for glFrustum.
+  */
+  void ComputePerspectiveFrustum(float &left, float &right,
+								 float &bottom, float &top,
+								 float &near, float &far,
+								 const AxisAlignedBox3 &sceneBBox) const;
+
+  /** Computes parameters for glOrtho.
+  */
+  void ComputeOrthoFrustum(float &left, float &right,
+						   float &bottom, float &top,
+						   float &near, float &far,
+						   const AxisAlignedBox3 &sceneBBox) const;
+
+  int ComputeIntersection(const AxisAlignedBox3 &box);
+
+  Vector3 GetMainDirection() const;
+
+  bool IsValid() { return mFlags & VALID; }
+  bool SetValid() { return mFlags |= VALID; }
+
+  Beam():mFlags(STORE_KD_NODES+STORE_OBJECTS), mKdNodes(0), mObjects(0), mViewCells(0), mMesh(NULL)
+  {
+  }
+
+  ~Beam();
+
+  /** Creates beam mesh bounded at zfar.
+  */
+  void CreateMesh(const float zfar);
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Exporter.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Exporter.h	(revision 535)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Exporter.h	(revision 535)
@@ -0,0 +1,143 @@
+#ifndef __EXPORTER_H
+#define __EXPORTER_H
+
+#include <string>
+#include <vector>
+using namespace std;
+
+#include "Material.h"
+#include "Containers.h"
+#include "VssRay.h"
+
+class KdTree;
+class BspTree;
+class VspKdTree;
+class SceneGraphNode;
+class Ray;
+class AxisAlignedBox3;
+class Intersectable;
+class BspLeaf;
+class Polygon3;
+class VssTree;
+class VspBspTree;
+class RssTree;
+class Mesh;
+class Beam;
+
+class Exporter
+{
+protected:
+  string mFilename;
+  bool mWireframe;
+  bool mUseForcedMaterial;
+  Material mForcedMaterial;
+
+  bool mExportRayDensity;
+  
+public:
+  
+  Exporter(const string filename):mFilename(filename),
+				  mWireframe(false),
+				  mUseForcedMaterial(false),
+				  mExportRayDensity(false)
+  {
+  }
+  virtual ~Exporter() {}
+  
+  virtual bool ExportScene(SceneGraphNode *node) = 0;
+
+  virtual bool
+  ExportBox(const AxisAlignedBox3 &box) = 0;
+
+  virtual bool
+  ExportKdTree(const KdTree &tree) = 0;
+
+  virtual bool
+  ExportVssTree(const VssTree &tree) = 0;
+
+  virtual bool
+  ExportVssTree2(const VssTree &tree,
+				 const Vector3 direction
+				 ) = 0;
+
+  virtual bool
+  ExportVspKdTree(const VspKdTree &tree, const int maxPvs = 0) = 0;
+
+  virtual bool
+  ExportBspTree(const BspTree &tree) = 0;
+
+//    virtual bool
+//    ExportRays(const vector<Ray> &rays,
+//  	     const float length=1000,
+//  	     const RgbColor &color = RgbColor(1,1,1)
+//  	     ) = 0;
+  
+  virtual bool
+  ExportRays(const RayContainer &rays,
+			 const float length=1000,
+			 const RgbColor &color = RgbColor(1,1,1)
+			 ) = 0;
+  
+  virtual bool
+  ExportRays(const VssRayContainer &rays,
+			 const RgbColor &color = RgbColor(1,1,1)
+			 ) = 0;
+  
+  virtual void 
+  ExportViewCells(const ViewCellContainer &viewCells) = 0;
+  virtual void 
+  ExportViewCell(ViewCell *viewCell) = 0;
+  virtual void
+  ExportIntersectable(Intersectable *object) = 0;
+
+  virtual void 
+  ExportBspSplitPlanes(const BspTree &tree) = 0;
+  virtual void 
+  ExportBspSplits(const BspTree &tree, const bool exportDepth = false) = 0;
+
+  virtual void
+  ExportLeavesGeometry(const BspTree &tree, const vector<BspLeaf *> &leaves) = 0;
+  
+  virtual void 
+  ExportBspSplits(const VspBspTree &tree, const bool exportDepth = false) = 0;
+
+  virtual void 
+  ExportPolygons(const PolygonContainer &polys) = 0;
+
+  virtual void 
+  ExportBspLeaves(const BspTree &tree, const int maxPvs = 0) = 0;
+
+  virtual void
+  ExportGeometry(const ObjectContainer &objects) = 0;
+
+  virtual void
+  ExportMesh(Mesh *mesh) = 0;
+
+  virtual bool
+  ExportRssTree2(const RssTree &tree,
+				 const Vector3 direction) = 0;
+
+  virtual void ExportBeam(const Beam &beam, const AxisAlignedBox3 &box) = 0;
+
+  void SetExportRayDensity(const bool d) { mExportRayDensity = d; }
+  
+  void SetWireframe() { mWireframe = true; }
+  void SetFilled() { mWireframe = false; }
+
+  void SetForcedMaterial(const Material &m) {
+    mForcedMaterial = m;
+    mUseForcedMaterial = true;
+  }
+  void ResetForcedMaterial() {
+    mUseForcedMaterial = false;
+  }
+    
+  static Exporter *
+  GetExporter(const string filename);
+
+  virtual void ExportViewpoint(const Vector3 &point, const Vector3 &direction) = 0;
+};
+ 
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp	(revision 580)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp	(revision 580)
@@ -0,0 +1,1019 @@
+#include <stack>
+#include <algorithm>
+#include <queue>
+#include "Environment.h"
+#include "Mesh.h"
+#include "KdTree.h"
+#include "ViewCell.h"
+#include "Beam.h"
+
+int KdNode::mailID = 1;
+
+
+KdNode::KdNode(KdInterior *parent):mParent(parent), mailbox(0)
+{
+  if (parent)
+    mDepth = parent->mDepth+1;
+  else
+    mDepth = 0;
+}
+
+KdTree::KdTree()
+{
+  mRoot = new KdLeaf(NULL, 0);
+  environment->GetIntValue("KdTree.Termination.maxDepth", mTermMaxDepth);
+  environment->GetIntValue("KdTree.Termination.minCost", mTermMinCost);
+  environment->GetFloatValue("KdTree.Termination.maxCostRatio", mMaxCostRatio);
+  environment->GetFloatValue("KdTree.Termination.ct_div_ci", mCt_div_ci);
+  environment->GetFloatValue("KdTree.splitBorder", mSplitBorder);
+
+  environment->GetBoolValue("KdTree.sahUseFaces", mSahUseFaces);
+
+  char splitType[64];
+  environment->GetStringValue("KdTree.splitMethod", splitType);
+  
+  mSplitMethod = SPLIT_SPATIAL_MEDIAN;
+  if (strcmp(splitType, "spatialMedian") == 0)
+    mSplitMethod = SPLIT_SPATIAL_MEDIAN;
+  else
+    if (strcmp(splitType, "objectMedian") == 0)
+      mSplitMethod = SPLIT_OBJECT_MEDIAN;
+    else
+      if (strcmp(splitType, "SAH") == 0)
+	mSplitMethod = SPLIT_SAH;
+      else {
+	cerr<<"Wrong kd split type "<<splitType<<endl;
+	exit(1);
+      }
+  splitCandidates = NULL;
+}
+
+bool
+KdTree::Construct()
+{
+  if (!splitCandidates)
+    splitCandidates = new vector<SortableEntry>;
+
+  // first construct a leaf that will get subdivide
+  KdLeaf *leaf = (KdLeaf *) mRoot;
+
+  mStat.nodes = 1;
+
+  mBox.Initialize();
+  
+  ObjectContainer::const_iterator mi;
+  for ( mi = leaf->mObjects.begin();
+	mi != leaf->mObjects.end();
+	mi++) {
+    mBox.Include((*mi)->GetBox());
+  }
+
+  cout <<"KdTree Root Box:"<< mBox<<endl;
+  mRoot = Subdivide(TraversalData(leaf, mBox, 0));
+
+  // remove the allocated array
+  delete splitCandidates;
+
+  return true;
+}
+
+KdNode *
+KdTree::Subdivide(const TraversalData &tdata)
+{
+
+  KdNode *result = NULL;
+
+  priority_queue<TraversalData> tStack;
+  //  stack<STraversalData> tStack;
+  
+  tStack.push(tdata);
+  AxisAlignedBox3 backBox, frontBox;
+
+  
+  while (!tStack.empty()) {
+
+#if 0
+    if ( GetMemUsage() > maxMemory ) {
+      // count statistics on unprocessed leafs
+      while (!tStack.empty()) {
+	EvaluateLeafStats(tStack.top());
+	tStack.pop();
+      }
+      break;
+    }
+#endif
+
+    TraversalData data = tStack.top();
+    tStack.pop();
+    
+    KdNode *node = SubdivideNode((KdLeaf *) data.mNode,
+				 data.mBox,
+				 backBox,
+				 frontBox
+				 );
+    if (result == NULL)
+      result = node;
+    
+    if (!node->IsLeaf()) {
+
+      KdInterior *interior = (KdInterior *) node;
+      // push the children on the stack
+      tStack.push(TraversalData(interior->mBack, backBox, data.mDepth+1));
+      tStack.push(TraversalData(interior->mFront, frontBox, data.mDepth+1));
+      
+    } else {
+      EvaluateLeafStats(data);
+    }
+  }
+  
+  return result;
+
+}
+
+
+
+bool
+KdTree::TerminationCriteriaMet(const KdLeaf *leaf)
+{
+  //  cerr<<"\n OBJECTS="<<leaf->mObjects.size()<<endl;
+  return
+    (leaf->mObjects.size() <= mTermMinCost) ||
+    (leaf->mDepth >= mTermMaxDepth);
+  
+}
+
+
+int
+KdTree::SelectPlane(KdLeaf *leaf,
+		    const AxisAlignedBox3 &box,
+		    float &position
+		    )
+{
+  int axis = -1;
+  
+  switch (mSplitMethod)
+    {
+    case SPLIT_SPATIAL_MEDIAN: {
+      axis = box.Size().DrivingAxis();
+      position = (box.Min()[axis] + box.Max()[axis])*0.5f;
+      break;
+    }
+    case SPLIT_SAH: {
+      int objectsBack, objectsFront;
+      float costRatio;
+      bool mOnlyDrivingAxis = false;
+      if (mOnlyDrivingAxis) {
+				axis = box.Size().DrivingAxis();
+				costRatio = BestCostRatio(leaf,
+																	box,
+																	axis,
+																	position,
+																	objectsBack,
+																	objectsFront);
+      } else {
+				costRatio = MAX_FLOAT;
+				for (int i=0; i < 3; i++) {
+					float p;
+					float r = BestCostRatio(leaf,
+																	box,
+																	i,
+																	p,
+																	objectsBack,
+																	objectsFront);
+					if (r < costRatio) {
+						costRatio = r;
+						axis = i;
+						position = p;
+					}
+				}
+      }
+      
+      if (costRatio > mMaxCostRatio) {
+				//	cout<<"Too big cost ratio "<<costRatio<<endl;
+				axis = -1;
+      }
+      break;
+    }
+    
+    }
+  return axis;
+}
+
+KdNode *
+KdTree::SubdivideNode(
+		      KdLeaf *leaf,
+		      const AxisAlignedBox3 &box,
+		      AxisAlignedBox3 &backBBox,
+		      AxisAlignedBox3 &frontBBox
+		      )
+{
+  
+  if (TerminationCriteriaMet(leaf))
+	  return leaf;
+
+  float position;
+  
+  // select subdivision axis
+  int axis = SelectPlane( leaf, box, position );
+
+  if (axis == -1) {
+    return leaf;
+  }
+  
+  mStat.nodes+=2;
+  mStat.splits[axis]++;
+  
+  // add the new nodes to the tree
+  KdInterior *node = new KdInterior(leaf->mParent);
+
+  node->mAxis = axis;
+  node->mPosition = position;
+  node->mBox = box;
+  
+  backBBox = box;
+  frontBBox = box;
+  
+  // first count ray sides
+  int objectsBack = 0;
+  int objectsFront = 0;
+  
+  backBBox.SetMax(axis, position);
+  frontBBox.SetMin(axis, position);
+
+  ObjectContainer::const_iterator mi;
+
+  for ( mi = leaf->mObjects.begin();
+	mi != leaf->mObjects.end();
+	mi++) {
+    // determine the side of this ray with respect to the plane
+    AxisAlignedBox3 box = (*mi)->GetBox();
+    if (box.Max(axis) > position ) 
+      objectsFront++;
+    
+    if (box.Min(axis) < position )
+      objectsBack++;
+  }
+
+  
+  KdLeaf *back = new KdLeaf(node, objectsBack);
+  KdLeaf *front = new KdLeaf(node, objectsFront);
+
+  // replace a link from node's parent
+  if (  leaf->mParent )
+    leaf->mParent->ReplaceChildLink(leaf, node);
+
+  // and setup child links
+  node->SetupChildLinks(back, front);
+  
+  for (mi = leaf->mObjects.begin();
+       mi != leaf->mObjects.end();
+       mi++) {
+    // determine the side of this ray with respect to the plane
+    AxisAlignedBox3 box = (*mi)->GetBox();
+
+    if (box.Max(axis) >= position )
+      front->mObjects.push_back(*mi);
+    
+    if (box.Min(axis) < position )
+      back->mObjects.push_back(*mi);
+    
+    mStat.objectRefs -= (int)leaf->mObjects.size();
+    mStat.objectRefs += objectsBack + objectsFront;
+  }
+  
+  delete leaf;
+  return node;
+}
+
+
+
+void
+KdTreeStatistics::Print(ostream &app) const
+{
+  app << "===== KdTree statistics ===============\n";
+
+  app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
+
+  app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
+
+  app << "#N_SPLITS ( Number of splits in axes x y z dx dy dz \n";
+  for (int i=0; i<7; i++)
+    app << splits[i] <<" ";
+  app <<endl;
+
+  app << "#N_RAYREFS ( Number of rayRefs )\n" <<
+    rayRefs << "\n";
+
+  app << "#N_RAYRAYREFS  ( Number of rayRefs / ray )\n" <<
+    rayRefs/(double)rays << "\n";
+
+  app << "#N_LEAFRAYREFS  ( Number of rayRefs / leaf )\n" <<
+    rayRefs/(double)Leaves() << "\n";
+
+  app << "#N_MAXOBJECTREFS  ( Max number of rayRefs / leaf )\n" <<
+    maxObjectRefs << "\n";
+
+  app << "#N_NONEMPTYRAYREFS  ( Number of rayRefs in nonEmpty leaves / non empty leaf )\n" <<
+    rayRefsNonZeroQuery/(double)(Leaves() - zeroQueryNodes) << "\n";
+
+  app << "#N_LEAFDOMAINREFS  ( Number of query domain Refs / leaf )\n" <<
+    objectRefs/(double)Leaves() << "\n";
+
+  //  app << setprecision(4);
+
+  app << "#N_PEMPTYLEAVES  ( Percentage of leaves with zero query domains )\n"<<
+    zeroQueryNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maxdepth )\n"<<
+    maxDepthNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_PMINCOSTLEAVES  ( Percentage of leaves with minCost )\n"<<
+    minCostNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_ADDED_RAYREFS  (Number of dynamically added ray references )\n"<<
+    addedRayRefs<<endl;
+
+  app << "#N_REMOVED_RAYREFS  (Number of dynamically removed ray references )\n"<<
+    removedRayRefs<<endl;
+
+  //  app << setprecision(4);
+
+  //  app << "#N_CTIME  ( Construction time [s] )\n"
+  //      << Time() << " \n";
+
+  app << "===== END OF KdTree statistics ==========\n";
+
+}
+
+
+
+void
+KdTree::EvaluateLeafStats(const TraversalData &data)
+{
+
+  // the node became a leaf -> evaluate stats for leafs
+  KdLeaf *leaf = (KdLeaf *)data.mNode;
+
+  if (data.mDepth > mTermMaxDepth)
+    mStat.maxDepthNodes++;
+  
+  if ( (int)(leaf->mObjects.size()) < mTermMinCost)
+    mStat.minCostNodes++;
+  
+  
+  if ( (int)(leaf->mObjects.size()) > mStat.maxObjectRefs)
+    mStat.maxObjectRefs = (int)leaf->mObjects.size();
+  
+}
+
+
+
+void
+KdTree::SortSplitCandidates(
+			    KdLeaf *node,
+			    const int axis
+			    )
+{
+  splitCandidates->clear();
+  
+  int requestedSize = 2*(int)node->mObjects.size();
+  // creates a sorted split candidates array
+  if (splitCandidates->capacity() > 500000 &&
+      requestedSize < (int)(splitCandidates->capacity()/10) ) {
+    delete splitCandidates;
+    splitCandidates = new vector<SortableEntry>;
+  }
+  
+  splitCandidates->reserve(requestedSize);
+  
+  // insert all queries 
+  for(ObjectContainer::const_iterator mi = node->mObjects.begin();
+      mi != node->mObjects.end();
+      mi++) {
+    AxisAlignedBox3 box = (*mi)->GetBox();
+
+    splitCandidates->push_back(SortableEntry(SortableEntry::BOX_MIN,
+					     box.Min(axis),
+					     *mi)
+			       );
+    
+    
+    splitCandidates->push_back(SortableEntry(SortableEntry::BOX_MAX,
+					     box.Max(axis),
+					     *mi)
+			       );
+  }
+  
+  stable_sort(splitCandidates->begin(), splitCandidates->end());
+}
+
+
+float
+KdTree::BestCostRatio(
+											KdLeaf *node,
+											const AxisAlignedBox3 &box,
+											const int axis,
+											float &position,
+											int &objectsBack,
+											int &objectsFront
+											)
+{
+
+  SortSplitCandidates(node, axis);
+  
+  // go through the lists, count the number of objects left and right
+  // and evaluate the following cost funcion:
+  // C = ct_div_ci  + (ol + or)/queries
+
+  float totalIntersections = 0.0f;
+  vector<SortableEntry>::const_iterator ci;
+
+  for(ci = splitCandidates->begin();
+      ci < splitCandidates->end();
+      ci++) 
+    if ((*ci).type == SortableEntry::BOX_MIN) {
+      totalIntersections += (*ci).intersectable->IntersectionComplexity();
+    }
+	
+  float intersectionsLeft = 0;
+  float intersectionsRight = totalIntersections;
+	
+  int objectsLeft = 0, objectsRight = (int)node->mObjects.size();
+  
+  float minBox = box.Min(axis);
+  float maxBox = box.Max(axis);
+  float boxArea = box.SurfaceArea();
+  
+  float minBand = minBox + mSplitBorder*(maxBox - minBox);
+  float maxBand = minBox + (1.0f - mSplitBorder)*(maxBox - minBox);
+  
+  float minSum = 1e20f;
+  
+  for(ci = splitCandidates->begin();
+      ci < splitCandidates->end();
+      ci++) {
+    switch ((*ci).type) {
+    case SortableEntry::BOX_MIN:
+      objectsLeft++;
+      intersectionsLeft += (*ci).intersectable->IntersectionComplexity();
+      break;
+    case SortableEntry::BOX_MAX:
+      objectsRight--;
+      intersectionsRight -= (*ci).intersectable->IntersectionComplexity();
+      break;
+    }
+
+    if ((*ci).value > minBand && (*ci).value < maxBand) {
+      AxisAlignedBox3 lbox = box;
+      AxisAlignedBox3 rbox = box;
+      lbox.SetMax(axis, (*ci).value);
+      rbox.SetMin(axis, (*ci).value);
+
+      float sum;
+      if (mSahUseFaces)
+				sum = intersectionsLeft*lbox.SurfaceArea() + intersectionsRight*rbox.SurfaceArea();
+      else
+				sum = objectsLeft*lbox.SurfaceArea() + objectsRight*rbox.SurfaceArea();
+      
+      //      cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl;
+      //      cout<<"cost= "<<sum<<endl;
+      
+      if (sum < minSum) {
+				minSum = sum;
+				position = (*ci).value;
+				
+				objectsBack = objectsLeft;
+				objectsFront = objectsRight;
+      }
+    }
+  }
+  
+  float oldCost = mSahUseFaces ? totalIntersections : node->mObjects.size();
+  float newCost = mCt_div_ci + minSum/boxArea;
+  float ratio = newCost/oldCost;
+  
+#if 0
+  cout<<"===================="<<endl;
+  cout<<"costRatio="<<ratio<<" pos="<<position<<" t="<<(position - minBox)/(maxBox - minBox)
+      <<"\t o=("<<objectsBack<<","<<objectsFront<<")"<<endl;
+#endif
+  return ratio;
+}
+
+int
+KdTree::CastRay(
+				Ray &ray
+				)
+{
+  int hits = 0;
+  
+  stack<RayTraversalData> tStack;
+  
+  float maxt = 1e6;
+  float mint = 0;
+ 
+  Intersectable::NewMail();
+
+  if (!mBox.GetMinMaxT(ray, &mint, &maxt))
+    return 0;
+
+  if (mint < 0)
+    mint = 0;
+  
+  maxt += Limits::Threshold;
+  
+  Vector3 entp = ray.Extrap(mint);
+  Vector3 extp = ray.Extrap(maxt);
+  
+  KdNode *node = mRoot;
+  KdNode *farChild;
+  float position;
+  int axis;
+  
+  while (1) {
+    if (!node->IsLeaf()) {
+      KdInterior *in = (KdInterior *) node;
+      position = in->mPosition;
+      axis = in->mAxis;
+
+      if (entp[axis] <= position) {
+				if (extp[axis] <= position) {
+					node = in->mBack;
+					// cases N1,N2,N3,P5,Z2,Z3
+					continue;
+				} else {
+					// case N4
+					node = in->mBack;
+					farChild = in->mFront;
+				}
+      }
+      else {
+				if (position <= extp[axis]) {
+					node = in->mFront;
+					// cases P1,P2,P3,N5,Z1
+					continue;
+				} else {
+					node = in->mFront;
+					farChild = in->mBack;
+					// case P4
+				}
+			}
+      // $$ modification 3.5.2004 - hints from Kamil Ghais
+      // case N4 or P4
+      float tdist = (position - ray.GetLoc(axis)) / ray.GetDir(axis);
+      tStack.push(RayTraversalData(farChild, extp, maxt));
+      extp = ray.GetLoc() + ray.GetDir()*tdist;
+      maxt = tdist;
+		} else {
+			// compute intersection with all objects in this leaf
+			KdLeaf *leaf = (KdLeaf *) node;
+			if (ray.mFlags & Ray::STORE_KDLEAVES)
+				ray.kdLeaves.push_back(leaf);
+			
+			ObjectContainer::const_iterator mi;
+			for ( mi = leaf->mObjects.begin();
+						mi != leaf->mObjects.end();
+						mi++) {
+				Intersectable *object = *mi;
+				if (!object->Mailed() ) {
+					object->Mail();
+					if (ray.mFlags & Ray::STORE_TESTED_OBJECTS)
+						ray.testedObjects.push_back(object);
+					hits += object->CastRay(ray);
+				}
+			}
+			
+			if (hits && ray.GetType() == Ray::LOCAL_RAY)
+				if (ray.intersections[0].mT <= maxt)
+					break;
+			
+			// get the next node from the stack
+			if (tStack.empty())
+				break;
+			
+			entp = extp;
+			mint = maxt;
+			if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f)
+				break;
+			
+			RayTraversalData &s  = tStack.top();
+			node = s.mNode;
+			extp = s.mExitPoint;
+			maxt = s.mMaxT;
+			tStack.pop();
+		}
+  }
+  return hits;
+}
+
+int KdTree::CastLineSegment(const Vector3 &origin,
+							const Vector3 &termination,
+							vector<ViewCell *> &viewcells)
+{
+	int hits = 0;
+
+	float mint = 0.0f, maxt = 1.0f;
+	const Vector3 dir = termination - origin;
+
+	stack<RayTraversalData> tStack;
+
+	Intersectable::NewMail();
+
+	//maxt += Limits::Threshold;
+
+	Vector3 entp = origin;
+	Vector3 extp = termination;
+
+	KdNode *node = mRoot;
+	KdNode *farChild;
+
+	float position;
+	int axis;
+
+	while (1)
+	{
+		if (!node->IsLeaf())
+		{
+			KdInterior *in = dynamic_cast<KdInterior *>(node);
+			position = in->mPosition;
+			axis = in->mAxis;
+
+			if (entp[axis] <= position)
+			{
+				if (extp[axis] <= position)
+				{
+					node = in->mBack;
+					// cases N1,N2,N3,P5,Z2,Z3
+					continue;
+				} 
+				else
+				{
+					// case N4
+					node = in->mBack;
+					farChild = in->mFront;
+				}
+			}
+			else
+			{
+				if (position <= extp[axis])
+				{
+					node = in->mFront;
+					// cases P1,P2,P3,N5,Z1
+					continue;
+				}
+				else
+				{
+					node = in->mFront;
+					farChild = in->mBack;
+					// case P4
+				}
+			}
+
+ 			// $$ modification 3.5.2004 - hints from Kamil Ghais
+			// case N4 or P4
+			float tdist = (position - origin[axis]) / dir[axis];
+			//tStack.push(RayTraversalData(farChild, extp, maxt)); //TODO
+			extp = origin + dir * tdist;
+			maxt = tdist;
+		}
+		else
+		{
+			// compute intersection with all objects in this leaf
+			KdLeaf *leaf = dynamic_cast<KdLeaf *>(node);
+
+			// add view cell to intersections
+			ViewCell *vc = leaf->mViewCell;
+
+			if (!vc->Mailed())
+			{
+				vc->Mail();
+				viewcells.push_back(vc);
+				++ hits;
+			}
+
+			// get the next node from the stack
+			if (tStack.empty())
+				break;
+
+			entp = extp;
+			mint = maxt;
+			
+			RayTraversalData &s  = tStack.top();
+			node = s.mNode;
+			extp = s.mExitPoint;
+			maxt = s.mMaxT;
+			tStack.pop();
+		}
+	}
+
+	return hits;
+}
+
+
+void
+KdTree::CollectObjects(KdNode *n, ObjectContainer &objects)
+{
+  stack<KdNode *> nodeStack;
+
+  nodeStack.push(n);
+
+  while (!nodeStack.empty()) {
+    KdNode *node = nodeStack.top();
+    nodeStack.pop();
+    if (node->IsLeaf()) {
+      KdLeaf *leaf = (KdLeaf *)node;
+      for (int j=0; j < leaf->mObjects.size(); j++) {
+				Intersectable *object = leaf->mObjects[j];
+				if (!object->Mailed()) {
+					object->Mail();
+					objects.push_back(object);
+				}
+      }
+    } else {
+      KdInterior *interior = (KdInterior *)node;
+      nodeStack.push(interior->mFront);
+      nodeStack.push(interior->mBack);
+    }
+  }
+}
+
+// Find random neighbor which was not mailed
+KdNode *
+KdTree::FindRandomNeighbor(KdNode *n,
+													 bool onlyUnmailed
+													 )
+{
+  stack<KdNode *> nodeStack;
+  
+  nodeStack.push(mRoot);
+
+  AxisAlignedBox3 box = GetBox(n);
+  int mask = rand();
+
+  while (!nodeStack.empty()) {
+    KdNode *node = nodeStack.top();
+    nodeStack.pop();
+    if (node->IsLeaf()) {
+      if ( node != n && (!onlyUnmailed || !node->Mailed()) )
+	return node;
+    } else {
+      KdInterior *interior = (KdInterior *)node;
+      if (interior->mPosition > box.Max(interior->mAxis))
+	nodeStack.push(interior->mBack);
+      else
+	if (interior->mPosition < box.Min(interior->mAxis))
+	  nodeStack.push(interior->mFront);
+	else {
+	  // random decision
+	  if (mask&1)
+	    nodeStack.push(interior->mBack);
+	  else
+	    nodeStack.push(interior->mFront);
+	  mask = mask>>1;
+	}
+    }
+  }
+  
+  return NULL;
+}
+
+int
+KdTree::FindNeighbors(KdNode *n,
+		      vector<KdNode *> &neighbors,
+		      bool onlyUnmailed
+		      )
+{
+  stack<KdNode *> nodeStack;
+  
+  nodeStack.push(mRoot);
+
+  AxisAlignedBox3 box = GetBox(n);
+
+  while (!nodeStack.empty()) {
+    KdNode *node = nodeStack.top();
+    nodeStack.pop();
+    if (node->IsLeaf()) {
+      if ( node != n && (!onlyUnmailed || !node->Mailed()) ) 
+	neighbors.push_back(node);
+    } else {
+      KdInterior *interior = (KdInterior *)node;
+      if (interior->mPosition > box.Max(interior->mAxis))
+				nodeStack.push(interior->mBack);
+      else
+				if (interior->mPosition < box.Min(interior->mAxis))
+					nodeStack.push(interior->mFront);
+				else {
+					// random decision
+					nodeStack.push(interior->mBack);
+					nodeStack.push(interior->mFront);
+				}
+    }
+  }
+  
+  return (int)neighbors.size();
+}
+
+// Find random neighbor which was not mailed
+KdNode *
+KdTree::GetRandomLeaf(const Plane3 &plane)
+{
+  stack<KdNode *> nodeStack;
+  
+  nodeStack.push(mRoot);
+  
+  int mask = rand();
+  
+  while (!nodeStack.empty()) {
+    KdNode *node = nodeStack.top();
+    nodeStack.pop();
+    if (node->IsLeaf()) {
+      return node;
+    } else {
+      KdInterior *interior = (KdInterior *)node;
+      KdNode *next;
+	if (GetBox(interior->mBack).Side(plane) < 0)
+	  next = interior->mFront;
+	else
+	  if (GetBox(interior->mFront).Side(plane) < 0)
+	    next = interior->mBack;
+	  else {
+	    // random decision
+	    if (mask&1)
+	      next = interior->mBack;
+	    else
+	      next = interior->mFront;
+	    mask = mask>>1;
+	  }
+	nodeStack.push(next);
+    }
+  }
+  
+  
+  return NULL;
+}
+
+void
+KdTree::CollectLeaves(vector<KdLeaf *> &leaves)
+{
+  stack<KdNode *> nodeStack;
+  nodeStack.push(mRoot);
+
+  while (!nodeStack.empty()) {
+    KdNode *node = nodeStack.top();
+    nodeStack.pop();
+    if (node->IsLeaf()) {
+      KdLeaf *leaf = (KdLeaf *)node;
+      leaves.push_back(leaf);
+    } else {
+      KdInterior *interior = (KdInterior *)node;
+      nodeStack.push(interior->mBack);
+      nodeStack.push(interior->mFront);
+    }
+  }
+}
+
+void
+KdTree::CreateAndCollectViewCells(ViewCellContainer &vc) const
+{
+  stack<KdNode *> nodeStack;
+  nodeStack.push(mRoot);
+
+  while (!nodeStack.empty()) {
+    KdNode *node = nodeStack.top();
+    nodeStack.pop();
+    if (node->IsLeaf()) {
+      KdLeaf *leaf = (KdLeaf *)node;
+	  // kdtree used as view cell container => create view cell
+	  KdViewCell *viewCell = new KdViewCell();
+	  leaf->mViewCell = viewCell;
+	  // push back pointer to this leaf
+	  viewCell->mLeaf = leaf;
+      vc.push_back(viewCell);
+    } else {
+      KdInterior *interior = (KdInterior *)node;
+      nodeStack.push(interior->mBack);
+      nodeStack.push(interior->mFront);
+    }
+  }
+}
+
+int
+KdTree::CollectLeafPvs()
+{
+  int totalPvsSize = 0;
+  stack<KdNode *> nodeStack;
+  
+  nodeStack.push(mRoot);
+  
+  while (!nodeStack.empty()) {
+    KdNode *node = nodeStack.top();
+    nodeStack.pop();
+    if (node->IsLeaf()) {
+      KdLeaf *leaf = (KdLeaf *)node;
+      for (int j=0; j < leaf->mObjects.size(); j++) {
+	Intersectable *object = leaf->mObjects[j];
+	if (!object->Mailed()) {
+	  object->Mail();
+	  // add this node to pvs of all nodes it can see
+	  KdPvsMap::iterator ni = object->mKdPvs.mEntries.begin();
+	  for (; ni != object->mKdPvs.mEntries.end(); ni++) {
+	    KdNode *node = (*ni).first;
+	    // $$ JB TEMPORARY solution -> should add object PVS or explictly computed
+	    // kd tree PVS
+		float contribution;
+		if (leaf->mKdPvs.AddSample(node, 1.0f, contribution))
+	      totalPvsSize++;
+	  }
+	}
+      }
+    } else {
+      KdInterior *interior = (KdInterior *)node;
+      nodeStack.push(interior->mFront);
+      nodeStack.push(interior->mBack);
+    }
+  }
+
+  return totalPvsSize;
+}
+
+
+KdNode *
+KdTree::GetRandomLeaf(const bool onlyUnmailed)
+{
+  stack<KdNode *> nodeStack;
+  nodeStack.push(mRoot);
+  
+  int mask = rand();
+	
+  while (!nodeStack.empty()) {
+    KdNode *node = nodeStack.top();
+    nodeStack.pop();
+    if (node->IsLeaf()) {
+      if ( (!onlyUnmailed || !node->Mailed()) )
+				return node;
+    } else {
+      KdInterior *interior = (KdInterior *)node;
+			// random decision
+			if (mask&1)
+				nodeStack.push(interior->mBack);
+			else
+				nodeStack.push(interior->mFront);
+			mask = mask>>1;
+		}
+	}
+  return NULL;
+}
+
+
+int
+KdTree::CastBeam(
+				 Beam &beam
+				 )
+{
+  stack<KdNode *> nodeStack;
+  nodeStack.push(mRoot);
+  
+  while (!nodeStack.empty()) {
+    KdNode *node = nodeStack.top();
+    nodeStack.pop();
+	
+	int side = beam.ComputeIntersection(GetBox(node));
+	switch (side) {
+	case -1:
+	  beam.mKdNodes.push_back(node);
+	  break;
+	case 0:
+	  if (node->IsLeaf())
+		beam.mKdNodes.push_back(node);
+	  else {
+		KdInterior *interior = (KdInterior *)node;
+		KdNode *first = interior->mBack;
+		KdNode *second = interior->mFront;
+		
+		if (interior->mAxis < 3) {
+		  // spatial split -> decide on the order of the nodes
+		  if (beam.mPlanes[0].mNormal[interior->mAxis] > 0)
+			swap(first, second);
+		}
+
+		nodeStack.push(first);
+		nodeStack.push(second);
+	  }
+	  break;
+	  // default: cull
+	}
+  }
+
+  if (beam.mFlags & Beam::STORE_OBJECTS)
+  {
+	  vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
+	
+	  Intersectable::NewMail();
+	  for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
+	  {
+		  CollectObjects(*it, beam.mObjects);
+	  }
+  }
+
+  return beam.mKdNodes.size();
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp	(revision 611)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp	(revision 611)
@@ -0,0 +1,3104 @@
+#include "Plane3.h"
+#include "ViewCellBsp.h"
+#include "Mesh.h"
+#include "common.h"
+#include "ViewCell.h"
+#include "Environment.h"
+#include "Polygon3.h"
+#include "Ray.h"
+#include "AxisAlignedBox3.h"
+#include "Triangle3.h"
+#include "Tetrahedron3.h"
+#include "ViewCellsManager.h"
+#include "Exporter.h"
+#include "Plane3.h"
+#include <stack>
+
+
+
+//-- static members
+
+int BspNode::sMailId = 1;
+
+/** Evaluates split plane classification with respect to the plane's 
+	contribution for a minimum number splits in the tree.
+*/
+const float BspTree::sLeastPolySplitsTable[] = {0, 0, 1, 0};
+/** Evaluates split plane classification with respect to the plane's 
+	contribution for a balanced tree.
+*/
+const float BspTree::sBalancedPolysTable[] = {1, -1, 0, 0};
+
+/** Evaluates split plane classification with respect to the plane's 
+	contribution for a minimum number of ray splits.
+*/
+const float BspTree::sLeastRaySplitsTable[] = {0, 0, 1, 1, 0};
+/** Evaluates split plane classification with respect to the plane's 
+	contribution for balanced rays.
+*/
+const float BspTree::sBalancedRaysTable[] = {1, -1, 0, 0, 0};
+
+int BspTree::sFrontId = 0; 
+int BspTree::sBackId = 0;
+int BspTree::sFrontAndBackId = 0;
+
+
+/****************************************************************/
+/*                  class BspNode implementation                */
+/****************************************************************/
+
+
+BspNode::BspNode(): 
+mParent(NULL), mTreeValid(true), mTimeStamp(0)
+{}
+
+BspNode::BspNode(BspInterior *parent): 
+mParent(parent), mTreeValid(true)
+{}
+
+
+bool BspNode::IsRoot() const 
+{
+	return mParent == NULL;
+}
+
+
+BspInterior *BspNode::GetParent() 
+{ 
+	return mParent; 
+}
+
+
+void BspNode::SetParent(BspInterior *parent)
+{
+	mParent = parent;
+}
+
+
+bool BspNode::IsSibling(BspNode *n) const
+{
+	return  ((this != n) && mParent && 
+			 (mParent->GetFront() == n) || (mParent->GetBack() == n));
+}
+
+
+int BspNode::GetDepth() const
+{
+	int depth = 0;
+	BspNode *p = mParent;
+	
+	while (p)
+	{
+		p = p->mParent;
+		++ depth;
+	}
+
+	return depth;
+}
+
+
+bool BspNode::TreeValid() const
+{
+	return mTreeValid;
+}
+
+
+void BspNode::SetTreeValid(const bool v)
+{
+	mTreeValid = v;
+}
+
+
+/****************************************************************/
+/*              class BspInterior implementation                */
+/****************************************************************/
+
+
+BspInterior::BspInterior(const Plane3 &plane): 
+mPlane(plane), mFront(NULL), mBack(NULL)
+{}
+
+BspInterior::~BspInterior() 
+{ 
+	DEL_PTR(mFront); 
+	DEL_PTR(mBack);
+}
+
+bool BspInterior::IsLeaf() const
+{ 
+	return false; 
+}
+
+BspNode *BspInterior::GetBack() 
+{
+	return mBack;
+}
+
+BspNode *BspInterior::GetFront() 
+{
+	return mFront;
+}
+
+Plane3 BspInterior::GetPlane() const
+{
+	return mPlane;
+}
+
+void BspInterior::ReplaceChildLink(BspNode *oldChild, BspNode *newChild) 
+{
+	if (mBack == oldChild)
+		mBack = newChild;
+	else
+		mFront = newChild;
+}
+
+void BspInterior::SetupChildLinks(BspNode *b, BspNode *f) 
+{
+    mBack = b;
+    mFront = f;
+}
+
+/****************************************************************/
+/*                  class BspLeaf implementation                */
+/****************************************************************/
+
+
+BspLeaf::BspLeaf(): mViewCell(NULL), mPvs(NULL)
+{
+}
+
+
+BspLeaf::~BspLeaf()
+{
+	DEL_PTR(mPvs);
+}
+
+
+BspLeaf::BspLeaf(ViewCell *viewCell): 
+mViewCell(viewCell)
+{
+}
+
+
+BspLeaf::BspLeaf(BspInterior *parent): 
+BspNode(parent), mViewCell(NULL), mPvs(NULL)
+{}
+
+
+
+BspLeaf::BspLeaf(BspInterior *parent, ViewCell *viewCell): 
+BspNode(parent), mViewCell(viewCell), mPvs(NULL)
+{
+}
+
+ViewCell *BspLeaf::GetViewCell() const
+{
+	return mViewCell;
+}
+
+void BspLeaf::SetViewCell(ViewCell *viewCell)
+{
+	mViewCell = viewCell;
+}
+
+
+bool BspLeaf::IsLeaf() const 
+{ 
+	return true; 
+}
+
+
+/*********************************************************************/
+/*                       class BspTree implementation                */
+/*********************************************************************/
+
+BspTree::BspTree():  
+mRoot(NULL), 
+mUseAreaForPvs(false),
+mGenerateViewCells(true),
+mTimeStamp(0)
+{
+	Randomize(); // initialise random generator for heuristics
+
+	mOutOfBoundsCell = GetOrCreateOutOfBoundsCell();
+
+	//-- termination criteria for autopartition
+	environment->GetIntValue("BspTree.Termination.maxDepth", mTermMaxDepth);
+	environment->GetIntValue("BspTree.Termination.minPvs", mTermMinPvs);
+	environment->GetIntValue("BspTree.Termination.minPolygons", mTermMinPolys);
+	environment->GetIntValue("BspTree.Termination.minRays", mTermMinRays);
+	environment->GetFloatValue("BspTree.Termination.minProbability", mTermMinProbability);	
+	environment->GetFloatValue("BspTree.Termination.maxRayContribution", mTermMaxRayContribution);
+	environment->GetFloatValue("BspTree.Termination.minAccRayLenght", mTermMinAccRayLength);
+
+	//-- factors for bsp tree split plane heuristics
+	environment->GetFloatValue("BspTree.Factor.verticalSplits", mVerticalSplitsFactor);
+	environment->GetFloatValue("BspTree.Factor.largestPolyArea", mLargestPolyAreaFactor);
+	environment->GetFloatValue("BspTree.Factor.blockedRays", mBlockedRaysFactor);
+	environment->GetFloatValue("BspTree.Factor.leastRaySplits", mLeastRaySplitsFactor);
+	environment->GetFloatValue("BspTree.Factor.balancedRays", mBalancedRaysFactor);
+	environment->GetFloatValue("BspTree.Factor.pvs", mPvsFactor);
+	environment->GetFloatValue("BspTree.Factor.leastSplits" , mLeastSplitsFactor);
+	environment->GetFloatValue("BspTree.Factor.balancedPolys", mBalancedPolysFactor);
+	environment->GetFloatValue("BspTree.Factor.balancedViewCells", mBalancedViewCellsFactor);
+	environment->GetFloatValue("BspTree.Termination.ct_div_ci", mCtDivCi);
+
+	//-- termination criteria for axis aligned split
+	environment->GetFloatValue("BspTree.Termination.AxisAligned.ct_div_ci", mAxisAlignedCtDivCi);
+	environment->GetFloatValue("BspTree.Termination.maxCostRatio", mMaxCostRatio);
+	environment->GetIntValue("BspTree.Termination.AxisAligned.minPolys", 
+							 mTermMinPolysForAxisAligned);
+	environment->GetIntValue("BspTree.Termination.AxisAligned.minRays", 
+							 mTermMinRaysForAxisAligned);
+	environment->GetIntValue("BspTree.Termination.AxisAligned.minObjects", 
+							 mTermMinObjectsForAxisAligned);
+	//-- partition criteria
+	environment->GetIntValue("BspTree.maxPolyCandidates", mMaxPolyCandidates);
+	environment->GetIntValue("BspTree.maxRayCandidates", mMaxRayCandidates);
+	environment->GetIntValue("BspTree.splitPlaneStrategy", mSplitPlaneStrategy);
+	environment->GetFloatValue("BspTree.AxisAligned.splitBorder", mSplitBorder);
+	environment->GetIntValue("BspTree.maxTests", mMaxTests);
+	environment->GetIntValue("BspTree.Termination.maxViewCells", mMaxViewCells);
+
+	environment->GetFloatValue("BspTree.Construction.epsilon", mEpsilon);
+
+	mSubdivisionStats.open("subdivisionStats.log");
+
+    Debug << "BSP max depth: " << mTermMaxDepth << endl;
+	Debug << "BSP min PVS: " << mTermMinPvs << endl;
+	Debug << "BSP min probability: " << mTermMinProbability << endl;
+	Debug << "BSP max polys: " << mTermMinPolys << endl;
+	Debug << "BSP max rays: " << mTermMinRays << endl;
+	Debug << "BSP max polygon candidates: " << mMaxPolyCandidates << endl;
+	Debug << "BSP max plane candidates: " << mMaxRayCandidates << endl;
+
+	Debug << "Split plane strategy: ";
+	if (mSplitPlaneStrategy & RANDOM_POLYGON)
+		Debug << "random polygon ";
+	if (mSplitPlaneStrategy & AXIS_ALIGNED)
+		Debug << "axis aligned ";
+	if (mSplitPlaneStrategy & LEAST_SPLITS)     
+		Debug << "least splits ";
+	if (mSplitPlaneStrategy & BALANCED_POLYS)
+		Debug << "balanced polygons ";
+	if (mSplitPlaneStrategy & BALANCED_VIEW_CELLS)
+		Debug << "balanced view cells ";
+	if (mSplitPlaneStrategy & LARGEST_POLY_AREA)
+		Debug << "largest polygon area ";
+	if (mSplitPlaneStrategy & VERTICAL_AXIS)
+		Debug << "vertical axis ";
+	if (mSplitPlaneStrategy & BLOCKED_RAYS)
+		Debug << "blocked rays ";
+	if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
+		Debug << "least ray splits ";
+	if (mSplitPlaneStrategy & BALANCED_RAYS)
+		Debug << "balanced rays ";
+	if (mSplitPlaneStrategy & PVS)
+		Debug << "pvs";
+
+	Debug << endl;
+}
+
+
+const BspTreeStatistics &BspTree::GetStatistics() const 
+{
+	return mStat;
+}
+
+
+int BspTree::SplitPolygons(const Plane3 &plane,
+						   PolygonContainer &polys, 
+						   PolygonContainer &frontPolys, 
+						   PolygonContainer &backPolys, 
+						   PolygonContainer &coincident) const
+{
+	int splits = 0;
+
+#ifdef _Debug
+	Debug << "splitting polygons of node " << this << " with plane " << mPlane << endl;
+#endif
+	PolygonContainer::const_iterator it, it_end = polys.end();
+
+	for (it = polys.begin(); it != polys.end(); ++ it)	
+	{
+		Polygon3 *poly = *it;
+	
+		//-- classify polygon
+		const int cf = poly->ClassifyPlane(plane, mEpsilon);
+
+		switch (cf)
+		{
+			case Polygon3::COINCIDENT:
+				coincident.push_back(poly);
+				break;			
+			case Polygon3::FRONT_SIDE:	
+				frontPolys.push_back(poly);
+				break;
+			case Polygon3::BACK_SIDE:
+				backPolys.push_back(poly);
+				break;
+			case Polygon3::SPLIT:
+				{
+					Polygon3 *front_piece = new Polygon3(poly->mParent);
+					Polygon3 *back_piece = new Polygon3(poly->mParent);
+
+					//-- split polygon into front and back part
+					poly->Split(plane, 
+								*front_piece, 
+								*back_piece,
+								mEpsilon);
+					
+					++ splits; // increase number of splits
+
+					//-- inherit rays from parent polygon for blocked ray criterium
+					poly->InheritRays(*front_piece, *back_piece);
+				
+					// check if polygons still valid 
+					if (front_piece->Valid(mEpsilon))
+						frontPolys.push_back(front_piece);
+					else
+						DEL_PTR(front_piece);
+				
+					if (back_piece->Valid(mEpsilon))
+						backPolys.push_back(back_piece);
+					else				
+						DEL_PTR(back_piece);
+				
+#ifdef _DEBUG
+					Debug << "split " << *poly << endl << *front_piece << endl << *back_piece << endl;
+#endif
+					DEL_PTR(poly);
+				}
+				break;
+			default:
+                Debug << "SHOULD NEVER COME HERE\n";
+				break;
+		}
+	}
+
+	return splits;
+}
+
+
+void BspTreeStatistics::Print(ostream &app) const
+{
+	app << "===== BspTree statistics ===============\n";
+
+	app << setprecision(4);
+
+	app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
+
+	app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
+
+	app << "#N_INTERIORS ( Number of interior nodes )\n" << Interior() << "\n";
+
+	app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
+
+	app << "#N_POLYSPLITS ( Number of polygon splits )\n" << polySplits << "\n";
+
+	app << "#AXIS_ALIGNED_SPLITS (number of axis aligned splits)\n" << splits[0] + splits[1] + splits[2] << endl;
+
+	app << "#N_SPLITS ( Number of splits in axes x y z\n";
+
+	for (int i = 0; i < 3; ++ i)
+		app << splits[i] << " ";
+	app << endl;
+
+	app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maximum depth )\n" 
+		<<	maxDepthNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMINPVSLEAVES  ( Percentage of leaves with mininimal PVS )\n" 
+		<< minPvsNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMINRAYSLEAVES  ( Percentage of leaves with minimal number of rays)\n" 
+		<< minRaysNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_MAXCOSTNODES  ( Percentage of leaves with terminated because of max cost ratio )\n"
+		<< maxCostNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMINPROBABILITYLEAVES  ( Percentage of leaves with mininum probability )\n"
+		<< minProbabilityNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMAXRAYCONTRIBLEAVES  ( Percentage of leaves with maximal ray contribution )\n" 
+		<<	maxRayContribNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth << endl;
+
+	app << "#N_PMINDEPTH ( Minimal reached depth )\n" << minDepth << endl;
+
+	app << "#AVGDEPTH ( average depth )\n" << AvgDepth() << endl;
+
+	app << "#N_INPUTPOLYGONS (number of input polygons )\n" << polys << endl;
+
+	app << "#N_INVALIDLEAVES (number of invalid leaves )\n" << invalidLeaves << endl;
+
+	app << "#N_RAYS (number of rays / leaf)\n" << AvgRays() << endl;
+	//app << "#N_PVS: " << pvs << endl;
+
+	app << "#N_ROUTPUT_INPUT_POLYGONS ( ratio polygons after subdivision / input polygons )\n" <<
+		 (polys + polySplits) / (double)polys << endl;
+	
+	app << "===== END OF BspTree statistics ==========\n";
+}
+
+
+BspTree::~BspTree()
+{
+	DEL_PTR(mRoot);
+
+	// TODO must be deleted if used!!
+	//if (mGenerateViewCells) DEL_PTR(mOutOfBoundsCell);
+}
+
+BspViewCell *BspTree::GetOutOfBoundsCell()
+{
+	return mOutOfBoundsCell;
+}
+
+
+BspNode *BspTree::GetRoot() const
+{
+	return mRoot;
+}
+
+BspViewCell *BspTree::GetOrCreateOutOfBoundsCell()
+{
+	if (!mOutOfBoundsCell)
+	{
+		mOutOfBoundsCell = new BspViewCell();
+		mOutOfBoundsCell->SetId(-1);
+		mOutOfBoundsCell->SetValid(false);
+	}
+
+	return mOutOfBoundsCell;
+}
+
+
+void BspTree::InsertViewCell(ViewCell *viewCell)
+{
+	PolygonContainer *polys = new PolygonContainer();
+
+	// don't generate new view cell, insert this one
+	mGenerateViewCells = false;
+	// extract polygons that guide the split process
+	mStat.polys += AddMeshToPolygons(viewCell->GetMesh(), *polys, viewCell);
+	mBox.Include(viewCell->GetBox()); // add to BSP aabb
+
+	InsertPolygons(polys);
+}
+
+
+void BspTree::InsertPolygons(PolygonContainer *polys)
+{	
+	BspTraversalStack tStack;
+
+	// traverse existing tree or create new tree
+    if (!mRoot)
+		mRoot = new BspLeaf();
+
+	tStack.push(BspTraversalData(mRoot, 
+								 polys, 
+								 0, 
+								 mOutOfBoundsCell, 
+								 new BoundedRayContainer(), 
+								 0, 
+								 mUseAreaForPvs ? mBox.SurfaceArea() : mBox.GetVolume(), 
+								 new BspNodeGeometry()));
+
+	while (!tStack.empty())
+	{
+		// filter polygons donw the tree
+		BspTraversalData tData = tStack.top();
+	    tStack.pop();
+			
+		if (!tData.mNode->IsLeaf())
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(tData.mNode);
+
+			//-- filter view cell polygons down the tree until a leaf is reached
+			if (!tData.mPolygons->empty())
+			{
+				PolygonContainer *frontPolys = new PolygonContainer();
+				PolygonContainer *backPolys = new PolygonContainer();
+				PolygonContainer coincident;
+
+				int splits = 0;
+		
+				// split viewcell polygons with respect to split plane
+				splits += SplitPolygons(interior->GetPlane(),
+										*tData.mPolygons, 
+										*frontPolys, 
+										*backPolys, 
+										coincident);
+				
+				// extract view cells associated with the split polygons
+				ViewCell *frontViewCell = GetOrCreateOutOfBoundsCell();
+				ViewCell *backViewCell = GetOrCreateOutOfBoundsCell();
+			
+				BspTraversalData frontData(interior->GetFront(), 
+										   frontPolys, 
+										   tData.mDepth + 1,
+										   mOutOfBoundsCell,	
+										   tData.mRays,
+										   tData.mPvs,
+										   mUseAreaForPvs ? mBox.SurfaceArea() : mBox.GetVolume(), 
+										   new BspNodeGeometry());
+
+				BspTraversalData backData(interior->GetBack(), 
+										  backPolys,
+										  tData.mDepth + 1,
+										  mOutOfBoundsCell,	
+										  tData.mRays,
+										  tData.mPvs,
+										   mUseAreaForPvs ? mBox.SurfaceArea() : mBox.GetVolume(), 
+										  new BspNodeGeometry());
+
+				if (!mGenerateViewCells)
+				{
+					ExtractViewCells(frontData,
+									 backData,
+									 coincident,
+									 interior->mPlane);
+				}
+
+				// don't need coincident polygons anymore
+				CLEAR_CONTAINER(coincident);
+
+				mStat.polySplits += splits;
+
+				// push the children on the stack
+				tStack.push(frontData);
+				tStack.push(backData);
+			}
+
+			// cleanup
+			DEL_PTR(tData.mPolygons);
+			DEL_PTR(tData.mRays);
+		}
+		else
+		{
+			// reached leaf => subdivide current viewcell
+			BspNode *subRoot = Subdivide(tStack, tData);
+		}
+	}
+}
+
+int BspTree::AddMeshToPolygons(Mesh *mesh, 
+							   PolygonContainer &polys, 
+							   MeshInstance *parent)
+{
+	FaceContainer::const_iterator fi;
+	
+	// copy the face data to polygons
+	for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi)
+	{
+		Polygon3 *poly = new Polygon3((*fi), mesh);
+		
+		if (poly->Valid(mEpsilon))
+		{
+			poly->mParent = parent; // set parent intersectable
+			polys.push_back(poly);
+		}
+		else
+			DEL_PTR(poly);
+	}
+	return (int)mesh->mFaces.size();
+}
+
+
+int BspTree::AddToPolygonSoup(const ViewCellContainer &viewCells, 
+							  PolygonContainer &polys, 
+							  int maxObjects)
+{
+	int limit = (maxObjects > 0) ? 
+		Min((int)viewCells.size(), maxObjects) : (int)viewCells.size();
+  
+	int polysSize = 0;
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		if (viewCells[i]->GetMesh()) // copy the mesh data to polygons
+		{
+			mBox.Include(viewCells[i]->GetBox()); // add to BSP tree aabb
+			polysSize += AddMeshToPolygons(viewCells[i]->GetMesh(), polys, viewCells[i]);
+		}
+	}
+
+	return polysSize;
+}
+
+
+int BspTree::AddToPolygonSoup(const ObjectContainer &objects,
+							  PolygonContainer &polys, 
+							  int maxObjects,
+							  bool addToBbox)
+{
+	int limit = (maxObjects > 0) ? 
+		Min((int)objects.size(), maxObjects) : (int)objects.size();
+  
+	for (int i = 0; i < limit; ++i)
+	{
+		Intersectable *object = objects[i];//*it;
+		Mesh *mesh = NULL;
+
+		switch (object->Type()) // extract the meshes
+		{
+		case Intersectable::MESH_INSTANCE:
+			mesh = dynamic_cast<MeshInstance *>(object)->GetMesh();
+			break;
+		case Intersectable::VIEW_CELL:
+			mesh = dynamic_cast<ViewCell *>(object)->GetMesh();
+			break;
+			// TODO: handle transformed mesh instances
+		default:
+			Debug << "intersectable type not supported" << endl;
+			break;
+		}
+		
+        if (mesh) // copy the mesh data to polygons
+		{
+			if (addToBbox)
+			{
+				mBox.Include(object->GetBox()); // add to BSP tree aabb
+			}
+		
+			AddMeshToPolygons(mesh, polys, mOutOfBoundsCell);
+		}
+	}
+
+	return (int)polys.size();
+}
+
+
+void BspTree::Construct(const ViewCellContainer &viewCells)
+{
+	mStat.nodes = 1;
+	mBox.Initialize(); 	// initialise bsp tree bounding box
+
+ 	// copy view cell meshes into one big polygon soup
+	PolygonContainer *polys = new PolygonContainer();
+	mStat.polys = AddToPolygonSoup(viewCells, *polys);
+
+	// view cells are given
+	mGenerateViewCells = false;
+	// construct tree from the view cell polygons
+	Construct(polys, new BoundedRayContainer());
+}
+
+
+void BspTree::Construct(const ObjectContainer &objects)
+{
+	mStat.nodes = 1;
+	mBox.Initialize(); 	// initialise bsp tree bounding box
+	
+	PolygonContainer *polys = new PolygonContainer();
+
+	mGenerateViewCells = true;
+	// copy mesh instance polygons into one big polygon soup
+	mStat.polys = AddToPolygonSoup(objects, *polys);
+
+	// construct tree from polygon soup
+	Construct(polys, new BoundedRayContainer());
+}
+
+
+void BspTree::Construct(const RayContainer &sampleRays,
+						AxisAlignedBox3 *forcedBoundingBox)
+{
+    mStat.nodes = 1;
+	mBox.Initialize(); 	// initialise BSP tree bounding box
+	
+	if (forcedBoundingBox)
+		mBox = *forcedBoundingBox;
+
+	PolygonContainer *polys = new PolygonContainer();
+	BoundedRayContainer *rays = new BoundedRayContainer();
+
+	RayContainer::const_iterator rit, rit_end = sampleRays.end();
+
+	// generate view cells
+	mGenerateViewCells = true;
+
+	long startTime = GetTime();
+
+	Debug << "**** Extracting polygons from rays ****\n";
+
+	std::map<Face *, Polygon3 *> facePolyMap;
+
+	//-- extract polygons intersected by the rays
+	for (rit = sampleRays.begin(); rit != rit_end; ++ rit)
+	{
+		Ray *ray = *rit;
+	
+		// get ray-face intersection. Store polygon representing the rays together
+		// with rays intersecting the face.
+		if (!ray->intersections.empty())
+		{
+			MeshInstance *obj = dynamic_cast<MeshInstance *>(ray->intersections[0].mObject);
+			Face *face = obj->GetMesh()->mFaces[ray->intersections[0].mFace];
+
+			std::map<Face *, Polygon3 *>::iterator it = facePolyMap.find(face);
+
+			if (it != facePolyMap.end()) 
+			{
+				//store rays if needed for heuristics
+				if (mSplitPlaneStrategy & BLOCKED_RAYS)
+					(*it).second->mPiercingRays.push_back(ray);
+			} 
+			else
+			{	//store rays if needed for heuristics
+				Polygon3 *poly = new Polygon3(face, obj->GetMesh());
+				poly->mParent = obj;
+				polys->push_back(poly);
+
+				if (mSplitPlaneStrategy & BLOCKED_RAYS)
+					poly->mPiercingRays.push_back(ray);
+
+				facePolyMap[face] = poly;
+			}
+		}
+	}
+	
+	facePolyMap.clear();
+
+	// compute bounding box
+	if (!forcedBoundingBox)
+		Polygon3::IncludeInBox(*polys, mBox);
+
+	//-- store rays
+	for (rit = sampleRays.begin(); rit != rit_end; ++ rit)
+	{
+		Ray *ray = *rit;
+        ray->SetId(-1); // reset id
+
+		float minT, maxT;
+		if (mBox.GetRaySegment(*ray, minT, maxT))
+			rays->push_back(new BoundedRay(ray, minT, maxT));
+	}
+
+	mStat.polys = (int)polys->size();
+
+	Debug << "**** Finished polygon extraction ****" << endl;
+	Debug << (int)polys->size() << " polys extracted from " << (int)sampleRays.size() << " rays" << endl;
+	Debug << "extraction time: " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
+
+	Construct(polys, rays);
+}
+
+
+void BspTree::Construct(const ObjectContainer &objects, 
+						const RayContainer &sampleRays,
+						AxisAlignedBox3 *forcedBoundingBox)
+{
+    mStat.nodes = 1;
+	mBox.Initialize(); 	// initialise BSP tree bounding box
+	
+	if (forcedBoundingBox)
+		mBox = *forcedBoundingBox;
+
+	BoundedRayContainer *rays = new BoundedRayContainer();
+	PolygonContainer *polys = new PolygonContainer();
+	
+	mGenerateViewCells = true;
+
+	// copy mesh instance polygons into one big polygon soup
+	mStat.polys = AddToPolygonSoup(objects, *polys, 0, !forcedBoundingBox);
+
+
+	RayContainer::const_iterator rit, rit_end = sampleRays.end();
+
+	//-- store rays
+	for (rit = sampleRays.begin(); rit != rit_end; ++ rit)
+	{
+		Ray *ray = *rit;
+        ray->SetId(-1); // reset id
+
+		float minT, maxT;
+		if (mBox.GetRaySegment(*ray, minT, maxT))
+			rays->push_back(new BoundedRay(ray, minT, maxT));
+	}
+
+	Debug << "tree has " << (int)polys->size() << " polys, " << (int)sampleRays.size() << " rays" << endl;
+	Construct(polys, rays);
+}
+
+
+void BspTree::Construct(PolygonContainer *polys, BoundedRayContainer *rays)
+{
+	BspTraversalStack tStack;
+
+	mRoot = new BspLeaf();
+
+	// constrruct root node geometry
+	BspNodeGeometry *geom = new BspNodeGeometry();
+	ConstructGeometry(mRoot, *geom);
+
+	BspTraversalData tData(mRoot, 
+						   polys, 
+						   0, 
+						   GetOrCreateOutOfBoundsCell(), 
+						   rays, 
+						   ComputePvsSize(*rays), 
+						   mUseAreaForPvs ? geom->GetArea() : geom->GetVolume(), 
+						   geom);
+
+	mTotalCost = tData.mPvs * tData.mProbability / mBox.GetVolume();
+	mTotalPvsSize = tData.mPvs;
+	
+	mSubdivisionStats 
+			<< "#ViewCells\n1\n" <<  endl
+			<< "#RenderCostDecrease\n0\n" << endl 
+			<< "#TotalRenderCost\n" << mTotalCost << endl
+			<< "#AvgRenderCost\n" << mTotalPvsSize << endl;
+
+	tStack.push(tData);
+
+	// used for intermediate time measurements and progress
+	long interTime = GetTime();	
+	int nleaves = 500;
+
+	mStat.Start();
+	cout << "Contructing bsp tree ...\n";
+	long startTime = GetTime();
+	while (!tStack.empty()) 
+	{
+		tData = tStack.top();
+
+	    tStack.pop();
+
+		// subdivide leaf node
+		BspNode *r = Subdivide(tStack, tData);
+
+		if (r == mRoot)
+            Debug << "BSP tree construction time spent at root: " 
+				  << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
+
+		if (mStat.Leaves() >= nleaves)
+		{
+			nleaves += 500;
+			
+			cout << "leaves=" << mStat.Leaves() << endl;
+			Debug << "needed "
+				  << TimeDiff(interTime, GetTime())*1e-3 
+				  << " secs to create 500 leaves" << endl;
+			interTime = GetTime();
+		}
+	}
+
+	cout << "finished\n";
+
+	mStat.Stop();
+}
+
+
+bool BspTree::TerminationCriteriaMet(const BspTraversalData &data) const
+{
+	return 
+		(((int)data.mPolygons->size() <= mTermMinPolys) || 
+		 ((int)data.mRays->size() <= mTermMinRays) ||
+		 (data.mPvs <= mTermMinPvs) ||
+		 (data.mProbability <= mTermMinProbability) ||
+		 (data.mDepth >= mTermMaxDepth) ||
+		 (mStat.Leaves() >= mMaxViewCells) ||
+		 (data.GetAvgRayContribution() > mTermMaxRayContribution));
+}
+
+
+BspNode *BspTree::Subdivide(BspTraversalStack &tStack, BspTraversalData &tData)
+{
+	//-- terminate traversal  
+	if (TerminationCriteriaMet(tData))		
+	{
+		BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode);
+	
+		BspViewCell *viewCell;
+
+		// generate new view cell for each leaf
+		if (mGenerateViewCells)
+			viewCell = new BspViewCell();
+		else
+			// add view cell to leaf
+			viewCell = dynamic_cast<BspViewCell *>(tData.mViewCell);
+		
+		leaf->SetViewCell(viewCell);
+		viewCell->mLeaf = leaf;
+
+		if (mUseAreaForPvs)
+			viewCell->SetArea(tData.mProbability);
+		else
+			viewCell->SetVolume(tData.mProbability);
+		
+		//-- add pvs
+		if (viewCell != mOutOfBoundsCell)
+		{
+			int conSamp = 0, sampCon = 0;
+			AddToPvs(leaf, *tData.mRays, conSamp, sampCon);
+			
+			mStat.contributingSamples += conSamp;
+			mStat.sampleContributions += sampCon;
+		}
+
+		EvaluateLeafStats(tData);
+		
+		//-- clean up
+		
+		// discard polygons
+		CLEAR_CONTAINER(*tData.mPolygons);
+		// discard rays
+		CLEAR_CONTAINER(*tData.mRays);
+
+		DEL_PTR(tData.mPolygons);
+		DEL_PTR(tData.mRays);
+		DEL_PTR(tData.mGeometry);
+
+		return leaf;
+	}
+
+	//-- continue subdivision
+	PolygonContainer coincident;
+	
+	BspTraversalData tFrontData(NULL, new PolygonContainer(), tData.mDepth + 1, mOutOfBoundsCell, 
+								new BoundedRayContainer(), 0, 0, new BspNodeGeometry());
+	BspTraversalData tBackData(NULL, new PolygonContainer(), tData.mDepth + 1, mOutOfBoundsCell, 
+							   new BoundedRayContainer(), 0, 0, new BspNodeGeometry());
+
+	int pvsData = tData.mPvs;
+	float cData = (float)tData.mPvs * tData.mProbability;
+
+	// create new interior node and two leaf nodes
+	BspInterior *interior = 
+		SubdivideNode(tData, tFrontData, tBackData, coincident);
+
+
+	if (1)
+	{
+		float cFront = (float)tFrontData.mPvs * tFrontData.mProbability;
+		float cBack = (float)tBackData.mPvs * tBackData.mProbability;
+		
+		float costDecr = 
+			(cFront + cBack - cData) / mBox.GetVolume();
+
+		
+		mTotalCost += costDecr;
+		mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - pvsData;
+
+		mSubdivisionStats 
+			<< "#ViewCells\n" << mStat.Leaves() << endl
+			<< "#RenderCostDecrease\n" << -costDecr << endl 
+			<< "#TotalRenderCost\n" << mTotalCost << endl
+			<< "#AvgRenderCost\n" << mTotalPvsSize / mStat.Leaves() << endl;
+	}
+
+	// extract view cells from coincident polygons according to plane normal
+    // only if front or back polygons are empty
+	if (!mGenerateViewCells)
+	{
+   		ExtractViewCells(tFrontData,
+						 tBackData,
+						 coincident,
+						 interior->mPlane);			 
+	}
+
+	// don't need coincident polygons anymory
+	CLEAR_CONTAINER(coincident);
+
+	// push the children on the stack
+	tStack.push(tFrontData);
+	tStack.push(tBackData);
+
+	// cleanup
+	DEL_PTR(tData.mNode);
+
+	DEL_PTR(tData.mPolygons);
+	DEL_PTR(tData.mRays);
+	DEL_PTR(tData.mGeometry);		
+	
+	return interior;
+}
+
+void BspTree::ExtractViewCells(BspTraversalData &frontData,
+							   BspTraversalData &backData, 
+							   const PolygonContainer &coincident,
+							   const Plane3 &splitPlane) const
+{
+	// if not empty, tree is further subdivided => don't have to find view cell
+	bool foundFront = !frontData.mPolygons->empty();
+	bool foundBack = !frontData.mPolygons->empty();
+
+	PolygonContainer::const_iterator it = 
+		coincident.begin(), it_end = coincident.end();
+
+	//-- find first view cells in front and back leafs
+	for (; !(foundFront && foundBack) && (it != it_end); ++ it)
+	{
+		if (DotProd((*it)->GetNormal(), splitPlane.mNormal) > 0)
+		{
+			backData.mViewCell = dynamic_cast<ViewCell *>((*it)->mParent);
+			foundBack = true;
+		}
+		else
+		{
+			frontData.mViewCell = dynamic_cast<ViewCell *>((*it)->mParent);
+			foundFront = true;
+		}
+	}
+}
+
+BspInterior *BspTree::SubdivideNode(BspTraversalData &tData,
+									BspTraversalData &frontData,
+									BspTraversalData &backData,
+									PolygonContainer &coincident)
+{
+	mStat.nodes += 2;
+	
+	BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode);
+
+	
+	
+	// select subdivision plane
+	BspInterior *interior = 
+		new BspInterior(SelectPlane(leaf, tData)); 
+	
+	
+#ifdef _DEBUG
+	Debug << interior << endl;
+#endif
+	
+
+	// subdivide rays into front and back rays
+	SplitRays(interior->mPlane, *tData.mRays, *frontData.mRays, *backData.mRays);
+	
+	
+
+	// subdivide polygons with plane
+	mStat.polySplits += SplitPolygons(interior->GetPlane(),
+									  *tData.mPolygons, 
+									  *frontData.mPolygons, 
+									  *backData.mPolygons, 
+									  coincident);
+
+	
+
+    // compute pvs
+	frontData.mPvs = ComputePvsSize(*frontData.mRays);
+	backData.mPvs = ComputePvsSize(*backData.mRays);
+
+	// split geometry and compute area
+	if (1)
+	{
+		tData.mGeometry->SplitGeometry(*frontData.mGeometry, 
+									   *backData.mGeometry, 
+									   interior->mPlane,
+									   mBox,
+									   mEpsilon);
+	
+		
+		if (mUseAreaForPvs)
+		{
+			frontData.mProbability = frontData.mGeometry->GetArea();
+			backData.mProbability = backData.mGeometry->GetArea();
+		}
+		else
+		{
+			frontData.mProbability = frontData.mGeometry->GetVolume();
+			backData.mProbability = tData.mProbability - frontData.mProbability;
+		}
+	}
+
+	//-- create front and back leaf
+
+	BspInterior *parent = leaf->GetParent();
+
+	// replace a link from node's parent
+	if (!leaf->IsRoot())
+	{
+		parent->ReplaceChildLink(leaf, interior);
+		interior->SetParent(parent);
+	}
+	else // new root
+	{
+		mRoot = interior;
+	}
+
+	// and setup child links
+	interior->SetupChildLinks(new BspLeaf(interior), new BspLeaf(interior));
+	
+	frontData.mNode = interior->GetFront();
+	backData.mNode = interior->GetBack();
+	
+	frontData.mNode->mTimeStamp = mTimeStamp;
+	backData.mNode->mTimeStamp = mTimeStamp ++;
+
+	//DEL_PTR(leaf);
+	return interior;
+}
+
+
+void BspTree::SortSplitCandidates(const PolygonContainer &polys, 
+								  const int axis, 
+								  vector<SortableEntry> &splitCandidates) const
+{
+	splitCandidates.clear();
+
+	int requestedSize = 2 * (int)polys.size();
+	// creates a sorted split candidates array  
+	splitCandidates.reserve(requestedSize);
+
+	PolygonContainer::const_iterator it, it_end = polys.end();
+
+	AxisAlignedBox3 box;
+
+	// insert all queries 
+	for(it = polys.begin(); it != it_end; ++ it)
+	{
+		box.Initialize();
+		box.Include(*(*it));
+		
+		splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MIN, box.Min(axis), *it));
+		splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MAX, box.Max(axis), *it));
+	}
+
+	stable_sort(splitCandidates.begin(), splitCandidates.end());
+}
+
+
+float BspTree::BestCostRatio(const PolygonContainer &polys,
+							 const AxisAlignedBox3 &box,
+							 const int axis,
+							 float &position,
+							 int &objectsBack,
+							 int &objectsFront) const
+{
+	vector<SortableEntry> splitCandidates;
+
+	SortSplitCandidates(polys, axis, splitCandidates);
+	
+	// go through the lists, count the number of objects left and right
+	// and evaluate the following cost funcion:
+	// C = ct_div_ci  + (ol + or)/queries
+	
+	int objectsLeft = 0, objectsRight = (int)polys.size();
+	
+	float minBox = box.Min(axis);
+	float maxBox = box.Max(axis);
+	float boxArea = box.SurfaceArea();
+  
+	float minBand = minBox + mSplitBorder * (maxBox - minBox);
+	float maxBand = minBox + (1.0f - mSplitBorder) * (maxBox - minBox);
+	
+	float minSum = 1e20f;
+	vector<SortableEntry>::const_iterator ci, ci_end = splitCandidates.end();
+
+	for(ci = splitCandidates.begin(); ci != ci_end; ++ ci) 
+	{
+		switch ((*ci).type) 
+		{
+			case SortableEntry::POLY_MIN:
+				++ objectsLeft;
+				break;
+			case SortableEntry::POLY_MAX:
+			    -- objectsRight;
+				break;
+			default:
+				break;
+		}
+		
+		if ((*ci).value > minBand && (*ci).value < maxBand) 
+		{
+			AxisAlignedBox3 lbox = box;
+			AxisAlignedBox3 rbox = box;
+			lbox.SetMax(axis, (*ci).value);
+			rbox.SetMin(axis, (*ci).value);
+
+			const float sum = objectsLeft * lbox.SurfaceArea() + 
+					 		  objectsRight * rbox.SurfaceArea();
+      
+			if (sum < minSum) 
+			{
+				minSum = sum;
+				position = (*ci).value;
+
+				objectsBack = objectsLeft;
+				objectsFront = objectsRight;
+			}
+		}
+	}
+  
+	const float oldCost = (float)polys.size();
+	const float newCost = mAxisAlignedCtDivCi + minSum / boxArea;
+	const float ratio = newCost / oldCost;
+
+
+#if 0
+  Debug << "====================" << endl;
+  Debug << "costRatio=" << ratio << " pos=" << position<<" t=" << (position - minBox)/(maxBox - minBox)
+      << "\t o=(" << objectsBack << "," << objectsFront << ")" << endl;
+#endif
+  return ratio;
+}
+
+bool BspTree::SelectAxisAlignedPlane(Plane3 &plane, 
+									 const PolygonContainer &polys) const
+{
+	AxisAlignedBox3 box;
+	box.Initialize();
+	
+	// create bounding box of region
+	Polygon3::IncludeInBox(polys, box);
+        
+	int objectsBack = 0, objectsFront = 0;
+	int axis = 0;
+	float costRatio = MAX_FLOAT;
+	Vector3 position;
+
+	//-- area subdivision
+	for (int i = 0; i < 3; ++ i) 
+	{
+		float p = 0;
+		float r = BestCostRatio(polys, box, i, p, objectsBack, objectsFront);
+		
+		if (r < costRatio)
+		{
+			costRatio = r;
+			axis = i;
+			position = p;
+		}
+	}
+	
+	if (costRatio >= mMaxCostRatio)
+		return false;
+
+	Vector3 norm(0,0,0); norm[axis] = 1.0f;
+	plane = Plane3(norm, position);
+
+	return true;
+}
+
+
+Plane3 BspTree::SelectPlane(BspLeaf *leaf, BspTraversalData &data)
+{
+	if (data.mPolygons->empty() && data.mRays->empty())
+	{
+		Debug << "Warning: No autopartition polygon candidate available\n";
+	
+		// return axis aligned split
+		AxisAlignedBox3 box;
+		box.Initialize();
+	
+		// create bounding box of region
+		Polygon3::IncludeInBox(*data.mPolygons, box);
+
+		const int axis = box.Size().DrivingAxis();
+		const Vector3 position = (box.Min()[axis] + box.Max()[axis]) * 0.5f;
+
+		Vector3 norm(0,0,0); norm[axis] = 1.0f;
+		return Plane3(norm, position);
+	}
+	
+	if ((mSplitPlaneStrategy & AXIS_ALIGNED) &&
+		((int)data.mPolygons->size() > mTermMinPolysForAxisAligned) &&
+		((int)data.mRays->size() > mTermMinRaysForAxisAligned) &&
+		((mTermMinObjectsForAxisAligned < 0) || 
+		 (Polygon3::ParentObjectsSize(*data.mPolygons) > mTermMinObjectsForAxisAligned)))
+	{
+		Plane3 plane;
+		if (SelectAxisAlignedPlane(plane, *data.mPolygons))
+			return plane;
+	}
+
+	// simplest strategy: just take next polygon
+	if (mSplitPlaneStrategy & RANDOM_POLYGON)
+	{
+        if (!data.mPolygons->empty())
+		{
+			Polygon3 *nextPoly = 
+				(*data.mPolygons)[(int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1))];
+			return nextPoly->GetSupportingPlane();
+		}
+		else
+		{
+			const int candidateIdx = (int)RandomValue(0, (Real)((int)data.mRays->size() - 1));
+			BoundedRay *bRay = (*data.mRays)[candidateIdx];
+
+			Ray *ray = bRay->mRay;
+						
+			const Vector3 minPt = ray->Extrap(bRay->mMinT);
+			const Vector3 maxPt = ray->Extrap(bRay->mMaxT);
+
+			const Vector3 pt = (maxPt + minPt) * 0.5;
+
+			const Vector3 normal = ray->GetDir();
+			
+			return Plane3(normal, pt);
+		}
+
+		return Plane3();
+	}
+
+	// use heuristics to find appropriate plane
+	return SelectPlaneHeuristics(leaf, data); 
+}
+
+
+Plane3 BspTree::ChooseCandidatePlane(const BoundedRayContainer &rays) const
+{	
+	const int candidateIdx = (int)RandomValue(0, (Real)((int)rays.size() - 1));
+	BoundedRay *bRay = rays[candidateIdx];
+	Ray *ray = bRay->mRay;
+
+	const Vector3 minPt = ray->Extrap(bRay->mMinT);
+	const Vector3 maxPt = ray->Extrap(bRay->mMaxT);
+
+	const Vector3 pt = (maxPt + minPt) * 0.5;
+
+	const Vector3 normal = ray->GetDir();
+			
+	return Plane3(normal, pt);
+}
+
+Plane3 BspTree::ChooseCandidatePlane2(const BoundedRayContainer &rays) const
+{	
+	Vector3 pt[3];
+	int idx[3];
+	int cmaxT = 0;
+	int cminT = 0;
+	bool chooseMin = false;
+
+	for (int j = 0; j < 3; j ++)
+	{
+		idx[j] = (int)RandomValue(0, Real((int)rays.size() * 2 - 1));
+				
+		if (idx[j] >= (int)rays.size())
+		{
+			idx[j] -= (int)rays.size();		
+			chooseMin = (cminT < 2);
+		}
+		else
+			chooseMin = (cmaxT < 2);
+
+		BoundedRay *bRay = rays[idx[j]];
+		pt[j] = chooseMin ? bRay->mRay->Extrap(bRay->mMinT) : 
+							bRay->mRay->Extrap(bRay->mMaxT);
+	}	
+			
+	return Plane3(pt[0], pt[1], pt[2]);
+}
+
+Plane3 BspTree::ChooseCandidatePlane3(const BoundedRayContainer &rays) const
+{	
+	Vector3 pt[3];
+	
+	int idx1 = (int)RandomValue(0, (Real)((int)rays.size() - 1));
+	int idx2 = (int)RandomValue(0, (Real)((int)rays.size() - 1));
+
+	// check if rays different
+	if (idx1 == idx2)
+		idx2 = (idx2 + 1) % (int)rays.size();
+
+	const BoundedRay *ray1 = rays[idx1];
+	const BoundedRay *ray2 = rays[idx2];
+
+	// normal vector of the plane parallel to both lines
+	const Vector3 norm = 
+		Normalize(CrossProd(ray1->mRay->GetDir(), ray2->mRay->GetDir()));
+
+	const Vector3 orig1 = ray1->mRay->Extrap(ray1->mMinT);
+	const Vector3 orig2 = ray2->mRay->Extrap(ray2->mMinT);
+
+	// vector from line 1 to line 2
+	const Vector3 vd = orig1 - orig2;
+	
+	// project vector on normal to get distance
+	const float dist = DotProd(vd, norm);
+
+	// point on plane lies halfway between the two planes
+	const Vector3 planePt = orig1 + norm * dist * 0.5;
+
+	return Plane3(norm, planePt);
+}
+
+
+Plane3 BspTree::SelectPlaneHeuristics(BspLeaf *leaf, BspTraversalData &data)
+{
+	float lowestCost = MAX_FLOAT;
+	Plane3 bestPlane;
+	// intermediate plane
+	Plane3 plane;
+
+	const int limit = Min((int)data.mPolygons->size(), mMaxPolyCandidates);
+	int maxIdx = (int)data.mPolygons->size();
+	
+	for (int i = 0; i < limit; ++ i)
+	{
+		// assure that no index is taken twice
+		const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx));
+				
+		Polygon3 *poly = (*data.mPolygons)[candidateIdx];
+
+		// swap candidate to the end to avoid testing same plane
+		std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]);
+		//Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)];
+
+		// evaluate current candidate
+		const float candidateCost = 
+			SplitPlaneCost(poly->GetSupportingPlane(), data);
+
+		if (candidateCost < lowestCost)
+		{
+			bestPlane = poly->GetSupportingPlane();
+			lowestCost = candidateCost;
+		}
+	}
+	
+	//-- choose candidate planes extracted from rays
+	for (int i = 0; i < mMaxRayCandidates; ++ i)
+	{
+		plane = ChooseCandidatePlane3(*data.mRays);
+		const float candidateCost = SplitPlaneCost(plane, data);
+
+		if (candidateCost < lowestCost)
+		{
+			bestPlane = plane;	
+			lowestCost = candidateCost;
+		}
+	}
+
+#ifdef _DEBUG
+	Debug << "plane lowest cost: " << lowestCost << endl;
+#endif
+
+	return bestPlane;
+}
+
+
+float BspTree::SplitPlaneCost(const Plane3 &candidatePlane, 
+							  const PolygonContainer &polys) const
+{
+	float val = 0;
+
+	float sumBalancedPolys = 0;
+	float sumSplits = 0;
+	float sumPolyArea = 0;
+	float sumBalancedViewCells = 0;
+	float sumBlockedRays = 0;
+	float totalBlockedRays = 0;
+	//float totalArea = 0;
+	int totalViewCells = 0;
+
+	// need three unique ids for each type of view cell
+	// for balanced view cells criterium
+	ViewCell::NewMail();
+	const int backId = ViewCell::sMailId;
+	ViewCell::NewMail();
+	const int frontId = ViewCell::sMailId;
+	ViewCell::NewMail();
+	const int frontAndBackId = ViewCell::sMailId;
+
+	bool useRand;;
+	int limit;
+
+	// choose test polyongs randomly if over threshold
+	if ((int)polys.size() > mMaxTests)
+	{
+		useRand = true;
+		limit = mMaxTests;
+	}
+	else
+	{
+		useRand = false;
+		limit = (int)polys.size();
+	}
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		const int testIdx = useRand ? (int)RandomValue(0, (Real)(limit - 1)) : i;
+
+		Polygon3 *poly = polys[testIdx];
+
+        const int classification = 
+			poly->ClassifyPlane(candidatePlane, mEpsilon);
+
+		if (mSplitPlaneStrategy & BALANCED_POLYS)
+			sumBalancedPolys += sBalancedPolysTable[classification];
+		
+		if (mSplitPlaneStrategy & LEAST_SPLITS)
+			sumSplits += sLeastPolySplitsTable[classification];
+
+		if (mSplitPlaneStrategy & LARGEST_POLY_AREA)
+		{
+			if (classification == Polygon3::COINCIDENT)
+				sumPolyArea += poly->GetArea();
+			//totalArea += area;
+		}
+		
+		if (mSplitPlaneStrategy & BLOCKED_RAYS)
+		{
+			const float blockedRays = (float)poly->mPiercingRays.size();
+		
+			if (classification == Polygon3::COINCIDENT)
+				sumBlockedRays += blockedRays;
+			
+			totalBlockedRays += blockedRays;
+		}
+
+		// assign view cells to back or front according to classificaion
+		if (mSplitPlaneStrategy & BALANCED_VIEW_CELLS)
+		{
+			MeshInstance *viewCell = poly->mParent;
+		
+			// assure that we only count a view cell 
+			// once for the front and once for the back side of the plane
+			if (classification == Polygon3::FRONT_SIDE)
+			{
+				if ((viewCell->mMailbox != frontId) && 
+					(viewCell->mMailbox != frontAndBackId))
+				{
+					sumBalancedViewCells += 1.0;
+
+					if (viewCell->mMailbox != backId)
+						viewCell->mMailbox = frontId;
+					else
+						viewCell->mMailbox = frontAndBackId;
+					
+					++ totalViewCells;
+				}
+			}
+			else if (classification == Polygon3::BACK_SIDE)
+			{
+				if ((viewCell->mMailbox != backId) &&
+				    (viewCell->mMailbox != frontAndBackId))
+				{
+					sumBalancedViewCells -= 1.0;
+
+					if (viewCell->mMailbox != frontId)
+						viewCell->mMailbox = backId;
+					else
+						viewCell->mMailbox = frontAndBackId; 
+
+					++ totalViewCells;
+				}
+			}
+		}
+	}
+
+	const float polysSize = (float)polys.size() + Limits::Small;
+
+	// all values should be approx. between 0 and 1 so they can be combined
+	// and scaled with the factors according to their importance
+	if (mSplitPlaneStrategy & BALANCED_POLYS)
+		val += mBalancedPolysFactor * fabs(sumBalancedPolys) / polysSize;
+	
+	if (mSplitPlaneStrategy & LEAST_SPLITS)  
+		val += mLeastSplitsFactor * sumSplits / polysSize;
+
+	if (mSplitPlaneStrategy & LARGEST_POLY_AREA) 
+		// HACK: polys.size should be total area so scaling is between 0 and 1
+		val += mLargestPolyAreaFactor * (float)polys.size() / sumPolyArea;
+
+	if (mSplitPlaneStrategy & BLOCKED_RAYS)
+		if (totalBlockedRays != 0)
+			val += mBlockedRaysFactor * (totalBlockedRays - sumBlockedRays) / totalBlockedRays;
+
+	if (mSplitPlaneStrategy & BALANCED_VIEW_CELLS)
+		val += mBalancedViewCellsFactor * fabs(sumBalancedViewCells) / 
+			((float)totalViewCells + Limits::Small);
+	
+	return val;
+}
+
+
+inline void BspTree::GenerateUniqueIdsForPvs()
+{
+	ViewCell::NewMail(); sBackId = ViewCell::sMailId;
+	ViewCell::NewMail(); sFrontId = ViewCell::sMailId;
+	ViewCell::NewMail(); sFrontAndBackId = ViewCell::sMailId;
+}
+
+
+float BspTree::SplitPlaneCost(const Plane3 &candidatePlane, 
+							  const BoundedRayContainer &rays,
+							  const int pvs,
+							  const float probability,
+							  const BspNodeGeometry &cell) const
+{
+	float val = 0;
+
+	float sumBalancedRays = 0;
+	float sumRaySplits = 0;
+
+	int frontPvs = 0;
+	int backPvs = 0;
+
+	// probability that view point lies in child
+	float pOverall = 0;
+	float pFront = 0;
+	float pBack = 0;
+
+	const bool pvsUseLen = false;
+
+	if (mSplitPlaneStrategy & PVS)
+	{
+		// create unique ids for pvs heuristics
+		GenerateUniqueIdsForPvs();
+
+		// construct child geometry with regard to the candidate split plane
+		BspNodeGeometry frontCell;
+		BspNodeGeometry backCell;
+
+		cell.SplitGeometry(frontCell, 
+						   backCell, 
+						   candidatePlane,
+						   mBox,
+						   mEpsilon);
+
+		if (mUseAreaForPvs)
+		{
+			pFront = frontCell.GetArea();
+			pBack = backCell.GetArea();
+		}
+		else
+		{
+			pFront = frontCell.GetVolume();
+			pBack = pOverall - pFront;
+		}
+		
+
+		pOverall = probability;
+	}
+			
+	bool useRand;
+	int limit;
+
+	// choose test polyongs randomly if over threshold
+	if ((int)rays.size() > mMaxTests)
+	{
+		useRand = true;
+		limit = mMaxTests;
+	}
+	else
+	{
+		useRand = false;
+		limit = (int)rays.size();
+	}
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		const int testIdx = useRand ? (int)RandomValue(0, (Real)(limit - 1)) : i;
+	
+		BoundedRay *bRay = rays[testIdx];
+
+		Ray *ray = bRay->mRay;
+		const float minT = bRay->mMinT;
+		const float maxT = bRay->mMaxT;
+
+		Vector3 entP, extP;
+
+		const int cf = 
+			ray->ClassifyPlane(candidatePlane, minT, maxT, entP, extP);
+
+		if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
+		{
+			sumBalancedRays += sBalancedRaysTable[cf];
+		}
+		
+		if (mSplitPlaneStrategy & BALANCED_RAYS)
+		{
+			sumRaySplits += sLeastRaySplitsTable[cf];
+		}
+
+		if (mSplitPlaneStrategy & PVS)
+		{
+			// in case the ray intersects an object
+			// assure that we only count the object 
+			// once for the front and once for the back side of the plane
+			
+			// add the termination object
+			if (!ray->intersections.empty())
+				AddObjToPvs(ray->intersections[0].mObject, cf, frontPvs, backPvs);
+			
+			// add the source object
+			AddObjToPvs(ray->sourceObject.mObject, cf, frontPvs, backPvs);
+		}
+	}
+
+	const float raysSize = (float)rays.size() + Limits::Small;
+
+	if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
+		val += mLeastRaySplitsFactor * sumRaySplits / raysSize;
+
+	if (mSplitPlaneStrategy & BALANCED_RAYS)
+		val += mBalancedRaysFactor * fabs(sumBalancedRays) /  raysSize;
+
+	const float denom = pOverall * (float)pvs * 2.0f + Limits::Small;
+
+	if (mSplitPlaneStrategy & PVS)
+	{
+		val += mPvsFactor * (frontPvs * pFront + (backPvs * pBack)) / denom;
+
+		// give penalty to unbalanced split
+		if (0)
+		if (((pFront * 0.2 + Limits::Small) > pBack) || 
+			(pFront < (pBack * 0.2 + Limits::Small)))
+			val += 0.5;
+	}
+
+	
+#ifdef _DEBUG
+	Debug << "totalpvs: " << pvs << " ptotal: " << pOverall
+		  << " frontpvs: " << frontPvs << " pFront: " << pFront 
+		  << " backpvs: " << backPvs << " pBack: " << pBack << endl << endl;
+#endif
+	
+	return val;
+}
+
+void BspTree::AddObjToPvs(Intersectable *obj,
+						  const int cf,
+						  int &frontPvs,
+						  int &backPvs) const
+{
+	if (!obj)
+		return;
+	// TODO: does this really belong to no pvs?
+	//if (cf == Ray::COINCIDENT) return;
+
+	// object belongs to both PVS
+	const bool bothSides = (cf == Ray::FRONT_BACK) || 
+						   (cf == Ray::BACK_FRONT) ||
+						   (cf == Ray::COINCIDENT);
+
+	if ((cf == Ray::FRONT) || bothSides)
+	{
+		if ((obj->mMailbox != sFrontId) && 
+			(obj->mMailbox != sFrontAndBackId))
+		{
+			++ frontPvs;
+
+			if (obj->mMailbox == sBackId)
+				obj->mMailbox = sFrontAndBackId;	
+			else
+				obj->mMailbox = sFrontId;								
+		}
+	}
+	
+	if ((cf == Ray::BACK) || bothSides)
+	{
+		if ((obj->mMailbox != sBackId) &&
+			(obj->mMailbox != sFrontAndBackId))
+		{
+			++ backPvs;
+
+			if (obj->mMailbox == sFrontId)
+				obj->mMailbox = sFrontAndBackId; 
+			else
+				obj->mMailbox = sBackId;				
+		}
+	}
+}
+
+float BspTree::SplitPlaneCost(const Plane3 &candidatePlane,
+							  BspTraversalData &data) const
+{
+	float val = 0;
+
+	if (mSplitPlaneStrategy & VERTICAL_AXIS)
+	{
+		Vector3 tinyAxis(0,0,0); tinyAxis[mBox.Size().TinyAxis()] = 1.0f;
+		// we put a penalty on the dot product between the "tiny" vertical axis
+		// and the split plane axis
+		val += mVerticalSplitsFactor * 
+			   fabs(DotProd(candidatePlane.mNormal, tinyAxis));
+	}
+
+	// the following criteria loop over all polygons to find the cost value
+	if ((mSplitPlaneStrategy & BALANCED_POLYS)      ||
+		(mSplitPlaneStrategy & LEAST_SPLITS)        ||
+		(mSplitPlaneStrategy & LARGEST_POLY_AREA)   ||
+		(mSplitPlaneStrategy & BALANCED_VIEW_CELLS) ||
+		(mSplitPlaneStrategy & BLOCKED_RAYS))
+	{
+		val += SplitPlaneCost(candidatePlane, *data.mPolygons);
+	}
+
+	// the following criteria loop over all rays to find the cost value
+	if ((mSplitPlaneStrategy & BALANCED_RAYS)      ||
+		(mSplitPlaneStrategy & LEAST_RAY_SPLITS)   ||
+		(mSplitPlaneStrategy & PVS))
+	{
+		val += SplitPlaneCost(candidatePlane, *data.mRays, data.mPvs, 
+							  data.mProbability, *data.mGeometry);
+	}
+
+	// return linear combination of the sums
+	return val;
+}
+
+void BspTree::CollectLeaves(vector<BspLeaf *> &leaves) const
+{
+	stack<BspNode *> nodeStack;
+	nodeStack.push(mRoot);
+ 
+	while (!nodeStack.empty()) 
+	{
+		BspNode *node = nodeStack.top();
+    
+		nodeStack.pop();
+    
+		if (node->IsLeaf()) 
+		{
+			BspLeaf *leaf = (BspLeaf *)node;		
+			leaves.push_back(leaf);
+		} 
+		else 
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			nodeStack.push(interior->GetBack());
+			nodeStack.push(interior->GetFront());
+		}
+	}
+}
+
+
+AxisAlignedBox3 BspTree::GetBoundingBox() const
+{
+	return mBox;
+}
+
+
+void BspTree::EvaluateLeafStats(const BspTraversalData &data)
+{
+	// the node became a leaf -> evaluate stats for leafs
+	BspLeaf *leaf = dynamic_cast<BspLeaf *>(data.mNode);
+
+	// store maximal and minimal depth
+	if (data.mDepth > mStat.maxDepth)
+		mStat.maxDepth = data.mDepth;
+
+	if (data.mDepth < mStat.minDepth)
+		mStat.minDepth = data.mDepth;
+
+	// accumulate depth to compute average depth
+	mStat.accumDepth += data.mDepth;
+	// accumulate rays to compute rays /  leaf
+	mStat.accumRays += (int)data.mRays->size();
+
+	if (data.mDepth >= mTermMaxDepth)
+		++ mStat.maxDepthNodes;
+
+	if (data.mPvs < mTermMinPvs)
+		++ mStat.minPvsNodes;
+
+	if ((int)data.mRays->size() < mTermMinRays)
+		++ mStat.minRaysNodes;
+
+	if (data.GetAvgRayContribution() > mTermMaxRayContribution)
+		++ mStat.maxRayContribNodes;
+	
+	if (data.mProbability <= mTermMinProbability) 
+		++ mStat.minProbabilityNodes;
+
+#ifdef _DEBUG
+	Debug << "BSP stats: "
+		  << "Depth: " << data.mDepth << " (max: " << mTermMaxDepth << "), "
+		  << "PVS: " << data.mPvs << " (min: " << mTermMinPvs << "), "
+		  << "Probability: " << data.mProbability << " (min: " << mTermMinProbability << "), "
+		  << "#polygons: " << (int)data.mPolygons->size() << " (max: " << mTermMinPolys << "), "
+		  << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), " 
+		  << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "=, "
+		  << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl;
+#endif
+}
+
+int
+BspTree::_CastRay(Ray &ray)
+{
+	int hits = 0;
+  
+	stack<BspRayTraversalData> tStack;
+  
+	float maxt, mint;
+
+	if (!mBox.GetRaySegment(ray, mint, maxt))
+		return 0;
+
+	ViewCell::NewMail();
+
+	Vector3 entp = ray.Extrap(mint);
+	Vector3 extp = ray.Extrap(maxt);
+  
+	BspNode *node = mRoot;
+	BspNode *farChild = NULL;
+	
+	while (1)
+	{
+		if (!node->IsLeaf()) 
+		{
+			BspInterior *in = dynamic_cast<BspInterior *>(node);
+			
+			Plane3 splitPlane = in->GetPlane();
+			const int entSide = splitPlane.Side(entp);
+			const int extSide = splitPlane.Side(extp);
+
+			if (entSide < 0)
+			{
+				node = in->GetBack();
+
+				if(extSide <= 0) // plane does not split ray => no far child
+					continue;
+					
+				farChild = in->GetFront(); // plane splits ray
+
+			} else if (entSide > 0)
+			{
+				node = in->GetFront();
+
+				if (extSide >= 0) // plane does not split ray => no far child
+					continue;
+
+				farChild = in->GetBack(); // plane splits ray			
+			}
+			else // ray and plane are coincident
+			{
+				// WHAT TO DO IN THIS CASE ?
+				//break;
+				node = in->GetFront();
+				continue;
+			}
+
+			// push data for far child
+			tStack.push(BspRayTraversalData(farChild, extp, maxt));
+
+			// find intersection of ray segment with plane
+			float t;
+			extp = splitPlane.FindIntersection(ray.GetLoc(), extp, &t);
+			maxt *= t;
+			
+		} else // reached leaf => intersection with view cell
+		{
+			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+      
+			if (!leaf->mViewCell->Mailed())
+			{
+			  //				ray.bspIntersections.push_back(Ray::BspIntersection(maxt, leaf));
+				leaf->mViewCell->Mail();
+				++ hits;
+			}
+			
+   			//-- fetch the next far child from the stack
+			if (tStack.empty())
+				break;
+      
+			entp = extp;
+			mint = maxt; // NOTE: need this?
+
+			if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f)
+				break;
+
+			BspRayTraversalData &s = tStack.top();
+
+			node = s.mNode;
+			extp = s.mExitPoint;
+			maxt = s.mMaxT;
+
+			tStack.pop();
+		}
+	}
+
+	return hits;
+}
+
+
+int BspTree::CastLineSegment(const Vector3 &origin,
+							 const Vector3 &termination,
+							 vector<ViewCell *> &viewcells)
+{
+	int hits = 0;
+	stack<BspRayTraversalData> tStack;
+
+	float mint = 0.0f, maxt = 1.0f;
+
+	Intersectable::NewMail();
+	ViewCell::NewMail();
+
+	Vector3 entp = origin;
+	Vector3 extp = termination;
+
+	BspNode *node = mRoot;
+	BspNode *farChild = NULL;
+
+	while (1) 
+	{
+		if (!node->IsLeaf())  
+		{
+			BspInterior *in = dynamic_cast<BspInterior *>(node);
+		
+			Plane3 splitPlane = in->GetPlane();
+			
+			const int entSide = splitPlane.Side(entp);
+			const int extSide = splitPlane.Side(extp);
+
+			if (entSide < 0) 
+			{
+				node = in->GetBack();
+		
+				if(extSide <= 0) // plane does not split ray => no far child
+					continue;
+		
+				farChild = in->GetFront(); // plane splits ray
+		
+			} 
+			else if (entSide > 0) 
+			{
+				node = in->GetFront();
+			
+				if (extSide >= 0) // plane does not split ray => no far child
+					continue;
+			
+				farChild = in->GetBack(); // plane splits ray			
+			}
+			else // ray and plane are coincident
+			{
+				// WHAT TO DO IN THIS CASE ?
+				//break;
+				node = in->GetFront();
+				continue;
+			}
+		
+			// push data for far child
+			tStack.push(BspRayTraversalData(farChild, extp, maxt));
+		
+			// find intersection of ray segment with plane
+			float t;
+			extp = splitPlane.FindIntersection(origin, extp, &t);
+			maxt *= t;  
+		} 
+		else 
+		{
+			// reached leaf => intersection with view cell
+			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+		
+			if (!leaf->mViewCell->Mailed()) 
+			{
+				viewcells.push_back(leaf->mViewCell);
+				leaf->mViewCell->Mail();
+				hits++;
+			}
+		
+			//-- fetch the next far child from the stack
+			if (tStack.empty())
+				break;
+	    
+			entp = extp;
+			mint = maxt; // NOTE: need this?
+		
+			BspRayTraversalData &s = tStack.top();
+		
+			node = s.mNode;
+			extp = s.mExitPoint;
+			maxt = s.mMaxT;
+		
+			tStack.pop();
+		}
+	}
+	return hits;
+}
+
+
+void BspTree::CollectViewCells(ViewCellContainer &viewCells) const
+{
+	stack<BspNode *> nodeStack;
+	nodeStack.push(mRoot);
+
+	ViewCell::NewMail();
+
+	while (!nodeStack.empty()) 
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+
+		if (node->IsLeaf()) 
+		{
+			ViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->mViewCell;
+
+			if (!viewCell->Mailed()) 
+			{
+				viewCell->Mail();
+				viewCells.push_back(viewCell);
+			}
+		}
+		else 
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			nodeStack.push(interior->GetFront());
+			nodeStack.push(interior->GetBack());
+		}
+	}
+}
+
+
+BspTreeStatistics &BspTree::GetStat()
+{
+	return mStat;
+}
+
+
+float BspTree::AccumulatedRayLength(BoundedRayContainer &rays) const
+{
+	float len = 0;
+
+	BoundedRayContainer::const_iterator it, it_end = rays.end();
+
+	for (it = rays.begin(); it != it_end; ++ it)
+	{
+		len += SqrDistance((*it)->mRay->Extrap((*it)->mMinT), 
+						   (*it)->mRay->Extrap((*it)->mMaxT));
+	}
+
+	return len;
+}
+
+
+int BspTree::SplitRays(const Plane3 &plane,
+					   BoundedRayContainer &rays, 
+					   BoundedRayContainer &frontRays, 
+					   BoundedRayContainer &backRays)
+{
+	int splits = 0;
+	
+	while (!rays.empty())
+	{
+		BoundedRay *bRay = rays.back();
+		Ray *ray = bRay->mRay;
+		float minT = bRay->mMinT;
+		float maxT = bRay->mMaxT;
+
+		rays.pop_back();
+	
+		Vector3 entP, extP;
+
+		const int cf = 
+			ray->ClassifyPlane(plane, minT, maxT, entP, extP);
+		
+		// set id to ray classification
+		ray->SetId(cf);
+
+		switch (cf)
+		{
+		case Ray::COINCIDENT: // TODO: should really discard ray?
+			frontRays.push_back(bRay);
+			//DEL_PTR(bRay);
+			break;
+		case Ray::BACK:
+			backRays.push_back(bRay);
+			break;
+		case Ray::FRONT:
+			frontRays.push_back(bRay);
+			break;
+		case Ray::FRONT_BACK:
+			{
+				// find intersection of ray segment with plane
+				const float t = plane.FindT(ray->GetLoc(), extP);
+				
+				const float newT = t * maxT;
+
+				frontRays.push_back(new BoundedRay(ray, minT, newT));
+				backRays.push_back(new BoundedRay(ray, newT, maxT));
+
+				DEL_PTR(bRay);
+			}
+			break;
+		case Ray::BACK_FRONT:
+			{
+				// find intersection of ray segment with plane
+				const float t = plane.FindT(ray->GetLoc(), extP);
+				const float newT = t * bRay->mMaxT;
+
+				backRays.push_back(new BoundedRay(ray, minT, newT));
+				frontRays.push_back(new BoundedRay(ray, newT, maxT));
+
+				DEL_PTR(bRay);
+
+				++ splits;
+			}
+			break;
+		default:
+			Debug << "Should not come here 4" << endl;
+			break;
+		}
+	}
+
+	return splits;
+}
+
+void BspTree::ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const
+{
+	BspNode *lastNode;
+	do
+	{
+		lastNode = n;
+
+		// want to get planes defining geometry of this node => don't take
+		// split plane of node itself
+		n = n->GetParent();
+		
+		if (n)
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(n);
+			Plane3 halfSpace = dynamic_cast<BspInterior *>(interior)->GetPlane();
+
+            if (interior->GetFront() != lastNode)
+				halfSpace.ReverseOrientation();
+
+			halfSpaces.push_back(halfSpace);
+		}
+	}
+	while (n);
+}
+
+
+
+void BspTree::ConstructGeometry(ViewCell *vc, 
+								BspNodeGeometry &vcGeom) const
+{
+	ViewCellContainer leaves;
+	mViewCellsTree->CollectLeaves(vc, leaves);
+
+	ViewCellContainer::const_iterator it, it_end = leaves.end();
+
+	for (it = leaves.begin(); it != it_end; ++ it)
+	{
+		BspLeaf *l = dynamic_cast<BspViewCell *>(*it)->mLeaf;
+		ConstructGeometry(l, vcGeom);
+	}
+}
+
+
+void BspTree::SetViewCellsManager(ViewCellsManager *vcm)
+{
+	mViewCellsManager = vcm;
+}
+
+
+void BspTree::ConstructGeometry(BspNode *n, BspNodeGeometry &geom) const
+{
+	vector<Plane3> halfSpaces;
+	ExtractHalfSpaces(n, halfSpaces);
+
+	PolygonContainer candidates;
+
+	// bounded planes are added to the polygons (reverse polygons
+	// as they have to be outfacing
+	for (int i = 0; i < (int)halfSpaces.size(); ++ i)
+	{
+		Polygon3 *p = GetBoundingBox().CrossSection(halfSpaces[i]);
+		
+		if (p->Valid(mEpsilon))
+		{
+			candidates.push_back(p->CreateReversePolygon());
+			DEL_PTR(p);
+		}
+	}
+
+	// add faces of bounding box (also could be faces of the cell)
+	for (int i = 0; i < 6; ++ i)
+	{
+		VertexContainer vertices;
+	
+		for (int j = 0; j < 4; ++ j)
+			vertices.push_back(mBox.GetFace(i).mVertices[j]);
+
+		candidates.push_back(new Polygon3(vertices));
+	}
+
+	for (int i = 0; i < (int)candidates.size(); ++ i)
+	{
+		// polygon is split by all other planes
+		for (int j = 0; (j < (int)halfSpaces.size()) && candidates[i]; ++ j)
+		{
+			if (i == j) // polygon and plane are coincident
+				continue;
+
+			VertexContainer splitPts;
+			Polygon3 *frontPoly, *backPoly;
+
+			const int cf = candidates[i]->
+				ClassifyPlane(halfSpaces[j], mEpsilon);
+			
+			switch (cf)
+			{
+				case Polygon3::SPLIT:
+					frontPoly = new Polygon3();
+					backPoly = new Polygon3();
+
+					candidates[i]->Split(halfSpaces[j], 
+										 *frontPoly, 
+										 *backPoly,
+										 mEpsilon);
+
+					DEL_PTR(candidates[i]);
+
+					if (frontPoly->Valid(mEpsilon))
+						candidates[i] = frontPoly;
+					else
+						DEL_PTR(frontPoly);
+
+					DEL_PTR(backPoly);
+					break;
+				case Polygon3::BACK_SIDE:
+					DEL_PTR(candidates[i]);
+					break;
+				// just take polygon as it is
+				case Polygon3::FRONT_SIDE:
+				case Polygon3::COINCIDENT:
+				default:
+					break;
+			}
+		}
+		
+		if (candidates[i])
+			geom.mPolys.push_back(candidates[i]);
+	}
+}
+
+
+typedef pair<BspNode *, BspNodeGeometry *> bspNodePair;
+
+
+int BspTree::FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors,
+						   const bool onlyUnmailed) const
+{
+	stack<bspNodePair> nodeStack;
+	
+	BspNodeGeometry nodeGeom;
+	ConstructGeometry(n, nodeGeom);
+	
+	// split planes from the root to this node
+	// needed to verify that we found neighbor leaf
+	// TODO: really needed?
+	vector<Plane3> halfSpaces;
+	ExtractHalfSpaces(n, halfSpaces);
+
+
+	BspNodeGeometry *rgeom = new BspNodeGeometry();
+	ConstructGeometry(mRoot, *rgeom);
+
+	nodeStack.push(bspNodePair(mRoot, rgeom));
+
+	while (!nodeStack.empty())
+	{
+		BspNode *node = nodeStack.top().first;
+		BspNodeGeometry *geom = nodeStack.top().second;
+	
+		nodeStack.pop();
+
+		if (node->IsLeaf())
+		{
+			// test if this leaf is in valid view space
+			if (node->TreeValid() &&
+				(node != n) && 
+				(!onlyUnmailed || !node->Mailed()))
+			{
+				bool isAdjacent = true;
+
+				if (1)
+				{
+					// test all planes of current node if still adjacent
+					for (int i = 0; (i < halfSpaces.size()) && isAdjacent; ++ i)
+					{
+						const int cf =
+							Polygon3::ClassifyPlane(geom->mPolys,
+													halfSpaces[i],
+													mEpsilon);
+
+						if (cf == Polygon3::BACK_SIDE)
+						{
+							isAdjacent = false;
+						}
+					}
+				}
+				else
+				{
+					// TODO: why is this wrong??
+					// test all planes of current node if still adjacent
+					for (int i = 0; (i < (int)nodeGeom.mPolys.size()) && isAdjacent; ++ i)
+					{
+						Polygon3 *poly = nodeGeom.mPolys[i];
+
+						const int cf =
+							Polygon3::ClassifyPlane(geom->mPolys,
+													poly->GetSupportingPlane(),
+													mEpsilon);
+
+						if (cf == Polygon3::BACK_SIDE)
+						{
+							isAdjacent = false;
+						}
+					}
+				}
+				// neighbor was found
+				if (isAdjacent)
+				{	
+					neighbors.push_back(dynamic_cast<BspLeaf *>(node));
+				}
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			const int cf = Polygon3::ClassifyPlane(nodeGeom.mPolys,
+												   interior->GetPlane(),
+												   mEpsilon);
+			
+			BspNode *front = interior->GetFront();
+			BspNode *back = interior->GetBack();
+            
+			BspNodeGeometry *fGeom = new BspNodeGeometry();
+			BspNodeGeometry *bGeom = new BspNodeGeometry();
+
+			geom->SplitGeometry(*fGeom,
+								*bGeom,
+								interior->GetPlane(),
+								mBox,
+								mEpsilon);
+		
+			if (cf == Polygon3::FRONT_SIDE)
+			{
+				nodeStack.push(bspNodePair(interior->GetFront(), fGeom));
+				DEL_PTR(bGeom);
+			}
+			else
+			{
+				if (cf == Polygon3::BACK_SIDE)
+				{
+					nodeStack.push(bspNodePair(interior->GetBack(), bGeom));
+					DEL_PTR(fGeom);
+				}
+				else
+				{	// random decision
+					nodeStack.push(bspNodePair(front, fGeom));
+					nodeStack.push(bspNodePair(back, bGeom));
+				}
+			}
+		}
+	
+		DEL_PTR(geom);
+	}
+
+	return (int)neighbors.size();
+}
+
+
+BspLeaf *BspTree::GetRandomLeaf(const Plane3 &halfspace)
+{
+    stack<BspNode *> nodeStack;
+  	nodeStack.push(mRoot);
+	
+	int mask = rand();
+  
+	while (!nodeStack.empty()) 
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+	  
+		if (node->IsLeaf()) 
+		{
+			return dynamic_cast<BspLeaf *>(node);
+		} 
+		else 
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+			BspNode *next;
+	
+			BspNodeGeometry geom;
+			// todo: not very efficient: constructs full cell everytime
+			ConstructGeometry(interior, geom);
+
+			const int cf = Polygon3::ClassifyPlane(geom.mPolys, 
+												   halfspace, 
+												   mEpsilon);
+
+			if (cf == Polygon3::BACK_SIDE)
+				next = interior->GetFront();
+			else
+				if (cf == Polygon3::FRONT_SIDE)
+					next = interior->GetFront();
+			else 
+			{
+				// random decision
+				if (mask & 1)
+					next = interior->GetBack();
+				else
+					next = interior->GetFront();
+				mask = mask >> 1;
+			}
+
+			nodeStack.push(next);
+		}
+	}
+	
+	return NULL;
+}
+
+
+BspLeaf *BspTree::GetRandomLeaf(const bool onlyUnmailed)
+{
+	stack<BspNode *> nodeStack;
+	
+	nodeStack.push(mRoot);
+
+	int mask = rand();
+	
+	while (!nodeStack.empty()) 
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+		
+		if (node->IsLeaf()) 
+		{
+			if ( (!onlyUnmailed || !node->Mailed()) )
+				return dynamic_cast<BspLeaf *>(node);
+		}
+		else 
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			// random decision
+			if (mask & 1)
+				nodeStack.push(interior->GetBack());
+			else
+				nodeStack.push(interior->GetFront());
+
+			mask = mask >> 1;
+		}
+	}
+	
+	return NULL;
+}
+
+
+void BspTree::AddToPvs(BspLeaf *leaf,
+					   const BoundedRayContainer &rays, 
+					   int &sampleContributions,
+					   int &contributingSamples)
+{
+	sampleContributions = 0;
+	contributingSamples = 0;
+
+    BoundedRayContainer::const_iterator it, it_end = rays.end();
+
+	ViewCell *vc = leaf->GetViewCell();
+
+	// add contributions from samples to the PVS
+	for (it = rays.begin(); it != it_end; ++ it)
+	{
+		int contribution = 0;
+		Ray *ray = (*it)->mRay;
+		float relContribution;
+		if (!ray->intersections.empty())
+		  contribution += vc->GetPvs().AddSample(ray->intersections[0].mObject,
+												 1.0f,
+												 relContribution);
+		
+		if (ray->sourceObject.mObject)
+			contribution += vc->GetPvs().AddSample(ray->sourceObject.mObject,
+												   1.0f,
+												   relContribution);
+		
+		if (contribution)
+		{
+			sampleContributions += contribution;
+			++ contributingSamples;
+		}
+
+		//if (ray->mFlags & Ray::STORE_BSP_INTERSECTIONS)
+		//	ray->bspIntersections.push_back(Ray::BspIntersection((*it)->mMinT, this));
+	}
+}
+
+
+int BspTree::ComputePvsSize(const BoundedRayContainer &rays) const
+{
+	int pvsSize = 0;
+
+	BoundedRayContainer::const_iterator rit, rit_end = rays.end();
+
+	Intersectable::NewMail();
+
+	for (rit = rays.begin(); rit != rays.end(); ++ rit)
+	{
+		Ray *ray = (*rit)->mRay;
+		
+		if (!ray->intersections.empty())
+		{
+			if (!ray->intersections[0].mObject->Mailed())
+			{
+				ray->intersections[0].mObject->Mail();
+				++ pvsSize;
+			}
+		}
+		if (ray->sourceObject.mObject)
+		{
+			if (!ray->sourceObject.mObject->Mailed())
+			{
+				ray->sourceObject.mObject->Mail();
+				++ pvsSize;
+			}
+		}
+	}
+
+	return pvsSize;
+}
+
+
+float BspTree::GetEpsilon() const
+{
+	return mEpsilon;
+}
+
+
+int BspTree::CollectMergeCandidates(const vector<BspLeaf *> leaves,
+									vector<MergeCandidate> &candidates)
+{
+	BspLeaf::NewMail();
+	
+	vector<BspLeaf *>::const_iterator it, it_end = leaves.end();
+
+	int numCandidates = 0;
+
+	// find merge candidates and push them into queue
+	for (it = leaves.begin(); it != it_end; ++ it)
+	{
+		BspLeaf *leaf = *it;
+		
+		// the same leaves must not be part of two merge candidates
+		leaf->Mail();
+		vector<BspLeaf *> neighbors;
+		FindNeighbors(leaf, neighbors, true);
+
+		vector<BspLeaf *>::const_iterator nit, nit_end = neighbors.end();
+
+		// TODO: test if at least one ray goes from one leaf to the other
+		for (nit = neighbors.begin(); nit != nit_end; ++ nit)
+		{
+			if ((*nit)->GetViewCell() != leaf->GetViewCell())
+			{
+				MergeCandidate mc(leaf->GetViewCell(), (*nit)->GetViewCell());
+				candidates.push_back(mc);
+
+				++ numCandidates;
+				if ((numCandidates % 1000) == 0)
+				{
+					cout << "collected " << numCandidates << " merge candidates" << endl;
+				}
+			}
+		}
+	}
+
+	Debug << "merge queue: " << (int)candidates.size() << endl;
+	Debug << "leaves in queue: " << numCandidates << endl;
+	
+
+	return (int)leaves.size();
+}
+
+
+int BspTree::CollectMergeCandidates(const VssRayContainer &rays, 
+									vector<MergeCandidate> &candidates)
+{
+	ViewCell::NewMail();
+	long startTime = GetTime();
+	
+	map<BspLeaf *, vector<BspLeaf*> > neighborMap;
+	ViewCellContainer::const_iterator iit;
+
+	int numLeaves = 0;
+	
+	BspLeaf::NewMail();
+
+	for (int i = 0; i < (int)rays.size(); ++ i)
+	{  
+		VssRay *ray = rays[i];
+	
+		// traverse leaves stored in the rays and compare and 
+		// merge consecutive leaves (i.e., the neighbors in the tree)
+		if (ray->mViewCells.size() < 2)
+			continue;
+
+		iit = ray->mViewCells.begin();
+		BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*(iit ++));
+		BspLeaf *leaf = bspVc->mLeaf;
+		
+		// traverse intersections 
+		// consecutive leaves are neighbors => add them to queue
+		for (; iit != ray->mViewCells.end(); ++ iit)
+		{
+			// next pair
+			BspLeaf *prevLeaf = leaf;
+			bspVc = dynamic_cast<BspViewCell *>(*iit);
+            leaf = bspVc->mLeaf;
+
+			// view space not valid or same view cell
+			if (!leaf->TreeValid() || !prevLeaf->TreeValid() ||
+				(leaf->GetViewCell() == prevLeaf->GetViewCell()))
+				continue;
+
+           	vector<BspLeaf *> &neighbors = neighborMap[leaf];
+			
+			bool found = false;
+
+			// both leaves inserted in queue already =>
+			// look if double pair already exists
+			if (leaf->Mailed() && prevLeaf->Mailed())
+			{
+				vector<BspLeaf *>::const_iterator it, it_end = neighbors.end();
+				
+                for (it = neighbors.begin(); !found && (it != it_end); ++ it)
+					if (*it == prevLeaf)
+						found = true; // already in queue
+			}
+		
+			if (!found)
+			{
+				// this pair is not in map yet
+				// => insert into the neighbor map and the queue
+				neighbors.push_back(prevLeaf);
+				neighborMap[prevLeaf].push_back(leaf);
+
+				leaf->Mail();
+				prevLeaf->Mail();
+		
+				MergeCandidate mc(leaf->GetViewCell(), prevLeaf->GetViewCell());
+				
+				candidates.push_back(mc);
+
+				if (((int)candidates.size() % 1000) == 0)
+				{
+					cout << "collected " << (int)candidates.size() << " merge candidates" << endl;
+				}
+			}
+        }
+	}
+
+	Debug << "neighbormap size: " << (int)neighborMap.size() << endl;
+	Debug << "merge queue: " << (int)candidates.size() << endl;
+	Debug << "leaves in queue: " << numLeaves << endl;
+
+
+	//-- collect the leaves which haven't been found by ray casting
+#if 0
+	cout << "finding additional merge candidates using geometry" << endl;
+	vector<BspLeaf *> leaves;
+	CollectLeaves(leaves, true);
+	Debug << "found " << (int)leaves.size() << " new leaves" << endl << endl;
+	CollectMergeCandidates(leaves, candidates);
+#endif
+
+	return numLeaves;
+}
+
+
+
+
+/***************************************************************/
+/*              BspNodeGeometry Implementation                 */
+/***************************************************************/
+
+
+BspNodeGeometry::BspNodeGeometry(const BspNodeGeometry &rhs)
+{
+	mPolys.reserve(rhs.mPolys.size());
+	
+	PolygonContainer::const_iterator it, it_end = rhs.mPolys.end();
+	for (it = rhs.mPolys.begin(); it != it_end; ++ it)
+	{
+		Polygon3 *poly = *it;
+		mPolys.push_back(new Polygon3(*poly));
+	}
+}
+
+
+BspNodeGeometry::~BspNodeGeometry()
+{
+	CLEAR_CONTAINER(mPolys);
+}
+
+
+float BspNodeGeometry::GetArea() const 
+{ 
+	return Polygon3::GetArea(mPolys);
+}
+
+
+float BspNodeGeometry::GetVolume() const
+{
+	//-- compute volume using tetrahedralization of the geometry
+	//   and adding the volume of the single tetrahedrons
+	float volume = 0;
+	const float f = 1.0f / 6.0f;
+
+	PolygonContainer::const_iterator pit, pit_end = mPolys.end();
+
+	// note: can take arbitrary point, e.g., the origin. However,
+	// we rather take the center of mass to prevents precision errors
+	const Vector3 center = CenterOfMass();
+
+	for (pit = mPolys.begin(); pit != pit_end; ++ pit)
+	{
+		Polygon3 *poly = *pit;
+		const Vector3 v0 = poly->mVertices[0] - center;
+
+		for (int i = 1; i < (int)poly->mVertices.size() - 1; ++ i)
+		{
+			const Vector3 v1 = poly->mVertices[i] - center;
+			const Vector3 v2 = poly->mVertices[i + 1] - center;
+
+			volume += f * (DotProd(v0, CrossProd(v1, v2)));
+		}
+	}
+
+	return volume;
+}
+
+
+Vector3 BspNodeGeometry::CenterOfMass() const
+{
+	int n = 0;
+
+	Vector3 center(0,0,0);
+
+	PolygonContainer::const_iterator pit, pit_end = mPolys.end();
+
+	for (pit = mPolys.begin(); pit != pit_end; ++ pit)
+	{
+		Polygon3 *poly = *pit;
+		
+		VertexContainer::const_iterator vit, vit_end = poly->mVertices.end();
+
+		for(vit = poly->mVertices.begin(); vit != vit_end; ++ vit)
+		{
+			center += *vit;
+			++ n;
+		}
+	}
+
+	return center / (float)n;
+}
+
+
+void BspNodeGeometry::AddToMesh(Mesh &mesh)
+{
+	PolygonContainer::const_iterator it, it_end = mPolys.end();
+	
+	for (it = mPolys.begin(); it != mPolys.end(); ++ it)
+	{
+		(*it)->AddToMesh(mesh);
+	}
+}
+
+
+void BspNodeGeometry::SplitGeometry(BspNodeGeometry &front,
+									BspNodeGeometry &back,
+									const Plane3 &splitPlane,
+									const AxisAlignedBox3 &box,
+									const float epsilon) const
+{	
+	// get cross section of new polygon
+	Polygon3 *planePoly = box.CrossSection(splitPlane);
+
+	// split polygon with all other polygons
+	planePoly = SplitPolygon(planePoly, epsilon);
+
+	//-- new polygon splits all other polygons
+	for (int i = 0; i < (int)mPolys.size(); ++ i)
+	{
+		/// don't use epsilon here to get exact split planes
+		const int cf = 
+			mPolys[i]->ClassifyPlane(splitPlane, Limits::Small);
+			
+		switch (cf)
+		{
+			case Polygon3::SPLIT:
+				{
+					Polygon3 *poly = new Polygon3(mPolys[i]->mVertices);
+
+					Polygon3 *frontPoly = new Polygon3();
+					Polygon3 *backPoly = new Polygon3();
+				
+					poly->Split(splitPlane, 
+								*frontPoly, 
+								*backPoly,
+								epsilon);
+
+					DEL_PTR(poly);
+
+					if (frontPoly->Valid(epsilon))
+						front.mPolys.push_back(frontPoly);
+					else
+						DEL_PTR(frontPoly);
+
+					if (backPoly->Valid(epsilon))
+						back.mPolys.push_back(backPoly);
+					else
+						DEL_PTR(backPoly);
+				}
+				
+				break;
+			case Polygon3::BACK_SIDE:
+				back.mPolys.push_back(new Polygon3(mPolys[i]->mVertices));			
+				break;
+			case Polygon3::FRONT_SIDE:
+				front.mPolys.push_back(new Polygon3(mPolys[i]->mVertices));	
+				break;
+			case Polygon3::COINCIDENT:
+				//front.mPolys.push_back(CreateReversePolygon(mPolys[i]));
+				back.mPolys.push_back(new Polygon3(mPolys[i]->mVertices));
+				break;
+			default:
+				break;
+		}
+	}
+
+	//-- finally add the new polygon to the child node geometries
+	if (planePoly)
+	{
+		// add polygon with normal pointing into positive half space to back cell
+		back.mPolys.push_back(planePoly);
+		// add polygon with reverse orientation to front cell
+		front.mPolys.push_back(planePoly->CreateReversePolygon());
+	}
+}
+
+
+Polygon3 *BspNodeGeometry::SplitPolygon(Polygon3 *planePoly,
+										const float epsilon) const
+{
+	if (!planePoly->Valid(epsilon))
+		DEL_PTR(planePoly);
+
+	// polygon is split by all other planes
+	for (int i = 0; (i < (int)mPolys.size()) && planePoly; ++ i)
+	{
+		Plane3 plane = mPolys[i]->GetSupportingPlane();
+
+		/// don't use epsilon here to get exact split planes
+		const int cf = 
+			planePoly->ClassifyPlane(plane, Limits::Small);
+			
+		// split new polygon with all previous planes
+		switch (cf)
+		{
+			case Polygon3::SPLIT:
+				{
+					Polygon3 *frontPoly = new Polygon3();
+					Polygon3 *backPoly = new Polygon3();
+
+					planePoly->Split(plane, 
+									 *frontPoly, 
+									 *backPoly,
+									 epsilon);
+					
+					// don't need anymore
+					DEL_PTR(planePoly);
+					DEL_PTR(frontPoly);
+
+					// back polygon is belonging to geometry
+					if (backPoly->Valid(epsilon))
+						planePoly = backPoly;
+					else
+						DEL_PTR(backPoly);
+				}
+				break;
+			case Polygon3::FRONT_SIDE:
+				DEL_PTR(planePoly);
+                break;
+			// polygon is taken as it is
+			case Polygon3::BACK_SIDE:
+			case Polygon3::COINCIDENT:
+			default:
+				break;
+		}
+	}
+
+	return planePoly;
+}
+
+
+ViewCell *
+BspTree::GetViewCell(const Vector3 &point)
+{
+  if (mRoot == NULL)
+	return NULL;
+  
+
+  stack<BspNode *> nodeStack;
+  nodeStack.push(mRoot);
+  
+  ViewCell *viewcell = NULL;
+  
+  while (!nodeStack.empty())  {
+	BspNode *node = nodeStack.top();
+	nodeStack.pop();
+	
+	if (node->IsLeaf()) {
+	  viewcell = dynamic_cast<BspLeaf *>(node)->mViewCell;
+	  break;
+	} else {
+	  
+	  BspInterior *interior = dynamic_cast<BspInterior *>(node);
+		
+	  // random decision
+	  if (interior->GetPlane().Side(point) < 0)
+		nodeStack.push(interior->GetBack());
+	  else
+		nodeStack.push(interior->GetFront());
+	}
+  }
+  
+  return viewcell;
+}
+
+
+void BspNodeGeometry::IncludeInBox(AxisAlignedBox3 &box)
+{
+	Polygon3::IncludeInBox(mPolys, box);
+}
+
+
+bool BspTree::Export(ofstream &stream)
+{
+	ExportNode(mRoot, stream);
+
+	return true;
+}
+
+
+void BspTree::ExportNode(BspNode *node, ofstream &stream)
+{
+	if (node->IsLeaf())
+	{
+		BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+			
+		int id = -1;
+		if (leaf->GetViewCell() != mOutOfBoundsCell)
+			id = leaf->GetViewCell()->GetId();
+
+		stream << "<Leaf viewCellId=\"" << id << "\" />" << endl;
+	}
+	else
+	{
+		BspInterior *interior = dynamic_cast<BspInterior *>(node);
+	
+		Plane3 plane = interior->GetPlane();
+		stream << "<Interior plane=\"" << plane.mNormal.x << " " 
+			   << plane.mNormal.y << " " << plane.mNormal.z << " " 
+			   << plane.mD << "\">" << endl;
+
+		ExportNode(interior->GetBack(), stream);
+		ExportNode(interior->GetFront(), stream);
+
+		stream << "</Interior>" << endl;
+	}
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h	(revision 613)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h	(revision 613)
@@ -0,0 +1,608 @@
+#ifndef _ViewCell_H__
+#define _ViewCell_H__
+
+#include "Mesh.h"
+#include "Containers.h"
+#include "Ray.h"
+#include "Statistics.h"
+#include "Material.h"
+//namespace GtpVisibilityPreprocessor {
+
+struct Triangle3;
+
+class BspInterior;
+class BspPvs;
+class BspLeaf;
+class VspKdTree;
+class VspKdLeaf;
+class KdLeaf;
+class ViewCellInterior;
+class MergeCandidate;
+class ViewCellsManager;
+
+/** Statistics for a view cell partition.
+*/
+
+class ViewCellsStatistics: public StatisticsBase
+{
+public:
+
+	/// number of view cells
+	int viewCells;
+
+	/// size of the PVS
+	int pvsSize;
+
+	/// largest PVS of all view cells
+	int maxPvs;
+
+	/// smallest PVS of all view cells
+	int minPvs;
+
+	/// view cells with empty PVS
+	int emptyPvs;
+
+	/// number of leaves covering the view space
+	int leaves;
+
+	/// largest number of leaves covered by one view cell
+	int maxLeaves;
+
+	int invalid;
+
+    // Constructor
+	ViewCellsStatistics()
+	{
+		Reset();
+	}
+
+	double AvgLeaves() const {return (double)leaves / (double)viewCells;};
+	double AvgPvs() const {return (double)pvsSize / (double)viewCells;};
+
+	void Reset()
+	{
+		viewCells = 0;
+		pvsSize = 0;
+		maxPvs = 0;
+
+		minPvs = 999999;
+		emptyPvs = 0;
+		leaves = 0;
+		maxLeaves = 0;
+		invalid = 0;
+	}
+
+	void Print(ostream &app) const;
+
+	friend ostream &operator<<(ostream &s, const ViewCellsStatistics &stat)
+	{
+		stat.Print(s);
+		return s;
+	}
+};
+
+
+/**
+	View cell with an optional mesh representation
+*/
+
+
+class ViewCell: public MeshInstance
+{
+public:
+	ViewCell();
+
+	/** Constructor taking a mesh representing the shape of	the viewcell.
+	*/
+	ViewCell(Mesh *mesh);
+
+	/** Default destructor.
+	*/
+	virtual ~ViewCell() {}
+
+	/** Returns Pvs.
+	*/
+	const ObjectPvs &GetPvs() const;
+	ObjectPvs &GetPvs();
+
+	int Type() const;
+
+  void SetParent(ViewCellInterior *parent);
+
+	/** Adds a passing ray to the passing ray container.
+	*/
+	void AddPassingRay(const Ray &ray, const int contributions);
+
+	/** Returns volume of the view cell.
+	*/
+	float GetVolume() const;
+
+	/** Returns area of the view cell.
+	*/
+	float GetArea() const;
+
+	/** Sets the volume of the view cell.
+	*/
+	void SetVolume(float volume);
+	
+	/** Sets the area of the view cell.
+	*/
+	void SetArea(float area);
+
+
+	/** if this view cell is the root of a view cell hierarchy
+	*/
+	bool IsRoot() const;
+
+	/** Returns parent view cell.
+	*/
+	ViewCellInterior *GetParent() const;
+
+	
+	/** Sets the mesh for this view cell.
+	*/
+	void SetMesh(Mesh *mesh);
+
+	void SetValid(const bool valid);
+	bool GetValid() const;
+
+
+  /** set color for visiualizations */
+  void SetColor(const RgbColor &color) {
+	mColor = color;
+  }
+
+  /** get color for visualuzations */
+  RgbColor GetColor() const {
+	return mColor;
+  }
+
+  
+	/// parent view cell in the view cell hierarchy
+	ViewCellInterior *mParent;
+
+	/// Rays piercing this view cell.
+	RayContainer mPiercingRays;
+
+
+	/** if this is a view cell correspending to a leaf in a hierarchy.
+	*/
+	virtual bool IsLeaf() const = 0;
+
+  static bool SmallerPvs(const ViewCell *a,
+						 const ViewCell *b) {
+	return a->GetPvs().GetSize() < b->GetPvs().GetSize();
+  }
+
+
+	void SetMergeCost(const float mergeCost);
+	float GetMergeCost() const;
+	static void NewMail(const int reserve = 1) {
+		sMailId += sReservedMailboxes;
+		sReservedMailboxes = reserve;
+	}
+	void Mail() { mMailbox = sMailId; }
+	bool Mailed() const { return mMailbox == sMailId; }
+
+	void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
+	bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
+
+	int IncMail() { return ++mMailbox - sMailId; }
+
+
+						 
+	// last mail id -> warning not thread safe!
+	// both mailId and mailbox should be unique for each thread!!!
+	static int sMailId;
+	static int sReservedMailboxes;
+	
+	bool mIsActive;
+
+	
+protected:
+
+	/// the potentially visible objects
+	ObjectPvs mPvs;
+
+	float mVolume;
+	float mArea;
+
+	float mMergeCost;
+
+	bool mValid;
+
+  /** color used for consistent visualization */
+  RgbColor mColor;
+};
+
+
+class ViewCellInterior: public ViewCell
+{
+public:
+	ViewCellInterior();
+	~ViewCellInterior();
+
+	ViewCellInterior(Mesh *mesh);
+	
+
+	/** Sets pointer from parent to child and vice versa.
+	*/
+	void SetupChildLink(ViewCell *l);
+	void RemoveChildLink(ViewCell *l);
+	bool IsLeaf() const;
+
+	ViewCellContainer mChildren;
+
+  void SetCost(const float c) {
+	mCost = c;
+  }
+  float GetCost() const {
+	return mCost;
+  }
+  
+protected:
+  /** overall cost resulting from the merge */
+  float mCost;
+};
+
+/**
+	View cell belonging to a hierarchy.
+*/
+template<typename T>
+class ViewCellLeaf: public ViewCell
+{
+public:
+
+	ViewCellLeaf<T>(): mLeaf(NULL) {}
+	ViewCellLeaf<T>(Mesh *mesh):
+		ViewCell(mesh), mLeaf(NULL) {}
+
+	
+
+	bool IsLeaf() const
+	{
+		return true;
+	}
+
+	/// Leaf of some hierarchy which is part of this view cell.
+	T mLeaf;
+};
+
+
+typedef ViewCellLeaf<BspLeaf *> BspViewCell;
+typedef ViewCellLeaf<KdLeaf *> KdViewCell;
+typedef ViewCellLeaf<VspKdLeaf *> VspKdViewCell;
+
+
+
+class ViewCellsTree
+{
+	friend class ViewCellsManager;
+public:
+	ViewCellsTree(ViewCellsManager *vcm);
+	~ViewCellsTree();
+
+	/** Returns number of leaves this view cell consists of.
+	*/
+	int GetSize(ViewCell *vc) const;
+
+	/** Collects leaves corresponding to a view cell.
+	*/
+	void CollectLeaves(ViewCell *vc, ViewCellContainer &leaves) const;
+
+	/** Merges view cells according to some cost heuristics.
+	*/
+	int ConstructMergeTree(const VssRayContainer &rays, const ObjectContainer &objects);
+	
+	/** Refines view cells using shuffling, i.e., border leaves 
+		of two view cells are exchanged if the resulting view cells
+		are tested to be "better" than the old ones.
+		@returns number of refined view cells
+	*/
+	int RefineViewCells(const VssRayContainer &rays, const ObjectContainer &objects);
+
+  /** Assign colors to the viewcells so that they can be renderered interactively without
+	  color flickering.
+  */
+  void AssignRandomColors();
+	/** Updates view cell stats for this particular view cell
+	*/
+	void UpdateViewCellsStats(ViewCell *vc, ViewCellsStatistics &vcStat);
+	
+
+  /** Get costs resulting from each merge step. */
+  void GetCostFunction(vector<float> &costFunction);
+  
+
+	/** Returns optimal set of view cells for a given number of view cells.
+	*/
+	void CollectBestViewCellSet(ViewCellContainer &viewCells, const int numViewCells);
+
+	/** Root of view cells tree.
+	*/
+	ViewCell *GetRoot() const;
+
+	/** Returns pvs of view cell.
+		@note pvs is returned per reference if tree is not compressed,
+		per copy else.
+	*/
+	void GetPvs(ViewCell *vc, ObjectPvs &pvs) const;
+
+	/** Returns pvs size of view cell.
+	*/
+	int GetPvsSize(ViewCell *vc) const;
+
+	/** Returns actual number of object in this pvs and the children.
+	*/
+	int GetNumPvsEntries(ViewCell *vc) const;
+
+	/** Returns memory cost of this view cell.
+	*/
+	float GetMemoryCost(ViewCell *vc) const;
+
+	/** Compresses the pvs of the view cells from the root.
+	*/
+	void CompressViewCellsPvs();
+
+	/** If view cells in this tree have compressed pvs.
+	*/
+	bool IsCompressed() const;
+
+	ViewCell *GetActiveViewCell(ViewCell *vc) const;
+
+	/** Propagates pvs up the tree to the root.
+	*/
+	void PropagateUpPvs(ViewCell *vc);
+
+	bool Export(ofstream &stream);
+
+
+protected:
+
+
+	//////////////////////////////////////////////////////////////
+	//                 merge options                            //
+	//////////////////////////////////////////////////////////////
+	
+
+	/** Returns cost of this leaf according to current heuristics.
+	*/
+	float GetCostHeuristics(ViewCell *vc) const;
+
+	/** Returns cost of leaf.
+	*/
+	float GetRenderCost(ViewCell *vc) const;
+
+	/** Evaluates the merge cost of this merge candidate pair.
+	*/
+	void EvalMergeCost(MergeCandidate &mc) const;
+
+	/** Variance of leaf.
+	*/
+	float GetVariance(ViewCell *vc) const;
+
+	/** Standard deviation of leaf.
+	*/
+	float GetDeviation(ViewCell *vc) const;
+
+	/** Tries to set this merge candidate to valid. 
+		@returns false if both view cells are the same
+	*/
+	bool ValidateMergeCandidate(MergeCandidate &mc) const;
+
+	/** Merge view cells of leaves l1 and l2.
+		@returns difference in pvs size
+	*/
+	ViewCellInterior *MergeViewCells(ViewCell *l, ViewCell *r, int &pvsDiff); //const;
+
+	/** Shuffles, i.e. takes border leaf from view cell 1 and adds it 
+		to view cell 2.
+	*/
+	void ShuffleLeaf(ViewCell *leaf, ViewCellInterior *vc1, ViewCellInterior *vc2) const;	
+		
+	/** Shuffles the leaves, i.e., tests if exchanging
+		the leaves helps in improving the view cells.
+	*/
+	bool ShuffleLeaves(MergeCandidate &mc) const;
+
+	/** Calculates cost for merge of view cell 1 and 2.
+	*/
+	float EvalShuffleCost(ViewCell *leaf, 
+						  ViewCellInterior *vc1, 
+						  ViewCellInterior *vc2) const;
+
+	/** Exports a snapshot of the merged view cells to disc.
+	*/
+	void ExportMergedViewCells(ViewCellContainer &viewCells, 
+							   const ObjectContainer &objects,
+							   const int numNewViewCells);
+
+	/** merge queue must be reset after some time because expected value
+		may not be valid.
+	*/
+	void ResetMergeQueue();
+
+	/** Updates the current top level of view cells.
+		@returns number of newly merged view cells
+	*/
+	int UpdateActiveViewCells(ViewCellContainer &viewCells);
+
+	void PullUpVisibility(ViewCellInterior *interior);
+
+	void CompressViewCellsPvs(ViewCell *root);
+
+	/** Returns memory usage of view cells.
+	*/
+	float GetMemUsage() const;
+	
+	/**
+		Exports single view cell.
+		NOTE: should be in exporter!!
+	*/
+	void ExportViewCell(ViewCell *viewCell, ofstream &stream);
+
+
+
+	/// if the view cell tree hold compressed pvs
+	bool mIsCompressed;
+
+	ViewCellsManager *mViewCellsManager;
+	ViewCell *mRoot;
+
+	/// if merge visualization should be shown
+	bool mExportMergedViewCells;
+
+	
+		
+	ViewCellContainer mMergedViewCells;
+	
+
+	bool mRefineViewCells;
+
+	/// weights between variance and render cost increase (must be between zero and one)
+	float mRenderCostWeight;
+
+	/// overall cost used to normalize cost ratio
+	float mOverallCost;
+	float mExpectedCost;
+    float mDeviation;
+	float mAvgRenderCost;
+
+	int mUseAreaForPvs;
+
+	int mNumActiveViewCells;
+
+	/// minimal number of view cells
+	int mMergeMinViewCells;
+	/// maximal cost ratio for the merge
+	float mMergeMaxCostRatio;
+
+	ofstream mStats;
+
+	typedef priority_queue<MergeCandidate> MergeQueue;
+
+	MergeQueue mMergeQueue;
+
+	float mMaxMemory;
+
+};
+
+
+/**
+	Candidate for leaf merging based on priority.
+*/
+class MergeCandidate
+{  
+	friend class ViewCellsTree;
+
+public:
+
+	MergeCandidate(ViewCell *l, ViewCell *r);
+
+	/** If this merge pair is still valid.
+	*/
+	bool IsValid() const;
+
+	
+	friend bool operator<(const MergeCandidate &leafa, const MergeCandidate &leafb)
+	{
+		return leafb.GetMergeCost() < leafa.GetMergeCost();
+	}
+
+	void SetLeftViewCell(ViewCell *l);
+	void SetRightViewCell(ViewCell *l);
+
+	ViewCell *GetLeftViewCell() const;
+	ViewCell *GetRightViewCell() const;
+
+	ViewCell *GetInitialLeftViewCell() const;
+	ViewCell *GetInitialRightViewCell() const;
+
+	/** Returns the increase of the standard deviation of this merge candidate.
+	*/
+	float GetDeviationIncr() const;
+
+	/** Merge cost of this candidate pair.
+	*/
+	float GetMergeCost() const;
+
+	/** Render cost of this candidate.
+	*/
+	float GetRenderCost() const;
+	
+	static float sRenderCostWeight;
+
+protected:
+
+	/// render cost increase by this merge
+	float mRenderCost;
+	/// increase / decrease of standard deviation
+	float mDeviationIncr;
+
+	ViewCell *mLeftViewCell;
+	ViewCell *mRightViewCell;
+
+	ViewCell *mInitialLeftViewCell;
+	ViewCell *mInitialRightViewCell;
+};
+
+
+class MergeStatistics: public StatisticsBase
+{
+public:
+	
+	int merged;
+	int siblings;
+	int candidates;
+	int nodes;
+
+	int accTreeDist;
+	int maxTreeDist;
+	
+	Real collectTime;
+	Real mergeTime;
+
+	Real overallCost;
+
+	Real expectedRenderCost;
+	Real deviation;
+	Real heuristics;
+
+	// Constructor
+	MergeStatistics() 
+	{
+		Reset();
+	}
+	
+	double AvgTreeDist() const {return (double)accTreeDist / (double)merged;}; 
+
+	void Reset() 
+	{
+		nodes = 0;
+		merged = 0;
+		siblings = 0;
+		candidates = 0;
+	
+		accTreeDist = 0;
+		maxTreeDist = 0;
+
+		collectTime = 0;
+		mergeTime = 0;
+		overallCost = 0;
+
+		expectedRenderCost = 0;
+		deviation = 0;
+		heuristics = 0;
+
+	}
+
+	void Print(ostream &app) const;
+
+	friend ostream &operator<<(ostream &s, const MergeStatistics &stat) 
+	{
+		stat.Print(s);
+		return s;
+	} 
+};
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/MutualVisibility.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/MutualVisibility.cpp	(revision 386)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/MutualVisibility.cpp	(revision 386)
@@ -0,0 +1,710 @@
+#include <assert.h>
+#include <stack>
+using namespace std;
+#include "KdTree.h"
+#include "AxisAlignedBox3.h"
+#include "Ray.h"
+#include "MutualVisibility.h"
+#include "Exporter.h"
+#include "Mesh.h"
+#include "Triangle3.h"
+#include "SceneGraph.h"
+
+void
+RayShaft::Init(
+	       const Rectangle3 &source,
+	       const Rectangle3 &target)
+{
+  mDepth = 0;
+  mSource = source;
+  mTarget = target;
+}
+
+
+Vector3
+RayShaft::GetIntersectionPoint(const int rayIndex,
+			       const int depth) const
+{
+  Vector3 origin, direction;
+  Ray ray;
+  GetRaySegment(rayIndex, ray);
+  if (depth >= mSamples[rayIndex].mIntersections.size()) {
+    cerr<<"depth of sample out of limits"<<endl;
+    exit(1);
+  }
+  return ray.Extrap(mSamples[rayIndex].mIntersections[depth].mT);
+}
+
+void
+RayShaft::GetRaySegment(const int i, Ray &ray) const
+{
+  Vector3 origin, direction;
+  GetRay(i, origin, direction);
+  ray.Init(origin, direction, Ray::LINE_SEGMENT);
+  if ( mSamples[i].IsValid() ) {
+    origin = ray.Extrap(mSamples[i].mMinT);
+    direction = ray.Extrap(mSamples[i].mMaxT) - origin;
+    ray.Init(origin, direction, Ray::LINE_SEGMENT);
+  }
+}
+
+void
+RayShaft::GetRay(const int rayIndex,
+		 Vector3 &origin,
+		 Vector3 &direction) const
+{
+  
+  assert(rayIndex < 4);
+  
+  origin = mSource.mVertices[rayIndex];
+  direction = mTarget.mVertices[rayIndex] - origin;
+}
+
+void
+MutualVisibilitySampler::PerformSplit(
+				      const RayShaft &sample,
+				      const bool splitSource,
+				      const int axis,
+				      RayShaft &sample1,
+				      RayShaft &sample2
+				      )
+{
+  
+
+  // split the triangles
+
+  if (splitSource) {
+    sample1.mTarget = sample.mTarget;
+    sample2.mTarget = sample.mTarget;
+    sample.mSource.Split(
+			 axis,
+			 sample1.mSource,
+			 sample2.mSource);
+  } else {
+    
+    sample1.mSource = sample.mSource;
+    sample2.mSource = sample.mSource;
+    
+    sample.mTarget.Split(
+			 axis,
+			 sample1.mTarget,
+			 sample2.mTarget);
+  }
+  
+  // split the intersections
+  switch (axis) {
+  case 0:
+    sample1.mSamples[0].mIntersections = sample.mSamples[0].mIntersections;
+    sample1.mSamples[3].mIntersections = sample.mSamples[3].mIntersections;
+    
+    sample2.mSamples[1].mIntersections = sample.mSamples[1].mIntersections;
+    sample2.mSamples[2].mIntersections = sample.mSamples[2].mIntersections;
+    break;
+
+  case 1:
+    sample1.mSamples[0].mIntersections = sample.mSamples[0].mIntersections;
+    sample1.mSamples[1].mIntersections = sample.mSamples[1].mIntersections;
+
+    sample2.mSamples[2].mIntersections = sample.mSamples[2].mIntersections;
+    sample2.mSamples[3].mIntersections = sample.mSamples[3].mIntersections;
+    break;
+  }
+
+  // the intersections for the new shaft rays will be established
+  // later
+  sample1.mDepth = sample2.mDepth = sample.mDepth+1;
+}
+
+float
+MutualVisibilitySampler::GetSpatialAngle(const RayShaft &shaft,
+					 const Vector3 &point
+					 )
+{
+  const int sampleIndices[]={
+    0,1,2,
+    0,2,3
+  };
+  
+  float sum = 0.0f;
+  int i, j=0;
+
+  if (!shaft.IsValid())
+    return 2.0f*mSolidAngleThreshold;
+
+  for (i=0; i < 2; i++) {
+    Triangle3 triangle(shaft.GetIntersectionPoint(sampleIndices[j++], 0),
+		       shaft.GetIntersectionPoint(sampleIndices[j++], 0),
+		       shaft.GetIntersectionPoint(sampleIndices[j++], 0));
+    sum += triangle.GetSpatialAngle(point);
+  }
+
+  return sum;
+}
+
+
+void
+MutualVisibilitySampler::ComputeError(RayShaft &shaft)
+{
+  // evaluate minimal error which can be achieved by more precise evaluation
+  // if this is above the threshold do not proceed further
+
+  // check whether the samples pierce the same mesh
+  Intersectable::NewMail();
+  int i, j;
+  for (i=0; i < 4; i++) {
+    RaySample *sample = &shaft.mSamples[i];
+    for (j=0; j < sample->mIntersections.size(); j++)
+      sample->mIntersections[j].mObject->Mail();
+  }
+
+  for (i=0; i < 4; i++) {
+    RaySample *sample = &shaft.mSamples[i];
+    for (j=0; j < sample->mIntersections.size(); j++) {
+      if (sample->mIntersections[j].mObject->IncMail() == 4) {
+	cerr<<"T";
+	shaft.mError = 0.0f;
+	return;
+      }
+    }
+  }
+    
+  
+  float maxAngle = GetSpatialAngle(shaft,
+				   shaft.mTarget.GetCenter());
+  
+  for (i=0; i < 3; i++) {
+    float angle = GetSpatialAngle(shaft,
+				  shaft.mTarget.mVertices[i]);
+    if (angle > maxAngle)
+      maxAngle = angle;
+  }
+
+  maxAngle = MAX_FLOAT;
+  shaft.mError = maxAngle;
+}
+
+
+void
+MutualVisibilitySampler::ConstructInitialSamples2(
+						  const AxisAlignedBox3 &source,
+						  const AxisAlignedBox3 &target,
+						  vector<RayShaft *> &samples
+						  )
+{
+  // get all rectangles potentially visible from the source box
+  int i;
+  int sourceMask = 0;
+  for (i=0; i < 8; i++)
+    sourceMask |= source.GetFaceVisibilityMask(target.GetVertex(i));
+
+  // now for each visble source face find all visible target faces
+  for (i=0; i < 6; i++) {
+    Rectangle3 sourceFace = source.GetFace(i);
+    if ( sourceMask &(1<<i) ) {
+      int mask = target.GetFaceVisibilityMask(sourceFace);
+      // construct triangle samples for all visible rectangles
+      for (int j=0; j < 6; j++)
+	if (mask & (1<<j)) {
+	  AddInitialSamples2(sourceFace, target.GetFace(j), samples);
+	}
+    }
+  }
+}
+
+void
+MutualVisibilitySampler::ConstructInitialSamples3(
+						  const AxisAlignedBox3 &source,
+						  const AxisAlignedBox3 &target,
+						  vector<RayShaft *> &samples
+						  )
+{
+  // get all rectangles potentially visible from the source box
+  int i;
+  int sourceMask = 0;
+  for (i=0; i < 8; i++)
+    sourceMask |= source.GetFaceVisibilityMask(target.GetVertex(i));
+
+  // now for each visble source face find all visible target faces
+  int face;
+  for (face=0; face < 6; face++) {
+    if ( sourceMask & (1<<face) ) {
+      Rectangle3 sourceRect = source.GetFace(face);
+
+      Vector3 targetCenter = target.Center();
+      
+      Vector3 normal = sourceRect.GetNormal();
+      
+      Plane3 sourcePlane(normal, sourceRect.GetVertex(0));
+      
+      Plane3 targetPlane(normal, target.GetVertex(0));
+
+      int i;
+      for (i=1; i < 8; i++) {
+	Vector3 v = target.GetVertex(i);
+	if (targetPlane.Distance(v) < 0)
+	  targetPlane = Plane3(normal, v);
+      }
+  
+      Vector3 xBasis = Normalize(sourceRect.GetVertex(1) - sourceRect.GetVertex(0));
+      Vector3 yBasis = Normalize(sourceRect.GetVertex(3) - sourceRect.GetVertex(0));
+
+      // cast rays between the centers of the boxes
+      Vector3 targetRCenter = targetPlane.FindIntersection(sourceRect.GetCenter(),
+							   targetCenter);
+      
+      Rectangle3 targetRect;
+      
+      float targetDist[4];
+      targetDist[0] = targetDist[1] = targetDist[2] = targetDist[3] = 0.0f;
+      
+      // cast rays between corresponding vertices of the boxes
+      int j;
+      int intersections=0;
+      for (i=0; i < 4; i++)
+	for (j=0; j < 8; j++) {
+	  Vector3 v;
+	  Vector3 diff;
+	  bool coplanar;
+	  float dist;
+	  
+	  v = targetPlane.FindIntersection(sourceRect.GetVertex(i),
+					   target.GetVertex(j),
+					   NULL,
+					   &coplanar);
+	  if (!coplanar) {
+	    // evaluate target and 
+	    diff = targetRCenter - v;
+	    dist = DotProd(diff, xBasis);
+	    if (dist < targetDist[0])
+	      targetDist[0] = dist;
+	    if (dist > targetDist[1])
+	      targetDist[1] = dist;
+
+	    dist = DotProd(diff, yBasis);
+
+	    if (dist < targetDist[2])
+	      targetDist[2] = dist;
+	    if (dist > targetDist[3])
+	      targetDist[3] = dist;
+	    intersections++;
+	  }
+	}
+      
+      if (intersections>=4) {
+	targetRect.mVertices[0] = targetRCenter + targetDist[0]*xBasis + targetDist[2]*yBasis;
+	targetRect.mVertices[1] = targetRCenter + targetDist[1]*xBasis + targetDist[2]*yBasis;
+	targetRect.mVertices[2] = targetRCenter + targetDist[1]*xBasis + targetDist[3]*yBasis;
+	targetRect.mVertices[3] = targetRCenter + targetDist[0]*xBasis + targetDist[3]*yBasis;
+	
+	//	cout<<sourceRect<<targetRect<<endl;
+	AddInitialSamples(sourceRect, targetRect, samples);
+      }
+    }
+  }
+}
+
+void
+MutualVisibilitySampler::ConstructInitialSamples(
+						 const AxisAlignedBox3 &source,
+						 const AxisAlignedBox3 &target,
+						 vector<RayShaft *> &samples
+						 )
+{
+  Vector3 sourceCenter = source.Center();
+  Vector3 targetCenter = target.Center();
+  Vector3 normal = Normalize(sourceCenter - targetCenter );
+  
+  Plane3 sourcePlane(normal, source.GetVertex(0));
+  int i;
+  for (i=1; i < 8; i++) {
+    Vector3 v = source.GetVertex(i);
+    if (sourcePlane.Distance(v) > 0)
+      sourcePlane = Plane3(normal, v);
+  }
+  
+  Plane3 targetPlane(normal, target.GetVertex(0));
+  for (i=1; i < 8; i++) {
+    Vector3 v = target.GetVertex(i);
+    if (targetPlane.Distance(v) < 0)
+      targetPlane = Plane3(normal, v);
+  }
+
+  
+  Vector3 xBasis = CrossProd(Vector3(0,1,0), normal);
+
+  if (Magnitude(xBasis) > 1e-6)
+    xBasis.Normalize();
+  else {
+    xBasis = Normalize(CrossProd(Vector3(0,0,1), normal));
+  }
+
+  Vector3 yBasis = Normalize( CrossProd(normal, xBasis) );
+  // cast rays between the centers of the boxes
+  Vector3 targetRCenter = targetPlane.FindIntersection(sourceCenter,
+						       targetCenter);
+  
+  Vector3 sourceRCenter = sourcePlane.FindIntersection(sourceCenter,
+						       targetCenter);
+  
+
+  Rectangle3 sourceRect;
+  Rectangle3 targetRect;
+
+
+  if (0) {
+  float scale = Magnitude(source.Size())*0.7f;
+  sourceRect.mVertices[0] = sourceRCenter - scale*xBasis - scale*yBasis;
+  sourceRect.mVertices[1] = sourceRCenter + scale*xBasis - scale*yBasis;
+  sourceRect.mVertices[2] = sourceRCenter + scale*xBasis + scale*yBasis;
+  sourceRect.mVertices[3] = sourceRCenter - scale*xBasis + scale*yBasis;
+
+  scale = Magnitude(target.Size())*0.7f;
+  targetRect.mVertices[0] = targetRCenter - scale*xBasis - scale*yBasis;
+  targetRect.mVertices[1] = targetRCenter + scale*xBasis - scale*yBasis;
+  targetRect.mVertices[2] = targetRCenter + scale*xBasis + scale*yBasis;
+  targetRect.mVertices[3] = targetRCenter - scale*xBasis + scale*yBasis;
+  }
+
+
+  float sourceDist[4];
+  float targetDist[4];
+  sourceDist[0] = sourceDist[1] = sourceDist[2] = sourceDist[3] = 0.0f;
+  targetDist[0] = targetDist[1] = targetDist[2] = targetDist[3] = 0.0f;
+
+  // cast rays between corresponding vertices of the boxes
+  int j;
+  for (i=0; i < 8; i++)
+    for (j=0; j < 8; j++) {
+      Vector3 v;
+      Vector3 diff;
+      bool coplanar;
+      float dist;
+      v = sourcePlane.FindIntersection(source.GetVertex(i),
+				       target.GetVertex(j),
+				       NULL,
+				       &coplanar);
+      if (!coplanar) {
+	// evaluate source and 
+	diff = sourceRCenter - v;
+	dist = DotProd(diff, xBasis);
+	if (dist < sourceDist[0])
+	  sourceDist[0] = dist;
+	if (dist > sourceDist[1])
+	  sourceDist[1] = dist;
+
+	dist = DotProd(diff, yBasis);
+	if (dist < sourceDist[2])
+	  sourceDist[2] = dist;
+	if (dist > sourceDist[3])
+	  sourceDist[3] = dist;
+      }
+      
+      v = targetPlane.FindIntersection(source.GetVertex(i),
+				       target.GetVertex(j),
+				       NULL,
+				       &coplanar);
+      if (!coplanar) {
+	// evaluate target and 
+	diff = targetRCenter - v;
+	dist = DotProd(diff, xBasis);
+	if (dist < targetDist[0])
+	  targetDist[0] = dist;
+	if (dist > targetDist[1])
+	  targetDist[1] = dist;
+	dist = DotProd(diff, yBasis);
+	if (dist < targetDist[2])
+	  targetDist[2] = dist;
+	if (dist > targetDist[3])
+	  targetDist[3] = dist;
+      }
+    }
+
+  sourceRect.mVertices[0] = sourceRCenter + sourceDist[0]*xBasis + sourceDist[2]*yBasis;
+  sourceRect.mVertices[1] = sourceRCenter + sourceDist[1]*xBasis + sourceDist[2]*yBasis;
+  sourceRect.mVertices[2] = sourceRCenter + sourceDist[1]*xBasis + sourceDist[3]*yBasis;
+  sourceRect.mVertices[3] = sourceRCenter + sourceDist[0]*xBasis + sourceDist[3]*yBasis;
+
+  targetRect.mVertices[0] = targetRCenter + targetDist[0]*xBasis + targetDist[2]*yBasis;
+  targetRect.mVertices[1] = targetRCenter + targetDist[1]*xBasis + targetDist[2]*yBasis;
+  targetRect.mVertices[2] = targetRCenter + targetDist[1]*xBasis + targetDist[3]*yBasis;
+  targetRect.mVertices[3] = targetRCenter + targetDist[0]*xBasis + targetDist[3]*yBasis;
+
+
+  cout<<sourceRect<<targetRect<<endl;
+  AddInitialSamples(sourceRect, targetRect, samples);
+}
+
+void
+MutualVisibilitySampler::AddInitialSamples(
+					   const Rectangle3 &sourceRect,
+					   const Rectangle3 &targetRect,
+					   vector<RayShaft *> &samples
+					   )
+{
+
+  RayShaft *sample = new RayShaft(sourceRect, 
+				  targetRect);
+  samples.push_back(sample);
+}
+
+void
+MutualVisibilitySampler::AddInitialSamples2(
+					    const Rectangle3 &sourceRect,
+					    const Rectangle3 &targetRect,
+					    vector<RayShaft *> &samples
+					    )
+{
+  // align the rectangles properly
+  Rectangle3 sRect, tRect;
+  if (DotProd(sourceRect.GetNormal(), targetRect.GetNormal()) < -0.99f) {
+    int i;
+    for (i=0; i < 4; i++) {
+      tRect.mVertices[i] = targetRect.mVertices[( 7 - i )%4];
+    }
+    
+    RayShaft *sample = new RayShaft(sourceRect, 
+				    tRect);
+    samples.push_back(sample);
+  }
+  
+  return;
+  
+  float minDist = MAX_FLOAT;
+  int startI;
+  int startJ;
+  int i, j;
+
+  
+  for (i=0; i < 4; i++) {
+    for (j=0; j < 4; j++) {
+      float dist = Distance(sourceRect.mVertices[i], targetRect.mVertices[j]);
+      if (dist < minDist) {
+	minDist = dist;
+	startI = i;
+	startJ = j;
+      }
+    }
+  }
+  for (i=0; i < 4; i++) {
+    sRect.mVertices[i] = sourceRect.mVertices[(startI + i )%4];
+    tRect.mVertices[i] = targetRect.mVertices[(4 + startJ - i )%4];
+  }
+  
+  RayShaft *sample = new RayShaft(sRect, 
+				  tRect);
+  samples.push_back(sample);
+}
+
+
+void
+MutualVisibilitySampler::ExportShafts(vector<RayShaft *> &shafts,
+				      const bool singleFile)
+{
+  static int id = 0;
+  char filename[64];
+  if (id > 20)
+    return;
+  
+  Exporter *exporter = NULL;
+  for (int i=0; i < shafts.size(); i++) {
+    if (!exporter) {
+      if (singleFile)
+	sprintf(filename, "shafts-single-%04d.x3d", id++);
+      else
+	sprintf(filename, "shafts%04d-%02d.x3d", id++, i);
+      exporter = Exporter::GetExporter(filename);
+    }
+    
+    exporter->SetWireframe();
+    //    exporter->ExportScene(mSceneGraph->mRoot);
+
+    exporter->ExportBox(mSource);
+    exporter->ExportBox(mTarget);
+
+    exporter->SetFilled();
+
+
+    RayShaft *shaft = shafts[i];
+    Mesh *mesh = new Mesh;
+    mesh->AddRectangle(shaft->mSource);
+    mesh->AddRectangle(shaft->mTarget);
+    vector<Ray *> rays;
+    for (int j=0; j < 4; j++) {
+      Ray *ray = new Ray;
+      shaft->GetRaySegment(j, *ray);
+      rays.push_back(ray);
+    }
+    
+    Material m = RandomMaterial();
+    exporter->SetForcedMaterial(m);
+    MeshInstance mi(mesh);
+    exporter->ExportIntersectable(&mi);
+    exporter->ExportRays(rays, -1.0f, m.mDiffuseColor);
+    if (!singleFile) {
+      delete exporter;
+      exporter = NULL;
+    }
+  }
+  if (exporter)
+    delete exporter;
+  
+}
+
+int
+MutualVisibilitySampler::CastRays(RayShaft &shaft)
+{
+  Ray ray;
+  int i;
+
+  for (i=0; i < 4; i++)
+    if (!shaft.mSamples[i].IsProcessed()) {
+      Vector3 origin, direction;
+      shaft.GetRay(i, origin, direction);
+      // determine intersections with the boxes
+      ray.Init(origin, direction, Ray::LINE_SEGMENT);
+      float stmin, stmax = 0.0f, ttmin=1.0f, ttmax;
+      bool valid = true;
+      
+      if (mUseBoxes) {
+	if (mSource.GetMinMaxT(ray, &stmin, &stmax) &&
+	    mTarget.GetMinMaxT(ray, &ttmin, &ttmax)) {
+	  shaft.mSamples[i].mMinT = stmax;
+	  shaft.mSamples[i].mMaxT = ttmin;
+	  origin = ray.Extrap(stmax);
+	  direction = ray.Extrap(ttmin) - origin;
+	  // reinit the ray
+	  ray.Init(origin, direction, Ray::LINE_SEGMENT);
+	} else
+	  valid = false;
+      } else {
+	shaft.mSamples[i].mMinT = 0.0f;
+	shaft.mSamples[i].mMaxT = 1.0f;
+      }
+      if (valid) {
+	if (!mKdTree->CastRay(ray)) {
+	  cerr<<"V"<<endl;
+	  return VISIBLE;
+	}
+	shaft.mSamples[i].mIntersections = ray.intersections;
+	cerr<<"I";
+      } else {
+	cerr<<"X";
+	shaft.mSamples[i].SetInvalid();
+      }
+    }
+  return INVISIBLE;
+}
+
+int
+MutualVisibilitySampler::ComputeVisibility()
+{
+  int result = INVISIBLE;
+
+  vector<RayShaft *> shafts;
+  ConstructInitialSamples3(mSource, mTarget, shafts);
+	
+  if (1)
+    ExportShafts(shafts, false);
+
+  stack<RayShaft *> shaftStack;
+  int i;
+  for (i=0; i < shafts.size(); i++)
+    shaftStack.push(shafts[i]);
+
+  shafts.clear();
+  Ray ray;
+  
+// now process the shafts as long as we have something to do
+  while (!shaftStack.empty()) {
+    RayShaft *shaft = shaftStack.top();
+    shaftStack.pop();
+    
+//      // cast a new ray
+//      int triangleSplitEdge = SetupExtremalRay(sample, source, ray);
+    
+    if (CastRays(*shaft) == VISIBLE) {
+      result = VISIBLE;
+      break;
+    }
+		
+    // compute error ....
+    ComputeError(*shaft);
+    cout<<shaft->mDepth<<"|";
+    if (shaft->IsValid())
+      shafts.push_back(shaft);
+
+    if (shaft->mDepth < 10 &&
+				shaft->mError > mSolidAngleThreshold) {
+      
+      // generate 2 new samples
+      RayShaft *newSamples[2];
+      newSamples[0] = new RayShaft;
+      newSamples[1] = new RayShaft;
+      
+      // chose what to split
+      bool splitSource = shaft->mSource.GetArea() > shaft->mTarget.GetArea();
+      int axis;
+      if (splitSource) {
+				axis = shaft->mSource.DominantAxis();
+      } else {
+				axis = shaft->mTarget.DominantAxis();
+      }
+      
+      PerformSplit(*shaft, splitSource, axis, *newSamples[0], *newSamples[1]);
+      //      delete shaft;
+      shaftStack.push(newSamples[0]);
+      shaftStack.push(newSamples[1]);
+    } else {
+      // store a terminal shaft
+    }
+
+  }
+  
+  while (!shaftStack.empty()) {
+    RayShaft *shaft = shaftStack.top();
+    shaftStack.pop();
+    delete shaft;
+  }
+
+  if (0)
+    ExportShafts(shafts, true);
+
+  for (i=0; i < shafts.size(); i++) {
+    delete shafts[i];
+  }
+
+  return result;
+}
+
+MutualVisibilitySampler::MutualVisibilitySampler(SceneGraph *sceneGraph,
+																								 KdTree *kdTree,
+																								 const AxisAlignedBox3 &source,
+																								 const AxisAlignedBox3 &target,
+																								 const float solidAngleThreshold)
+{
+  mSceneGraph = sceneGraph;
+  mKdTree = kdTree;
+  mSource = source;
+  mTarget = target;
+  mUseBoxes = true;
+  mSolidAngleThreshold = solidAngleThreshold;
+}
+  
+
+int
+ComputeBoxVisibility(SceneGraph *sceneGraph,
+										 KdTree *kdTree,
+										 const AxisAlignedBox3 &source,
+										 const AxisAlignedBox3 &target,
+										 const float solidAngleThreshold)
+{
+  MutualVisibilitySampler
+		sampler(sceneGraph, kdTree, source, target, solidAngleThreshold);
+
+  
+  int visibility = sampler.ComputeVisibility();
+
+  return visibility;
+  
+}
+  
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RenderSimulator.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RenderSimulator.cpp	(revision 605)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RenderSimulator.cpp	(revision 605)
@@ -0,0 +1,163 @@
+#include "RenderSimulator.h"
+#include "KdTree.h"
+#include "ViewCellBsp.h"
+#include "ViewCell.h"
+#include "VspBspTree.h"
+#include "VspKdTree.h"
+#include "ViewCellsManager.h"
+
+void SimulationStatistics::Print(ostream &app) const
+{
+	app << "===== Render Simulation statistics ===============\n";
+
+	app << setprecision(4);
+
+	app << "#N_CTIME  ( Simulation time [s] )\n" << Time() << " \n";
+
+	app << "#MAX_COST ( maximal cost of a view cell )\n" << maxCost << "\n";
+
+	app << "#MIN_COST ( minimal cost of a view cell )\n" << minCost << "\n";
+
+	app << "#AVG_RENDER_TIME ( average render time )\n" << avgRenderTime << "\n";
+
+	app << "#AVG_RENDER_TIME_NO_OVERHEAD ( average render time without overhead )\n" 
+		<< avgRtWithoutOverhead << "\n";
+	
+	app << "#VALID_MAX_COST ( maximal cost of a valid view cell )\n" << validMaxCost << "\n";
+
+	app << "#VALID_MIN_COST ( minimal cost of a valid view cell )\n" << validMinCost << "\n";
+
+	app << "#VALID_AVG_RENDER_TIME ( average render time )\n" << validAvgRenderTime << "\n";
+
+	app << "#VALID_AVG_RENDER_TIME_NO_OVERHEAD ( valid average render time without overhead )\n" 
+		<< validAvgRtWithoutOverhead << "\n";
+	
+	app << "===== END OF Render Simulation statistics ==========\n";
+}
+
+RenderSimulator::RenderSimulator(ViewCellsManager *viewCellsManager):
+Renderer(NULL, viewCellsManager),
+mObjRenderCost(0.0f), 
+mVcOverhead(0.0f), 
+mMoveSpeed(0.0f)
+{}
+
+
+RenderSimulator::RenderSimulator(ViewCellsManager *viewCellsManager,
+								 float objRenderCost, 
+								 float vcOverhead, 
+								 float moveSpeed):
+Renderer(NULL, viewCellsManager),
+mObjRenderCost(objRenderCost), 
+mVcOverhead(vcOverhead), 
+mMoveSpeed(moveSpeed)
+{
+}
+
+
+void RenderSimulator::SetObjectRenderCost(const float objRenderCost)
+{
+	mObjRenderCost = objRenderCost;
+}
+
+
+void RenderSimulator::SetVcOverhead(const float vcOverhead)
+{
+	mVcOverhead = vcOverhead;
+}
+
+
+void RenderSimulator::SetMoveSpeed(const float moveSpeed)
+{
+	mMoveSpeed = moveSpeed;
+}
+
+
+bool RenderSimulator::RenderScene()
+{
+	mSimulationStatistics.Reset();
+	mSimulationStatistics.Start();
+
+	Real renderTime = 0;
+	Real validRenderTime = 0;
+
+	// overhead for loading the PVS of the view cells
+	float loadPvsOverhead = 0;
+	float validLoadPvsOverhead = 0;
+
+	ViewCellContainer::const_iterator it, 
+		it_end = mViewCellsManager->GetViewCells().end();
+
+	
+	for (it = mViewCellsManager->GetViewCells().begin(); it != it_end; ++ it)
+	{
+		ViewCell *vc = *it;
+
+		const bool valid = vc->GetValid();
+	
+
+		// probability of view cell
+		const float pInVc = mViewCellsManager->GetProbability(vc);
+
+		//Debug << "vc prob: " << pInVc << endl;
+
+		// compute render time of PVS times probability
+		// that view point is in view cell
+		const float vcCost = pInVc * 
+			mViewCellsManager->GetRendercost(vc, mObjRenderCost);
+	
+		renderTime += vcCost;
+
+		// crossing the border of a view cell is depending on the move 
+		// speed and the probability that a view cell border is crossed
+		loadPvsOverhead += GetCrossVcProbability() * mVcOverhead;
+		
+		//-- update statistics
+
+		if (vcCost > mSimulationStatistics.maxCost)
+			mSimulationStatistics.maxCost = vcCost;
+		else if (vcCost < mSimulationStatistics.minCost)
+			mSimulationStatistics.minCost = vcCost;
+
+		//-- different statistics for only valid view cells
+		if (valid)
+		{
+			validLoadPvsOverhead += GetCrossVcProbability() * mVcOverhead;
+			validRenderTime += vcCost;
+		
+			if (vcCost > mSimulationStatistics.validMaxCost)
+				mSimulationStatistics.validMaxCost = vcCost;
+			else if (vcCost < mSimulationStatistics.validMinCost)
+				mSimulationStatistics.validMinCost = vcCost;
+		}
+	}
+	
+	mSimulationStatistics.avgRtWithoutOverhead = renderTime;
+	mSimulationStatistics.avgRenderTime = renderTime + loadPvsOverhead;
+
+	mSimulationStatistics.validAvgRtWithoutOverhead = renderTime;
+	mSimulationStatistics.validAvgRenderTime = renderTime + loadPvsOverhead;
+	
+	mSimulationStatistics.Stop();
+
+	return true;
+}
+
+
+float RenderSimulator::GetCrossVcProbability() const
+{
+	// assume the view cells are uniformly distributed
+	//NOTE: should I take move speed relative to view space or absolute?
+	const float vcNum = 
+		(float)mViewCellsManager->GetViewCells().size();
+
+	const float prop = mMoveSpeed * vcNum;
+
+	// clamp probability between 0 and 1
+	return min(1.0f, prop);
+}
+
+void RenderSimulator::GetStatistics(SimulationStatistics &simStats) const
+{
+	simStats = mSimulationStatistics;
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SceneGraph.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SceneGraph.cpp	(revision 576)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SceneGraph.cpp	(revision 576)
@@ -0,0 +1,133 @@
+//#include <boost/algorithm/string.hpp>
+
+#include <stack>
+#include "SceneGraph.h"
+#include "X3dExporter.h"
+#include "Intersectable.h"
+
+
+bool
+SceneGraph::Export( const string filename )
+{
+  if (strstr(filename.c_str(), ".x3d")) {
+    X3dExporter exporter(filename);
+    exporter.ExportScene(mRoot);
+    return true;
+  } else {
+    cerr<<"Error: Currently unsuported export format, filename "<<filename<<endl;
+    
+  }
+  
+  
+    return false;
+  
+}
+
+
+int
+SceneGraph::CollectObjects(ObjectContainer *instances)
+{
+	instances->clear();
+  int number = 0;
+  stack<SceneGraphNode *> nodeStack;
+  
+  nodeStack.push(mRoot);
+  
+  while (!nodeStack.empty()) {
+    SceneGraphNode *node = nodeStack.top();
+    nodeStack.pop();
+
+    ObjectContainer::const_iterator mi = node->mGeometry.begin();
+    for (; mi != node->mGeometry.end(); mi++)
+	  instances->push_back(*mi);
+	
+    SceneGraphNodeContainer::iterator ni = node->mChildren.begin();
+    for (; ni != node->mChildren.end(); ni++) {
+      nodeStack.push(*ni);
+      number++;
+    }
+    
+  }
+  return number;
+}
+
+
+int
+SceneGraph::AssignObjectIds()
+{
+  int id = 1;
+  stack<SceneGraphNode *> nodeStack;
+  
+  nodeStack.push(mRoot);
+  
+  while (!nodeStack.empty()) {
+    SceneGraphNode *node = nodeStack.top();
+    nodeStack.pop();
+		
+    ObjectContainer::iterator mi = node->mGeometry.begin();
+    for (; mi != node->mGeometry.end(); mi++) {
+	  // $$ JB remove object id=2601 (for debugging purposes in atlanta scene)
+	  if (1) //id != 2601)
+		(*mi)->SetId(id++);
+	  else {
+		node->mGeometry.erase(mi);
+		--mi;
+		id++;
+	  }
+	}
+    
+    SceneGraphNodeContainer::iterator ni = node->mChildren.begin();
+    for (; ni != node->mChildren.end(); ni++) {
+      nodeStack.push(*ni);
+    }
+  }
+	// return max id
+  return id;
+}
+
+void
+SceneGraph::GetStatistics(int &intersectables, int &faces) const
+{
+  stack<SceneGraphNode *> nodeStack;
+  
+  nodeStack.push(mRoot);
+  faces = 0;
+	intersectables = 0;
+  while (!nodeStack.empty()) {
+    SceneGraphNode *node = nodeStack.top();
+    nodeStack.pop();
+		
+    ObjectContainer::const_iterator mi = node->mGeometry.begin();
+    for (; mi != node->mGeometry.end(); mi++) {
+			intersectables++;
+			faces += (*mi)->NumberOfFaces();
+		}
+    
+    SceneGraphNodeContainer::iterator ni = node->mChildren.begin();
+    for (; ni != node->mChildren.end(); ni++) {
+      nodeStack.push(*ni);
+    }
+  }
+	
+}
+
+
+void
+SceneGraphNode::UpdateBox()
+{
+  AxisAlignedBox3 box;
+  
+  box.Initialize();
+  
+  ObjectContainer::const_iterator mi = mGeometry.begin();
+  for (; mi != mGeometry.end(); mi++)
+	box.Include((*mi)->GetBox());
+  
+  SceneGraphNodeContainer::iterator ni = mChildren.begin();
+  for (; ni != mChildren.end(); ni++) {
+	(*ni)->UpdateBox();
+	box.Include((*ni)->mBox);
+  }
+  
+  mBox = box;
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ExactPreprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ExactPreprocessor.h	(revision 439)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ExactPreprocessor.h	(revision 439)
@@ -0,0 +1,16 @@
+#ifndef _ExactPreprocessor_H__
+#define _ExactPreprocessor_H__
+
+#include "Preprocessor.h"
+
+  /** Exact visibility preprocessing. The implementation is based on 6D BSP and
+      Plucker coordinates */
+  class ExactPreprocessor : public Preprocessor {
+  public:
+    virtual bool ComputeVisibility();
+
+  };
+  
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Polytope.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Polytope.h	(revision 372)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Polytope.h	(revision 372)
@@ -0,0 +1,47 @@
+#ifndef _Polytope_h__
+#define _Polytope_h__
+
+#include "Containers.h"
+
+class Hyperplane;
+
+/** Contains a list of hyperplanes
+*/
+typedef vector<Hyperplane *> HyperplaneContainer;
+
+/** Class representing a polyhedron in 5d projected space.
+*/
+class Polyhedron
+{
+public:
+	Polyhedron() {}
+
+	/** Adds plane to polyhedron equations
+	*/
+	void AddPlane(Hyperplane *plane) {mHyperPlanes.push_back(plane);}
+	/** Returns true if polyhedron is bounded.
+	*/
+	virtual bool IsBounded();
+
+protected:
+
+	/// the hyperplanes define the polyhedron
+	HyperplaneContainer mHyperPlanes;
+};
+
+/** Class representing a polytope (i.e., a bounded polyhedron) in 5d projected space.
+*/
+class Polytope: public Polyhedron
+{
+public:
+	Polytope(const Polyhedron &boundedPoly);
+
+    /** Split polytope into 2 polytopes front and back.
+		@param plane the split plane
+	*/
+	void Split(Hyperplane *plane, Polytope *front, Polytope *back);
+
+	virtual bool IsBounded() {return true;}
+};
+
+#endif // Polytope
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Vector3.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Vector3.cpp	(revision 492)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Vector3.cpp	(revision 492)
@@ -0,0 +1,252 @@
+#include "Matrix4x4.h"
+#include "Vector3.h"
+#include "Halton.h"
+
+// Given min a vector to minimize and a candidate vector, replace
+// elements of min whose corresponding elements in Candidate are
+// smaller.  This function is used for finding objects' bounds,
+// among other things.
+void
+Minimize(Vector3 &min, const Vector3 &Candidate)
+{
+  if (Candidate.x < min.x)
+    min.x = Candidate.x;
+  if (Candidate.y < min.y)
+    min.y = Candidate.y;
+  if (Candidate.z < min.z)
+    min.z = Candidate.z;
+}
+
+// Given min a vector to minimize and a candidate vector, replace
+// elements of min whose corresponding elements in Candidate are
+// larger.  This function is used for finding objects' bounds,
+// among other things.
+void
+Maximize(Vector3 &max, const Vector3 &Candidate)
+{
+  if (Candidate.x > max.x)
+    max.x = Candidate.x;
+  if (Candidate.y > max.y)
+    max.y = Candidate.y;
+  if (Candidate.z > max.z)
+    max.z = Candidate.z;
+}
+
+// Project the vector onto the YZ, XZ, or XY plane depending on which.
+// which      Coordinate plane to project onto
+// 0          YZ
+// 1          XZ
+// 2          XY
+// This function is used by the polygon intersection code.
+
+void
+Vector3::ExtractVerts(float *px, float *py, int which) const
+{
+  switch (which) {
+    case 0:
+      *px = y;
+      *py = z;
+      break;
+    case 1:
+      *px = x;
+      *py = z;
+      break;
+    case 2:
+      *px = x;
+      *py = y;
+      break;
+  }
+}
+
+// returns the axis, where the vector has the largest value
+int
+Vector3::DrivingAxis(void) const
+{
+  int axis = 0;
+  float val = fabs(x);
+
+  if (fabs(y) > val) {
+    val = fabs(y);
+    axis = 1;
+  }
+
+  if (fabs(z) > val)
+    axis = 2;
+
+  return axis;
+}
+
+// returns the axis, where the vector has the smallest value
+int
+Vector3::TinyAxis(void) const
+{
+  int axis = 0;
+  float val = fabs(x);
+
+  if (fabs(y) < val) {
+    val = fabs(y);
+    axis = 1;
+  }
+
+  if (fabs(z) < val)
+    axis = 2;
+
+  return axis;
+}
+
+
+// Construct a view vector ViewN, and the vector ViewU perpendicular
+// to ViewN and lying in the plane given by ViewNxUpl
+// the last vector of ortogonal system is ViewV, that is
+// perpendicular to both ViewN and ViewU. 
+// |ViewN| = |ViewU| = |ViewV| = 1
+// The ViewN vector pierces the center of the synthesized image
+//     ViewU vector goes from the center image rightwards
+//     ViewV vector goes from the center image upwards
+void
+ViewVectors(const Vector3 &DirAt, const Vector3 &Viewer,
+            const Vector3 &UpL, Vector3 &ViewV, Vector3 &ViewU,
+            Vector3 &ViewN)
+{
+  Vector3 U, V, N;
+  Vector3 Up = Normalize(UpL);
+
+  N = -Normalize(DirAt);
+
+  V = Normalize(Up - DirAt);
+  V -= N * DotProd(V, N);
+  V = Normalize(V);
+  U = CrossProd(V, N);
+
+  ViewU = U; // rightwards
+  ViewV = V; // upwards
+  ViewN = -N; // forwards
+#ifdef _DEBUG
+  const float eps = 1e-3;
+  if (fabs(Magnitude(ViewU) - 1.0) > eps) {
+    Debug << "ViewU magnitude error= " << Magnitude(ViewU) << "\n";
+  }
+  if (fabs(Magnitude(ViewV) - 1.0) > eps) {
+    Debug << "ViewU magnitude error= " << Magnitude(ViewV) << "\n";
+  }
+  if (fabs(Magnitude(ViewN) - 1.0) > eps) {
+    Debug << "ViewU magnitude error= " << Magnitude(ViewN) << "\n";
+  }
+#endif // _DEBUG
+
+  return;
+}
+
+// Given the intersection point `P', you have available normal `N'
+// of unit length. Let us suppose the incoming ray has direction `D'.
+// Then we can construct such two vectors `U' and `V' that
+// `U',`N', and `D' are coplanar, and `V' is perpendicular
+// to the vectors `N','D', and `V'. Then 'N', 'U', and 'V' create
+// the orthonormal base in space R3.
+void
+TangentVectors(Vector3 &U,
+	       Vector3 &V, // output
+	       const Vector3 &normal, // input
+	       const Vector3 &dirIncoming)
+{
+#ifdef _DEBUG
+  float d = Magnitude(normal); 
+  if ( (d < 0.99) ||
+       (d > 1.01) ) {
+    Debug << " The normal has not unit length = " << d << endl;
+  }
+  d = Magnitude(dirIncoming); 
+  if ( (d < 0.99) ||
+       (d > 1.01) ) {
+    Debug << " The incoming dir has not unit length = " << d << endl;
+  }
+#endif
+  
+  V = CrossProd(normal, dirIncoming);
+
+  if (SqrMagnitude(V) < 1e-3) {
+    // the normal and dirIncoming are colinear
+    // we can/have to generate arbitrary perpendicular vector to normal.
+    if (fabs(normal.x) < 0.6)
+      V.SetValue(0.0, -normal.z, normal.y);
+    else {
+      if (fabs(normal.y) < 0.6)
+	V.SetValue(-normal.z, 0.0, normal.x);
+      else
+	V.SetValue(-normal.y, normal.x, 0.0);
+    }
+  }
+  V = Normalize(V);
+
+  U = CrossProd(normal, V);
+#ifdef _DEBUG
+  d = SqrMagnitude(U);
+  if ( (d < 0.99) ||
+       (d > 1.01) ) {
+    Debug << "The size of U vector incorrect\n";
+  }
+#endif
+  return;  
+}
+
+Vector3
+UniformRandomVector()
+{
+  //  float r1 = RandomValue(0.0f, 1.0f);
+  //  float r2 = RandomValue(0.0f, 1.0f);
+  float r1, r2;
+	
+  halton2.GetNext(r1, r2);
+	
+	
+  float cosTheta = 1.0f - 2*r1;
+  float sinTheta = sqrt(1 - sqr(cosTheta));
+  float fi = 2.0f*M_PI*r2;
+  
+  Vector3 dir(sinTheta*sin(fi),
+			  cosTheta,
+			  sinTheta*cos(fi));
+  
+  return dir;
+}
+
+Vector3
+UniformRandomVector(const Vector3 &normal)
+{
+  //  float r1 = RandomValue(0.0f, 1.0f);
+  //  float r2 = RandomValue(0.0f, 1.0f);
+  float r1, r2;
+  
+  halton2.GetNext(r1, r2);
+  
+  
+  float cosTheta = 1.0f - r1;
+  float sinTheta = sqrt(1 - sqr(cosTheta));
+  float fi = 2.0f*M_PI*r2;
+  
+  Vector3 dir(sinTheta*sin(fi),
+			  cosTheta,
+			  sinTheta*cos(fi));
+  
+  
+  //  return Normalize(dir);
+  
+  Matrix4x4 m = RotationVectorsMatrix(
+									  normal,
+									  Vector3(0,1,0));
+  Matrix4x4 mi = Invert(m);
+  m = m*RotationVectorsMatrix(
+							  Vector3(0,1,0),
+							  Normalize(dir))*mi;
+  
+  return TransformNormal(m, normal);
+  
+  //    return TransformNormal(
+  //  			 RotationVectorsMatrix(
+  //  					       Vector3(0,1,0),
+  //  					       Normalize(dir)
+  //  					       ),
+  //  			 normal
+  //  			 );
+}
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Halton.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Halton.cpp	(revision 492)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Halton.cpp	(revision 492)
@@ -0,0 +1,7 @@
+
+#include "Halton.h"
+
+// global halton generator
+
+Halton2 halton2;
+float Halton2::_invBases[2];
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 599)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 599)
@@ -0,0 +1,488 @@
+#include "SceneGraph.h"
+#include "Exporter.h"
+#include "UnigraphicsParser.h"
+#include "X3dParser.h"
+#include "Preprocessor.h"
+#include "ViewCell.h"
+#include "Environment.h"
+#include "ViewCellsManager.h"
+#include "ViewCellBsp.h"
+#include "VspBspTree.h"
+#include "VspKdTree.h"
+#include "RenderSimulator.h"
+#include "GlRenderer.h"
+
+Preprocessor *preprocessor;
+
+Preprocessor::Preprocessor():
+mKdTree(NULL),
+mBspTree(NULL),
+mVspKdTree(NULL),
+mVspBspTree(NULL),
+mViewCellsManager(NULL)
+{
+  environment->GetBoolValue("Preprocessor.useGlRenderer", mUseGlRenderer);
+  
+  // renderer will be constructed when the scene graph and viewcell manager will be known
+  renderer = NULL;
+  
+  environment->GetBoolValue("Preprocessor.useGlDebugger", mUseGlDebugger);
+  environment->GetBoolValue("Preprocessor.quitOnFinish", mQuitOnFinish);
+
+}
+
+
+Preprocessor::~Preprocessor()
+{
+  Debug<<"Deleting view cells manager...\n";
+  DEL_PTR(mViewCellsManager);
+  Debug<<"done.\n";
+  Debug<<"Deleting bsp tree...\n";
+  DEL_PTR(mBspTree);
+  Debug<<"done.\n";
+  Debug<<"Deleting kd tree...\n";
+  DEL_PTR(mKdTree);
+  Debug<<"done.\n";
+  Debug<<"Deleting vspkd tree...\n";
+  DEL_PTR(mVspKdTree);
+  Debug<<"done.\n";
+  Debug<<"Deleting vspbsp tree...\n";
+  DEL_PTR(mVspBspTree);
+  Debug<<"done.\n";
+}
+
+int
+SplitFilenames(const string str, vector<string> &filenames)
+{
+	int pos = 0;
+
+	while(1) {
+		int npos = (int)str.find(';', pos);
+		
+		if (npos < 0 || npos - pos < 1)
+			break;
+		filenames.push_back(string(str, pos, npos - pos));
+		pos = npos + 1;
+	}
+	
+	filenames.push_back(string(str, pos, str.size() - pos));
+	return (int)filenames.size();
+}
+
+bool
+Preprocessor::LoadScene(const string filename)
+{
+	// use leaf nodes of the original spatial hiearrchy as occludees
+	mSceneGraph = new SceneGraph;
+  
+	Parser *parser;
+	vector<string> filenames;
+	int files = SplitFilenames(filename, filenames);
+	cout<<files<<endl;
+	bool result = false;
+	if (files == 1) {
+		
+		if (strstr(filename.c_str(), ".x3d"))
+			parser = new X3dParser;
+		else
+			parser = new UnigraphicsParser;
+
+		cout<<filename<<endl;
+		result = parser->ParseFile(filename, &mSceneGraph->mRoot);
+
+		delete parser;
+
+	} else {
+		// root for different files
+		mSceneGraph->mRoot = new SceneGraphNode;
+		for (int i= 0; i < filenames.size(); i++) {
+			if (strstr(filenames[i].c_str(), ".x3d"))
+				parser = new X3dParser;
+			else
+				parser = new UnigraphicsParser;
+			
+			SceneGraphNode *node;
+			if (parser->ParseFile(filenames[i], &node)) {
+				mSceneGraph->mRoot->mChildren.push_back(node);
+				// at least one file parsed
+				result = true;
+			}
+			delete parser;
+		}
+	}
+	
+
+	if (result) {
+	  
+	  mSceneGraph->AssignObjectIds();
+	  int intersectables, faces;
+	  mSceneGraph->GetStatistics(intersectables, faces);
+	  cout<<filename<<" parsed successfully."<<endl;
+	  cout<<"#NUM_OBJECTS (Total numner of objects)\n"<<intersectables<<endl;
+	  cout<<"#NUM_FACES (Total numner of faces)\n"<<faces<<endl;
+	  mSceneGraph->CollectObjects(&mObjects);
+	  mSceneGraph->mRoot->UpdateBox();
+	}
+	
+	
+	return result;
+}
+
+bool
+Preprocessor::ExportPreprocessedData(const string filename)
+{
+  return false;
+}
+
+bool
+Preprocessor::BuildKdTree()
+{
+  mKdTree = new KdTree;
+  // add mesh instances of the scene graph to the root of the tree
+  KdLeaf *root = (KdLeaf *)mKdTree->GetRoot();
+  mSceneGraph->CollectObjects(&root->mObjects);
+  
+  mKdTree->Construct();
+  return true;
+}
+
+void
+Preprocessor::KdTreeStatistics(ostream &s)
+{
+  s<<mKdTree->GetStatistics();
+}
+
+void
+Preprocessor::BspTreeStatistics(ostream &s)
+{
+	s << mBspTree->GetStatistics();
+}
+
+bool
+Preprocessor::Export( const string filename,
+					  const bool scene,
+					  const bool kdtree,
+					  const bool bsptree
+					  )
+{
+  Exporter *exporter = Exporter::GetExporter(filename);
+	
+  if (exporter) {
+    if (scene)
+      exporter->ExportScene(mSceneGraph->mRoot);
+
+    if (kdtree) {
+      exporter->SetWireframe();
+      exporter->ExportKdTree(*mKdTree);
+    }
+
+	if (bsptree) {
+		//exporter->SetWireframe();
+		exporter->ExportBspTree(*mBspTree);
+	}
+
+    delete exporter;
+    return true;
+  }
+
+  return false;
+}
+
+
+bool Preprocessor::PrepareViewCells()
+{
+	//-- parse view cells construction method
+	environment->GetBoolValue("ViewCells.loadFromFile", mLoadViewCells);
+	char buf[100];
+	
+	if (mLoadViewCells)
+	{
+		environment->GetStringValue("ViewCells.filename", buf);
+		mViewCellsManager = ViewCellsManager::LoadViewCells(buf, &mObjects);
+	}
+	else
+	{
+		//-- parse type of view cell container
+		char viewCellsStr[64];
+		environment->GetStringValue("ViewCells.type", viewCellsStr);
+	    mViewCellsManager = CreateViewCellsManager(viewCellsStr);
+	}
+
+	float objRenderCost = 0, vcOverhead = 0, moveSpeed = 0;
+
+	environment->GetFloatValue("Simulation.objRenderCost",objRenderCost);
+	environment->GetFloatValue("Simulation.vcOverhead", vcOverhead);
+	environment->GetFloatValue("Simulation.moveSpeed", moveSpeed);
+
+	mRenderSimulator = 
+		new RenderSimulator(mViewCellsManager, objRenderCost, vcOverhead, moveSpeed);
+
+	mViewCellsManager->SetRenderer(mRenderSimulator);
+
+
+	if (mUseGlRenderer || mUseGlDebugger)
+	{
+		// NOTE: render texture should be power of 2 and square
+		// renderer must be initialised
+		renderer = new GlRendererBuffer(1024, 768, mSceneGraph, mViewCellsManager, mKdTree);
+		//		renderer->makeCurrent();
+	}
+
+
+	environment->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace);
+	
+	return true;
+}
+
+
+ViewCellsManager *Preprocessor::CreateViewCellsManager(const char *name)
+{
+	if (strcmp(name, "kdTree") == 0)
+	{
+		mViewCellsManager = new KdViewCellsManager(mKdTree);
+	}
+	else if (strcmp(name, "bspTree") == 0)
+	{
+		Debug << "view cell type: Bsp" << endl;
+
+		mBspTree = new BspTree();
+		mViewCellsManager = new BspViewCellsManager(mBspTree);
+	}
+	else if (strcmp(name, "vspBspTree") == 0)
+	{
+		Debug << "view cell type: VspBsp" << endl;
+
+		mVspBspTree = new VspBspTree();
+		mViewCellsManager = new VspBspViewCellsManager(mVspBspTree);
+	}
+	else if (strcmp(name, "vspKdTree") == 0)
+	{
+		mVspKdTree = new VspKdTree();		
+	
+		mViewCellsManager = new VspKdViewCellsManager(mVspKdTree);
+	}
+	else if (strcmp(name, "sceneDependent") == 0)
+	{
+		//TODO
+		mBspTree = new BspTree();
+
+		Debug << "view cell type: Bsp" << endl;
+		
+		mViewCellsManager = new BspViewCellsManager(mBspTree);
+	}
+	else
+	{
+		cerr<<"Wrong view cells type" << name << endl;
+		exit(1);
+	}
+
+	return mViewCellsManager;
+}
+
+
+// use ascii format to store rays
+#define USE_ASCII 0
+
+
+inline bool ilt(Intersectable *obj1, Intersectable *obj2)
+{
+	return obj1->mId < obj2->mId;
+}
+
+
+bool Preprocessor::LoadSamples(VssRayContainer &samples, 
+							   ObjectContainer &objects) const
+{
+	std::stable_sort(objects.begin(), objects.end(), ilt);
+	char fileName[100];
+	environment->GetStringValue("Preprocessor.samplesFilename", fileName);
+	
+    Vector3 origin, termination;
+	// HACK: needed only for lower_bound algorithm to find the 
+	// intersected objects
+	MeshInstance sObj(NULL);
+	MeshInstance tObj(NULL);
+
+#if USE_ASCII
+	ifstream samplesIn(fileName, ios::binary);
+	if (!samplesIn.is_open())
+		return false;
+
+	string buf;
+	while (!(getline(samplesIn, buf)).eof())
+	{
+		sscanf(buf.c_str(), "%f %f %f %f %f %f %d %d", 
+			   &origin.x, &origin.y, &origin.z,
+			   &termination.x, &termination.y, &termination.z, 
+			   &(sObj.mId), &(tObj.mId));
+		
+		Intersectable *sourceObj = NULL;
+		Intersectable *termObj = NULL;
+		
+		if (sObj.mId >= 0)
+		{
+			ObjectContainer::iterator oit =
+				lower_bound(objects.begin(), objects.end(), &sObj, ilt);
+			sourceObj = *oit;
+		}
+		
+		if (tObj.mId >= 0)
+		{
+			ObjectContainer::iterator oit =
+				lower_bound(objects.begin(), objects.end(), &tObj, ilt);
+			termObj = *oit;
+		}
+
+		samples.push_back(new VssRay(origin, termination, sourceObj, termObj));
+	}
+#else
+	ifstream samplesIn(fileName, ios::binary);
+	if (!samplesIn.is_open())
+		return false;
+
+	while (1)
+	{
+		 samplesIn.read(reinterpret_cast<char *>(&origin), sizeof(Vector3));
+		 samplesIn.read(reinterpret_cast<char *>(&termination), sizeof(Vector3));
+		 samplesIn.read(reinterpret_cast<char *>(&(sObj.mId)), sizeof(int));
+		 samplesIn.read(reinterpret_cast<char *>(&(tObj.mId)), sizeof(int));
+		
+		 if (samplesIn.eof())
+			break;
+
+		Intersectable *sourceObj = NULL;
+		Intersectable *termObj = NULL;
+		
+		if (sObj.mId >= 0)
+		{
+			ObjectContainer::iterator oit =
+				lower_bound(objects.begin(), objects.end(), &sObj, ilt);
+			sourceObj = *oit;
+		}
+		
+		if (tObj.mId >= 0)
+		{
+			ObjectContainer::iterator oit =
+				lower_bound(objects.begin(), objects.end(), &tObj, ilt);
+			termObj = *oit;
+		}
+
+		samples.push_back(new VssRay(origin, termination, sourceObj, termObj));
+	}
+
+#endif
+	samplesIn.close();
+
+	return true;
+}
+
+
+bool Preprocessor::ExportSamples(const VssRayContainer &samples) const
+{
+	char fileName[100];
+	environment->GetStringValue("Preprocessor.samplesFilename", fileName);
+	
+
+	VssRayContainer::const_iterator it, it_end = samples.end();
+	
+#if USE_ASCII
+	ofstream samplesOut(fileName);
+	if (!samplesOut.is_open())
+		return false;
+
+	for (it = samples.begin(); it != it_end; ++ it)
+	{
+		VssRay *ray = *it;
+		int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;		
+		int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;	
+
+		samplesOut << ray->GetOrigin().x << " " << ray->GetOrigin().y << " " << ray->GetOrigin().z << " " 
+				   << ray->GetTermination().x << " " << ray->GetTermination().y << " " << ray->GetTermination().z << " " 
+				   << sourceid << " " << termid << "\n";
+	}
+#else
+	ofstream samplesOut(fileName, ios::binary);
+	if (!samplesOut.is_open())
+		return false;
+
+	for (it = samples.begin(); it != it_end; ++ it)
+	{	
+		VssRay *ray = *it;
+		Vector3 origin(ray->GetOrigin());
+		Vector3 termination(ray->GetTermination());
+		
+		int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;		
+		int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;		
+
+		samplesOut.write(reinterpret_cast<char *>(&origin), sizeof(Vector3));
+		samplesOut.write(reinterpret_cast<char *>(&termination), sizeof(Vector3));
+		samplesOut.write(reinterpret_cast<char *>(&sourceid), sizeof(int));
+		samplesOut.write(reinterpret_cast<char *>(&termid), sizeof(int));
+    }
+#endif
+	samplesOut.close();
+	return true;
+}
+
+
+
+bool
+Preprocessor::GenerateRays(
+						   const int number,
+						   const int sampleType,
+						   SimpleRayContainer &rays
+						   )
+{
+  Vector3 origin, direction; 
+  int startSize = rays.size();
+  for (int i=0; rays.size() - startSize  < number; i++) {
+	// now get the direction
+	switch (sampleType) {
+	case OBJECT_BASED_DISTRIBUTION: {
+	  mViewCellsManager->GetViewPoint(origin);
+	  Vector3 point;
+	  Vector3 normal;
+	  int i = RandomValue(0, mObjects.size() - 1);
+	  Intersectable *object = mObjects[i];
+	  object->GetRandomSurfacePoint(point, normal);
+	  direction = point - origin;
+	}
+	  break;
+	case OBJECT_DIRECTION_BASED_DISTRIBUTION: {
+	  int i = RandomValue(0, mObjects.size() - 1);
+	  Intersectable *object = mObjects[i];
+	  Vector3 normal;
+	  object->GetRandomSurfacePoint(origin, normal);
+	  direction = UniformRandomVector(normal);
+	  origin += 0.1f*direction;
+	}
+	  break;
+	case DIRECTION_BASED_DISTRIBUTION:
+	  mViewCellsManager->GetViewPoint(origin);
+	  direction = UniformRandomVector();
+	  break;
+	case DIRECTION_BOX_BASED_DISTRIBUTION: {
+	  mViewCellsManager->GetViewPoint(origin);
+	  float alpha = RandomValue(0.0f, 2*M_PI);
+	  float beta = RandomValue(-M_PI/2, M_PI/2);
+	  direction = VssRay::GetDirection(alpha, beta);
+	  break;
+	}
+	case SPATIAL_BOX_BASED_DISTRIBUTION:
+	  mViewCellsManager->GetViewPoint(origin);
+	  direction = mKdTree->GetBox().GetRandomPoint() - origin;
+	  break;
+	default:
+	  // unsuported distribution type
+	  return false;
+	}
+	// $$ jb the pdf is yet not correct for all sampling methods!
+	float pdf = 1.0f;
+	float c = Magnitude(direction);
+	if (c > Limits::Small) {
+	  direction*=1.0f/c;
+	  rays.AddRay(SimpleRay(origin, direction, pdf));
+	}
+  }
+  return true;
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Plane3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Plane3.h	(revision 504)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Plane3.h	(revision 504)
@@ -0,0 +1,104 @@
+#ifndef _Plane3_H__
+#define _Plane3_H__
+
+#include "Vector3.h"
+
+  
+/** 3D Plane */
+class Plane3 {
+public:
+
+  Vector3 mNormal;
+  float mD;
+  
+  Plane3() {}
+  
+  Plane3(const Vector3 &a,
+		 const Vector3 &b,
+		 const Vector3 &c
+	 ) {
+    Vector3 v1=a-b, v2=c-b;
+    mNormal = Normalize(CrossProd(v2,v1));
+    mD = -DotProd(b, mNormal);
+  }
+
+  Plane3(const Vector3 &normal,
+		 const Vector3 &point
+		 ):mNormal(normal)
+  {
+    mD = -DotProd(normal, point);
+  }
+
+  void ReverseOrientation()
+  {
+	  mNormal *= -1;
+	  mD *= -1;
+  }
+
+  float Distance(const Vector3 &v) const {
+    return DotProd(v, mNormal) + mD;
+  }
+
+  int Side(const Vector3 &v, const float threshold = 1e-6) const {
+    return signum(Distance(v), threshold);
+  }
+
+  /** Finds intersection of line segment between points a and b with plane.
+	  @param a start point
+	  @param b end point
+	  @param t if not NULL, returns parameter value of intersections
+	  @param coplanar if not NULL, returns true if plane and line segments are coplanar.
+  */
+  Vector3 FindIntersection(const Vector3 &a,
+						   const Vector3 &b,
+						   float *t = NULL,
+						   bool *coplanar = NULL) const 
+  {
+    const Vector3 v = b - a; // line from A to B
+    float dv = DotProd(v, mNormal);
+    
+    if (signum(dv) == 0)
+	{
+		if (coplanar) (*coplanar) = true;	
+		if (t) (*t) = 0;
+		return a;
+	}
+	
+	if (coplanar) (*coplanar) = false;
+    float u = - Distance(a) / dv; // TODO: could be done more efficiently
+    
+	if (t) (*t) = u;
+	
+    return a + u * v;
+  }
+  
+  /** Finds value of intersection parameter t on line segment from a to b.
+      @returns -1 if coplanar, else parameter t
+  */
+  float FindT(const Vector3 &a, const Vector3 &b) const 
+  {	  
+	  const Vector3 v = b - a; // line from A to B
+	  const float dv = DotProd(v, mNormal);
+    
+	  // does not intersect or coincident
+	  if (signum(dv) == 0)
+		  return 0;
+	
+	  return - Distance(a) / dv; // TODO: could be done more efficiently
+  }
+
+  friend bool
+  PlaneIntersection(const Plane3 &a, const Plane3 &b, const Plane3 &c, Vector3 &result);
+  
+  friend ostream &operator<<(ostream &s, const Plane3 p) {
+    s<<p.mNormal<<" "<<p.mD;
+    return s;
+  }
+
+  
+};
+  
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RssTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RssTree.cpp	(revision 579)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RssTree.cpp	(revision 579)
@@ -0,0 +1,2806 @@
+// ================================================================
+// $Id: lsds_kdtree.cpp,v 1.18 2005/04/16 09:34:21 bittner Exp $
+// ****************************************************************
+/**
+   The KD tree based LSDS
+*/
+// Initial coding by
+/**
+   @author Jiri Bittner
+*/
+
+// Standard headers
+#include <stack>
+#include <queue>
+#include <algorithm>
+#include <fstream>
+#include <string>
+
+#include "RssTree.h"
+
+#include "Environment.h"
+#include "VssRay.h"
+#include "Intersectable.h"
+#include "Ray.h"
+#include "Containers.h"
+#include "ViewCell.h"
+#include "Exporter.h"
+#include "Preprocessor.h"
+#include "SceneGraph.h"
+
+#define DEBUG_SPLIT_COST 0
+#define DEBUG_SPLITS 0
+
+// Static variables
+int
+RssTreeLeaf::mailID = 0;
+
+inline void
+AddObject2Pvs(Intersectable *object,
+			  const int side,
+			  int &pvsBack,
+			  int &pvsFront)
+{
+  
+  if (!object)
+	return;
+  
+  if (side <= 0) {
+	if (!object->Mailed() && !object->Mailed(2)) {
+	  pvsBack++;
+	  if (object->Mailed(1))
+		object->Mail(2);
+	  else
+		object->Mail();
+	}
+  }
+  
+  if (side >= 0) {
+	if (!object->Mailed(1) && !object->Mailed(2)) {
+	  pvsFront++;
+	  if (object->Mailed())
+		object->Mail(2);
+	  else
+		object->Mail(1);
+	}
+  }
+}
+
+inline void
+AddViewcells2Pvs(const ViewCellContainer &viewcells,
+				 const int side,
+				 int &viewcellsBack,
+				 int &viewcellsFront)
+{
+  ViewCellContainer::const_iterator it = viewcells.begin();
+  
+  for (; it != viewcells.end(); ++it) {
+	ViewCell *viewcell = *it;
+	if (side <= 0) {
+	  if (!viewcell->Mailed() && !viewcell->Mailed(2)) {
+		viewcellsBack++;
+		if (viewcell->Mailed(1))
+		  viewcell->Mail(2);
+		else
+		  viewcell->Mail();
+	  }
+	}
+	
+	if (side >= 0) {
+	  if (!viewcell->Mailed(1) && !viewcell->Mailed(2)) {
+		viewcellsFront++;
+		if (viewcell->Mailed())
+		  viewcell->Mail(2);
+		else
+		  viewcell->Mail(1);
+	  }
+	}
+  }
+}
+
+
+// Constructor
+RssTree::RssTree()
+{
+  environment->GetIntValue("RssTree.maxDepth", termMaxDepth);
+  environment->GetIntValue("RssTree.minPvs", termMinPvs);
+  environment->GetIntValue("RssTree.minRays", termMinRays);
+  environment->GetFloatValue("RssTree.maxRayContribution", termMaxRayContribution);
+  environment->GetFloatValue("RssTree.maxCostRatio", termMaxCostRatio);
+
+  environment->GetFloatValue("RssTree.minSize", termMinSize);
+  termMinSize = sqr(termMinSize);
+	
+  environment->GetFloatValue("RssTree.refDirBoxMaxSize", refDirBoxMaxSize);
+  refDirBoxMaxSize = sqr(refDirBoxMaxSize);
+  
+  environment->GetFloatValue("RssTree.epsilon", epsilon);
+  environment->GetFloatValue("RssTree.ct_div_ci", ct_div_ci);
+	
+  environment->GetFloatValue("RssTree.maxTotalMemory", maxTotalMemory);
+  environment->GetFloatValue("RssTree.maxStaticMemory", maxStaticMemory);
+  
+  environment->GetFloatValue("RssTree.maxStaticMemory", maxStaticMemory);
+
+
+  
+  environment->GetIntValue("RssTree.accessTimeThreshold", accessTimeThreshold);
+  //= 1000;
+  environment->GetIntValue("RssTree.minCollapseDepth", minCollapseDepth);
+  //  int minCollapseDepth = 4;
+
+  //  pRefDirThresh = cos(0.5*M_PI - M_PI*refDirAngle/180.0);
+  //  cosRefDir = cos(M_PI*refDirAngle/180.0);
+  //  sinRefDir = sin(M_PI*refDirAngle/180.0);
+  
+  
+  // split type
+  char sname[128];
+  environment->GetStringValue("RssTree.splitType", sname);
+  string name(sname);
+	
+  if (name.compare("regular") == 0)
+    splitType = ESplitRegular;
+  else
+    if (name.compare("heuristic") == 0)
+      splitType = ESplitHeuristic;
+	else
+	  if (name.compare("hybrid") == 0)
+		splitType = ESplitHybrid;
+	  else {
+		cerr<<"Invalid RssTree split type "<<name<<endl;
+		exit(1);
+	  }
+	
+  environment->GetBoolValue("RssTree.randomize", randomize);
+  environment->GetBoolValue("RssTree.splitUseOnlyDrivingAxis", mSplitUseOnlyDrivingAxis);
+
+  environment->GetBoolValue("RssTree.interleaveDirSplits", mInterleaveDirSplits);
+  environment->GetIntValue("RssTree.dirSplitDepth", mDirSplitDepth);
+
+  environment->GetBoolValue("RssTree.importanceBasedCost", mImportanceBasedCost);
+  
+  environment->GetIntValue("RssTree.maxRays", mMaxRays);
+
+  environment->GetBoolValue("RssTree.perObjectTree", mPerObjectTree);
+  
+  //  mRoots;
+  
+  splitCandidates = new vector<SortableEntry>;
+}
+
+
+RssTree::~RssTree()
+{
+  for (int i=0; i < mRoots.size(); i++)
+	if (mRoots[i])
+	  delete mRoots[i];
+}
+
+
+
+
+void
+RssStatistics::Print(ostream &app) const
+{
+  app << "###### RssTree statistics ######\n";
+
+  app << "#N_RAYS ( Number of rays )\n"
+      << rays <<endl;
+
+  app << "#N_INITPVS ( Initial PVS size )\n"
+      << initialPvsSize <<endl;
+  
+  app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
+
+  app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
+
+  app << "#N_SPLITS ( Number of splits in axes x y z dx dy dz \n";
+  for (int i=0; i<7; i++)
+    app << splits[i] <<" ";
+  app <<endl;
+
+  app << "#N_RAYREFS ( Number of rayRefs )\n" <<
+    rayRefs << "\n";
+
+  app << "#N_RAYRAYREFS  ( Number of rayRefs / ray )\n" <<
+    rayRefs/(double)rays << "\n";
+
+  app << "#N_LEAFRAYREFS  ( Number of rayRefs / leaf )\n" <<
+    rayRefs/(double)Leaves() << "\n";
+
+  app << "#N_MAXRAYREFS  ( Max number of rayRefs / leaf )\n" <<
+    maxRayRefs << "\n";
+
+
+  //  app << setprecision(4);
+
+  app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maxdepth )\n"<<
+    maxDepthNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_PMINPVSLEAVES  ( Percentage of leaves with minPvs )\n"<<
+    minPvsNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_PMINRAYSLEAVES  ( Percentage of leaves with minRays )\n"<<
+    minRaysNodes*100/(double)Leaves()<<endl;
+	
+  app << "#N_PMINSIZELEAVES  ( Percentage of leaves with minSize )\n"<<
+    minSizeNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_PMAXRAYCONTRIBLEAVES  ( Percentage of leaves with maximal ray contribution )\n"<<
+    maxRayContribNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_PMAXCOSTRATIOLEAVES  ( Percentage of leaves with max cost ratio )\n"<<
+    maxCostRatioNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_ADDED_RAYREFS  (Number of dynamically added ray references )\n"<<
+    addedRayRefs<<endl;
+
+  app << "#N_REMOVED_RAYREFS  (Number of dynamically removed ray references )\n"<<
+    removedRayRefs<<endl;
+
+  //  app << setprecision(4);
+
+  app << "#N_CTIME  ( Construction time [s] )\n"
+      << Time() << " \n";
+
+  app << "###### END OF RssTree statistics ######\n";
+
+}
+
+
+void
+RssTree::UpdatePvsSize(RssTreeLeaf *leaf)
+{
+  if (!leaf->mValidPvs) {
+	Intersectable::NewMail();
+	int pvsSize = 0;
+	for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		ri != leaf->rays.end();
+		ri++)
+	  if ((*ri).mRay->IsActive()) {
+		Intersectable *object;
+		object = (*ri).GetObject();
+		if (object && !object->Mailed()) {
+		  pvsSize++;
+		  object->Mail();
+		}
+	  }
+	leaf->SetPvsSize(pvsSize);
+	
+	ComputeImportance(leaf);
+  }
+}
+
+bool
+RssTree::ClipRay(
+				 RssTreeNode::RayInfo &rayInfo,
+				 const AxisAlignedBox3 &box
+				 )
+{
+  float tmin, tmax;
+  static Ray ray;
+  cerr<<"Clip not reimplented yet...Quiting\n";
+  exit(1);
+  ray.Init(rayInfo.GetOrigin(), rayInfo.GetDir(), Ray::LINE_SEGMENT);
+
+  if (!box.ComputeMinMaxT(ray, &tmin, &tmax) || tmin>=tmax)
+	return false;
+  
+  // now check if the ray origin lies inside the box
+  if ( tmax < rayInfo.mRay->GetSize() ) {
+	// this ray does not leave the box
+	rayInfo.mRay->SetupEndPoints(
+								 ray.Extrap(tmax),
+								 rayInfo.mRay->mTermination
+								 );
+	return true;
+  }
+
+  return false;
+}
+
+
+void
+RssTree::Construct(
+				   ObjectContainer &objects,
+				   VssRayContainer &rays
+				   // forced bounding box is only used when computing from-box
+				   // visibility
+				   //				   AxisAlignedBox3 *forcedBoundingBox
+				   )
+{
+  cout<<"Constructing rss tree"<<endl<<flush;
+  stat.Start();
+  
+  maxMemory = maxStaticMemory;
+
+  //  if (root)
+  //    delete root;
+
+  if (mPerObjectTree) {
+	// get max id from the rays
+	int i;
+	mRoots.resize(objects.size());
+	for (i = 0; i < objects.size(); i++) {
+	  RssTreeLeaf *leaf = new RssTreeLeaf(NULL, 0);
+	  //	  leaf->bbox.Initialize();
+	  leaf->dirBBox.Initialize();
+	  leaf->dirBBox.SetMin(2, 0.0f);
+	  leaf->dirBBox.SetMax(2, 1.0f);
+	  
+	  mRoots[i] = leaf;
+	}
+	// init spatial bounding boxes
+	for (i = 0; i < objects.size(); i++) {
+	  GetRoot(objects[i])->bbox = objects[i]->GetBox();
+	}
+	stat.nodes = i;
+	stat.leaves = i;
+  } else {
+	mRoots.resize(1);
+	RssTreeLeaf *leaf = new RssTreeLeaf(NULL, rays.size());
+	leaf->bbox.Initialize();
+	leaf->dirBBox.Initialize();
+	leaf->dirBBox.SetMin(2, 0.0f);
+	leaf->dirBBox.SetMax(2, 1.0f);
+	mRoots[0] = leaf;
+	stat.nodes = 1;
+	stat.leaves = 1;
+  }
+
+  for(VssRayContainer::const_iterator ri = rays.begin();
+	  ri != rays.end();
+	  ri++) {
+	
+	  RssTreeNode::RayInfo info(*ri);
+	  
+	  // first construct a leaf that will get subdivide
+	  RssTreeLeaf *leaf = (RssTreeLeaf *) GetRoot(info.GetSourceObject());
+
+	  leaf->AddRay(info);
+	  
+	  // leaf bbox contains bbox of origins only
+	  leaf->bbox.Include((*ri)->GetOrigin());
+	  
+	  // include both origin and terminatin in the global bbox
+	  bbox.Include((*ri)->GetOrigin());
+	  bbox.Include((*ri)->GetTermination());
+	  
+	  Vector3 dVec = Vector3(
+							 (*ri)->GetDirParametrization(0),
+							 (*ri)->GetDirParametrization(1),
+							 0
+							 );
+
+	  leaf->dirBBox.Include(dVec);
+	  dirBBox.Include(dVec);
+  }
+
+  // make the z axis (unused) a unit size
+  // important for volume computation
+
+  
+  //  if ( forcedBoundingBox ) 
+  //	bbox = *forcedBoundingBox;
+  
+  cout<<"Bbox = "<<bbox<<endl;
+  cout<<"Dirr Bbox = "<<dirBBox<<endl;
+  
+  stat.rays = rays.size();
+  stat.initialPvsSize = 0;
+  for (int i=0; i < mRoots.size(); i++) {
+	RssTreeLeaf *leaf = (RssTreeLeaf *)mRoots[i];
+	stat.initialPvsSize += leaf->GetPvsSize();
+	UpdatePvsSize(leaf);
+	mRoots[i] = Subdivide(TraversalData(leaf, GetBBox(leaf), 0));
+  }
+  
+  if (splitCandidates) {
+    // force realease of this vector
+    delete splitCandidates;
+    splitCandidates = new vector<SortableEntry>;
+  }
+  
+  stat.Stop();
+  stat.Print(cout);
+  cout<<"#Total memory="<<GetMemUsage()<<endl;
+
+  // this rotine also updates importances etc...
+}
+
+int
+RssTree::UpdateSubdivision()
+{
+  priority_queue<TraversalData> tStack;
+  //  stack<TraversalData> tStack;
+  
+  //  tStack.push(TraversalData(root, bbox, 0));
+  PushRoots(tStack);
+			
+  AxisAlignedBox3 backBox;
+  AxisAlignedBox3 frontBox;
+
+  maxMemory = maxTotalMemory;
+  int subdivided = 0;
+  int lastMem = 0;
+  while (!tStack.empty()) {
+		
+	float mem = GetMemUsage();
+		
+	if ( lastMem/10 != ((int)mem)/10) {
+	  cout<<mem<<" MB"<<endl;
+	}
+	lastMem = (int)mem;
+		
+	if (  mem > maxMemory ) {
+      // count statistics on unprocessed leafs
+      while (!tStack.empty()) {
+		//				EvaluateLeafStats(tStack.top());
+		tStack.pop();
+      }
+      break;
+    }
+    
+    TraversalData data = tStack.top();
+    tStack.pop();
+
+	if (data.node->IsLeaf()) {
+	  RssTreeNode *node = SubdivideNode((RssTreeLeaf *) data.node,
+										data.bbox,
+										backBox,
+										frontBox
+										);
+	  if (!node->IsLeaf()) {
+		subdivided++;
+
+		
+		RssTreeInterior *interior = (RssTreeInterior *) node;
+		// push the children on the stack
+		tStack.push(TraversalData(interior->back, backBox, data.depth+1));
+		tStack.push(TraversalData(interior->front, frontBox, data.depth+1));
+	  } else {
+		//      EvaluateLeafStats(data);
+	  }
+	} else {
+	  RssTreeInterior *interior = (RssTreeInterior *) data.node;
+	  tStack.push(TraversalData(interior->back, GetBBox(interior->back), data.depth+1));
+	  tStack.push(TraversalData(interior->front, GetBBox(interior->front), data.depth+1));
+	}
+  }
+  return subdivided;
+}
+
+
+RssTreeNode *
+RssTree::Subdivide(const TraversalData &tdata)
+{
+  RssTreeNode *result = NULL;
+
+  priority_queue<TraversalData> tStack;
+  //  stack<TraversalData> tStack;
+  
+  tStack.push(tdata);
+
+  AxisAlignedBox3 backBox;
+  AxisAlignedBox3 frontBox;
+
+  
+  int lastMem = 0;
+  while (!tStack.empty()) {
+
+	float mem = GetMemUsage();
+		
+	if ( lastMem/10 != ((int)mem)/10) {
+	  cout<<mem<<" MB"<<endl;
+	}
+	lastMem = (int)mem;
+		
+	if (  mem > maxMemory ) {
+      // count statistics on unprocessed leafs
+      while (!tStack.empty()) {
+		EvaluateLeafStats(tStack.top());
+		tStack.pop();
+      }
+      break;
+    }
+    
+    TraversalData data = tStack.top();
+    tStack.pop();
+
+#if DEBUG_SPLITS
+	Debug<<"#Splitting node"<<endl;
+	data.node->Print(Debug);
+#endif
+	RssTreeNode *node = SubdivideNode((RssTreeLeaf *) data.node,
+									  data.bbox,
+									  backBox,
+									  frontBox
+									  );
+	
+
+	if (result == NULL)
+      result = node;
+    
+    if (!node->IsLeaf()) {
+			
+      RssTreeInterior *interior = (RssTreeInterior *) node;
+      // push the children on the stack
+      tStack.push(TraversalData(interior->back, backBox, data.depth+1));
+      tStack.push(TraversalData(interior->front, frontBox, data.depth+1));
+
+#if DEBUG_SPLITS
+	  Debug<<"#New nodes"<<endl;
+	  interior->back->Print(Debug);
+	  interior->front->Print(Debug);
+	  Debug<<"#####################################"<<endl;
+#endif
+	  
+    } else {
+      EvaluateLeafStats(data);
+    }
+  }
+
+  return result;
+}
+
+
+// returns selected plane for subdivision
+int
+RssTree::SelectPlane(
+					 RssTreeLeaf *leaf,
+					 const AxisAlignedBox3 &box,
+					 SplitInfo &info
+					 )
+{
+
+  BestCostRatio(leaf,
+				info);
+  
+#if DEBUG_SPLIT_COST
+  Debug<<"Split Info:"<<endl;
+  Debug<<"axis="<<info.axis<<" ratio="<<info.costRatio<<endl;
+  Debug<<"viewcells="<<info.viewCells<<
+	" viewcells back="<<info.viewCellsBack<<
+	" viewcells back="<<info.viewCellsFront<<endl;
+#endif
+  
+  if (info.costRatio > termMaxCostRatio) {
+	//		cout<<"Too big cost ratio "<<costRatio<<endl;
+	stat.maxCostRatioNodes++;
+	return -1;
+  }
+	
+#if 0	
+  cout<<
+	"pvs="<<leaf->mPvsSize<<
+	" rays="<<leaf->rays.size()<<
+	" rc="<<leaf->GetAvgRayContribution()<<
+	" axis="<<info.axis<<endl;
+#endif
+  
+  return info.axis;
+}
+
+
+void
+RssTree::GetCostRatio(
+					  RssTreeLeaf *leaf,
+					  SplitInfo &info
+					  )
+{
+
+  AxisAlignedBox3 box;
+  float minBox, maxBox;
+
+  if (info.axis < 3) {
+	box = GetBBox(leaf);
+	minBox = box.Min(info.axis);
+	maxBox = box.Max(info.axis);
+  }	else {
+	box = GetDirBBox(leaf);
+	minBox = box.Min(info.axis-3);
+	maxBox = box.Max(info.axis-3);
+  }
+	
+  float sizeBox = maxBox - minBox;
+
+  int pvsSize = leaf->GetPvsSize();
+
+  if (!mImportanceBasedCost) {
+	const int costMethod = 0;
+	
+	switch (costMethod) {
+	case 0: {
+	  //		float sum = raysBack*(position - minBox) + raysFront*(maxBox - position);
+	  float sum = info.pvsBack*(info.position - minBox) + info.pvsFront*(maxBox - info.position);
+	  float newCost = ct_div_ci + sum/sizeBox;
+	  float oldCost = pvsSize;
+	  info.costRatio = newCost/oldCost;
+	  break;
+	}
+	case 1: {
+	  float newContrib =
+		info.contributionBack/(info.position - minBox) + 
+		+
+		info.contributionFront/(maxBox - info.position);
+	  float oldContrib = info.contribution/sizeBox;
+	  info.costRatio = oldContrib/newContrib;
+	  break;
+	} 
+	case 2: {
+	  float sum =
+		info.viewCellsBack*(info.position - minBox) +
+		info.viewCellsFront*(maxBox - info.position);
+	  float newCost = ct_div_ci + sum/sizeBox;
+	  float oldCost = info.viewCells;
+	  info.costRatio = newCost/oldCost;
+	  break;
+	}
+	case 3: {
+	  float newCost = info.raysBack*info.pvsBack  + info.raysFront*info.pvsFront;
+	  float oldCost = leaf->rays.size()*pvsSize;
+	  info.costRatio = newCost/oldCost;
+	}
+	}
+  } else {
+	const int costMethod = 1;
+	// importance based cost
+	switch (costMethod) {
+	case 0: {
+	  break;
+	}
+	case 1: {
+	  float newContrib =
+		sqr(info.pvsBack/(info.raysBack + Limits::Small)) +
+		sqr(info.pvsFront/(info.raysFront + Limits::Small));
+	  float oldContrib = sqr(leaf->GetAvgRayContribution());
+	  info.costRatio = oldContrib/newContrib;
+	  break;
+	}
+	case 2: {
+	  float newCost = (info.pvsBack  + info.pvsFront)*0.5f;
+	  float oldCost = pvsSize;
+	  info.costRatio = newCost/oldCost;
+	  break;
+	}
+	case 3: {
+	  float newCost = abs(info.raysBack  - info.raysFront);
+	  float oldCost = leaf->rays.size();
+	  info.costRatio = newCost/oldCost;
+	  break;
+	}
+  }
+  }
+}
+							
+
+void
+RssTree::EvalCostRatio(
+					   RssTreeLeaf *leaf,
+					   SplitInfo &info
+					   )
+{
+  info.raysBack = 0;
+  info.raysFront = 0;
+  info.pvsFront = 0;
+  info.pvsBack = 0;
+  info.viewCells = 0;
+  info.viewCellsFront = 0;
+  info.viewCellsBack = 0;
+
+
+  float sumWeights = Limits::Small;
+  float sumWeightsBack = Limits::Small;
+  float sumWeightsFront = Limits::Small;
+  
+  float sumContribution = 0.0f;
+  float sumContributionBack = 0.0f;
+  float sumContributionFront = 0.0f;
+
+  Intersectable::NewMail();
+
+  // count the numebr of viewcells first
+  for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+	  ri != leaf->rays.end();
+	  ri++)
+	if ((*ri).mRay->IsActive()) {
+	  ViewCellContainer::const_iterator it = (*ri).mRay->mViewCells.begin();
+	  for (; it != (*ri).mRay->mViewCells.end(); ++it) {
+		if (!(*it)->Mailed()) {
+		  (*it)->Mail();
+		  info.viewCells++;
+		}
+	  }
+	}
+  
+  Intersectable::NewMail(3);
+  
+  // this is the main ray classification loop!
+  for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+	  ri != leaf->rays.end();
+	  ri++)
+	if ((*ri).mRay->IsActive()) {
+	  int side;
+	  
+	  
+	  // determine the side of this ray with respect to the plane
+	  side = (*ri).ComputeRaySide(info.axis, info.position);
+	  
+	  float weight, contribution;
+	  
+	  GetRayContribution(*ri, weight, contribution);
+	  sumWeights += weight;
+	  sumContribution += contribution;
+	  
+	  if (side <= 0) {
+		info.raysBack++;
+		sumWeightsBack += weight;
+		sumContributionBack += contribution;
+	  }
+	  
+	  if (side >= 0) {
+		info.raysFront++;
+		sumWeightsFront += weight;
+		sumContributionFront += contribution;
+	  }
+	  
+	  AddObject2Pvs((*ri).GetObject(), side, info.pvsBack, info.pvsFront);
+	  AddViewcells2Pvs((*ri).mRay->mViewCells,
+					   side,
+					   info.viewCellsBack,
+					   info.viewCellsFront);
+	}
+
+  info.contribution = sumContribution/sumWeights;
+  info.contributionBack = sumContributionBack/sumWeightsBack;
+  info.contributionFront = sumContributionFront/sumWeightsFront;
+  
+  GetCostRatio(
+			   leaf,
+			   info);
+  
+  //	cout<<axis<<" "<<pvsSize<<" "<<pvsBack<<" "<<pvsFront<<endl;
+  //  float oldCost = leaf->rays.size();
+  
+  //	cout<<"ratio="<<ratio<<endl;
+}
+
+void
+RssTree::BestCostRatio(
+					   RssTreeLeaf *leaf,
+					   SplitInfo &info
+					   )
+{
+  SplitInfo nInfo[5];
+  int bestAxis = -1;
+  
+  AxisAlignedBox3 sBox = GetBBox(leaf);
+  AxisAlignedBox3 dBox = GetDirBBox(leaf);
+  // int sAxis = box.Size().DrivingAxis();
+  int sAxis = sBox.Size().DrivingAxis();
+  int dAxis = dBox.Size().DrivingAxis() + 3;
+  
+  float dirSplitBoxSize = 0.01f;
+  bool allowDirSplit = Magnitude(sBox.Size())*dirSplitBoxSize < Magnitude(bbox.Size());
+		
+  
+  for (int axis = 0; axis < 5; axis++)
+	if (
+		(axis < 3 && (leaf->depth < mDirSplitDepth ||  mInterleaveDirSplits)) ||
+		(axis >= 3 && (leaf->depth >= mDirSplitDepth))
+		) {
+	  nInfo[axis].axis = axis;
+	  if (!mSplitUseOnlyDrivingAxis || axis == sAxis || axis == dAxis) {
+		
+		if (splitType == ESplitRegular) {
+		  if (axis < 3)
+			nInfo[axis].position = (sBox.Min()[axis] + sBox.Max()[axis])*0.5f;
+		  else
+			nInfo[axis].position = (dBox.Min()[axis-3] + dBox.Max()[axis-3])*0.5f;
+		  EvalCostRatio(leaf,
+						nInfo[axis]);
+		} else
+		  if (splitType == ESplitHeuristic) {
+			EvalCostRatioHeuristic(
+								   leaf,
+								   nInfo[axis]
+								   );
+		  } else
+			if (splitType == ESplitHybrid) {
+			  if (leaf->depth > 7)
+				EvalCostRatioHeuristic(
+									   leaf,
+									   nInfo[axis]
+									   );
+			  else {
+				if (axis < 3)
+				  nInfo[axis].position = (sBox.Min()[axis] + sBox.Max()[axis])*0.5f;
+				else
+				  nInfo[axis].position = (dBox.Min()[axis-3] + dBox.Max()[axis-3])*0.5f;
+				
+				EvalCostRatio(leaf,
+							  nInfo[axis]
+							  );
+			  }
+			} else {
+			  cerr<<"RssTree: Unknown split heuristics\n";
+			  exit(1);
+			}
+		
+		if ( bestAxis == -1)
+		  bestAxis = axis;
+		else
+		  if ( nInfo[axis].costRatio < nInfo[bestAxis].costRatio )
+			bestAxis = axis;
+	  }
+	}
+  
+  info = nInfo[bestAxis];
+}
+
+	
+void
+RssTree::EvalCostRatioHeuristic(
+								RssTreeLeaf *leaf,
+								SplitInfo &info
+								)
+{
+  AxisAlignedBox3 box;
+  float minBox, maxBox;
+	
+  if (info.axis < 3) {
+	box = GetBBox(leaf);
+	minBox = box.Min(info.axis);
+	maxBox = box.Max(info.axis);
+  } else {
+	box = GetDirBBox(leaf);
+	minBox = box.Min(info.axis-3);
+	maxBox = box.Max(info.axis-3);
+  }
+	
+  SortSplitCandidates(leaf, info.axis);
+  
+  // go through the lists, count the number of objects left and right
+  // and evaluate the following cost funcion:
+  // C = ct_div_ci  + (ql*rl + qr*rr)/queries
+  
+  SplitInfo currInfo;
+  currInfo.axis = info.axis;
+
+  currInfo.raysBack = 0;
+  currInfo.raysFront = leaf->rays.size();
+  
+  currInfo.pvsBack = 0;
+  currInfo.pvsFront = leaf->GetPvsSize();
+
+ 
+  float sizeBox = maxBox - minBox;
+  
+  float minBand = minBox + 0.1f*(maxBox - minBox);
+  float maxBand = minBox + 0.9f*(maxBox - minBox);
+	
+  // best cost ratio
+  info.costRatio = 1e20f;
+
+  currInfo.viewCells = 0;
+
+  Intersectable::NewMail();
+  // set all object as belonging to the fron pvs
+  for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+	  ri != leaf->rays.end();
+	  ri++)
+	if ((*ri).mRay->IsActive()) {
+	  Intersectable *object = (*ri).GetObject();
+	  if (object)
+		if (!object->Mailed()) {
+		  object->Mail();
+		  object->mCounter = 1;
+		} else
+		  object->mCounter++;
+	  
+	  // and do the same for all viewcells
+	  ViewCellContainer::const_iterator it = (*ri).mRay->mViewCells.begin();
+	  
+	  for (; it != (*ri).mRay->mViewCells.end(); ++it) {
+		ViewCell *viewcell = *it;
+		if (!viewcell->Mailed()) {
+		  currInfo.viewCells++;
+		  viewcell->Mail();
+		  viewcell->mCounter = 1;
+		} else
+		  viewcell->mCounter++;
+	  }
+	}
+
+  currInfo.viewCellsBack = 0;
+  currInfo.viewCellsFront = currInfo.viewCells;
+ 
+  Intersectable::NewMail();
+	
+  for(vector<SortableEntry>::const_iterator ci = splitCandidates->begin();
+	  ci < splitCandidates->end();
+	  ci++) {
+	switch ((*ci).type) {
+	case SortableEntry::ERayMin: {
+	  currInfo.raysFront--;
+	  currInfo.raysBack++;
+	  RssTreeNode::RayInfo *rayInfo = (RssTreeNode::RayInfo *) (*ci).data;
+	  Intersectable *object = rayInfo->GetObject();
+	  if (object) {
+		if (!object->Mailed()) {
+		  object->Mail();
+		  currInfo.pvsBack++;
+		}
+		if (--object->mCounter == 0)
+		  currInfo.pvsFront--;
+	  }
+	  ViewCellContainer::const_iterator it = rayInfo->mRay->mViewCells.begin();
+	  for (; it != rayInfo->mRay->mViewCells.end(); ++it) {
+		ViewCell *viewcell = *it;
+		if (!viewcell->Mailed()) {
+		  viewcell->Mail();
+		  currInfo.viewCellsBack++;
+		}
+		if (--viewcell->mCounter == 0)
+		  currInfo.viewCellsFront--;
+	  }
+	  break;
+	}
+	}
+
+	float position = (*ci).value;
+	
+	if (position > minBand && position < maxBand) {
+	  currInfo.position = position;
+	  
+	  GetCostRatio(
+				   leaf,
+				   currInfo);
+	  
+			
+	  //      cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl;
+	  //      cout<<"cost= "<<sum<<endl;
+	  
+	  if (currInfo.costRatio < info.costRatio) {
+		info = currInfo;
+      }
+    }
+  }
+  
+  
+  //  cout<<"===================="<<endl;
+  //  cout<<"costRatio="<<ratio<<" pos="<<position<<" t="<<(position - minBox)/(maxBox - minBox)
+  //      <<"\t q=("<<queriesBack<<","<<queriesFront<<")\t r=("<<raysBack<<","<<raysFront<<")"<<endl;
+}
+
+void
+RssTree::SortSplitCandidates(
+							 RssTreeLeaf *node,
+							 const int axis
+							 )
+{
+  
+  splitCandidates->clear();
+  
+  int requestedSize = 2*(node->rays.size());
+  // creates a sorted split candidates array
+  if (splitCandidates->capacity() > 500000 &&
+      requestedSize < (int)(splitCandidates->capacity()/10) ) {
+    
+    delete splitCandidates;
+    splitCandidates = new vector<SortableEntry>;
+  }
+  
+  splitCandidates->reserve(requestedSize);
+
+  // insert all queries 
+  for(RssTreeNode::RayInfoContainer::const_iterator ri = node->rays.begin();
+      ri < node->rays.end();
+      ri++) {
+	if ((*ri).mRay->IsActive()) {
+	  if (axis < 3) {
+		splitCandidates->push_back(SortableEntry(SortableEntry::ERayMin,
+												 (*ri).GetOrigin(axis),
+												 (void *)&(*ri))
+								   );
+	  } else {
+		float pos = (*ri).GetDirParametrization(axis-3);
+		splitCandidates->push_back(SortableEntry(SortableEntry::ERayMin,
+												 pos,
+												 (void *)&(*ri))
+								   );
+	  }
+	}
+  }
+  
+  stable_sort(splitCandidates->begin(), splitCandidates->end());
+}
+
+
+void
+RssTree::EvaluateLeafStats(const TraversalData &data)
+{
+
+  // the node became a leaf -> evaluate stats for leafs
+  RssTreeLeaf *leaf = (RssTreeLeaf *)data.node;
+
+  if (data.depth >= termMaxDepth)
+    stat.maxDepthNodes++;
+  
+  //  if ( (int)(leaf->rays.size()) < termMinCost)
+  //    stat.minCostNodes++;
+  if ( leaf->GetPvsSize() <= termMinPvs)
+	stat.minPvsNodes++;
+
+  if ( leaf->GetPvsSize() <= termMinRays)
+	stat.minRaysNodes++;
+
+  if (leaf->GetAvgRayContribution() > termMaxRayContribution )
+	stat.maxRayContribNodes++;
+	
+  if (SqrMagnitude(data.bbox.Size()) <= termMinSize) {
+	stat.minSizeNodes++;
+  }
+
+  if ( (int)(leaf->rays.size()) > stat.maxRayRefs)
+    stat.maxRayRefs = leaf->rays.size();
+
+}
+
+bool
+RssTree::TerminationCriteriaSatisfied(RssTreeLeaf *leaf)
+{
+  return ( (leaf->GetPvsSize() <= termMinPvs) ||
+		   (leaf->rays.size() <= termMinRays) ||
+		   //			 (leaf->GetAvgRayContribution() > termMaxRayContribution ) ||
+		   (leaf->depth >= termMaxDepth) ||
+		   (SqrMagnitude(GetBBox(leaf).Size()) <= termMinSize) 
+		   );
+}
+
+
+RssTreeNode *
+RssTree::SubdivideNode(
+					   RssTreeLeaf *leaf,
+					   const AxisAlignedBox3 &box,
+					   AxisAlignedBox3 &backBBox,
+					   AxisAlignedBox3 &frontBBox
+					   )
+{
+  
+  if (TerminationCriteriaSatisfied(leaf)) {
+#if 0
+	if (leaf->depth >= termMaxDepth) {
+	  cout<<"Warning: max depth reached depth="<<(int)leaf->depth<<" rays="<<leaf->rays.size()<<endl;
+	  cout<<"Bbox: "<<GetBBox(leaf)<<" dirbbox:"<<GetDirBBox(leaf)<<endl;
+	}
+#endif
+		
+	return leaf;
+  }
+	
+  SplitInfo info;
+	
+  // select subdivision axis
+  int axis = SelectPlane( leaf,
+						  box,
+						  info
+						  );
+  //  Debug<<"axis="<<axis<<" depth="<<(int)leaf->depth<<" rb="<<raysBack<<" rf="<<raysFront<<" pvsb="<<pvsBack<<" pvsf="<<pvsFront<<endl;
+  
+  if (axis == -1) {
+    return leaf;
+  }
+  
+  stat.nodes+=2;
+  stat.leaves += 1;
+  stat.splits[axis]++;
+
+  // add the new nodes to the tree
+  RssTreeInterior *node = new RssTreeInterior(leaf->parent);
+
+  node->axis = axis;
+  node->position = info.position;
+  //  node->bbox = box;
+  //  node->dirBBox = GetDirBBox(leaf);
+  
+  
+  RssTreeLeaf *back = new RssTreeLeaf(node, info.raysBack);
+  RssTreeLeaf *front = new RssTreeLeaf(node, info.raysFront);
+
+  
+  // update halton generator
+  back->halton.index = leaf->halton.index;
+  front->halton.index = leaf->halton.index;
+  
+  // replace a link from node's parent
+  if (  leaf->parent )
+    leaf->parent->ReplaceChildLink(leaf, node);
+  // and setup child links
+  node->SetupChildLinks(back, front);
+
+  back->bbox = leaf->bbox;
+  front->bbox = leaf->bbox;
+  back->dirBBox = leaf->dirBBox;
+  front->dirBBox = leaf->dirBBox;
+  
+  if (axis <= RssTreeNode::SPLIT_Z) {
+	back->bbox.SetMax(axis, info.position);
+    front->bbox.SetMin(axis, info.position);
+  } else {
+	back->dirBBox.SetMax(axis-3, info.position);
+    front->dirBBox.SetMin(axis-3, info.position);
+  }
+  
+  for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+	  ri != leaf->rays.end();
+	  ri++) {
+	if ((*ri).mRay->IsActive()) {
+	  
+	  // first unref ray from the former leaf
+	  (*ri).mRay->Unref();
+	  
+	  // Debug << "computed t: " << (*ri).mRay->mT << endl;
+	  // determine the side of this ray with respect to the plane
+	  int side = node->ComputeRaySide(*ri);
+	  
+	  if (side == 1) 
+		front->AddRay(*ri);
+	  else
+		back->AddRay(*ri);
+	} else
+	  (*ri).mRay->Unref();
+  }
+
+  // distribute the total number of rays according to the distribution
+  // of rays which remained
+  //  front->mTotalRays = front->rays.size()*leaf->mTotalRays/leaf->rays.size();
+  //  back->mTotalRays = back->rays.size()*leaf->mTotalRays/leaf->rays.size();
+  
+#if 0
+  front->SetPvsSize(pvsFront);
+  back->SetPvsSize(pvsBack);
+  // compute entropy as well
+  front->ComputeEntropyImportance();
+  back->ComputeEntropyImportance();
+#else
+  UpdatePvsSize(front);
+  UpdatePvsSize(back);
+#endif
+
+  
+  // update stats
+  stat.rayRefs -= (int)leaf->rays.size();
+  stat.rayRefs += info.raysBack + info.raysFront;
+
+  
+  delete leaf;
+  return node;
+}
+
+
+
+
+
+
+int
+RssTree::ReleaseMemory(const int time)
+{
+  stack<RssTreeNode *> tstack;
+  
+  // find a node in the tree which subtree will be collapsed
+  int maxAccessTime = time - accessTimeThreshold;
+  int released;
+
+  PushRoots(tstack);
+
+  while (!tstack.empty()) {
+    RssTreeNode *node = tstack.top();
+    tstack.pop();
+    
+ 
+    if (!node->IsLeaf()) {
+      RssTreeInterior *in = (RssTreeInterior *)node;
+      //      cout<<"depth="<<(int)in->depth<<" time="<<in->lastAccessTime<<endl;
+      if (in->depth >= minCollapseDepth &&
+		  in->lastAccessTime <= maxAccessTime) {
+		released = CollapseSubtree(node, time);
+		break;
+      }
+      
+      if (in->back->GetAccessTime() <  
+		  in->front->GetAccessTime()) {
+		tstack.push(in->front);
+		tstack.push(in->back);
+      } else {
+		tstack.push(in->back);
+		tstack.push(in->front);
+      }
+    }
+  }
+
+  while (tstack.empty()) {
+    // could find node to collaps...
+    //    cout<<"Could not find a node to release "<<endl;
+    break;
+  }
+  
+  return released;
+}
+
+
+
+
+RssTreeNode *
+RssTree::SubdivideLeaf(
+					   RssTreeLeaf *leaf
+					   )
+{
+  RssTreeNode *node = leaf;
+	
+  AxisAlignedBox3 leafBBox = GetBBox(leaf);
+
+  static int pass = 0;
+  pass ++;
+	
+  // check if we should perform a dynamic subdivision of the leaf
+  if (!TerminationCriteriaSatisfied(leaf)) {
+    
+	// memory check and realese...
+    if (GetMemUsage() > maxTotalMemory) {
+      ReleaseMemory( pass );
+    }
+    
+    AxisAlignedBox3 backBBox, frontBBox;
+
+    // subdivide the node
+    node =
+      SubdivideNode(leaf,
+					leafBBox,
+					backBBox,
+					frontBBox
+					);
+  }
+	
+  return node;
+}
+
+
+
+void
+RssTree::UpdateRays(
+					VssRayContainer &remove,
+					VssRayContainer &add
+					)
+{
+  RssTreeLeaf::NewMail();
+
+  // schedule rays for removal
+  for(VssRayContainer::const_iterator ri = remove.begin();
+      ri != remove.end();
+      ri++) {
+    (*ri)->ScheduleForRemoval();
+  }
+
+  int inactive=0;
+
+  for(VssRayContainer::const_iterator ri = remove.begin();
+      ri != remove.end();
+      ri++) {
+    if ((*ri)->ScheduledForRemoval())
+	  //      RemoveRay(*ri, NULL, false);
+	  // !!! BUG - with true it does not work correctly - aggreated delete
+      RemoveRay(*ri, NULL, true);
+    else
+      inactive++;
+  }
+
+
+  //  cout<<"all/inactive"<<remove.size()<<"/"<<inactive<<endl;
+  
+  for(VssRayContainer::const_iterator ri = add.begin();
+      ri != add.end();
+      ri++) {
+	RssTreeNode::RayInfo info(*ri);
+	//	if (mForcedBoundingBox==NULL || ClipRay(info, bbox))
+	AddRay(info);
+  }
+
+  stat.rayRefs += add.size() - remove.size();
+
+  UpdateTreeStatistics();
+  // check whether the tree should be prunned
+  if (stat.rayRefs > mMaxRays) {
+	PruneRays(mMaxRays);
+	//	UpdateTreeStatistics();
+  }
+  
+}
+
+  
+
+
+void
+RssTree::RemoveRay(VssRay *ray,
+				   vector<RssTreeLeaf *> *affectedLeaves,
+				   const bool removeAllScheduledRays
+				   )
+{
+	
+  stack<RayTraversalData> tstack;
+
+  PushRoots(tstack, RssTreeLeaf::RayInfo(ray));
+  
+  RayTraversalData data;
+
+  // cout<<"Number of ray refs = "<<ray->RefCount()<<endl;
+
+  while (!tstack.empty()) {
+    data = tstack.top();
+    tstack.pop();
+
+    if (!data.node->IsLeaf()) {
+      // split the set of rays in two groups intersecting the
+      // two subtrees
+
+      TraverseInternalNode(data, tstack);
+      
+    } else {
+      // remove the ray from the leaf
+      // find the ray in the leaf and swap it with the last ray...
+      RssTreeLeaf *leaf = (RssTreeLeaf *)data.node;
+      
+      if (!leaf->Mailed()) {
+		leaf->Mail();
+		if (affectedLeaves)
+		  affectedLeaves->push_back(leaf);
+	
+		if (removeAllScheduledRays) {
+		  int tail = (int)leaf->rays.size()-1;
+
+		  for (int i=0; i < (int)(leaf->rays.size()); i++) {
+			if (leaf->rays[i].mRay->ScheduledForRemoval()) {
+			  // find a ray to replace it with
+			  while (tail >= i && leaf->rays[tail].mRay->ScheduledForRemoval()) {
+				stat.removedRayRefs++;
+				leaf->rays[tail].mRay->Unref();
+				leaf->rays.pop_back();
+				tail--;
+			  }
+
+			  if (tail < i)
+				break;
+	      
+			  stat.removedRayRefs++;
+			  leaf->rays[i].mRay->Unref();
+			  leaf->rays[i] = leaf->rays[tail];
+			  leaf->rays.pop_back();
+			  tail--;
+			}
+		  }
+		}
+      }
+      
+      if (!removeAllScheduledRays)
+		for (int i=0; i < (int)leaf->rays.size(); i++) {
+		  if (leaf->rays[i].mRay == ray) {
+			stat.removedRayRefs++;
+			ray->Unref();
+			leaf->rays[i] = leaf->rays[leaf->rays.size()-1];
+			leaf->rays.pop_back();
+			// check this ray again
+			break;
+		  }
+		}
+      
+    }
+  }
+
+  if (ray->RefCount() != 0) {
+    cerr<<"Error: Number of remaining refs = "<<ray->RefCount()<<endl;
+    exit(1);
+  }
+  
+}
+
+
+void
+RssTree::AddRay(RssTreeNode::RayInfo &info)
+{
+
+  stack<RayTraversalData> tstack;
+
+  RssTreeNode *root = GetRoot(info.GetSourceObject());
+  tstack.push(RayTraversalData(root, info));
+  
+  RayTraversalData data;
+  
+  while (!tstack.empty()) {
+    data = tstack.top();
+    tstack.pop();
+
+    if (!data.node->IsLeaf()) {
+      TraverseInternalNode(data, tstack);
+    } else {
+      // remove the ray from the leaf
+      // find the ray in the leaf and swap it with the last ray...
+      RssTreeLeaf *leaf = (RssTreeLeaf *)data.node;
+      leaf->AddRay(data.rayData);
+      stat.addedRayRefs++;
+    }
+  }
+}
+
+void
+RssTree::TraverseInternalNode(
+							  RayTraversalData &data,
+							  stack<RayTraversalData> &tstack)
+{
+  RssTreeInterior *in =  (RssTreeInterior *) data.node;
+  
+  // determine the side of this ray with respect to the plane
+  int side = in->ComputeRaySide(data.rayData
+								);
+  
+  if (side == 1)
+	tstack.push(RayTraversalData(in->front, data.rayData));
+  else
+	tstack.push(RayTraversalData(in->back, data.rayData));
+  
+}
+
+
+int
+RssTree::CollapseSubtree(RssTreeNode *sroot, const int time)
+{
+  // first count all rays in the subtree
+  // use mail 1 for this purpose
+  stack<RssTreeNode *> tstack;
+  int rayCount = 0;
+  int totalRayCount = 0;
+  int collapsedNodes = 0;
+
+#if DEBUG_COLLAPSE
+  cout<<"Collapsing subtree"<<endl;
+  cout<<"acessTime="<<sroot->GetAccessTime()<<endl;
+  cout<<"depth="<<(int)sroot->depth<<endl;
+#endif
+
+  //    tstat.collapsedSubtrees++;
+  //    tstat.collapseDepths += (int)sroot->depth;
+  //    tstat.collapseAccessTimes += time - sroot->GetAccessTime();
+  
+  tstack.push(sroot);
+  VssRay::NewMail();
+	
+  while (!tstack.empty()) {
+    collapsedNodes++;
+    RssTreeNode *node = tstack.top();
+    tstack.pop();
+
+    if (node->IsLeaf()) {
+      RssTreeLeaf *leaf = (RssTreeLeaf *) node;
+      for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		  ri != leaf->rays.end();
+		  ri++) {
+				
+		totalRayCount++;
+		if ((*ri).mRay->IsActive() && !(*ri).mRay->Mailed()) {
+		  (*ri).mRay->Mail();
+		  rayCount++;
+		}
+      }
+    } else {
+      tstack.push(((RssTreeInterior *)node)->back);
+      tstack.push(((RssTreeInterior *)node)->front);
+    }
+  }
+  
+  VssRay::NewMail();
+
+  // create a new node that will hold the rays
+  RssTreeLeaf *newLeaf = new RssTreeLeaf( sroot->parent, rayCount );
+  if (  newLeaf->parent )
+    newLeaf->parent->ReplaceChildLink(sroot, newLeaf);
+  
+
+  tstack.push( sroot );
+
+  while (!tstack.empty()) {
+
+    RssTreeNode *node = tstack.top();
+    tstack.pop();
+
+    if (node->IsLeaf()) {
+      RssTreeLeaf *leaf = (RssTreeLeaf *) node;
+      
+      for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		  ri != leaf->rays.end();
+		  ri++) {
+				
+		// unref this ray from the old node
+				
+		if ((*ri).mRay->IsActive()) {
+		  (*ri).mRay->Unref();
+		  if (!(*ri).mRay->Mailed()) {
+			(*ri).mRay->Mail();
+			newLeaf->AddRay(*ri);
+		  }
+		} else
+		  (*ri).mRay->Unref();
+				
+      }
+    } else {
+      tstack.push(((RssTreeInterior *)node)->back);
+      tstack.push(((RssTreeInterior *)node)->front);
+    }
+  }
+  
+  // delete the node and all its children
+  delete sroot;
+  
+  //   for(RssTreeNode::SRayContainer::iterator ri = newLeaf->rays.begin();
+  //       ri != newLeaf->rays.end();
+  //       ri++)
+  //     (*ri).ray->UnMail(2);
+
+
+#if DEBUG_COLLAPSE
+  cout<<"Total memory before="<<GetMemUsage()<<endl;
+#endif
+
+  stat.nodes -= collapsedNodes - 1;
+  stat.leaves -= collapsedNodes/2 - 1;
+  stat.rayRefs -= totalRayCount - rayCount;
+  
+#if DEBUG_COLLAPSE
+  cout<<"collapsed nodes"<<collapsedNodes<<endl;
+  cout<<"collapsed rays"<<totalRayCount - rayCount<<endl;
+  cout<<"Total memory after="<<GetMemUsage()<<endl;
+  cout<<"================================"<<endl;
+#endif
+
+  //  tstat.collapsedNodes += collapsedNodes;
+  //  tstat.collapsedRays += totalRayCount - rayCount;
+    
+  return totalRayCount - rayCount;
+}
+
+
+int
+RssTree::GetPvsSize(const AxisAlignedBox3 &box) const
+{
+  stack<RssTreeNode *> tstack;
+  PushRoots(tstack);
+
+  Intersectable::NewMail();
+  int pvsSize = 0;
+	
+  while (!tstack.empty()) {
+    RssTreeNode *node = tstack.top();
+    tstack.pop();
+    
+ 
+    if (node->IsLeaf()) {
+	  RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+	  for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		  ri != leaf->rays.end();
+		  ri++)
+		if ((*ri).mRay->IsActive()) {
+		  Intersectable *object;
+		  object = (*ri).GetObject();
+		  if (object && !object->Mailed()) {
+			pvsSize++;
+			object->Mail();
+		  }
+		}
+	} else {
+	  RssTreeInterior *in = (RssTreeInterior *)node;
+	  if (in->axis < 3) {
+		if (box.Max(in->axis) >= in->position )
+		  tstack.push(in->front);
+				
+		if (box.Min(in->axis) <= in->position )
+		  tstack.push(in->back);
+	  } else {
+		// both nodes for directional splits
+		tstack.push(in->front);
+		tstack.push(in->back);
+	  }
+	}
+  }
+  return pvsSize;
+}
+
+int
+RssTree::CollectPvs(const AxisAlignedBox3 &box,
+					ObjectContainer &pvs
+					) const
+{
+  stack<RssTreeNode *> tstack;
+  PushRoots(tstack);
+  
+  Intersectable::NewMail();
+  
+  while (!tstack.empty()) {
+    RssTreeNode *node = tstack.top();
+    tstack.pop();
+    
+ 
+    if (node->IsLeaf()) {
+	  RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+	  for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		  ri != leaf->rays.end();
+		  ri++)
+		if ((*ri).mRay->IsActive()) {
+		  Intersectable *object;
+		  object = (*ri).GetObject();
+		  if (object && !object->Mailed()) {
+			pvs.push_back(object);
+			object->Mail();
+		  }
+		}
+	} else {
+	  RssTreeInterior *in = (RssTreeInterior *)node;
+	  if (in->axis < 3) {
+		if (box.Max(in->axis) >= in->position )
+		  tstack.push(in->front);
+		
+		if (box.Min(in->axis) <= in->position )
+		  tstack.push(in->back);
+	  } else {
+		// both nodes for directional splits
+		tstack.push(in->front);
+		tstack.push(in->back);
+	  }
+	}
+  }
+  return pvs.size();
+}
+
+void
+RssTree::UpdateTreeStatistics()
+{
+  stack<RssTreeNode *> tstack;
+  PushRoots(tstack);
+	
+  float sumPvsSize = 0.0f;
+  float sumRayContribution = 0.0f;
+  float sumWeightedRayContribution = 0.0f;
+  float sumImportance = 0.0f;
+  float sumPvsEntropy = 0.0f;
+  float sumRayLengthEntropy = 0.0f;
+  float sumRays = 0.0f;
+  
+  int leaves = 0;
+
+  while (!tstack.empty()) {
+    RssTreeNode *node = tstack.top();
+    tstack.pop();
+		
+    if (node->IsLeaf()) {
+	  leaves++;
+	  RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+	  UpdatePvsSize(leaf);
+	  
+	  sumPvsSize += leaf->GetPvsSize();
+	  sumRayContribution += leaf->GetAvgRayContribution();
+	  
+
+	  RssTreeNode::RayInfoContainer::const_iterator it = leaf->rays.begin();
+	  for (;it != leaf->rays.end(); ++it) {
+		float weight, contribution;
+		GetRayContribution(*it, weight, contribution);
+		sumWeightedRayContribution += weight*contribution;
+	  }
+	  
+	  //	  sumPvsEntropy += leaf->mPvsEntropy;
+	  //	  sumRayLengthEntropy += leaf->mRayLengthEntropy;
+	  sumRays += leaf->rays.size();
+	  
+	  float imp = leaf->GetImportance();
+	  
+	  //	  if (imp > 1.0f)
+	  //		cout<<"warning imp > 1.0f:"<<imp<<endl;
+	  
+	  sumImportance += imp;
+	  
+
+	} else {
+	  RssTreeInterior *in = (RssTreeInterior *)node;
+	  // both nodes for directional splits
+	  tstack.push(in->front);
+	  tstack.push(in->back);
+	}
+  }
+  
+  stat.avgPvsSize = sumPvsSize/(float)leaves;
+  stat.avgRays = sumRays/(float)leaves;
+  stat.avgRayContribution = sumRayContribution/(float)leaves;
+  //  avgPvsEntropy = sumPvsEntropy/(float)leaves;
+  //  avgRayLengthEntropy = sumRayLengthEntropy/(float)leaves;
+  stat.avgImportance = sumImportance/(float)leaves;
+  stat.avgWeightedRayContribution = sumWeightedRayContribution/(float)sumRays;
+  stat.rayRefs = (int)sumRays;
+}
+
+
+
+int
+RssTree::GenerateRays(
+					  const float ratioPerLeaf,
+					  SimpleRayContainer &rays)
+{
+  stack<RssTreeNode *> tstack;
+  PushRoots(tstack);
+	
+  while (!tstack.empty()) {
+    RssTreeNode *node = tstack.top();
+    tstack.pop();
+		
+    if (node->IsLeaf()) {
+	  RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+	  float c = leaf->GetImportance();
+	  int num = (c*ratioPerLeaf + 0.5);
+	  //			cout<<num<<" ";
+
+	  for (int i=0; i < num; i++) {
+		Vector3 origin = GetBBox(leaf).GetRandomPoint();
+		Vector3 dirVector = GetDirBBox(leaf).GetRandomPoint();
+		Vector3 direction = VssRay::GetDirection(dirVector.x, dirVector.y);
+		//cout<<"dir vector.x="<<dirVector.x<<"direction'.x="<<atan2(direction.x, direction.y)<<endl;
+		rays.push_back(SimpleRay(origin, direction));
+	  }
+			
+	} else {
+	  RssTreeInterior *in = (RssTreeInterior *)node;
+	  // both nodes for directional splits
+	  tstack.push(in->front);
+	  tstack.push(in->back);
+	}
+  }
+
+  return rays.size();
+}
+
+void
+RssTree::CollectLeaves(vector<RssTreeLeaf *> &leaves)
+{
+  stack<RssTreeNode *> tstack;
+  PushRoots(tstack);
+	
+  while (!tstack.empty()) {
+    RssTreeNode *node = tstack.top();
+    tstack.pop();
+		
+    if (node->IsLeaf()) {
+	  RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+	  leaves.push_back(leaf);
+	} else {
+	  RssTreeInterior *in = (RssTreeInterior *)node;
+	  // both nodes for directional splits
+	  tstack.push(in->front);
+	  tstack.push(in->back);
+	}
+  }
+}
+
+bool
+RssTree::ValidLeaf(RssTreeLeaf *leaf) const
+{
+  return true;
+  //return leaf->rays.size() > termMinRays/4;
+}
+
+
+void
+RssTree::PickEdgeRays(RssTreeLeaf *leaf,
+					  int &r1,
+					  int &r2
+					  )
+{
+  int nrays = leaf->rays.size();
+
+  if (nrays == 2) {
+	r1 = 0;
+	r2 = 1;
+	return;
+  }
+
+#if 1
+  int tries = min(20, nrays);
+
+  while (--tries) {
+	r1 = Random(nrays);
+	r2 = Random(nrays);
+	if (leaf->rays[r1].GetObject() != leaf->rays[r2].GetObject())
+	  break;
+  }
+
+  if (r1 == r2)
+	r2 = (r1+1)%leaf->rays.size();
+
+#else
+  // pick a random ray
+  int base = Random(nrays);
+  RssTreeNode::RayInfo *baseRay = &leaf->rays[base];
+  Intersectable *baseObject = baseRay->GetObject();
+  
+  // and a random 5D derivative which will be used to find the minimal projected distances
+  Vector3 spatialDerivative;
+  Vector3 directionalDerivative;
+
+  while (1) {
+	spatialDerivative = Vector3(RandomValue(-1.0f, 1.0f),
+								RandomValue(-1.0f, 1.0f),
+								RandomValue(-1.0f, 1.0f));
+	float m = Magnitude(spatialDerivative);
+	if (m != 0) {
+	  spatialDerivative /= m*Magnitude(GetBBox(leaf).Size());
+	  break;
+	}
+  }
+
+  while (1) {
+	directionalDerivative = Vector3(RandomValue(-1.0f, 1.0f),
+									RandomValue(-1.0f, 1.0f),
+									0.0f);
+	float m = Magnitude(directionalDerivative);
+	if (m != 0) {
+	  directionalDerivative /= m*Magnitude(GetDirBBox(leaf).Size());
+	  break;
+	}
+  }
+
+  // now find the furthest sample from the same object and the closest from a different object
+  int i = 0;
+  float minDist = MAX_FLOAT;
+  float maxDist = -MAX_FLOAT;
+  r1 = base;
+  r2 = base;
+  for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+	  ri != leaf->rays.end();
+	  ri++, i++) {
+	float dist = RssTreeNode::RayInfo::SqrDistance5D(*baseRay,
+													 *ri,
+													 spatialDerivative,
+													 directionalDerivative
+													 );
+
+	if ((*ri).GetObject() == baseObject) {
+	  if (dist > maxDist) {
+		maxDist = dist;
+		r1 = i;
+	  }
+	} else {
+	  if (dist > 0.0f && dist < minDist) {
+		minDist = dist;
+		r2 = i;
+	  }
+	}
+  }
+  
+#endif
+}
+
+
+struct RayNeighbor {
+  int rayInfo;
+  float distance;
+  RayNeighbor():rayInfo(0), distance(MAX_FLOAT) {}
+};
+
+void
+RssTree::FindSilhouetteRays(RssTreeLeaf *leaf,
+							vector<RssTreeLeaf::SilhouetteRays> &rays
+							)
+{
+  // for every leaf find its neares neighbor from a different object
+  vector<RayNeighbor> neighbors(leaf->rays.size());
+  int i, j;
+  for (i=0; i < leaf->rays.size(); i++)
+	for (j=0; j < leaf->rays.size(); j++)
+	  if (i!=j) {
+		float d = RssTreeLeaf::RayInfo::Distance(leaf->rays[i], leaf->rays[j]);
+		if (d < neighbors[i].distance) {
+		  neighbors[i].distance = d;
+		  neighbors[i].rayInfo = j;
+		}
+	  }
+
+  // now check which are the pairs of nearest neighbors
+  for (i=0; i < leaf->rays.size(); i++) {
+	int j = neighbors[i].rayInfo;
+	if (neighbors[j].rayInfo == i) {
+	  // this is a silhouette edge pair
+	  if (i < j) {
+		// generate an silhoutte ray pair
+		rays.push_back(RssTreeLeaf::SilhouetteRays(&leaf->rays[i],
+												   &leaf->rays[j]));
+	  }
+	} else {
+	  // this is not a silhouette ray - delete???
+	}
+  }
+  
+}
+
+
+bool
+GetRandomTripple(vector<RssTreeLeaf::RayInfo *> &rays,
+				 const int index,
+				 int &i1,
+				 int &i2,
+				 int &i3)
+{
+  int found = 0;
+  int indices[3];
+
+  int size = rays.size();
+  // use russian roulete selection for the tripple
+  // number of free positions for the bullet
+  int positions = size - 1;
+  int i;
+  for (i=0; i < size; i++) {
+	if (rays[i]->mRay->Mailed())
+	  positions--;
+  }
+  
+  if (positions < 3)
+	return false;
+  
+  for (i=0; i < size; i++) {
+	if (i != index && !rays[i]->mRay->Mailed()) {
+	  float p = (3 - found)/(float)positions;
+	  if (Random(1.0f) < p) {
+		indices[found] = i;
+		found++;
+	  }
+	}
+	positions--;
+  }
+  return true; // corr. matt
+}
+
+bool
+RssTree::IsRayConvexCombination(const RssTreeNode::RayInfo &ray,
+								const RssTreeNode::RayInfo &r1,
+								const RssTreeNode::RayInfo &r2,
+								const RssTreeNode::RayInfo &r3)
+{
+  
+
+  return false;
+}
+
+int
+RssTree::RemoveInteriorRays(
+							RssTreeLeaf *leaf
+							)
+{
+#if 1
+  // first collect all objects refered in this leaf
+  map<Intersectable *, vector<RssTreeLeaf::RayInfo *> > rayMap;
+  
+  RssTreeLeaf::RayInfoContainer::iterator it = leaf->rays.begin();
+  for (; it != leaf->rays.end(); ++it) {
+	Intersectable *object = (*it).GetObject();
+	
+	rayMap[object].push_back(&(*it));
+// 	vector<RayInfo *> *data = rayMap.Find(object);
+// 	if (data) {
+// 	  data->push_back(&(*it));
+// 	} else {
+// 	  //	  rayMap[object] = vector<RayInfo *>;
+// 	  rayMap[object].push_back(&(*it));
+// 	}
+  }
+
+  // now go through all objects
+  map<Intersectable *, vector<RssTreeLeaf::RayInfo *> >::iterator mi;
+
+  // infos of mailed rays are scheduled for removal
+  VssRay::NewMail();
+  for (mi = rayMap.begin(); mi != rayMap.end(); ++ mi) {
+	vector<RssTreeLeaf::RayInfo *> &rays = (*mi).second;
+	vector<RssTreeLeaf::RayInfo *>::iterator ri = rays.begin();
+	int rayIndex = 0;
+	
+	for (; ri != rays.end(); ++ri, ++rayIndex) {
+	  RssTreeNode::RayInfo *ray = *ri;
+	  int tries = rays.size();
+	  for (int i = 0; i < tries; i++) {
+		int r1, r2, r3;
+		GetRandomTripple(rays,
+						 rayIndex,
+						 r1,
+						 r2,
+						 r3);
+		if (IsRayConvexCombination(*ray,
+								   *rays[r1],
+								   *rays[r2],
+								   *rays[r3])) {
+		  ray->mRay->Mail();
+		}
+	  }
+	}
+  }
+  
+
+#endif  
+	return 0;
+}
+
+void
+RssTree::GenerateLeafRays(RssTreeLeaf *leaf,
+						  const int numberOfRays,
+						  SimpleRayContainer &rays)
+{
+
+  if (numberOfRays == 0)
+	return;
+  
+  
+  int nrays = leaf->rays.size();
+  int startIndex = rays.size();
+  
+  AxisAlignedBox3 box = GetBBox(leaf);
+  AxisAlignedBox3 dirBox = GetDirBBox(leaf);
+
+
+  const float smoothRange = 0.0f;
+  if (smoothRange != 0.0f) {
+	box.Scale(1.0f + smoothRange);
+	dirBox.Scale(1.0f + smoothRange);
+  }
+  
+  
+  Exporter *exporter = NULL;
+  VssRayContainer selectedRays;
+  static int counter = 0;
+  if (counter < 0) {
+	char filename[128];
+	sprintf(filename, "selected-rays%04d.x3d", counter);
+	exporter = Exporter::GetExporter(filename);
+	//	exporter->SetWireframe();
+	//	exporter->ExportKdTree(*mKdTree);
+	exporter->SetWireframe();
+	exporter->ExportScene(preprocessor->mSceneGraph->mRoot);
+	exporter->SetWireframe();
+	exporter->ExportBox(box);
+	exporter->SetFilled();
+	counter++;
+  }
+  
+  int numberOfTries = numberOfRays*4;
+  int generated = 0;
+
+  Intersectable::NewMail();
+  vector<Intersectable *> pvs(0);
+  pvs.reserve(leaf->GetPvsSize());
+  for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+	  ri != leaf->rays.end();
+	  ri++) {
+	Intersectable *object = (*ri).GetObject();
+	if (object) {
+	  if (!object->Mailed()) {
+		object->Mail();
+		object->mCounter = 1;
+		pvs.push_back(object);
+		if (exporter)
+		  exporter->ExportIntersectable(object);
+	  } else {
+		object->mCounter++;
+	  }
+	}
+  }
+  // sort objects based on their mCounter
+  sort(pvs.begin(), pvs.end(), Intersectable::GreaterCounter);
+  
+  float extendedConvexCombinationProb = 0.0f; //0.7f
+  float silhouetteCheckPercentage = 1.0f; //0.5f
+  for (int i=0; generated < numberOfRays && i < numberOfTries; i++) {
+	bool useExtendedConvexCombination = ((nrays >= 2) && (Random(1.0f) <
+														  extendedConvexCombinationProb));
+	
+	Vector3 origin, direction;
+	// generate half of convex combination and half of random rays
+	if (useExtendedConvexCombination) {
+	  // pickup 2 random rays
+	  int r1, r2;
+	  PickEdgeRays(leaf, r1, r2);
+
+	  
+	  Vector3 o1 = leaf->rays[r1].GetOrigin();
+	  Vector3 o2 = leaf->rays[r2].GetOrigin();
+	  
+	  const float overlap = 0.0f;
+	  float w1, w2;
+	  GenerateExtendedConvexCombinationWeights2(w1, w2, overlap);
+	  origin = w1*o1 + w2*o2;
+	  GenerateExtendedConvexCombinationWeights2(w1, w2, overlap);
+	  direction =
+		w1*leaf->rays[r1].GetDir() +
+		w2*leaf->rays[r2].GetDir();
+	} else {
+	  Vector3 dirVector;
+
+	  Vector3 pVector;
+	  Vector3 dVector;
+
+	  bool useHalton = true;
+	  
+	  if (useHalton) {
+		// generate a random 5D vector
+		pVector = Vector3(leaf->halton.GetNumber(1),
+						  leaf->halton.GetNumber(2),
+						  leaf->halton.GetNumber(3));
+		
+		dVector = Vector3(leaf->halton.GetNumber(4),
+						  leaf->halton.GetNumber(5),
+						  0.0f);
+		
+		leaf->halton.GenerateNext();
+	  } else {
+		pVector = Vector3(RandomValue(0.0f, 1.0f),
+						  RandomValue(0.0f, 1.0f),
+						  RandomValue(0.0f, 1.0f));
+		
+		dVector = Vector3(RandomValue(0.0f, 1.0f),
+						  RandomValue(0.0f, 1.0f),
+						  0.0f);
+	  }
+	  
+	  origin = box.GetPoint(pVector);
+	  dirVector = dirBox.GetPoint(dVector);
+
+	  direction = Vector3(sin(dirVector.x), sin(dirVector.y), cos(dirVector.x));
+	}
+
+	// shift the origin a little bit
+	direction.Normalize();
+	
+	//	float dist = Min(avgLength*0.5f, Magnitude(GetBBox(leaf).Size()));
+	float dist = 0.0f;
+	float minT, maxT;
+	// compute interection of the ray with the box
+
+	if (box.ComputeMinMaxT(origin, direction, &minT, &maxT) && minT < maxT)
+	  dist = maxT;
+  
+	
+	origin += direction*dist;
+	
+	bool intersects = false;
+	
+
+	if (i > numberOfRays*(1.0f - silhouetteCheckPercentage)) {
+	  if (exporter) {
+		VssRay *ray = new VssRay(origin, origin + 100*direction, NULL, NULL);
+		selectedRays.push_back(ray);
+	  }
+	  
+	  // check whether the ray does not intersect already visible objects
+	  Ray traversalRay;
+	  traversalRay.Init(origin, direction, Ray::LOCAL_RAY);
+	  for(vector<Intersectable *>::const_iterator oi = pvs.begin();
+		  oi != pvs.end();
+		  oi++) {
+		Intersectable *object = *oi;
+		// do not test every object
+		if (Random(1.0f) > 0.5f)
+		  break;
+		if ( object->CastRay(traversalRay) ) {
+		  intersects = true;
+		  break;
+		}
+	  }
+	}
+	
+	
+	if (!intersects) {
+	  //cout<<"dir vector.x="<<dirVector.x<<"direction'.x="<<atan2(direction.x, direction.y)<<endl;
+	  rays.push_back(SimpleRay(origin, direction));
+	  generated++;
+	}
+  }
+
+  
+  //  cout<<"desired="<<numberOfRays<<" tries="<<i<<endl;
+  // assign pdfs to the generated rays
+  float p = 1.0f; //(box.GetVolume()*dirBox.GetVolume())/i;
+  rays.mSumPdf = 0.0f;
+  for (i=startIndex; i < rays.size(); i++) {
+	rays[i].mPdf = p;
+	rays.mSumPdf += p;
+  }
+  
+  
+  if (exporter) {
+	exporter->ExportRays(selectedRays, RgbColor(1, 0, 0));
+	delete exporter;
+	CLEAR_CONTAINER(selectedRays);
+  }
+  
+  
+}
+
+int
+RssTree::PruneRays(RssTreeLeaf *leaf,
+				   const float contributionThreshold)
+{
+  int i;
+  int j;
+  
+  for (j=0, i=0; i < leaf->rays.size(); i++) {
+	
+	if (leaf->rays[i].mRay->mWeightedPvsContribution > contributionThreshold) {
+	  // copy a valid sample
+	  if (i!=j) 
+		leaf->rays[j] = leaf->rays[i];
+	  j++;
+	} else {
+	  // delete the ray
+	  leaf->rays[i].mRay->Unref();
+	  if (leaf->rays[i].mRay->RefCount() != 0) {
+		cerr<<"Error: refcount!=0, but"<<leaf->rays[j].mRay->RefCount()<<endl;
+		exit(1);
+	  }
+	  delete leaf->rays[i].mRay;
+	}
+  }
+
+
+  leaf->rays.resize(j);
+  int removed = (i-j);
+  stat.rayRefs -= removed;
+  return removed;
+}
+
+int
+RssTree::PruneRaysRandom(RssTreeLeaf *leaf,
+						 const float ratio)
+{
+  int i;
+  int j;
+  
+  for (j=0, i=0; i < leaf->rays.size(); i++) {
+	
+	if (Random(1.0f) < ratio) {
+	  // copy a valid sample
+	  if (i!=j) 
+		leaf->rays[j] = leaf->rays[i];
+	  j++;
+	} else {
+	  // delete the ray
+	  leaf->rays[i].mRay->Unref();
+	  if (leaf->rays[i].mRay->RefCount() != 0) {
+		cerr<<"Error: refcount!=0, but"<<leaf->rays[j].mRay->RefCount()<<endl;
+		exit(1);
+	  }
+	  delete leaf->rays[i].mRay;
+	}
+  }
+
+
+  leaf->rays.resize(j);
+  int removed = (i-j);
+  stat.rayRefs -= removed;
+  return removed;
+}
+
+int
+RssTree::PruneRaysContribution(RssTreeLeaf *leaf,
+							   const float ratio)
+{
+  int i;
+  
+  if (leaf->rays.size() == 0)
+	return 0;
+  
+  sort(leaf->rays.begin(),
+	   leaf->rays.end(),
+	   RssTreeLeaf::RayInfo::GreaterWeightedPvsContribution);
+
+  int desired = ratio*leaf->rays.size();
+  int removed = leaf->rays.size() - desired;
+  
+  for (i=desired; i < leaf->rays.size(); i++) {
+	// delete the ray
+	leaf->rays[i].mRay->Unref();
+	if (leaf->rays[i].mRay->RefCount() != 0) {
+	  cerr<<"Error: refcount!=0, but"<<leaf->rays[i].mRay->RefCount()<<endl;
+	  exit(1);
+	}
+	delete leaf->rays[i].mRay;
+  }
+  
+  leaf->rays.resize(desired);
+  stat.rayRefs -= removed;
+  return removed;
+}
+
+
+int
+RssTree::PruneRays(
+				   const int desired
+				   )
+{
+  bool globalPrunning = true;
+
+  stack<RssTreeNode *> tstack;
+  int prunned = 0;
+
+  Debug<<"Prunning rays...\nOriginal size "<<stat.rayRefs<<endl;
+
+  if (globalPrunning) {
+	VssRayContainer allRays;
+	allRays.reserve(stat.rayRefs);
+	CollectRays(allRays);
+	sort(allRays.begin(),
+		 allRays.end(),
+		 GreaterWeightedPvsContribution);
+	
+	if ( desired >= allRays.size() )
+	  return 0;
+	
+	float contributionThreshold = allRays[desired]->mWeightedPvsContribution;
+	
+	PushRoots(tstack);
+	
+	while (!tstack.empty()) {
+	  RssTreeNode *node = tstack.top();
+	  tstack.pop();
+	  
+	  if (node->IsLeaf()) {
+		RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+		prunned += PruneRays(leaf, contributionThreshold);
+	  } else {
+		RssTreeInterior *in = (RssTreeInterior *)node;
+		// both nodes for directional splits
+		tstack.push(in->front);
+		tstack.push(in->back);
+	  }
+	}
+  } else {
+	// prune random rays from each leaf so that the ratio's remain the same
+	PushRoots(tstack);
+	float ratio = desired/(float)stat.rayRefs;
+	
+	while (!tstack.empty()) {
+	  RssTreeNode *node = tstack.top();
+	  tstack.pop();
+	  
+	  if (node->IsLeaf()) {
+		RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+		// prunned += PruneRaysRandom(leaf, ratio);
+		prunned += PruneRaysContribution(leaf, ratio);
+	  } else {
+		RssTreeInterior *in = (RssTreeInterior *)node;
+		// both nodes for directional splits
+		tstack.push(in->front);
+		tstack.push(in->back);
+	  }
+	}
+
+	
+
+
+  }
+  
+  
+  
+  Debug<<"Remained "<<stat.rayRefs<<" rays"<<endl;
+  
+  return prunned;
+}
+
+int
+RssTree::GenerateRays(const int numberOfRays,
+					  const int numberOfLeaves,
+					  SimpleRayContainer &rays)
+{
+
+
+  vector<RssTreeLeaf *> leaves;
+	
+  CollectLeaves(leaves);
+	
+  sort(leaves.begin(),
+	   leaves.end(),
+	   GreaterContribution);
+			 
+
+  float sumContrib = 0.0;
+  int i;
+  int k = 0;
+  for (i=0; i < leaves.size() && k < numberOfLeaves; i++)
+	if (ValidLeaf(leaves[i])) {
+	  float c = leaves[i]->GetImportance();
+	  sumContrib += c;
+	  //		cout<<"ray contrib "<<i<<" : "<<c<<endl;
+	  k++;
+	}
+				
+  float avgContrib = sumContrib/numberOfLeaves;
+  
+  // always generate at leat n ray per leaf
+  int fixedPerLeaf = 1;
+  int fixed = 1*leaves.size();
+  int iGenerated = numberOfRays;
+  float ratioPerLeaf = iGenerated /(avgContrib*numberOfLeaves);
+
+  k = 0;
+  for (i=0; i < leaves.size() && k < numberOfLeaves; i++)
+	if (ValidLeaf(leaves[i])) {
+	  k++;
+	  RssTreeLeaf *leaf = leaves[i];
+	  float c = leaf->GetImportance();
+
+	  int num = fixedPerLeaf + (int)(c*ratioPerLeaf + 0.5f);
+	  GenerateLeafRays(leaf, num, rays);
+	}
+
+  return rays.size();
+}
+
+
+float
+RssTree::GetAvgPvsSize()
+{
+  stack<RssTreeNode *> tstack;
+  PushRoots(tstack);
+
+  int sumPvs = 0;
+  int leaves = 0;
+  while (!tstack.empty()) {
+    RssTreeNode *node = tstack.top();
+    tstack.pop();
+		
+    if (node->IsLeaf()) {
+	  RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+	  // update pvs size
+	  UpdatePvsSize(leaf);
+	  sumPvs += leaf->GetPvsSize();
+	  leaves++;
+	} else {
+	  RssTreeInterior *in = (RssTreeInterior *)node;
+	  // both nodes for directional splits
+	  tstack.push(in->front);
+	  tstack.push(in->back);
+	}
+  }
+
+
+  return sumPvs/(float)leaves;
+}
+
+float weightAbsContributions = 0.0f;
+// if small very high importance of the last sample
+// if 1.0f then weighs = 1 1/2 1/3 1/4
+float passSampleWeightDecay = 1.0f;
+
+void
+RssTree::GetRayContribution(const RssTreeNode::RayInfo &info,
+							float &weight,
+							float &contribution)
+{
+  VssRay *ray = info.mRay;
+  weight = 1.0f/(mCurrentPass - ray->mPass + passSampleWeightDecay);
+  contribution =
+	weightAbsContributions*ray->mPvsContribution +
+	(1.0f - weightAbsContributions)*ray->mRelativePvsContribution;
+  // store the computed value
+  info.mRay->mWeightedPvsContribution = weight*contribution;
+}
+
+float
+RssTree::GetSampleWeight(const int pass)
+{
+  int passDiff = mCurrentPass - pass;
+  float weight;
+  if (1) 
+	weight = 1.0f/(passDiff + passSampleWeightDecay);
+  else 
+	switch (passDiff) {
+	case 0:
+	  weight = 1.0f;
+	  break;
+	default:
+	  weight = 0.0f;
+	  break;
+	  // 	case 1:
+// 	  weight = 0.5f;
+// 	  break;
+// 	case 2:
+// 	  weight = 0.25f;
+// 	  break;
+// 	case 3:
+// 	  weight = 0.12f;
+// 	  break;
+// 	case 4:
+// 	  weight = 0.06f;
+// 	  break;
+// 	default:
+// 	  weight = 0.03f;
+// 	  break;
+	}
+  return weight;
+}
+
+void
+RssTree::ComputeImportance(RssTreeLeaf *leaf) 
+{
+  if (0) 
+	leaf->mImportance = leaf->GetAvgRayContribution();
+  else {
+	RssTreeNode::RayInfoContainer::const_iterator it = leaf->rays.begin(),
+	  it_end = leaf->rays.end();
+	
+	float sumContributions = 0.0f;
+	float sumRelContributions = 0.0f;
+	float sumWeights = 0.0f;
+	for (; it != it_end; ++it) {
+	  VssRay *ray = (*it).mRay;
+	  float weight = GetSampleWeight(ray->mPass);
+	  
+	  sumContributions += weight*ray->mPvsContribution;
+	  sumRelContributions += weight*ray->mRelativePvsContribution;
+	  
+	  //	  sumWeights += weight;
+	  sumWeights += 1.0f;
+	}
+	// $$ 
+	// sumWeights = leaf->mTotalRays;
+	  
+	if (sumWeights != 0.0f) 
+	  leaf->mImportance =
+		(weightAbsContributions*sumContributions +
+		 (1.0f - weightAbsContributions)*sumRelContributions)/sumWeights;
+	else
+	  leaf->mImportance = 0.0f;
+	
+  }
+  
+  // return GetAvgRayContribution()*mImportance;
+  //return GetAvgRayContribution();
+}
+
+
+float
+RssTreeLeaf::GetImportance()  const
+{
+  return mImportance;
+}
+
+
+float
+RssTreeLeaf::ComputePvsEntropy() const
+{
+  int samples = 0;
+  Intersectable::NewMail();
+  // set all object as belonging to the fron pvs
+  for(RssTreeNode::RayInfoContainer::const_iterator ri = rays.begin();
+	  ri != rays.end();
+	  ri++)
+	if ((*ri).mRay->IsActive()) {
+	  Intersectable *object = (*ri).GetObject();
+	  if (object) {
+		if (!object->Mailed()) {
+		  object->Mail();
+		  object->mCounter = 1;
+		} else
+		  object->mCounter++;
+		samples++;
+	  }
+	}
+  
+  float entropy = 0.0f;
+  
+  if (samples > 1) {
+	Intersectable::NewMail();
+	for(RayInfoContainer::const_iterator ri = rays.begin();
+		ri != rays.end();
+		ri++) 
+	  if ((*ri).mRay->IsActive()) {
+		Intersectable *object = (*ri).GetObject();
+		if (object) {
+		  if (!object->Mailed()) {
+			object->Mail();
+			float p = object->mCounter/(float)samples;
+			entropy -= p*log(p);
+		  }
+		}
+	  }
+	entropy = entropy/log((float)samples);
+  }
+  else
+	entropy = 1.0f;
+  
+  return entropy;
+}
+
+float
+RssTreeLeaf::ComputeRayLengthEntropy() const
+{
+  // get sum of all ray lengths
+  // consider only passing rays or originating rays
+  float sum = 0.0f;
+  int samples = 0;
+  int i=0;
+  for(RayInfoContainer::const_iterator ri = rays.begin();
+      ri != rays.end();
+      ri++) 
+	if ((*ri).mRay->IsActive()) {
+//  	  float s;
+//  	  if (i == 0)
+//  		s = 200;
+//  	  else
+//  		s = 100;
+//  	  i++;
+	  
+	  sum += (*ri).mRay->GetSize();
+	  samples++;
+	}
+  
+  
+  float entropy = 0.0f;
+  
+  if (samples > 1) {
+	i = 0;
+	for(RayInfoContainer::const_iterator ri = rays.begin();
+		ri != rays.end();
+		ri++)
+	  if ((*ri).mRay->IsActive()) {
+//  		float s;
+//  		if (i==0)
+//  		  s = 200;
+//  		else
+//  		  s = 100;
+//  		i++;
+//  		float p = s/sum;
+		float p = (*ri).mRay->GetSize()/sum;
+		entropy -= p*log(p);
+	  }
+	entropy = entropy/log((float)samples);
+  } else
+	entropy = 1.0f;
+  
+  return entropy;
+}
+  
+
+
+float
+RssTreeLeaf::ComputeEntropyImportance() const
+{
+  
+  //  mEntropy = 1.0f - ComputeRayLengthEntropy();
+  return 1.0f - ComputePvsEntropy();
+}
+
+float
+RssTreeLeaf::ComputeRayContributionImportance() const
+{
+  //  mPvsEntropy = ComputePvsEntropy();
+  //  mRayLengthEntropy = ComputeRayLengthEntropy();
+  
+  //  mEntropy = 1.0f - ComputeRayLengthEntropy();
+  return 1.0f - ComputePvsEntropy();
+}
+
+
+AxisAlignedBox3
+RssTree::GetShrankedBBox(const RssTreeNode *node) const
+{
+  if (node->parent == NULL)
+	return bbox;
+  
+  if (!node->IsLeaf())
+	return ((RssTreeInterior *)node)->bbox;
+
+  // evaluate bounding box from the ray origins
+  AxisAlignedBox3 box;
+  box.Initialize();
+  RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+  for(RssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+	  ri != leaf->rays.end();
+	  ri++)
+	if ((*ri).mRay->IsActive()) {
+	  box.Include((*ri).GetOrigin());
+	}
+  return box;
+}
+
+
+int
+RssTree::CollectRays(VssRayContainer &rays,
+					 const int number)
+{
+  VssRayContainer allRays;
+  CollectRays(allRays);
+
+  
+  int desired = min(number, (int)allRays.size());
+  float prob = desired/(float)allRays.size();
+  while (rays.size() < desired) {
+	VssRayContainer::const_iterator it = allRays.begin();
+	for (; it != allRays.end() && rays.size() < desired; it++) {
+	  if (Random(1.0f) < prob)
+		rays.push_back(*it);
+	}
+  }
+  return (int)rays.size();
+}
+
+
+int
+RssTree::CollectRays(VssRayContainer &rays
+					 )
+{
+  VssRay::NewMail();
+
+  stack<RssTreeNode *> tstack;
+  PushRoots(tstack);
+  
+  while (!tstack.empty()) {
+    RssTreeNode *node = tstack.top();
+    tstack.pop();
+	
+    if (node->IsLeaf()) {
+	  RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+	  // update pvs size
+	  RssTreeNode::RayInfoContainer::const_iterator it = leaf->rays.begin();
+	  for (;it != leaf->rays.end(); ++it)
+		if (!(*it).mRay->Mailed()) {
+		  (*it).mRay->Mail();
+		  rays.push_back((*it).mRay);
+		}
+	} else {
+	  RssTreeInterior *in = (RssTreeInterior *)node;
+	  // both nodes for directional splits
+	  tstack.push(in->front);
+	  tstack.push(in->back);
+	}
+  }
+  
+  return (int)rays.size();
+}
+
+
+RssTreeNode *
+RssTree::GetRoot(Intersectable *object) const
+{
+  if (mPerObjectTree && object) {
+	int id = object->GetId()-1;
+	if (id < 0 || id >= mRoots.size()) {
+	  Debug<<"Error: object Id out of range, Id="<<id<<" roots.size()="<<mRoots.size()<<
+		endl<<flush;
+	  id = (int)mRoots.size()-1; // $$ last tree is used by all unsigned objects
+	}
+	return mRoots[id];
+  } else
+	return mRoots[0];
+}
+
+void
+RssTree::PushRoots(priority_queue<TraversalData> &st) const
+{
+  for (int i=0; i < mRoots.size(); i++)
+	st.push(TraversalData(mRoots[i], GetBBox(mRoots[i]), 0));
+}
+
+void
+RssTree::PushRoots(stack<RssTreeNode *> &st)  const
+{
+  for (int i=0; i < mRoots.size(); i++)
+	st.push(mRoots[i]);
+}
+
+void
+RssTree::PushRoots(stack<RayTraversalData> &st, RssTreeNode::RayInfo &info)  const
+{
+  for (int i=0; i < mRoots.size(); i++)
+	st.push(RayTraversalData(mRoots[i], info));
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Triangle3.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Triangle3.cpp	(revision 191)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Triangle3.cpp	(revision 191)
@@ -0,0 +1,7 @@
+#include "Triangle3.h"
+
+float
+Triangle3::GetSpatialAngle(const Vector3 &point) const
+{
+  return 0.0f;
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VssTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VssTree.cpp	(revision 551)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VssTree.cpp	(revision 551)
@@ -0,0 +1,2009 @@
+
+// ================================================================
+// $Id: lsds_kdtree.cpp,v 1.18 2005/04/16 09:34:21 bittner Exp $
+// ****************************************************************
+/**
+   The KD tree based LSDS
+*/
+// Initial coding by
+/**
+   @author Jiri Bittner
+*/
+
+// Standard headers
+#include <stack>
+#include <queue>
+#include <algorithm>
+#include <fstream>
+#include <string>
+
+#include "VssTree.h"
+
+#include "Environment.h"
+#include "VssRay.h"
+#include "Intersectable.h"
+#include "Ray.h"
+
+#define DEBUG_SPLIT_COST 0
+
+// Static variables
+int
+VssTreeLeaf::mailID = 0;
+
+inline void
+AddObject2Pvs(Intersectable *object,
+			  const int side,
+			  int &pvsBack,
+			  int &pvsFront)
+{
+  
+  if (!object)
+	return;
+  
+  if (side <= 0) {
+	if (!object->Mailed() && !object->Mailed(2)) {
+	  pvsBack++;
+	  if (object->Mailed(1))
+		object->Mail(2);
+	  else
+		object->Mail();
+	}
+  }
+  
+  if (side >= 0) {
+	if (!object->Mailed(1) && !object->Mailed(2)) {
+	  pvsFront++;
+	  if (object->Mailed())
+		object->Mail(2);
+	  else
+		object->Mail(1);
+	}
+  }
+}
+
+// Constructor
+VssTree::VssTree()
+{
+  environment->GetIntValue("VssTree.maxDepth", termMaxDepth);
+  environment->GetIntValue("VssTree.minPvs", termMinPvs);
+  environment->GetIntValue("VssTree.minRays", termMinRays);
+  environment->GetFloatValue("VssTree.maxRayContribution", termMaxRayContribution);
+  environment->GetFloatValue("VssTree.maxCostRatio", termMaxCostRatio);
+
+  environment->GetFloatValue("VssTree.minSize", termMinSize);
+  termMinSize = sqr(termMinSize);
+	
+  environment->GetFloatValue("VssTree.refDirBoxMaxSize", refDirBoxMaxSize);
+  refDirBoxMaxSize = sqr(refDirBoxMaxSize);
+  
+  environment->GetFloatValue("VssTree.epsilon", epsilon);
+  environment->GetFloatValue("VssTree.ct_div_ci", ct_div_ci);
+	
+  environment->GetFloatValue("VssTree.maxTotalMemory", maxTotalMemory);
+  environment->GetFloatValue("VssTree.maxStaticMemory", maxStaticMemory);
+  
+  
+
+
+  float refDirAngle;
+  environment->GetFloatValue("VssTree.refDirAngle", refDirAngle);
+  
+  environment->GetIntValue("VssTree.accessTimeThreshold", accessTimeThreshold);
+  //= 1000;
+  environment->GetIntValue("VssTree.minCollapseDepth", minCollapseDepth);
+  //  int minCollapseDepth = 4;
+
+  //  pRefDirThresh = cos(0.5*M_PI - M_PI*refDirAngle/180.0);
+  //  cosRefDir = cos(M_PI*refDirAngle/180.0);
+  //  sinRefDir = sin(M_PI*refDirAngle/180.0);
+  
+  
+  // split type
+  char sname[128];
+  environment->GetStringValue("VssTree.splitType", sname);
+  string name(sname);
+	
+  if (name.compare("regular") == 0)
+    splitType = ESplitRegular;
+  else
+    if (name.compare("heuristic") == 0)
+      splitType = ESplitHeuristic;
+	else
+	  if (name.compare("hybrid") == 0)
+		splitType = ESplitHybrid;
+	  else {
+		cerr<<"Invalid VssTree split type "<<name<<endl;
+		exit(1);
+	  }
+	
+  environment->GetBoolValue("VssTree.randomize", randomize);
+  environment->GetBoolValue("VssTree.splitUseOnlyDrivingAxis", mSplitUseOnlyDrivingAxis);
+  environment->GetBoolValue("VssTree.useRss", mUseRss);
+
+  environment->GetBoolValue("VssTree.interleaveDirSplits", mInterleaveDirSplits);
+  environment->GetIntValue("VssTree.dirSplitDepth", mDirSplitDepth);
+
+  root = NULL;
+  
+  splitCandidates = new vector<SortableEntry>;
+}
+
+
+VssTree::~VssTree()
+{
+  if (root)
+    delete root;
+}
+
+
+
+
+void
+VssStatistics::Print(ostream &app) const
+{
+  app << "===== VssTree statistics ===============\n";
+
+  app << "#N_RAYS ( Number of rays )\n"
+      << rays <<endl;
+
+  app << "#N_INITPVS ( Initial PVS size )\n"
+      << initialPvsSize <<endl;
+  
+  app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
+
+  app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
+
+  app << "#N_SPLITS ( Number of splits in axes x y z dx dy dz \n";
+  for (int i=0; i<7; i++)
+    app << splits[i] <<" ";
+  app <<endl;
+
+  app << "#N_RAYREFS ( Number of rayRefs )\n" <<
+    rayRefs << "\n";
+
+  app << "#N_RAYRAYREFS  ( Number of rayRefs / ray )\n" <<
+    rayRefs/(double)rays << "\n";
+
+  app << "#N_LEAFRAYREFS  ( Number of rayRefs / leaf )\n" <<
+    rayRefs/(double)Leaves() << "\n";
+
+  app << "#N_MAXRAYREFS  ( Max number of rayRefs / leaf )\n" <<
+    maxRayRefs << "\n";
+
+
+  //  app << setprecision(4);
+
+  app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maxdepth )\n"<<
+    maxDepthNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_PMINPVSLEAVES  ( Percentage of leaves with minPvs )\n"<<
+    minPvsNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_PMINRAYSLEAVES  ( Percentage of leaves with minRays )\n"<<
+    minRaysNodes*100/(double)Leaves()<<endl;
+	
+  app << "#N_PMINSIZELEAVES  ( Percentage of leaves with minSize )\n"<<
+    minSizeNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_PMAXRAYCONTRIBLEAVES  ( Percentage of leaves with maximal ray contribution )\n"<<
+    maxRayContribNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_PMAXCOSTRATIOLEAVES  ( Percentage of leaves with max cost ratio )\n"<<
+    maxCostRatioNodes*100/(double)Leaves()<<endl;
+
+  app << "#N_ADDED_RAYREFS  (Number of dynamically added ray references )\n"<<
+    addedRayRefs<<endl;
+
+  app << "#N_REMOVED_RAYREFS  (Number of dynamically removed ray references )\n"<<
+    removedRayRefs<<endl;
+
+  //  app << setprecision(4);
+
+  app << "#N_CTIME  ( Construction time [s] )\n"
+      << Time() << " \n";
+
+  app << "===== END OF VssTree statistics ==========\n";
+
+}
+
+
+void
+VssTreeLeaf::UpdatePvsSize()
+{
+  if (!mValidPvs) {
+	Intersectable::NewMail();
+	int pvsSize = 0;
+	for(VssTreeNode::RayInfoContainer::iterator ri = rays.begin();
+		ri != rays.end();
+		ri++)
+	  if ((*ri).mRay->IsActive()) {
+		Intersectable *object;
+#if BIDIRECTIONAL_RAY
+		object = (*ri).mRay->mOriginObject;
+		if (object && !object->Mailed()) {
+		  pvsSize++;
+		  object->Mail();
+		}
+#endif
+		object = (*ri).mRay->mTerminationObject;
+		if (object && !object->Mailed()) {
+		  pvsSize++;
+		  object->Mail();
+		}
+	  }
+	mPvsSize = pvsSize;
+	mValidPvs = true;
+
+  }
+}
+
+bool
+VssTree::ClipRay(
+				 VssTreeNode::RayInfo &rayInfo,
+				 const AxisAlignedBox3 &box
+				 )
+{
+  float tmin, tmax;
+  static Ray ray;
+  ray.Init(rayInfo.mRay->GetOrigin(), rayInfo.mRay->GetDir(), Ray::LINE_SEGMENT);
+  box.ComputeMinMaxT(ray, &tmin, &tmax);
+  if (tmin >= tmax)
+	return false;
+	
+  if (tmin > 0.0f)
+	rayInfo.SetMinT(tmin);
+
+  if (tmax < 1.0f)
+	rayInfo.SetMaxT(tmax);
+	
+  //  	vssRay->SetupEndPoints(
+  //  												 origin,
+  //  												 termination
+  //  												 );
+  return true;
+}
+
+
+void
+VssTree::Construct(
+				   VssRayContainer &rays,
+				   AxisAlignedBox3 *forcedBoundingBox
+				   )
+{
+  stat.Start();
+  
+  maxMemory = maxStaticMemory;
+
+  if (root)
+    delete root;
+	
+  root = new VssTreeLeaf(NULL, rays.size());
+  // first construct a leaf that will get subdivide
+  VssTreeLeaf *leaf = (VssTreeLeaf *) root;
+
+  stat.nodes = 1;
+  
+  bbox.Initialize();
+  dirBBox.Initialize();
+
+  if (mUseRss)
+	forcedBoundingBox = NULL;
+	
+  for(VssRayContainer::const_iterator ri = rays.begin();
+      ri != rays.end();
+      ri++) {
+		
+	VssTreeNode::RayInfo info(*ri);
+	if (forcedBoundingBox)
+	  if (!ClipRay(info, *forcedBoundingBox))
+		continue;
+	leaf->AddRay(info);
+		
+    bbox.Include((*ri)->GetOrigin());
+    bbox.Include((*ri)->GetTermination());
+    
+		
+	dirBBox.Include(Vector3(
+							(*ri)->GetDirParametrization(0),
+							(*ri)->GetDirParametrization(1),
+							0
+							)
+					);
+  }
+	
+	
+  if ( forcedBoundingBox ) 
+	bbox = *forcedBoundingBox;
+	
+  cout<<"Bbox = "<<bbox<<endl;
+  cout<<"Dirr Bbox = "<<dirBBox<<endl;
+
+  stat.rays = leaf->rays.size();
+  leaf->UpdatePvsSize();
+  leaf->ComputeEntropyImportance();
+
+  stat.initialPvsSize = leaf->GetPvsSize();
+  // Subdivide();
+  root = Subdivide(TraversalData(leaf, bbox, 0));
+
+  if (splitCandidates) {
+    // force realease of this vector
+    delete splitCandidates;
+    splitCandidates = new vector<SortableEntry>;
+  }
+  
+  stat.Stop();
+
+  stat.Print(cout);
+  cout<<"#Total memory="<<GetMemUsage()<<endl;
+
+}
+
+int
+VssTree::UpdateSubdivision()
+{
+  priority_queue<TraversalData> tStack;
+  //  stack<TraversalData> tStack;
+  
+  tStack.push(TraversalData(root, bbox, 0));
+	
+  AxisAlignedBox3 backBox;
+  AxisAlignedBox3 frontBox;
+
+  maxMemory = maxTotalMemory;
+  int subdivided = 0;
+  int lastMem = 0;
+  while (!tStack.empty()) {
+		
+	float mem = GetMemUsage();
+		
+	if ( lastMem/10 != ((int)mem)/10) {
+	  cout<<mem<<" MB"<<endl;
+	}
+	lastMem = (int)mem;
+		
+	if (  mem > maxMemory ) {
+      // count statistics on unprocessed leafs
+      while (!tStack.empty()) {
+		//				EvaluateLeafStats(tStack.top());
+		tStack.pop();
+      }
+      break;
+    }
+    
+    TraversalData data = tStack.top();
+    tStack.pop();
+
+	if (data.node->IsLeaf()) {
+	  VssTreeNode *node = SubdivideNode((VssTreeLeaf *) data.node,
+										data.bbox,
+										backBox,
+										frontBox
+										);
+	  if (!node->IsLeaf()) {
+		subdivided++;
+		VssTreeInterior *interior = (VssTreeInterior *) node;
+		// push the children on the stack
+		tStack.push(TraversalData(interior->back, backBox, data.depth+1));
+		tStack.push(TraversalData(interior->front, frontBox, data.depth+1));
+	  } else {
+		//      EvaluateLeafStats(data);
+	  }
+	} else {
+	  VssTreeInterior *interior = (VssTreeInterior *) data.node;
+	  tStack.push(TraversalData(interior->back, GetBBox(interior->back), data.depth+1));
+	  tStack.push(TraversalData(interior->front, GetBBox(interior->front), data.depth+1));
+	}
+  }
+  return subdivided;
+}
+
+
+VssTreeNode *
+VssTree::Subdivide(const TraversalData &tdata)
+{
+  VssTreeNode *result = NULL;
+
+  priority_queue<TraversalData> tStack;
+  //  stack<TraversalData> tStack;
+  
+  tStack.push(tdata);
+
+  AxisAlignedBox3 backBox;
+  AxisAlignedBox3 frontBox;
+
+  
+  int lastMem = 0;
+  while (!tStack.empty()) {
+
+	float mem = GetMemUsage();
+		
+	if ( lastMem/10 != ((int)mem)/10) {
+	  cout<<mem<<" MB"<<endl;
+	}
+	lastMem = (int)mem;
+		
+	if (  mem > maxMemory ) {
+      // count statistics on unprocessed leafs
+      while (!tStack.empty()) {
+		EvaluateLeafStats(tStack.top());
+		tStack.pop();
+      }
+      break;
+    }
+    
+    TraversalData data = tStack.top();
+    tStack.pop();
+    
+    VssTreeNode *node = SubdivideNode((VssTreeLeaf *) data.node,
+									  data.bbox,
+									  backBox,
+									  frontBox
+									  );
+    if (result == NULL)
+      result = node;
+    
+    if (!node->IsLeaf()) {
+			
+      VssTreeInterior *interior = (VssTreeInterior *) node;
+      // push the children on the stack
+      tStack.push(TraversalData(interior->back, backBox, data.depth+1));
+      tStack.push(TraversalData(interior->front, frontBox, data.depth+1));
+			
+    } else {
+      EvaluateLeafStats(data);
+    }
+  }
+
+  return result;
+}
+
+
+// returns selected plane for subdivision
+int
+VssTree::SelectPlane(
+					 VssTreeLeaf *leaf,
+					 const AxisAlignedBox3 &box,
+					 float &position,
+					 int &raysBack,
+					 int &raysFront,
+					 int &pvsBack,
+					 int &pvsFront
+					 )
+{
+
+  int minDirDepth = 6;
+  int axis;
+  float costRatio;
+	
+  costRatio = BestCostRatio(leaf,
+							axis,
+							position,
+							raysBack,
+							raysFront,
+							pvsBack,
+							pvsFront
+							);
+#if DEBUG_SPLIT_COST
+  cout<<axis<<" r="<<costRatio<<endl;
+#endif
+  if (costRatio > termMaxCostRatio) {
+	//		cout<<"Too big cost ratio "<<costRatio<<endl;
+	stat.maxCostRatioNodes++;
+	return -1;
+  }
+	
+#if 0	
+  cout<<
+	"pvs="<<leaf->mPvsSize<<
+	" rays="<<leaf->rays.size()<<
+	" rc="<<leaf->GetAvgRayContribution()<<
+	" axis="<<axis<<endl;
+#endif
+	
+  return axis;
+}
+
+
+float
+VssTree::GetCostRatio(
+					  VssTreeLeaf *leaf,
+					  const int axis,
+					  const float position,
+					  const int raysBack,
+					  const int raysFront,
+					  const int pvsBack,
+					  const int pvsFront
+					  )
+{
+  bool costImportance = true;
+
+  float ratio;
+  AxisAlignedBox3 box;
+  float minBox, maxBox;
+
+  if (axis < 3) {
+	box = GetBBox(leaf);
+	minBox = box.Min(axis);
+	maxBox = box.Max(axis);
+  }	else {
+	box = GetDirBBox(leaf);
+	minBox = box.Min(axis-3);
+	maxBox = box.Max(axis-3);
+  }
+	
+  float sizeBox = maxBox - minBox;
+
+  int pvsSize = leaf->GetPvsSize();
+
+  if (!costImportance) {
+	//		float sum = raysBack*(position - minBox) + raysFront*(maxBox - position);
+	float sum = pvsBack*(position - minBox) + pvsFront*(maxBox - position);
+	float newCost = ct_div_ci + sum/sizeBox;
+	float oldCost = pvsSize;
+	ratio = newCost/oldCost;
+  } else {
+	// importance based cost
+#if 0
+	float newContrib =
+	  ((position - minBox)*sqr(pvsBack/(raysBack + Limits::Small)) +
+	   (maxBox - position)*sqr(pvsFront/(raysFront + Limits::Small)))/sizeBox;
+		
+	//			float newContrib =
+	//				sqr(pvsBack/(raysBack + Limits::Small)) +
+	//				sqr(pvsFront/(raysFront + Limits::Small));
+	float oldContrib = sqr(leaf->GetAvgRayContribution());
+	ratio = oldContrib/newContrib;
+#else
+#if 1
+	float newCost = raysBack*pvsBack  + raysFront*pvsFront;
+	float oldCost = (float)leaf->rays.size()*pvsSize;
+	ratio = newCost/oldCost;
+#else
+	float newCost = (pvsBack  + pvsFront)*0.5f;
+	float oldCost = pvsSize;
+	ratio = newCost/oldCost;
+#endif
+#endif
+  }
+	
+  return ratio;
+}
+							
+
+float
+VssTree::EvalCostRatio(
+					   VssTreeLeaf *leaf,
+					   const int axis,
+					   const float position,
+					   int &raysBack,
+					   int &raysFront,
+					   int &pvsBack,
+					   int &pvsFront
+					   )
+{
+  raysBack = 0;
+  raysFront = 0;
+  pvsFront = 0;
+  pvsBack = 0;
+
+	
+  Intersectable::NewMail(3);
+	
+  if (axis <= VssTreeNode::SPLIT_Z) {
+    // this is the main ray classification loop!
+    for(VssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		ri != leaf->rays.end();
+		ri++)
+      if ((*ri).mRay->IsActive()) {
+		float t;
+		// determine the side of this ray with respect to the plane
+		int side = (*ri).ComputeRayIntersection(axis, position, t);
+		//				(*ri).mRay->mSide = side;
+				
+		if (side <= 0)
+		  raysBack++;
+				
+		if (side >= 0)
+		  raysFront++;
+				
+		AddObject2Pvs((*ri).mRay->mTerminationObject, side, pvsBack, pvsFront);
+      }
+		
+  } else {
+		
+	// directional split
+    for(VssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		ri != leaf->rays.end();
+		ri++)
+      if ((*ri).mRay->IsActive()) {
+				
+		// determine the side of this ray with respect to the plane
+		int side;
+		if ((*ri).mRay->GetDirParametrization(axis - 3) > position)
+		  side = 1;
+		else
+		  side = -1;
+
+		if (side <= 0)
+		  raysBack++;
+				
+		if (side >= 0)
+		  raysFront++;
+
+		//				(*ri).mRay->mSide = side;
+		AddObject2Pvs((*ri).mRay->mTerminationObject, side, pvsBack, pvsFront);
+				
+      }
+  }
+
+  float ratio = GetCostRatio(
+							 leaf,
+							 axis,
+							 position,
+							 raysBack,
+							 raysFront,
+							 pvsBack,
+							 pvsFront);
+
+  //	cout<<axis<<" "<<pvsSize<<" "<<pvsBack<<" "<<pvsFront<<endl;
+  //  float oldCost = leaf->rays.size();
+
+  //	cout<<"ratio="<<ratio<<endl;
+
+  return ratio;
+}
+
+float
+VssTree::BestCostRatio(
+					   VssTreeLeaf *leaf,
+					   int &axis,
+					   float &position,
+					   int &raysBack,
+					   int &raysFront,
+					   int &pvsBack,
+					   int &pvsFront
+					   )
+{
+  int nRaysBack[6], nRaysFront[6];
+  int nPvsBack[6], nPvsFront[6];
+  float nPosition[6];
+  float nCostRatio[6];
+  int bestAxis = -1;
+	
+  AxisAlignedBox3 sBox = GetBBox(leaf);
+  AxisAlignedBox3 dBox = GetDirBBox(leaf);
+  // int sAxis = box.Size().DrivingAxis();
+  int sAxis = sBox.Size().DrivingAxis();
+  int dAxis = dBox.Size().DrivingAxis() + 3;
+
+
+  float dirSplitBoxSize = 0.01f;
+  bool allowDirSplit = Magnitude(sBox.Size())*dirSplitBoxSize < Magnitude(bbox.Size());
+		
+  
+  for (axis = 0; axis < 5; axis++)
+	if (mInterleaveDirSplits ||
+		(axis < 3 && leaf->depth < mDirSplitDepth) ||
+		(axis >= 3 && leaf->depth >= mDirSplitDepth)
+		) {
+	  if (!mSplitUseOnlyDrivingAxis || axis == sAxis || axis == dAxis) {
+		
+		
+		if (splitType == ESplitRegular) {
+		  if (axis < 3)
+			nPosition[axis] = (sBox.Min()[axis] + sBox.Max()[axis])*0.5f;
+		  else
+			nPosition[axis] = (dBox.Min()[axis-3] + dBox.Max()[axis-3])*0.5f;
+		  
+		  nCostRatio[axis] = EvalCostRatio(leaf,
+										   axis,
+										   nPosition[axis],
+										   nRaysBack[axis],
+										   nRaysFront[axis],
+										   nPvsBack[axis],
+										   nPvsFront[axis]
+										   );
+		} else
+		  if (splitType == ESplitHeuristic) {
+			nCostRatio[axis] = EvalCostRatioHeuristic(
+													  leaf,
+													  axis,
+													  nPosition[axis],
+													  nRaysBack[axis],
+													  nRaysFront[axis],
+													  nPvsBack[axis],
+													  nPvsFront[axis]);
+		  } else
+			if (splitType == ESplitHybrid) {
+			  if (leaf->depth > 7)
+				nCostRatio[axis] = EvalCostRatioHeuristic(
+														  leaf,
+														  axis,
+														  nPosition[axis],
+														  nRaysBack[axis],
+														  nRaysFront[axis],
+														  nPvsBack[axis],
+														  nPvsFront[axis]);
+			  else {
+				if (axis < 3)
+				  nPosition[axis] = (sBox.Min()[axis] + sBox.Max()[axis])*0.5f;
+				else
+				  nPosition[axis] = (dBox.Min()[axis-3] + dBox.Max()[axis-3])*0.5f;
+				
+				nCostRatio[axis] = EvalCostRatio(leaf,
+												 axis,
+												 nPosition[axis],
+												 nRaysBack[axis],
+												 nRaysFront[axis],
+												 nPvsBack[axis],
+												 nPvsFront[axis]
+												 );
+			  }
+			} else {
+			  cerr<<"VssTree: Unknown split heuristics\n";
+			  exit(1);
+			}
+		
+		
+		if ( bestAxis == -1)
+		  bestAxis = axis;
+		else
+		  if ( nCostRatio[axis] < nCostRatio[bestAxis] )
+			bestAxis = axis;
+	  }
+	}
+  
+  axis = bestAxis;
+  position = nPosition[bestAxis];
+
+  raysBack = nRaysBack[bestAxis];
+  raysFront = nRaysFront[bestAxis];
+
+  pvsBack = nPvsBack[bestAxis];
+  pvsFront = nPvsFront[bestAxis];
+	
+  return nCostRatio[bestAxis];
+}
+
+	
+float
+VssTree::EvalCostRatioHeuristic(
+								VssTreeLeaf *leaf,
+								const int axis,
+								float &bestPosition,
+								int &raysBack,
+								int &raysFront,
+								int &pvsBack,
+								int &pvsFront
+								)
+{
+  AxisAlignedBox3 box;
+  float minBox, maxBox;
+	
+  if (axis < 3) {
+	box = GetBBox(leaf);
+	minBox = box.Min(axis);
+	maxBox = box.Max(axis);
+  } else {
+	box = GetDirBBox(leaf);
+	minBox = box.Min(axis-3);
+	maxBox = box.Max(axis-3);
+  }
+	
+  SortSplitCandidates(leaf, axis);
+  
+  // go through the lists, count the number of objects left and right
+  // and evaluate the following cost funcion:
+  // C = ct_div_ci  + (ql*rl + qr*rr)/queries
+	
+  int rl=0, rr = leaf->rays.size();
+  int pl=0, pr = leaf->GetPvsSize();
+  float sizeBox = maxBox - minBox;
+	
+  float minBand = minBox + 0.1*(maxBox - minBox);
+  float maxBand = minBox + 0.9*(maxBox - minBox);
+	
+  float minRatio = 1e20;
+	
+  Intersectable::NewMail();
+  // set all object as belonging to the fron pvs
+  for(VssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+	  ri != leaf->rays.end();
+	  ri++)
+	if ((*ri).mRay->IsActive()) {
+	  Intersectable *object = (*ri).mRay->mTerminationObject;
+	  if (object)
+		if (!object->Mailed()) {
+		  object->Mail();
+		  object->mCounter = 1;
+		} else
+		  object->mCounter++;
+	}
+	
+  Intersectable::NewMail();
+	
+  for(vector<SortableEntry>::const_iterator ci = splitCandidates->begin();
+	  ci < splitCandidates->end();
+	  ci++) {
+	VssRay *ray;
+	switch ((*ci).type) {
+	case SortableEntry::ERayMin: {
+	  rl++;
+	  ray = (VssRay *) (*ci).data;
+	  Intersectable *object = ray->mTerminationObject;
+	  if (object && !object->Mailed()) {
+		object->Mail();
+		pl++;
+	  }
+	  break;
+	}
+	case SortableEntry::ERayMax: {
+	  rr--;
+	  ray = (VssRay *) (*ci).data;
+	  Intersectable *object = ray->mTerminationObject;
+	  if (object) {
+		if (--object->mCounter == 0)
+		  pr--;
+	  }
+	  break;
+	}
+	}
+
+	float position = (*ci).value;
+		
+	if (position > minBand && position < maxBand) {
+			
+	  float ratio = GetCostRatio(
+								 leaf,
+								 axis,
+								 position,
+								 rl,
+								 rr,
+								 pl,
+								 pr);
+			
+			
+	  //      cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl;
+	  //      cout<<"cost= "<<sum<<endl;
+			
+	  if (ratio < minRatio) {
+		minRatio = ratio;
+		bestPosition = position;
+				
+		raysBack = rl;
+		raysFront = rr;
+				
+		pvsBack = pl;
+		pvsFront = pr;
+				
+      }
+    }
+  }
+
+  
+  //  cout<<"===================="<<endl;
+  //  cout<<"costRatio="<<ratio<<" pos="<<position<<" t="<<(position - minBox)/(maxBox - minBox)
+  //      <<"\t q=("<<queriesBack<<","<<queriesFront<<")\t r=("<<raysBack<<","<<raysFront<<")"<<endl;
+  return minRatio;
+}
+
+void
+VssTree::SortSplitCandidates(
+							 VssTreeLeaf *node,
+							 const int axis
+							 )
+{
+  
+  splitCandidates->clear();
+  
+  int requestedSize = 2*(node->rays.size());
+  // creates a sorted split candidates array
+  if (splitCandidates->capacity() > 500000 &&
+      requestedSize < (int)(splitCandidates->capacity()/10) ) {
+    
+    delete splitCandidates;
+    splitCandidates = new vector<SortableEntry>;
+  }
+  
+  splitCandidates->reserve(requestedSize);
+
+  // insert all queries 
+  for(VssTreeNode::RayInfoContainer::const_iterator ri = node->rays.begin();
+      ri < node->rays.end();
+      ri++) {
+	if ((*ri).mRay->IsActive()) {
+	  if (axis < 3) {
+		bool positive = (*ri).mRay->HasPosDir(axis);
+		splitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMin :
+												 SortableEntry::ERayMax,
+												 (*ri).ExtrapOrigin(axis),
+												 (void *)(*ri).mRay)
+								   );
+				
+		splitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMax :
+												 SortableEntry::ERayMin,
+												 (*ri).ExtrapTermination(axis),
+												 (void *)(*ri).mRay)
+								   );
+	  } else {
+		float pos = (*ri).mRay->GetDirParametrization(axis-3);
+		splitCandidates->push_back(SortableEntry(SortableEntry::ERayMin,
+												 pos - Limits::Small,
+												 (void *)(*ri).mRay)
+								   );
+				
+		splitCandidates->push_back(SortableEntry(SortableEntry::ERayMax,
+												 pos + Limits::Small,
+												 (void *)(*ri).mRay)
+								   );
+	  }
+	}
+  }
+
+  stable_sort(splitCandidates->begin(), splitCandidates->end());
+}
+
+
+void
+VssTree::EvaluateLeafStats(const TraversalData &data)
+{
+
+  // the node became a leaf -> evaluate stats for leafs
+  VssTreeLeaf *leaf = (VssTreeLeaf *)data.node;
+
+  if (data.depth >= termMaxDepth)
+    stat.maxDepthNodes++;
+  
+  //  if ( (int)(leaf->rays.size()) < termMinCost)
+  //    stat.minCostNodes++;
+  if ( leaf->GetPvsSize() < termMinPvs)
+	stat.minPvsNodes++;
+
+  if ( leaf->GetPvsSize() < termMinRays)
+	stat.minRaysNodes++;
+
+  if (0 && leaf->GetAvgRayContribution() > termMaxRayContribution )
+	stat.maxRayContribNodes++;
+	
+  if (SqrMagnitude(data.bbox.Size()) <= termMinSize) {
+	stat.minSizeNodes++;
+  }
+
+  if ( (int)(leaf->rays.size()) > stat.maxRayRefs)
+    stat.maxRayRefs = (int)leaf->rays.size();
+
+}
+
+bool
+VssTree::TerminationCriteriaSatisfied(VssTreeLeaf *leaf)
+{
+  return ( (leaf->GetPvsSize() < termMinPvs) ||
+		   (leaf->rays.size() < termMinRays) ||
+		   //			 (leaf->GetAvgRayContribution() > termMaxRayContribution ) ||
+		   (leaf->depth >= termMaxDepth) ||
+		   (SqrMagnitude(GetBBox(leaf).Size()) <= termMinSize)
+		   //		   ||
+		   //		   (mUseRss && leaf->mPassingRays == leaf->rays.size())
+		   );
+}
+
+
+VssTreeNode *
+VssTree::SubdivideNode(
+					   VssTreeLeaf *leaf,
+					   const AxisAlignedBox3 &box,
+					   AxisAlignedBox3 &backBBox,
+					   AxisAlignedBox3 &frontBBox
+					   )
+{
+  
+  if (TerminationCriteriaSatisfied(leaf)) {
+#if 0
+	if (leaf->depth >= termMaxDepth) {
+	  cout<<"Warning: max depth reached depth="<<(int)leaf->depth<<" rays="<<leaf->rays.size()<<endl;
+	  cout<<"Bbox: "<<GetBBox(leaf)<<" dirbbox:"<<GetDirBBox(leaf)<<endl;
+	}
+#endif
+		
+	return leaf;
+  }
+	
+  float position;
+	
+  // first count ray sides
+  int raysBack;
+  int raysFront;
+  int pvsBack;
+  int pvsFront;
+	
+  // select subdivision axis
+  int axis = SelectPlane( leaf, box, position, raysBack, raysFront, pvsBack, pvsFront);
+  //	cout<<axis<<" ";
+	
+  //	cout<<"rays back="<<raysBack<<" rays front="<<raysFront<<" pvs back="<<pvsBack<<" pvs front="<<
+  //		pvsFront<<endl;
+
+  if (axis == -1) {
+    return leaf;
+  }
+  
+  stat.nodes+=2;
+  stat.splits[axis]++;
+
+  // add the new nodes to the tree
+  VssTreeInterior *node = new VssTreeInterior(leaf->parent);
+
+  node->axis = axis;
+  node->position = position;
+  node->bbox = box;
+  node->dirBBox = GetDirBBox(leaf);
+  
+  backBBox = box;
+  frontBBox = box;
+
+  VssTreeLeaf *back = new VssTreeLeaf(node, raysBack);
+  VssTreeLeaf *front = new VssTreeLeaf(node, raysFront);
+
+  // replace a link from node's parent
+  if (  leaf->parent )
+    leaf->parent->ReplaceChildLink(leaf, node);
+  // and setup child links
+  node->SetupChildLinks(back, front);
+	
+  if (axis <= VssTreeNode::SPLIT_Z) {
+	backBBox.SetMax(axis, position);
+    frontBBox.SetMin(axis, position);
+		
+	for(VssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		ri != leaf->rays.end();
+		ri++) {
+      if ((*ri).mRay->IsActive()) {
+				
+		// first unref ray from the former leaf
+		(*ri).mRay->Unref();
+
+		// Debug << "computed t: " << (*ri).mRay->mT << endl;
+		// determine the side of this ray with respect to the plane
+		float t;
+		int side = node->ComputeRayIntersection(*ri, t);
+		
+		if (side == 0) {
+		  if ((*ri).mRay->HasPosDir(axis)) {
+			back->AddRay(VssTreeNode::RayInfo((*ri).mRay,
+											  (*ri).mMinT,
+											  t)
+						 );
+			front->AddRay(VssTreeNode::RayInfo((*ri).mRay,
+											   t,
+											   (*ri).mMaxT));
+		  } else {
+			back->AddRay(VssTreeNode::RayInfo((*ri).mRay,
+											  t,
+											  (*ri).mMaxT));
+			front->AddRay(VssTreeNode::RayInfo((*ri).mRay,
+											   (*ri).mMinT,
+											   t));
+		  }
+		} else
+		  if (side == 1) 
+			front->AddRay(*ri);
+		  else
+			back->AddRay(*ri);
+      } else
+		(*ri).mRay->Unref();
+    }
+  } else {
+    // rays front/back
+    
+    
+    for(VssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		ri != leaf->rays.end();
+		ri++) {
+      if ((*ri).mRay->IsActive()) {
+		// first unref ray from the former leaf
+		(*ri).mRay->Unref();
+
+		int side;
+		if ((*ri).mRay->GetDirParametrization(axis - 3) > position)
+		  side = 1;
+		else
+		  side = -1;
+				
+		if (side == 1)
+		  front->AddRay(*ri);
+		else
+		  back->AddRay(*ri);
+				
+      } else
+		(*ri).mRay->Unref();
+    }
+  }
+
+  front->SetPvsSize(pvsFront);
+  back->SetPvsSize(pvsBack);
+  // compute entropy as well
+  front->ComputeEntropyImportance();
+  back->ComputeEntropyImportance();
+  
+  // update stats
+  stat.rayRefs -= (int)leaf->rays.size();
+  stat.rayRefs += raysBack + raysFront;
+
+  
+  delete leaf;
+  return node;
+}
+
+
+
+
+
+
+int
+VssTree::ReleaseMemory(const int time)
+{
+  stack<VssTreeNode *> tstack;
+  
+  // find a node in the tree which subtree will be collapsed
+  int maxAccessTime = time - accessTimeThreshold;
+  int released;
+
+  tstack.push(root);
+
+  while (!tstack.empty()) {
+    VssTreeNode *node = tstack.top();
+    tstack.pop();
+    
+ 
+    if (!node->IsLeaf()) {
+      VssTreeInterior *in = (VssTreeInterior *)node;
+      //      cout<<"depth="<<(int)in->depth<<" time="<<in->lastAccessTime<<endl;
+      if (in->depth >= minCollapseDepth &&
+		  in->lastAccessTime <= maxAccessTime) {
+		released = CollapseSubtree(node, time);
+		break;
+      }
+      
+      if (in->back->GetAccessTime() <  
+		  in->front->GetAccessTime()) {
+		tstack.push(in->front);
+		tstack.push(in->back);
+      } else {
+		tstack.push(in->back);
+		tstack.push(in->front);
+      }
+    }
+  }
+
+  while (tstack.empty()) {
+    // could find node to collaps...
+    //    cout<<"Could not find a node to release "<<endl;
+    break;
+  }
+  
+  return released;
+}
+
+
+
+
+VssTreeNode *
+VssTree::SubdivideLeaf(
+					   VssTreeLeaf *leaf
+					   )
+{
+  VssTreeNode *node = leaf;
+	
+  AxisAlignedBox3 leafBBox = GetBBox(leaf);
+
+  static int pass = 0;
+  pass ++;
+	
+  // check if we should perform a dynamic subdivision of the leaf
+  if (!TerminationCriteriaSatisfied(leaf)) {
+    
+	// memory check and realese...
+    if (GetMemUsage() > maxTotalMemory) {
+      ReleaseMemory( pass );
+    }
+    
+    AxisAlignedBox3 backBBox, frontBBox;
+
+    // subdivide the node
+    node =
+      SubdivideNode(leaf,
+					leafBBox,
+					backBBox,
+					frontBBox
+					);
+  }
+	
+  return node;
+}
+
+
+
+void
+VssTree::UpdateRays(VssRayContainer &remove,
+					VssRayContainer &add
+					)
+{
+  VssTreeLeaf::NewMail();
+
+  // schedule rays for removal
+  for(VssRayContainer::const_iterator ri = remove.begin();
+      ri != remove.end();
+      ri++) {
+    (*ri)->ScheduleForRemoval();
+  }
+
+  int inactive=0;
+
+  for(VssRayContainer::const_iterator ri = remove.begin();
+      ri != remove.end();
+      ri++) {
+    if ((*ri)->ScheduledForRemoval())
+	  //      RemoveRay(*ri, NULL, false);
+	  // !!! BUG - with true it does not work correctly - aggreated delete
+      RemoveRay(*ri, NULL, true);
+    else
+      inactive++;
+  }
+
+
+  //  cout<<"all/inactive"<<remove.size()<<"/"<<inactive<<endl;
+  
+  for(VssRayContainer::const_iterator ri = add.begin();
+      ri != add.end();
+      ri++) {
+	VssTreeNode::RayInfo info(*ri);
+	if (ClipRay(info, bbox))
+	  AddRay(info);
+  }
+}
+
+
+void
+VssTree::RemoveRay(VssRay *ray,
+				   vector<VssTreeLeaf *> *affectedLeaves,
+				   const bool removeAllScheduledRays
+				   )
+{
+	
+  stack<RayTraversalData> tstack;
+
+  tstack.push(RayTraversalData(root, VssTreeNode::RayInfo(ray)));
+  
+  RayTraversalData data;
+
+  // cout<<"Number of ray refs = "<<ray->RefCount()<<endl;
+
+  while (!tstack.empty()) {
+    data = tstack.top();
+    tstack.pop();
+
+    if (!data.node->IsLeaf()) {
+      // split the set of rays in two groups intersecting the
+      // two subtrees
+
+      TraverseInternalNode(data, tstack);
+      
+    } else {
+      // remove the ray from the leaf
+      // find the ray in the leaf and swap it with the last ray...
+      VssTreeLeaf *leaf = (VssTreeLeaf *)data.node;
+      
+      if (!leaf->Mailed()) {
+		leaf->Mail();
+		if (affectedLeaves)
+		  affectedLeaves->push_back(leaf);
+	
+		if (removeAllScheduledRays) {
+		  int tail = leaf->rays.size()-1;
+
+		  for (int i=0; i < (int)(leaf->rays.size()); i++) {
+			if (leaf->rays[i].mRay->ScheduledForRemoval()) {
+			  // find a ray to replace it with
+			  while (tail >= i && leaf->rays[tail].mRay->ScheduledForRemoval()) {
+				stat.removedRayRefs++;
+				leaf->rays[tail].mRay->Unref();
+				leaf->rays.pop_back();
+				tail--;
+			  }
+
+			  if (tail < i)
+				break;
+	      
+			  stat.removedRayRefs++;
+			  leaf->rays[i].mRay->Unref();
+			  leaf->rays[i] = leaf->rays[tail];
+			  leaf->rays.pop_back();
+			  tail--;
+			}
+		  }
+		}
+      }
+      
+      if (!removeAllScheduledRays)
+		for (int i=0; i < (int)leaf->rays.size(); i++) {
+		  if (leaf->rays[i].mRay == ray) {
+			stat.removedRayRefs++;
+			ray->Unref();
+			leaf->rays[i] = leaf->rays[leaf->rays.size()-1];
+			leaf->rays.pop_back();
+			// check this ray again
+			break;
+		  }
+		}
+      
+    }
+  }
+
+  if (ray->RefCount() != 0) {
+    cerr<<"Error: Number of remaining refs = "<<ray->RefCount()<<endl;
+    exit(1);
+  }
+  
+}
+
+
+void
+VssTree::AddRay(VssTreeNode::RayInfo &info)
+{
+
+  stack<RayTraversalData> tstack;
+  
+  tstack.push(RayTraversalData(root, info));
+  
+  RayTraversalData data;
+  
+  while (!tstack.empty()) {
+    data = tstack.top();
+    tstack.pop();
+
+    if (!data.node->IsLeaf()) {
+      TraverseInternalNode(data, tstack);
+    } else {
+      // remove the ray from the leaf
+      // find the ray in the leaf and swap it with the last ray...
+      VssTreeLeaf *leaf = (VssTreeLeaf *)data.node;
+      leaf->AddRay(data.rayData);
+      stat.addedRayRefs++;
+    }
+  }
+}
+
+void
+VssTree::TraverseInternalNode(
+							  RayTraversalData &data,
+							  stack<RayTraversalData> &tstack)
+{
+  VssTreeInterior *in =  (VssTreeInterior *) data.node;
+  
+  if (in->axis <= VssTreeNode::SPLIT_Z) {
+	float t;
+    // determine the side of this ray with respect to the plane
+    int side = in->ComputeRayIntersection(data.rayData,
+										  t);
+    
+  
+    if (side == 0) {
+      if (data.rayData.mRay->HasPosDir(in->axis)) {
+		tstack.push(RayTraversalData(in->back,
+									 VssTreeNode::RayInfo(data.rayData.mRay,
+														  data.rayData.mMinT,
+														  t))
+					);
+				
+		tstack.push(RayTraversalData(in->front,
+									 VssTreeNode::RayInfo(data.rayData.mRay,
+														  t,
+														  data.rayData.mMaxT
+														  ))
+					);
+	
+      } else {
+		tstack.push(RayTraversalData(in->back,
+									 VssTreeNode::RayInfo(data.rayData.mRay,
+														  t,
+														  data.rayData.mMaxT
+														  ))
+					);
+				
+		tstack.push(RayTraversalData(in->front,
+									 VssTreeNode::RayInfo(data.rayData.mRay,
+														  data.rayData.mMinT,
+														  t))
+					);
+				
+				
+      }
+    } else
+      if (side == 1)
+		tstack.push(RayTraversalData(in->front, data.rayData));
+      else
+		tstack.push(RayTraversalData(in->back, data.rayData));
+  } 
+  else {
+    // directional split
+	if (data.rayData.mRay->GetDirParametrization(in->axis - 3) > in->position)
+	  tstack.push(RayTraversalData(in->front, data.rayData));
+	else
+	  tstack.push(RayTraversalData(in->back, data.rayData));
+  }
+}
+
+
+int
+VssTree::CollapseSubtree(VssTreeNode *sroot, const int time)
+{
+  // first count all rays in the subtree
+  // use mail 1 for this purpose
+  stack<VssTreeNode *> tstack;
+  int rayCount = 0;
+  int totalRayCount = 0;
+  int collapsedNodes = 0;
+
+#if DEBUG_COLLAPSE
+  cout<<"Collapsing subtree"<<endl;
+  cout<<"acessTime="<<sroot->GetAccessTime()<<endl;
+  cout<<"depth="<<(int)sroot->depth<<endl;
+#endif
+
+  //    tstat.collapsedSubtrees++;
+  //    tstat.collapseDepths += (int)sroot->depth;
+  //    tstat.collapseAccessTimes += time - sroot->GetAccessTime();
+  
+  tstack.push(sroot);
+  VssRay::NewMail();
+	
+  while (!tstack.empty()) {
+    collapsedNodes++;
+    VssTreeNode *node = tstack.top();
+    tstack.pop();
+
+    if (node->IsLeaf()) {
+      VssTreeLeaf *leaf = (VssTreeLeaf *) node;
+      for(VssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		  ri != leaf->rays.end();
+		  ri++) {
+				
+		totalRayCount++;
+		if ((*ri).mRay->IsActive() && !(*ri).mRay->Mailed()) {
+		  (*ri).mRay->Mail();
+		  rayCount++;
+		}
+      }
+    } else {
+      tstack.push(((VssTreeInterior *)node)->back);
+      tstack.push(((VssTreeInterior *)node)->front);
+    }
+  }
+  
+  VssRay::NewMail();
+
+  // create a new node that will hold the rays
+  VssTreeLeaf *newLeaf = new VssTreeLeaf( sroot->parent, rayCount );
+  if (  newLeaf->parent )
+    newLeaf->parent->ReplaceChildLink(sroot, newLeaf);
+  
+
+  tstack.push( sroot );
+
+  while (!tstack.empty()) {
+
+    VssTreeNode *node = tstack.top();
+    tstack.pop();
+
+    if (node->IsLeaf()) {
+      VssTreeLeaf *leaf = (VssTreeLeaf *) node;
+      
+      for(VssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		  ri != leaf->rays.end();
+		  ri++) {
+				
+		// unref this ray from the old node
+				
+		if ((*ri).mRay->IsActive()) {
+		  (*ri).mRay->Unref();
+		  if (!(*ri).mRay->Mailed()) {
+			(*ri).mRay->Mail();
+			newLeaf->AddRay(*ri);
+		  }
+		} else
+		  (*ri).mRay->Unref();
+				
+      }
+    } else {
+      tstack.push(((VssTreeInterior *)node)->back);
+      tstack.push(((VssTreeInterior *)node)->front);
+    }
+  }
+  
+  // delete the node and all its children
+  delete sroot;
+  
+  //   for(VssTreeNode::SRayContainer::iterator ri = newLeaf->rays.begin();
+  //       ri != newLeaf->rays.end();
+  //       ri++)
+  //     (*ri).ray->UnMail(2);
+
+
+#if DEBUG_COLLAPSE
+  cout<<"Total memory before="<<GetMemUsage()<<endl;
+#endif
+
+  stat.nodes -= collapsedNodes - 1;
+  stat.rayRefs -= totalRayCount - rayCount;
+  
+#if DEBUG_COLLAPSE
+  cout<<"collapsed nodes"<<collapsedNodes<<endl;
+  cout<<"collapsed rays"<<totalRayCount - rayCount<<endl;
+  cout<<"Total memory after="<<GetMemUsage()<<endl;
+  cout<<"================================"<<endl;
+#endif
+
+  //  tstat.collapsedNodes += collapsedNodes;
+  //  tstat.collapsedRays += totalRayCount - rayCount;
+    
+  return totalRayCount - rayCount;
+}
+
+
+int
+VssTree::GetPvsSize(const AxisAlignedBox3 &box) const
+{
+  stack<VssTreeNode *> tstack;
+  tstack.push(root);
+
+  Intersectable::NewMail();
+  int pvsSize = 0;
+	
+  while (!tstack.empty()) {
+    VssTreeNode *node = tstack.top();
+    tstack.pop();
+    
+ 
+    if (node->IsLeaf()) {
+	  VssTreeLeaf *leaf = (VssTreeLeaf *)node;
+	  for(VssTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
+		  ri != leaf->rays.end();
+		  ri++)
+		if ((*ri).mRay->IsActive()) {
+		  Intersectable *object;
+#if BIDIRECTIONAL_RAY
+		  object = (*ri).mRay->mOriginObject;
+		  if (object && !object->Mailed()) {
+			pvsSize++;
+			object->Mail();
+		  }
+#endif
+		  object = (*ri).mRay->mTerminationObject;
+		  if (object && !object->Mailed()) {
+			pvsSize++;
+			object->Mail();
+		  }
+		}
+	} else {
+	  VssTreeInterior *in = (VssTreeInterior *)node;
+	  if (in->axis < 3) {
+		if (box.Max(in->axis) >= in->position )
+		  tstack.push(in->front);
+				
+		if (box.Min(in->axis) <= in->position )
+		  tstack.push(in->back);
+	  } else {
+		// both nodes for directional splits
+		tstack.push(in->front);
+		tstack.push(in->back);
+	  }
+	}
+  }
+  return pvsSize;
+}
+
+void
+VssTree::GetRayContributionStatistics(
+									  float &minRayContribution,
+									  float &maxRayContribution,
+									  float &avgRayContribution
+									  )
+{
+  stack<VssTreeNode *> tstack;
+  tstack.push(root);
+	
+  minRayContribution = 1.0f;
+  maxRayContribution = 0.0f;
+  float sumRayContribution = 0.0f;
+  int leaves = 0;
+
+  while (!tstack.empty()) {
+    VssTreeNode *node = tstack.top();
+    tstack.pop();
+		
+    if (node->IsLeaf()) {
+	  leaves++;
+	  VssTreeLeaf *leaf = (VssTreeLeaf *)node;
+	  float c = leaf->GetImportance();
+	  if (c > maxRayContribution)
+		maxRayContribution = c;
+	  if (c < minRayContribution)
+		minRayContribution = c;
+	  sumRayContribution += c;
+			
+	} else {
+	  VssTreeInterior *in = (VssTreeInterior *)node;
+	  // both nodes for directional splits
+	  tstack.push(in->front);
+	  tstack.push(in->back);
+	}
+  }
+	
+  cout<<"sum="<<sumRayContribution<<endl;
+  cout<<"leaves="<<leaves<<endl;
+  avgRayContribution = sumRayContribution/(float)leaves;
+}
+
+
+int
+VssTree::GenerateRays(const float ratioPerLeaf,
+					  SimpleRayContainer &rays)
+{
+  stack<VssTreeNode *> tstack;
+  tstack.push(root);
+	
+  while (!tstack.empty()) {
+    VssTreeNode *node = tstack.top();
+    tstack.pop();
+		
+    if (node->IsLeaf()) {
+	  VssTreeLeaf *leaf = (VssTreeLeaf *)node;
+	  float c = leaf->GetImportance();
+	  int num = (c*ratioPerLeaf + 0.5);
+	  //			cout<<num<<" ";
+
+	  for (int i=0; i < num; i++) {
+		Vector3 origin = GetBBox(leaf).GetRandomPoint();
+		Vector3 dirVector = GetDirBBox(leaf).GetRandomPoint();
+		Vector3 direction = VssRay::GetDirection(dirVector.x, dirVector.y);
+		//cout<<"dir vector.x="<<dirVector.x<<"direction'.x="<<atan2(direction.x, direction.y)<<endl;
+		rays.push_back(SimpleRay(origin, direction));
+	  }
+			
+	} else {
+	  VssTreeInterior *in = (VssTreeInterior *)node;
+	  // both nodes for directional splits
+	  tstack.push(in->front);
+	  tstack.push(in->back);
+	}
+  }
+
+  return rays.size();
+}
+
+void
+VssTree::CollectLeaves(vector<VssTreeLeaf *> &leaves)
+{
+  stack<VssTreeNode *> tstack;
+  tstack.push(root);
+	
+  while (!tstack.empty()) {
+    VssTreeNode *node = tstack.top();
+    tstack.pop();
+		
+    if (node->IsLeaf()) {
+	  VssTreeLeaf *leaf = (VssTreeLeaf *)node;
+	  leaves.push_back(leaf);
+	} else {
+	  VssTreeInterior *in = (VssTreeInterior *)node;
+	  // both nodes for directional splits
+	  tstack.push(in->front);
+	  tstack.push(in->back);
+	}
+  }
+}
+
+bool
+VssTree::ValidLeaf(VssTreeLeaf *leaf) const
+{
+  return leaf->rays.size() > termMinRays/4;
+}
+
+
+void
+VssTree::GenerateLeafRays(VssTreeLeaf *leaf,
+						  const int numberOfRays,
+						  SimpleRayContainer &rays)
+{
+  int nrays = (int)leaf->rays.size();
+  for (int i=0; i < numberOfRays; i++) {
+	// pickup 3 random rays
+	int r1 = (int)RandomValue(0, nrays-1);
+	int r2 = (int)RandomValue(0, nrays-1);
+	int r3 = (int)RandomValue(0, nrays-1);
+		
+	Vector3 o1 = leaf->rays[r1].Extrap(RandomValue(leaf->rays[r1].GetMinT(), 
+												   leaf->rays[r1].GetMaxT()));
+
+	Vector3 o2 = leaf->rays[r2].Extrap(RandomValue(leaf->rays[r2].GetMinT(), 
+												   leaf->rays[r2].GetMaxT()));
+		
+	Vector3 o3 = leaf->rays[r3].Extrap(RandomValue(leaf->rays[r3].GetMinT(), 
+												   leaf->rays[r3].GetMaxT()));
+
+	const float overlap = 0.1f;
+		
+	Vector3 origin, direction;
+	bool useExtendedConvexCombination = true;
+	if (useExtendedConvexCombination) {
+	  float w1, w2, w3;
+	  GenerateExtendedConvexCombinationWeights(w1, w2, w3, overlap);
+	  origin = w1*o1 + w2*o2 + w3*o3;
+	  direction =
+		w1*leaf->rays[r1].mRay->GetDir() +
+		w2*leaf->rays[r2].mRay->GetDir() +
+		w3*leaf->rays[r3].mRay->GetDir();
+	} else {
+	  origin = GetBBox(leaf).GetRandomPoint();
+	  Vector3 dirVector = GetDirBBox(leaf).GetRandomPoint();
+	  direction = Vector3(sin(dirVector.x), sin(dirVector.y), cos(dirVector.x));
+	}
+	//cout<<"dir vector.x="<<dirVector.x<<"direction'.x="<<atan2(direction.x, direction.y)<<endl;
+	rays.push_back(SimpleRay(origin, direction));
+  }
+}
+
+int
+VssTree::GenerateRays(const int numberOfRays,
+					  const int numberOfLeaves,
+					  SimpleRayContainer &rays)
+{
+
+  vector<VssTreeLeaf *> leaves;
+	
+  CollectLeaves(leaves);
+	
+  sort(leaves.begin(),
+	   leaves.end(),
+	   GreaterContribution);
+			 
+
+  float sumContrib = 0.0;
+  int i;
+  int k = 0;
+  for (i=0; i < leaves.size() && k < numberOfLeaves; i++)
+	if (ValidLeaf(leaves[i])) {
+	  float c = leaves[i]->GetImportance();
+	  sumContrib += c;
+	  //		cout<<"ray contrib "<<i<<" : "<<c<<endl;
+	  k++;
+	}
+				
+  float avgContrib = sumContrib/numberOfLeaves;
+  float ratioPerLeaf = numberOfRays/(avgContrib*numberOfLeaves);
+  k = 0;
+  for (i=0; i < leaves.size() && k < numberOfLeaves; i++)
+	if (ValidLeaf(leaves[i])) {
+	  k++;
+	  VssTreeLeaf *leaf = leaves[i];
+	  float c = leaf->GetImportance();
+	  int num = (int)(c*ratioPerLeaf + 0.5f);
+	  GenerateLeafRays(leaf, num, rays);
+	}
+
+  return (int)rays.size();
+}
+
+
+float
+VssTree::GetAvgPvsSize()
+{
+  stack<VssTreeNode *> tstack;
+  tstack.push(root);
+
+  int sumPvs = 0;
+  int leaves = 0;
+  while (!tstack.empty()) {
+    VssTreeNode *node = tstack.top();
+    tstack.pop();
+		
+    if (node->IsLeaf()) {
+	  VssTreeLeaf *leaf = (VssTreeLeaf *)node;
+	  // update pvs size
+	  leaf->UpdatePvsSize();
+	  sumPvs += leaf->GetPvsSize();
+	  leaves++;
+	} else {
+	  VssTreeInterior *in = (VssTreeInterior *)node;
+	  // both nodes for directional splits
+	  tstack.push(in->front);
+	  tstack.push(in->back);
+	}
+  }
+
+
+  return sumPvs/(float)leaves;
+}
+
+	
+float
+VssTreeLeaf::GetImportance()  const
+{
+
+  if (1) {
+	//	return GetAvgRayContribution();
+	return GetPvsSize();
+  } else {
+	// return GetAvgRayContribution()*mEntropyImportance;
+	//return GetAvgRayContribution();
+	return mEntropyImportance;
+  }
+}
+
+
+float
+VssTreeLeaf::ComputePvsEntropy()
+{
+  int samples = 0;
+  Intersectable::NewMail();
+  // set all object as belonging to the fron pvs
+  for(VssTreeNode::RayInfoContainer::iterator ri = rays.begin();
+	  ri != rays.end();
+	  ri++)
+	if ((*ri).mRay->IsActive()) {
+	  Intersectable *object = (*ri).mRay->mTerminationObject;
+	  if (object) {
+		if (!object->Mailed()) {
+		  object->Mail();
+		  object->mCounter = 1;
+		} else
+		  object->mCounter++;
+		samples++;
+	  }
+	}
+  
+  float entropy = 0.0f;
+  
+  if (samples > 1) {
+	Intersectable::NewMail();
+	for(RayInfoContainer::const_iterator ri = rays.begin();
+		ri != rays.end();
+		ri++) 
+	  if ((*ri).mRay->IsActive()) {
+		Intersectable *object = (*ri).mRay->mTerminationObject;
+		if (object) {
+		  if (!object->Mailed()) {
+			object->Mail();
+			float p = object->mCounter/(float)samples;
+			entropy -= p*log(p);
+		  }
+		}
+	  }
+	entropy = entropy/log((float)samples);
+  }
+  else
+	entropy = 1.0f;
+  
+  return entropy;
+}
+
+float
+VssTreeLeaf::ComputeRayLengthEntropy()
+{
+  // get sum of all ray lengths
+  // consider only passing rays or originating rays
+  float sum = 0.0f;
+  int samples = 0;
+
+  for(RayInfoContainer::const_iterator ri = rays.begin();
+      ri != rays.end();
+      ri++) {
+	int rayClass = (*ri).GetRayClass();
+	if (
+		rayClass == RayInfo::PASSING_RAY
+		//		||
+		//		rayClass == RayInfo::SOURCE_RAY
+		//		rayClass == RayInfo::TERMINATION_RAY
+		) {
+	  float c = 1.0f - (*ri).GetMaxT();
+	  sum += (*ri).mRay->GetSize()*c;
+	  samples++;
+	}
+  }
+  
+  float entropy = 0.0f;
+  
+  if (samples > 1) {
+	for(RayInfoContainer::const_iterator ri = rays.begin();
+		ri != rays.end();
+		ri++) {
+	  int rayClass = (*ri).GetRayClass();
+	  if (
+		  rayClass == RayInfo::PASSING_RAY
+		  //		  ||
+		  //		  rayClass == RayInfo::SOURCE_RAY
+		  // rayClass == RayInfo::TERMINATION_RAY
+		  ) {
+		float c = 1.0f - (*ri).GetMaxT();
+		float p = (*ri).mRay->GetSize()*c/sum;
+		entropy -= p*log(p);
+	  }
+	}
+	entropy = entropy/log((float)samples);
+  } else
+	entropy = 1.0f;
+  
+  return entropy;
+}
+  
+float
+VssTreeLeaf::ComputeRayTerminationEntropy()
+{
+
+  return 0.0f;
+}
+
+
+void
+VssTreeLeaf::ComputeEntropyImportance()
+{
+  //  mEntropy = 1.0f - ComputeRayLengthEntropy();
+  mEntropyImportance = 1.0f - ComputePvsEntropy();
+  
+  //  cout<<"ei="<<mEntropyImportance<<" ";
+}
+
+
+int
+VssTree::CollectRays(VssRayContainer &rays,
+					 const int number)
+{
+  VssRayContainer allRays;
+  CollectRays(allRays);
+  
+  int desired = min(number, (int)allRays.size());
+  float prob = desired/(float)allRays.size();
+  while (rays.size() < desired) {
+	VssRayContainer::const_iterator it = allRays.begin();
+	for (; it != allRays.end() && rays.size() < desired; it++) {
+	  if (Random(1.0f) < prob)
+		rays.push_back(*it);
+	}
+  }
+  return rays.size();
+}
+
+
+int
+VssTree::CollectRays(VssRayContainer &rays
+					 )
+{
+  VssRay::NewMail();
+
+  stack<VssTreeNode *> tstack;
+  tstack.push(root);
+  
+  while (!tstack.empty()) {
+    VssTreeNode *node = tstack.top();
+    tstack.pop();
+	
+    if (node->IsLeaf()) {
+	  VssTreeLeaf *leaf = (VssTreeLeaf *)node;
+	  // update pvs size
+	  VssTreeNode::RayInfoContainer::const_iterator it = leaf->rays.begin();
+	  for (;it != leaf->rays.end(); ++it)
+		if (!(*it).mRay->Mailed()) {
+		  (*it).mRay->Mail();
+		  rays.push_back((*it).mRay);
+		}
+	} else {
+	  VssTreeInterior *in = (VssTreeInterior *)node;
+	  // both nodes for directional splits
+	  tstack.push(in->front);
+	  tstack.push(in->back);
+	}
+  }
+  
+  return rays.size();
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Ray.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Ray.cpp	(revision 564)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Ray.cpp	(revision 564)
@@ -0,0 +1,241 @@
+#include "Ray.h"
+#include "Plane3.h"
+#include "VssRay.h"
+
+// =========================================================
+// Ray .. static item used for generation of unique ID for
+// each instantiated ray
+
+// it has to start from 1, since 0 is default and for the first
+// ray initial value 0 will not work .. V.H.
+// The value 0 is reserved for particular purpose - the rays
+// that are converted to canonical space and thus the mailbox
+// rayID identification does not work for them!
+int
+Ray::genID = 1;
+
+// Precompute some Ray parameters. Most of them is used for
+// ropes traversal.
+
+void
+Ray::Init()
+{
+  //  if (mType == LOCAL_RAY)
+  //    intersections.reserve(1);
+  //  else
+  //    intersections.reserve(10);
+  
+  // apply the standard precomputation
+  Precompute();
+}
+
+void
+Ray::Precompute()
+{
+  // initialize inverted dir
+  invDir.SetValue(0.0);
+  
+  SetId();
+}
+
+void
+Ray::SetLoc(const Vector3 &l)
+{
+  loc = l;
+}
+
+// make such operation to slightly change the ray direction
+// in case any component of ray direction is zero.
+void
+Ray::CorrectZeroComponents()
+{
+  const float eps = 1e-6f;
+
+  // it does change the ray direction very slightly,
+  // but the size direction vector is not practically changed
+  
+  if (fabs(dir.x) < eps) {
+    if (dir.x < 0.0)
+      dir.x = -eps;
+    else
+      dir.x = eps;
+  }
+  
+  if (fabs(dir.y) < eps) {
+    if (dir.y < 0.0)
+      dir.y = -eps;
+    else
+      dir.y = eps;
+  }
+  
+  if (fabs(dir.z) < eps) {
+    if (dir.z < 0.0)
+      dir.z = -eps;
+    else
+      dir.z = eps;
+  }
+}
+
+
+void
+Ray::ComputeInvertedDir() const
+{
+  if ( (invDir.x != 0.0) ||
+       (invDir.y != 0.0) ||
+       (invDir.z != 0.0) )
+    return; // has been already precomputed
+
+  const float eps = 1e-6f;
+  const float invEps = 1e6f;
+  
+  // it does change the ray direction very slightly,
+  // but the size direction vector is not practically changed
+  
+  if (fabs(dir.x) < eps) {
+    if (dir.x < 0.0)
+      invDir.x = -invEps;
+    else
+      invDir.x = invEps;
+  }
+  else
+    invDir.x = 1.0f / dir.x;
+  
+  if (fabs(dir.y) < eps) {
+    if (dir.y < 0.0)
+      invDir.y = -invEps;
+    else
+      invDir.y = invEps;
+  }
+  else
+    invDir.y = 1.0f / dir.y;
+  
+  if (fabs(dir.z) < eps) {
+    if (dir.z < 0.0f)
+      invDir.z = -invEps;
+    else
+      invDir.z = invEps;
+  }
+  else
+    invDir.z = 1.0f / dir.z;
+
+  return;
+}
+
+void
+PassingRaySet::Reset()
+{
+  for (int i=0; i < 3*Resolution*Resolution; i++)
+    mDirectionalContributions[i] = 0;
+  mRays = 0;
+  mContributions = 0;
+}
+  
+void
+PassingRaySet::AddRay(const Ray &ray, const int contributions)
+{
+  int i = GetEntryIndex(ray.GetDir());
+  mRays++;
+  mContributions += contributions;
+  mDirectionalContributions[i] += contributions;
+}
+
+void
+PassingRaySet::AddRay2(const Ray &ray,
+					   const int objects,
+					   const int viewcells
+					   )
+{
+  int i = GetEntryIndex(ray.GetDir());
+  mRays++;
+  mContributions += objects*viewcells;
+  mDirectionalContributions[i] += objects*viewcells;
+}
+
+int
+PassingRaySet::GetEntryIndex(const Vector3 &direction) const
+{
+  // get face
+  int axis = direction.DrivingAxis();
+  Vector3 dir;
+  float k = direction[axis];
+  if ( k < 0.0f)
+    k = -k;
+
+  dir = direction/k;
+  float x, y;
+  dir.ExtractVerts(&x, &y, axis);
+  int ix = (int)((x + 1.0f)*0.5f*Resolution);
+  int iy = (int)((y + 1.0f)*0.5f*Resolution);
+
+  return Resolution*(Resolution*axis + iy) + ix;
+}
+
+int Ray::ClassifyPlane(const Plane3 &plane, 
+					   const float minT, 
+					   const float maxT,
+					   Vector3 &entP,
+					   Vector3 &extP) const
+{
+	entP = Extrap(minT);
+	extP = Extrap(maxT);
+  
+	const int entSide = plane.Side(entP);
+	const int extSide = plane.Side(extP);
+
+	if (entSide < 0)
+	{
+		if (extSide >= 0)
+		{
+			return BACK_FRONT;
+		}
+		return BACK;
+	}
+	else if (entSide > 0)
+	{
+		if (extSide <= 0)
+			return FRONT_BACK;
+			
+		return FRONT;
+	}
+	else if (entSide == 0)
+	{
+		if (extSide > 0)
+			return BACK_FRONT;
+		else if (extSide < 0)
+			return FRONT_BACK;
+	}
+	
+	return COINCIDENT;
+}
+
+
+ostream &
+operator<<(ostream &s, const PassingRaySet &set)
+{
+  s<<"Ray Set #rays="<<set.mRays<<" #contributions="<<set.mContributions<<endl;
+  for (int i=0; i < 3*sqr(PassingRaySet::Resolution); i++)
+    s<<set.mDirectionalContributions[i]<<" ";
+  s<<endl;
+  return s;
+}
+
+void
+Ray::Init(const VssRay &vssRay)
+{
+  loc = vssRay.mOrigin;
+  sourceObject = Intersection(0, vssRay.mOriginObject, 0);
+  mType = LOCAL_RAY;
+  
+  float len = vssRay.Length();
+  
+  if (!len)
+	len = Limits::Small;
+  
+  dir = vssRay.GetDir() / len;
+  
+  intersections.clear();
+  if (vssRay.mTerminationObject)
+	intersections.push_back(Intersection(len, vssRay.mTerminationObject, 0));
+  
+  Precompute();
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.h	(revision 535)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.h	(revision 535)
@@ -0,0 +1,149 @@
+#ifndef __X3DEXPORTER_H
+#define __X3DEXPORTER_H
+
+#include <string>
+using std::string;
+
+#include <iostream>
+#include <fstream>
+
+#include "Exporter.h"
+#include "Containers.h"
+#include "VssRay.h"
+#include "ViewCell.h"
+
+class SceneGraphNode;
+class Mesh;
+class Intersectable;
+class MeshInstance;
+class Polygon3;
+class ViewCell;
+class BspTree;
+class VspBspTree;
+class BspNode;
+//class VspKdViewCell;
+class Beam;
+
+class X3dExporter : public Exporter
+{
+  std::ofstream stream;
+
+public:
+
+  X3dExporter(const string filename);
+
+  ~X3dExporter();
+
+
+//    bool
+//    ExportRays(const vector<Ray> &rays,
+//  	     const float length=1000,
+//  	     const RgbColor &color = RgbColor(1,1,1));
+
+
+  bool
+  ExportKdTree(const KdTree &tree);
+
+  bool
+  ExportVssTree(const VssTree &tree);
+
+  bool
+  ExportVssTree2(const VssTree &tree,
+				 const Vector3 direction
+				 );
+
+  virtual bool
+  ExportRssTree2(const RssTree &tree,
+				 const Vector3 direction
+				 );
+
+  bool
+  ExportVspKdTree(const VspKdTree &tree, const int maxPvs);
+
+  bool ExportBspTree(const BspTree &tree);
+
+  bool
+  ExportScene(SceneGraphNode *root)
+  {
+    ExportSceneNode(root);
+    return true;
+  }
+
+  virtual void
+  ExportPolygon(Polygon3 *poly);
+
+  virtual void
+  ExportPolygons(const PolygonContainer &polys);
+
+  virtual bool
+  ExportBox(const AxisAlignedBox3 &box);
+
+  virtual void
+  ExportMeshInstance(MeshInstance *mi);
+
+  virtual void
+  ExportIntersectable(Intersectable *object);
+
+  virtual void
+  ExportMesh(Mesh *mesh);
+
+  virtual void
+  ExportViewCell(ViewCell *viewCell);
+
+  virtual void
+  ExportViewCells(const ViewCellContainer &viewCells);
+
+  virtual void
+  ExportGeometry(const ObjectContainer &objects);
+
+  bool
+  ExportRays(const RayContainer &rays,
+			 const float length=1000,
+			 const RgbColor &color = RgbColor(1,1,1));
+  bool
+  ExportRays(const VssRayContainer &rays,
+			 const RgbColor &color = RgbColor(1,1,1));
+
+  virtual void
+  ExportBspSplitPlanes(const BspTree &tree);
+
+  virtual void
+  ExportBspSplits(const BspTree &tree, const bool exportDepth);
+
+  virtual void
+  ExportLeavesGeometry(const BspTree &tree, const vector<BspLeaf *> &leaves);
+
+  virtual void
+  ExportBspLeaves(const BspTree &tree, const int maxPvs = 0);
+
+
+  virtual void
+  ExportBspSplits(const VspBspTree &tree, const bool exportDepth);
+
+  virtual void ExportBeam(const Beam &beam, const AxisAlignedBox3 &box);
+
+protected:
+
+
+  virtual void
+  ExportSceneNode(SceneGraphNode *node);
+
+  bool
+  ExportKdTreeRayDensity(const KdTree &tree);
+
+  bool
+  ExportBspTreeRayDensity(const BspTree &tree);
+
+  void ExportBspNodeSplits(BspNode *root,
+						   const AxisAlignedBox3 &box,
+						   const bool exportDepth,
+						   const bool epsilon);
+
+
+  void ExportViewpoint(const Vector3 &point, const Vector3 &direction);
+
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VssRay.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VssRay.h	(revision 556)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VssRay.h	(revision 556)
@@ -0,0 +1,322 @@
+#ifndef __VSS_RAY_H
+#define __VSS_RAY_H
+
+#include <vector>
+using namespace std;
+#include "Vector3.h"
+#include "Ray.h"
+#include "Containers.h"
+
+class AxisAlignedBox3;
+class Intersectable;
+
+class VssRay {
+public:
+  // various flags
+  enum {
+    FPosDirX = 1,  // the direction of ray in X-axis is positive
+    FPosDirY = 2,  // the direction of ray in Y-axis is positive
+    FPosDirZ = 4   // the direction of ray in Z-axis is positive
+  };
+
+  static int mailID;
+  int mMailbox;
+	
+  // side of the ray - used for the ray classification
+  //  char mSide;
+	
+  // computed t
+  //  float mT;
+
+  // inverse of the ray size
+  float mInvSize;
+  
+  // counter of references to this ray
+  short mRefCount;
+  
+  // various flags
+  char mFlags;
+	
+  Vector3 mOrigin;
+  Vector3 mTermination;
+	
+  /// Termination object for the ray
+  /// only the termination object is actually used
+  Intersectable *mOriginObject;
+  Intersectable *mTerminationObject;
+
+  ViewCellContainer mViewCells;
+  
+  ////////////////////////
+  // members related to importance sampling
+  // sampling pass in which this ray was generated
+  short mPass;
+
+  // number of cells where this ray made a contribution to the PVS
+  short mPvsContribution;
+  
+  // sum of relative ray contributions per object
+  float mRelativePvsContribution;
+
+
+  // weighted contribution to the pvs (based on the pass the ray was casted at)
+  // computed by the prperocessor
+  float mWeightedPvsContribution;
+
+  // probability of this ray
+  float mPdf;
+  
+  //////////////////////////////
+  VssRay(
+		 const Vector3 &origin,
+		 const Vector3 &termination,
+		 Intersectable *originObject,
+		 Intersectable *terminationObject,
+		 const int pass = 0,
+		 const float pdf = 1.0f
+		 ):
+	mMailbox(-1),
+    mOrigin(origin),
+    mTermination(termination),
+	mOriginObject(originObject),
+	mTerminationObject(terminationObject),
+	mRefCount(0),
+    mFlags(0),
+	mPass(pass),
+	mViewCells(0),
+	mWeightedPvsContribution(0),
+	mPdf(pdf)
+  {
+    Precompute();
+  }
+	
+  VssRay(const Ray &ray):
+	mRefCount(0),
+	mFlags(0),
+	mMailbox(-1),
+	mOriginObject(ray.sourceObject.mObject),
+	mPass(0),
+	mViewCells(0),
+	mPdf(1.0f)
+  {
+	if (ray.sourceObject.mObject)
+	  mOrigin = ray.Extrap(ray.sourceObject.mT);
+	else
+	  mOrigin = ray.GetLoc(); 
+	
+	//Debug << "origin: " << mOrigin << endl;
+	if (!ray.intersections.empty())
+	  {
+		mTermination = ray.Extrap(ray.intersections[0].mT);
+		mTerminationObject = ray.intersections[0].mObject;
+	  }
+	else
+	  {
+		mTermination = ray.Extrap(1e6);//TODO: should be Limits::Infinity
+		mTerminationObject = NULL;
+	  }
+	
+	Precompute();
+  }
+  
+  void Precompute() {
+    mFlags = 0;
+	Vector3 dir = GetDir();
+
+#define BIDIRECTIONAL_RAY 0
+#if BIDIRECTIONAL_RAY
+	if (dir.y < 0) {
+	  // swap objects and poits	
+	  swap(mOriginObject, mTerminationObject);
+	  swap(mOrigin, mTermination);
+	  dir = -dir;
+	}
+#endif
+	if (dir.x > 0.0f) mFlags |= FPosDirX;
+    if (dir.y > 0.0f) mFlags |= FPosDirY;
+    if (dir.z > 0.0f) mFlags |= FPosDirZ;
+
+    mInvSize = 1.0f/Magnitude(GetDir());
+  }
+
+  void Mail() { mMailbox = mailID; }
+  static void NewMail() { mailID++; }
+  bool Mailed() const { return mMailbox == mailID; }
+
+  bool Mailed(const int mail) {
+    return mMailbox >= mailID + mail;
+  }
+
+  int HitCount() const {
+#if BIDIRECTIONAL_RAY
+	if (mOriginObject && mTerminationObject)
+	  return 2;
+	if (mOriginObject || mTerminationObject)
+	  return 1;
+	return 0;
+#else
+	return (mTerminationObject) ? 1 : 0;
+#endif
+  }
+	
+  Vector3 GetOrigin() const { return mOrigin; }
+  Vector3 GetTermination() const { return mTermination; }
+  Vector3 GetDir() const { return mTermination - mOrigin; }
+  //  Vector3 GetNormalizedDir() const { return Normalize(termination - mOrigin); }
+  Vector3 GetNormalizedDir() const { return (mTermination - mOrigin)*mInvSize; }
+
+  float Length() const { return Distance(mOrigin, mTermination); }
+
+  Vector3 Extrap(const float t) const {
+	return GetOrigin() + t * GetDir();
+  }
+	
+  float GetDirParametrization(const int axis) const;
+  float GetOpositeDirParametrization(const int axis) const;
+
+  static float VssRay::GetDirParam(const int axis, const Vector3 dir);
+
+  float GetSize() const { return  1.0f/mInvSize; }
+  float GetInvSize() const { return  mInvSize; }
+  float GetOrigin(const int axis) const { return mOrigin[axis]; }
+  float GetTermination(const int axis) const { return mTermination[axis]; }
+  float GetDir(const int axis) const { return mTermination[axis] - mOrigin[axis]; }
+  float GetNormalizedDir(const int axis) const {
+    return (mTermination[axis] - mOrigin[axis])*mInvSize;
+  }
+	
+  bool
+  ComputeMinMaxT(const AxisAlignedBox3 &box,
+				 float &tmin,
+				 float &tmax) const;
+	
+  bool
+  Intersects(const AxisAlignedBox3 &box,
+			 float &tmin,
+			 float &tmax) const;
+	
+  bool
+  IntersectsSphere(const Vector3 &center,
+				   const float sqrRadius,
+				   Vector3 &point,
+				   float &t) const;
+	
+  void
+  Translate(const Vector3 &translation) {
+    mOrigin += translation;
+    mTermination += translation;
+  }
+
+  void SetupEndPoints(const Vector3 &origin,
+					  const Vector3 &termination)
+  {
+	mOrigin = origin;
+	mTermination = termination;
+	Precompute();
+  }
+											
+  bool HasPosDir(const int axis) const { return mFlags & (1<<axis); }
+
+  char Flags() const { return mFlags;}
+  void SetFlags(char orFlag) { mFlags |= orFlag;}
+  
+  bool IsActive() const { return mRefCount>0; }
+	
+  // reference counting for leaf nodes
+  int RefCount() const { return mRefCount; }
+  int Ref() { return mRefCount++; }
+	
+  void ScheduleForRemoval() { if (mRefCount>0) mRefCount = -mRefCount; }
+  bool ScheduledForRemoval() const { return mRefCount<0; }
+  void Unref() {
+    if (mRefCount > 0)
+      mRefCount--;
+    else
+      if (mRefCount < 0)
+		mRefCount++;
+      else {
+		cerr<<"Trying to unref already deleted ray!"<<endl;
+		exit(1);
+      }
+  }
+
+  static Vector3
+  GetDirection(const float a, const float b) {
+	return Vector3(sin(a), sin(b), cos(a));
+  }
+
+  friend bool GreaterWeightedPvsContribution(const VssRay * a,
+											 const VssRay *b) {
+	return a->mWeightedPvsContribution > b->mWeightedPvsContribution;
+  }
+
+  float SqrDistance(const Vector3 &point) const {
+	Vector3 diff = point - mOrigin;
+	float t = DotProd(diff, GetDir());
+	
+    if ( t <= 0.0f ) {
+	  t = 0.0f;
+    } else {
+	  if (t >= 1.0f) {
+		t = 1.0f;
+	  } else {
+        t /= SqrMagnitude(GetDir());
+	  }
+	  diff -= t*GetDir();
+	}
+    return SqrMagnitude(diff);
+  }
+
+};
+
+void
+GenerateExtendedConvexCombinationWeights(float &w1,
+										 float &w2,
+										 float &w3,
+										 const float overlap
+										 );
+
+void
+GenerateExtendedConvexCombinationWeights2(float &w1,
+										  float &w2,
+										  const float overlap
+										  );
+
+// --------------------------------------------------------------
+// For sorting rays
+// --------------------------------------------------------------
+struct  SortableEntry
+{
+  enum EType {
+    ERayMin,
+    ERayMax
+  };
+
+  int type;
+  float value;
+  void *data;
+  
+  SortableEntry() {}
+  SortableEntry(const int t, const float v, void *d):type(t),
+													 value(v),
+													 data(d) {}
+	
+  friend bool operator<(const SortableEntry &a, const SortableEntry &b) {
+    return a.value < b.value;
+  }
+};
+
+struct VssRayContainer : public vector<VssRay *>
+{
+  void PrintStatistics(ostream &s);
+  int SelectRays(const int number, VssRayContainer &selected) const;
+  int
+  GetContributingRays(VssRayContainer &selected,
+					  const int minPass
+					  ) const;
+  
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Statistics.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Statistics.h	(revision 469)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Statistics.h	(revision 469)
@@ -0,0 +1,41 @@
+#ifndef __STATISTICS_H
+#define __STATISTICS_H
+
+
+#include "common.h"
+
+// --------------------------------------------------------------
+// Statistics for search - base class
+// --------------------------------------------------------------
+class StatisticsBase
+{
+public:
+	
+  // return time diff. in s
+  static inline double TimeDiff(long time1, long time2) // in s
+  {
+    const double clk=1.0E-6; // ticks per second
+    long t=time2-time1;
+		
+    return ((t<0)?-t:t)*clk;
+  }
+	
+public:
+  long startTime;
+  long stopTime;
+  
+  void Start() {
+    startTime = GetTime();
+  }
+
+  void Stop() {
+    stopTime = GetTime();
+  }
+
+  float Time() const {
+    return (float)TimeDiff(startTime, stopTime);
+  }
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Tetrahedron3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Tetrahedron3.h	(revision 544)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Tetrahedron3.h	(revision 544)
@@ -0,0 +1,67 @@
+#ifndef __TETRAHEDRON3_H
+#define __TETRAHEDRON3_H
+
+#include "Triangle3.h"
+#include "Vector3.h"
+
+class Tetrahedron3 
+{
+public:
+  Vector3 mVertices[4];
+  
+  Tetrahedron3() {}
+  
+  Tetrahedron3(const Vector3 &a,
+			   const Vector3 &b,
+			   const Vector3 &c,
+			   const Vector3 &d) 
+  {
+	  Init(a, b, c, d);
+  }
+  
+  Tetrahedron3(const Triangle3 &t, const Vector3 &a)
+  {
+	  Init(t.mVertices[0], t.mVertices[1], t.mVertices[2], a);
+  }
+
+  void Init(const Vector3 &a,
+			const Vector3 &b,
+			const Vector3 &c,
+			const Vector3 &d) 
+  {
+	  mVertices[0] = a;
+	  mVertices[1] = b;
+	  mVertices[2] = c;
+	  mVertices[3] = c;
+  }
+
+  Triangle3 GetTriangle(const int i) const 
+  {
+	  switch(i)
+	  {
+	  case 0: 
+		  return Triangle3(mVertices[0],  mVertices[1], mVertices[2]);
+		  break;
+	  case 1:
+		  return Triangle3(mVertices[0],  mVertices[1], mVertices[3]);
+		  break;
+	  case 2:
+		  return Triangle3(mVertices[1],  mVertices[2], mVertices[3]);
+		  break;
+	  case 3:
+		  return Triangle3(mVertices[0],  mVertices[3], mVertices[2]);
+		  break;
+	  }
+	  return Triangle3();
+  }
+
+
+  float GetArea() const;
+  float GetVolume() const;
+  bool Valid() const;
+
+};
+
+
+#endif
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Environment.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Environment.h	(revision 492)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Environment.h	(revision 492)
@@ -0,0 +1,355 @@
+// ===================================================================
+// $Id: environ.h,v 1.1 2004/02/16 14:46:00 bittner Exp $
+//
+// environ.h
+//     Header file for environment operations, i.e.. reading
+//     environment file, reading command line parameters etc.
+//
+// Class: CEnvironment
+//
+/// Initial coding by
+/// @author             Tomas Kopal
+
+#ifndef __ENVIRONMENT_H__
+#define __ENVIRONMENT_H__
+
+// forward declarations
+
+#include "common.h"
+
+class Vector3;
+
+
+
+/// Enumeration type used to distinguish the type of the environment variable
+enum EOptType {
+  /// the integer variable
+  optInt,
+  /// the Real variable
+  optFloat,
+  /// the bool variable
+  optBool,
+  /// the vector variable
+  optVector,
+  /// the string variable
+  optString
+};
+
+class COption
+{
+public:
+  COption() {
+    name = NULL;
+    value = NULL;
+    abbrev = NULL;
+    defaultValue = NULL;
+    description = NULL;
+    pointer = NULL;
+  }
+
+  virtual ~COption() {
+    if (name)
+      delete name;
+    if (value)
+      delete value;
+    if (abbrev)
+      delete abbrev;
+    if (defaultValue)
+      delete defaultValue;
+    if (description)
+      delete description;
+    
+  }
+
+  EOptType type;
+  char *name;
+  char *value;
+  char *abbrev;
+  char *defaultValue;
+
+  char *description;
+  void *pointer;
+  friend ostream &operator <<(ostream &s, const COption &o) {
+    s<<o.name<<"\t";
+    if (o.abbrev)
+      s<<o.abbrev;
+    else
+      s<<"no abbrev";
+    s<<"\t";
+    if (o.value)
+      s<<o.value;
+    else
+      s<<"not set";
+    s<<"\t";
+    if (o.defaultValue)
+      s<<"["<<o.defaultValue<<"]";
+    else
+      s<<"[not set]";
+    s<<"\t";
+    if (o.description)
+      s<<endl<<o.description;
+    return s;
+  }
+  
+};
+
+/** CEnvironment class.
+  This class is used for reading command line, reading environment file and
+  managing options. Each recognizable option must be registered in the
+  constructor of this class.
+ */
+class Environment {
+  /**@name Variables */
+  //@{
+private:
+  /// Maximal number of options
+  int maxOptions;
+  /// Number of columns in the parameter table.
+  int numParams;
+  /// Number of rows in the parameter table.
+  int paramRows;
+  /// String with prefixes with non-optional parameters.
+  char *optionalParams;
+  /// Current row in the parameter table.
+  int curRow;
+
+  /** Parameter table itself.
+    The organization of this table is two dimensional array of character
+    strings. First column are parameters, all the other columns are options
+    prefixed by char passed to function GetCmdlineParams and paired with
+    corresponding parameters.
+   */
+  char ***params;
+
+  /// Number of registered options.
+  int numOptions;
+  /** Options table itself.
+    This table is two dimensional array of character strings with four
+    columns. First column contains name of the option, second it's value,
+    third eventual abbreviation, and finally the fourth contains the default
+    value specified when registering the option.
+    */
+  COption *options;
+  //  char ***options;
+  /** Options types.
+    This is auxiliary table to the table "options". It contains the type of
+    each option as specified when registering.
+    */
+  //  EOptType *optTypes;
+  //@}
+
+  /**@name Methods */
+  //@{
+  /** Auxiliary method for parsing environment file.
+    Function gets one string from buffer, skipping leading whitespaces, and
+    appends it at the end of the string parameter. Returns pointer to the next
+    string in the buffer with trailing whitespaces skipped. If no string in
+    the buffer can't be found, returns NULL.
+    @param buffer Input line for parsing.
+    @param string Buffer to append gathered string to.
+    @return Pointer to next string or NULL if not succesful.
+    */
+  char* ParseString(char *buffer, char *string) const; 
+  /** Method for checking variable type.
+    This method is used to check if the value of the variable can be taken
+    as the specified type.
+    @param value Tested value of the variable.
+    @param type The type of the variable.
+    @return true if the variable is of the specified type, false elsewhere.
+    */
+  bool CheckType(const char *value, const EOptType type) const;
+  //@}
+
+  int
+  FindOption(const char *name,
+	     const bool isFatal=false) const;
+
+  bool
+  ParseBool(const char *name) const;
+  void
+  ParseVector(const char *name, Vector3 &v) const;
+
+
+
+public:  
+  /**@name Methods */
+  //@{
+  /// Constructor of the CEnvironment class.
+  Environment();
+  /// Destructor of the CEnvironment class.
+  virtual ~Environment();
+  
+  /// This method is used as a help on available command line options.
+  virtual void PrintUsage(ostream &s) const;
+
+  virtual void SetStaticOptions();
+
+
+  /** Method for registering new option.
+      Using this method is possible to register new option with it's name, type,
+      abbreviation and default value.
+      @param name Name of the option.
+      @param type The type of the variable.
+      @param abbrev If not NULL, alias usable as a command line option.
+      @param defValue Implicit value used if not specified explicitly.
+  */
+  void RegisterOption(const char *name, const EOptType type,
+		      const char *abbrev, const char *defValue = NULL);
+  
+  /** Check if the specified switch is present in the command line.
+    Primary use of this function is to check for presence of some special
+    switch, e.g. -h for help. It can be used anytime.
+    @param argc Number of command line arguments.
+    @param argv Array of command line arguments.
+    @param swtch Switch we are checking for.
+    @return true if found, false elsewhere.
+   */
+  bool CheckForSwitch(const int argc,
+					  char **argv,
+					  const char swtch) const;
+  /** First pass of parsing command line.
+    This function parses command line and gets from there all non-optional
+    parameters (i.e. not prefixed by the dash) and builds a table of
+    parameters. According to param optParams, it also writes some optional
+    parameters to this table and pair them with corresponding non-optional
+    parameters.
+    @param argc Number of command line arguments.
+    @param argv Array of command line arguments.
+    @param optParams String consisting of prefixes to non-optional parameters.
+                     All prefixes must be only one character wide !
+   */
+  void ReadCmdlineParams(const int argc,
+						 char **argv,
+						 const char *optParams);
+  /** Reading of the environment file.
+    This function reads the environment file.
+    @param filename The name of the environment file to read.
+    @return true if OK, false in case of error.
+    */
+  bool ReadEnvFile(const char *filename);
+  /** Second pass of the command line parsing.
+    Performs parsing of the command line ignoring all parameters and options
+    read in the first pass. Builds table of options.
+    @param argc Number of command line arguments.
+    @param argv Array of command line arguments.
+    @param index Index of non-optional parameter, of which options should
+                 be read in.
+   */
+  void ParseCmdline(const int argc, char **argv, const int index);
+
+  /** Clears the environment data structures.
+    This function is intended to clear all data structures corresponding to
+    particular non-optional parameter to allow options for the next
+    non-optional parameter to be read. After this clearing, function
+    ReadEnvFile() can be called again to obtain next load of options.
+    */
+  //  void ClearEnvironment();
+  
+  /** Parameters number query function.
+    This function returns number of non-optional parameters specified on
+    the command line.
+    */
+  int GetParamNum() const { return paramRows; }
+  /** Returns the indexed parameter or corresponding optional parameter.
+   This function is used for queries on individual non-optional parameters.
+   The table must be constructed to allow this function to operate (i.e. the
+   first pass of command line parsing must be done).
+   @param name If space (' '), returns the non-optional parameter, else returns
+               the corresponding optional parameter.
+   @param index Index of the non-optional parameter to which all other options
+                corresponds.
+   @param value Return value of the queried parameter.
+   @return true if OK, false in case of error or if the parameter wasn't
+           specified.
+   */
+  bool GetParam(const char name, const int index, char *value) const;
+
+  /**@name Options query functions.
+   These functions are used for queries on individual options. The table must
+   be constructed to allow these functions to operate (i.e. the environment
+   file must be read and the second pass of command line parsing be done).
+   @param name Name of the option to retrieve.
+   @param value Return value of the queried option.
+   @param isFatal Boolean value specifying, if the function should exit or
+                  return false in case of error.
+   @return true if OK, false in case of error.
+   */
+  //@{
+  /// returns true, if the specified option has been specified
+  bool OptionPresent(const char *name) const;
+  /// returns named option as a integral value.
+  bool GetIntValue(const char *name,
+		   int &value,
+		   const bool isFatal = false) const;
+  
+  /// returns named option as a floating point value.
+  bool GetDoubleValue(const char *name,
+		      double &value,
+		      const bool isFatal = false) const;
+
+  /// returns named option as a floating point value.
+  bool GetRealValue(const char *name,
+		    Real &value,
+		    const bool isFatal = false) const;
+
+  bool GetFloatValue(const char *name,
+		     float &value,
+		     const bool isFatal = false) const;
+
+  /// returns named option as a boolean value.
+  bool GetBoolValue(const char *name,
+		    bool &value,
+		    const bool isFatal = false) const;
+
+  bool GetBool(const char *name, const bool isFatal = false) const;
+  
+  /// returns named option as a 3D vector.
+  bool GetVectorValue(const char *name,
+		      Vector3 &v,
+		      const bool isFatal = false) const;
+
+  /// returns named option as a character string.
+  bool GetStringValue(const char *name,
+											char *value,
+											const bool isFatal = false) const;
+  
+  //@}
+  /**@name Options set functions.
+   These functions are used for setting individual options.
+   @param name Name of the option to set.
+   @param value Value to set the option to.
+   */
+  //@{
+  /// sets named option as a integral value.
+  void SetInt(const char *name, const int value);
+  /// sets named option as a floating point value.
+  void SetFloat(const char *name, const Real value);
+  /// sets named option as a boolean value.
+  void SetBool(const char *name, const bool value);
+  /// sets named option as a 3D vector.
+  void SetVector(const char *name,
+		 const Vector3 &v);
+  /// sets named option as a character string.
+  void SetString(const char *name, const char *value);
+  //@}
+  //@}
+
+  void Parse(const int argc, char **argv, bool useExePath);
+
+  void
+  CodeString(char *buff, int max);
+
+  void
+  DecodeString(char *buff, int max);
+
+  void
+  SaveCodedFile(char *filenameText,
+		char *filenameCoded);
+
+};
+
+// global environment value
+extern Environment *environment;
+
+#endif // __ENVIRON_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ExactPreprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ExactPreprocessor.cpp	(revision 372)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ExactPreprocessor.cpp	(revision 372)
@@ -0,0 +1,11 @@
+#include "ExactPreprocessor.h"
+
+  
+bool
+ExactPreprocessor::ComputeVisibility()
+{
+  
+  return true;
+};
+
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Polytope.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Polytope.cpp	(revision 372)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Polytope.cpp	(revision 372)
@@ -0,0 +1,23 @@
+#include "Polytope.h"
+
+/************************************************
+ *         class Polyhedron implementation      *
+ ***********************************************/
+
+bool Polyhedron::IsBounded()
+{
+	return true;
+}
+
+/************************************************
+ *         class Polytope implementation        *
+ ***********************************************/
+
+Polytope::Polytope(const Polyhedron &boundedPoly)
+{
+}
+
+void Polytope::Split(Hyperplane *plane, Polytope *front, Polytope *back)
+{
+}
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RayInfo.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RayInfo.h	(revision 437)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RayInfo.h	(revision 437)
@@ -0,0 +1,92 @@
+#ifndef __RAYINFO_H__
+#define __RAYINFO_H__
+
+#include <vector>
+using namespace std;
+
+class VssRay;
+class RayInfo;
+class Plane3;
+class Vector3;
+
+typedef vector<RayInfo> RayInfoContainer;
+/** Structure holding additional info about
+	the ray during traversal.
+*/
+class RayInfo
+{
+public:
+	/// pointer to the actual ray
+	VssRay *mRay;
+	
+	// endpoints  - do we need them?
+#if USE_FIXEDPOINT_T
+	short mMinT, mMaxT;
+#else
+	float mMinT, mMaxT;
+#endif
+	
+	RayInfo();
+	
+	RayInfo(VssRay *r);
+	
+	RayInfo(VssRay *r, const float _min, const float _max);
+	
+	RayInfo(VssRay *r, const short _min, const float _max); 
+	
+	RayInfo(VssRay *r, const float _min, const short _max);
+		
+	friend bool operator<(const RayInfo &a, const RayInfo &b) 
+	{
+		return a.mRay < b.mRay;
+	}
+	
+	/** Extracts the scalar of the starting point of the ray segment
+		that lies in the axis.
+	*/
+	float ExtrapOrigin(const int axis) const;
+	/** Extracts the scalar of the termination point of the ray segment
+		that lies in the axis.
+	*/
+	float ExtrapTermination(const int axis) const;
+	
+	/** Extracts the starting point of the ray segment.
+	*/
+	Vector3 ExtrapOrigin() const;
+	
+	/** Extracts the end point of the ray segment.
+	*/
+	Vector3 ExtrapTermination() const;
+	
+	float GetMinT () const;
+	float GetMaxT () const;
+	
+	void SetMinT (const float t);
+	
+	void SetMaxT (const float t);
+
+	float SegmentLength() const;
+	float SqrSegmentLength() const;
+
+	/** Computes intersection of this ray with the axis aligned split plane.
+	
+		@param axis axis of the split plane
+		@param position scalar position of the split plane for the chosen axis
+		@param t returns the t parameter value of the ray intersection
+
+		@returns 0 if ray intersects plane, -1 if on back side of plane, 1 if on front side
+	*/
+	int ComputeRayIntersection(const int axis, const float position, float &t) const;
+
+	/** Computes intersection of this ray with the split plane.
+
+		@param splitPlane the split plane
+		@param t returns the t parameter value of the ray intersection
+
+		@returns 0 if ray intersects plane, -1 if on back side of plane, 1 if on front side
+	*/
+	int ComputeRayIntersection(const Plane3 &splitPlane, float &t) const;
+};
+
+#endif 
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.cpp	(revision 608)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.cpp	(revision 608)
@@ -0,0 +1,778 @@
+#include "SceneGraph.h"
+#include "KdTree.h"
+#include "RssPreprocessor.h"
+#include "X3dExporter.h"
+#include "Environment.h"
+#include "MutualVisibility.h"
+#include "Polygon3.h"
+#include "ViewCell.h"
+#include "VssRay.h"
+#include "RssTree.h"
+#include "ViewCellsManager.h"
+#include "RenderSimulator.h"
+#include "GlRenderer.h"
+
+static bool useViewSpaceBox = false;
+static bool use2dSampling = false;
+
+
+// not supported anymore!
+static bool fromBoxVisibility = false;
+
+
+RssPreprocessor::RssPreprocessor():
+  mPass(0),
+  mVssRays()
+{
+  // this should increase coherence of the samples
+  environment->GetIntValue("RssPreprocessor.samplesPerPass", mSamplesPerPass);
+  environment->GetIntValue("RssPreprocessor.initialSamples", mInitialSamples);
+  environment->GetIntValue("RssPreprocessor.vssSamples", mRssSamples);
+  environment->GetIntValue("RssPreprocessor.vssSamplesPerPass", mRssSamplesPerPass);
+  environment->GetBoolValue("RssPreprocessor.useImportanceSampling", mUseImportanceSampling);
+
+  environment->GetBoolValue("RssPreprocessor.Export.pvs", mExportPvs);
+  environment->GetBoolValue("RssPreprocessor.Export.rssTree", mExportRssTree);
+  environment->GetBoolValue("RssPreprocessor.Export.rays", mExportRays);
+  environment->GetIntValue("RssPreprocessor.Export.numRays", mExportNumRays);
+  environment->GetBoolValue("RssPreprocessor.useViewcells", mUseViewcells);
+  environment->GetBoolValue("RssPreprocessor.objectBasedSampling", mObjectBasedSampling);
+  environment->GetBoolValue("RssPreprocessor.directionalSampling", mDirectionalSampling);
+
+  environment->GetBoolValue("RssPreprocessor.loadInitialSamples", mLoadInitialSamples);
+  environment->GetBoolValue("RssPreprocessor.storeInitialSamples", mStoreInitialSamples);
+  environment->GetBoolValue("RssPreprocessor.updateSubdivision", mUpdateSubdivision);
+  
+  mStats.open("stats.log");
+  mRssTree = NULL;
+}
+
+
+bool
+RssPreprocessor::GenerateRays(
+							  const int number,
+							  const int sampleType,
+							  SimpleRayContainer &rays
+							  )
+{
+  bool result = false;
+
+  switch (sampleType) {
+  case RSS_BASED_DISTRIBUTION:
+  case RSS_SILHOUETTE_BASED_DISTRIBUTION:
+	if (mRssTree) {
+	  GenerateImportanceRays(mRssTree, number, rays);
+	  result = true;
+	  //	  rays.NormalizePdf();
+	}
+	break;
+  default:
+	result = Preprocessor::GenerateRays(number, sampleType, rays);
+  }
+
+  return result;
+}
+
+void
+RssPreprocessor::CastRays(
+						  SimpleRayContainer &rays,
+						  VssRayContainer &vssRays
+						  )
+{
+  for (int i=0; i < rays.size(); i++)
+	CastRay(rays[i].mOrigin, rays[i].mDirection, rays[i].mPdf, vssRays);
+}
+
+
+RssPreprocessor::~RssPreprocessor()
+{
+  // mVssRays get deleted in the tree
+  //  CLEAR_CONTAINER(mVssRays);
+}
+
+void
+RssPreprocessor::SetupRay(Ray &ray, 
+						  const Vector3 &point, 
+						  const Vector3 &direction
+						  )
+{
+  ray.intersections.clear();
+  // do not store anything else then intersections at the ray
+  ray.Init(point, direction, Ray::LOCAL_RAY);
+}
+
+int
+RssPreprocessor::CastRay(
+						 Vector3 &viewPoint,
+						 Vector3 &direction,
+						 const float probability,
+						 VssRayContainer &vssRays
+						 )
+{
+  int hits = 0;
+  static Ray ray;
+  AxisAlignedBox3 box = mKdTree->GetBox();
+
+  AxisAlignedBox3 sbox = box;
+  sbox.Enlarge(Vector3(-Limits::Small));
+  if (!sbox.IsInside(viewPoint))
+	return 0;
+	
+  SetupRay(ray, viewPoint, direction);
+
+  if (!mDetectEmptyViewSpace)
+	ray.mFlags &= ~Ray::CULL_BACKFACES;
+  else
+	ray.mFlags |= Ray::CULL_BACKFACES;
+
+
+  // cast ray to KD tree to find intersection with other objects
+  Intersectable *objectA, *objectB;
+  Vector3 pointA, pointB;
+  float bsize = Magnitude(box.Size());
+
+  
+  if (mKdTree->CastRay(ray)) {
+	objectA = ray.intersections[0].mObject;
+	pointA = ray.Extrap(ray.intersections[0].mT);
+  } else {
+	objectA = NULL;
+	// compute intersection with the scene bounding box
+	float tmin, tmax;
+	if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
+	  pointA = ray.Extrap(tmax);
+	else
+	  return 0;
+  }
+
+
+  if (mDetectEmptyViewSpace) {
+	SetupRay(ray, pointA, -direction);
+  } else
+	SetupRay(ray, viewPoint, -direction);
+	
+  if (!mDetectEmptyViewSpace)
+	ray.mFlags &= ~Ray::CULL_BACKFACES;
+  else
+	ray.mFlags |= Ray::CULL_BACKFACES;
+
+  if (mKdTree->CastRay(ray)) {
+	objectB = ray.intersections[0].mObject;
+	pointB = ray.Extrap(ray.intersections[0].mT);
+  } else {
+	objectB = NULL;
+	float tmin, tmax;
+	if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
+	  pointB = ray.Extrap(tmax);
+	else
+	  return 0;
+  }
+
+  //  if (objectA == NULL && objectB != NULL) {
+  if (mDetectEmptyViewSpace) {
+	// cast again to ensure that there is no objectA
+	SetupRay(ray, pointB, direction);
+	ray.mFlags |= Ray::CULL_BACKFACES;
+	if (mKdTree->CastRay(ray)) {
+	  objectA = ray.intersections[0].mObject;
+	  pointA = ray.Extrap(ray.intersections[0].mT);
+	}
+  }
+  
+  
+  VssRay *vssRay  = NULL;
+
+  bool validSample = (objectA != objectB);
+  if (validSample) {
+	if (objectA) {
+	  vssRay = new VssRay(pointB,
+						  pointA,
+						  objectB,
+						  objectA,
+						  mPass,
+						  probability
+						  );
+	  vssRays.push_back(vssRay);
+	  hits ++;
+
+	}
+	
+	if (objectB) {
+	  vssRay = new VssRay(pointA,
+						  pointB,
+						  objectA,
+						  objectB,
+						  mPass,
+						  probability
+						  );
+	  vssRays.push_back(vssRay);
+	  hits ++;
+	}
+  }
+  
+  return hits;
+}
+
+
+void
+RssPreprocessor::ExportObjectRays(VssRayContainer &rays,
+								  const int objectId)
+{
+  ObjectContainer::const_iterator oi;
+
+  Intersectable *object = NULL;
+  for (oi = mObjects.begin(); oi != mObjects.end(); ++oi)
+	if (objectId == (*oi)->GetId()) {
+	  object = *oi;
+	  break;
+	}
+
+  if (object == NULL)
+	return;
+  
+  VssRayContainer selectedRays;
+  VssRayContainer::const_iterator it= rays.begin(), it_end = rays.end();
+
+  
+  for (; it != it_end; ++it) {
+	if ((*it)->mTerminationObject == object)
+	  selectedRays.push_back(*it);
+  }
+  
+
+  Exporter *exporter = Exporter::GetExporter("object-rays.x3d");
+  //	exporter->SetWireframe();
+  //	exporter->ExportKdTree(*mKdTree);
+  exporter->SetFilled();
+  exporter->ExportIntersectable(object);
+  exporter->ExportRays(selectedRays, RgbColor(1, 0, 0));
+  
+  delete exporter;
+  
+}
+
+
+int
+RssPreprocessor::GenerateImportanceRays(RssTree *rssTree,
+										const int desiredSamples,
+										SimpleRayContainer &rays
+										)
+{
+  int num;
+
+  rssTree->UpdateTreeStatistics();
+
+  cout<<
+	"#RSS_AVG_PVS_SIZE\n"<<rssTree->stat.avgPvsSize<<endl<<
+	"#RSS_AVG_RAYS\n"<<rssTree->stat.avgRays<<endl<<
+	"#RSS_AVG_RAY_CONTRIB\n"<<rssTree->stat.avgRayContribution<<endl<<
+	"#RSS_AVG_PVS_ENTROPY\n"<<rssTree->stat.avgPvsEntropy<<endl<<
+	"#RSS_AVG_RAY_LENGTH_ENTROPY\n"<<rssTree->stat.avgRayLengthEntropy<<endl<<
+	"#RSS_AVG_IMPORTANCE\n"<<rssTree->stat.avgImportance<<endl;
+  
+  if (0) {
+	float p = desiredSamples/(float)(rssTree->stat.avgRayContribution*rssTree->stat.Leaves());
+	num = rssTree->GenerateRays(p, rays);
+  } else {
+	int leaves = rssTree->stat.Leaves()/1;
+	num = rssTree->GenerateRays(desiredSamples, leaves, rays);
+  }
+	
+	
+  return num;
+}
+
+
+bool
+RssPreprocessor::ExportRays(const char *filename,
+							const VssRayContainer &vssRays,
+							const int number
+							)
+{
+  cout<<"Exporting vss rays..."<<endl<<flush;
+	
+  Exporter *exporter = NULL;
+  exporter = Exporter::GetExporter(filename);
+  //	exporter->SetWireframe();
+  //	exporter->ExportKdTree(*mKdTree);
+  exporter->SetFilled();
+  // $$JB temporarily do not export the scene
+  if (1)
+	exporter->ExportScene(mSceneGraph->mRoot);
+  exporter->SetWireframe();
+
+  if (mViewSpaceBox) {
+	exporter->SetForcedMaterial(RgbColor(1,0,1));
+	exporter->ExportBox(*mViewSpaceBox);
+	exporter->ResetForcedMaterial();
+  }
+	
+  VssRayContainer rays;
+  
+  vssRays.SelectRays( number, rays);
+
+  exporter->ExportRays(rays, RgbColor(1, 0, 0));
+	
+  delete exporter;
+
+  cout<<"done."<<endl<<flush;
+
+  return true;
+}
+
+
+bool
+RssPreprocessor::ExportRssTree(char *filename,
+							   RssTree *tree,
+							   const Vector3 &dir
+							   )
+{
+  Exporter *exporter = Exporter::GetExporter(filename);
+  exporter->SetFilled();
+  exporter->ExportScene(mSceneGraph->mRoot);
+  //  exporter->SetWireframe();
+  bool result = exporter->ExportRssTree2( *tree, dir );
+  delete exporter;
+  return result;
+}
+
+bool
+RssPreprocessor::ExportRssTreeLeaf(char *filename,
+								   RssTree *tree,
+								   RssTreeLeaf *leaf)
+{
+  Exporter *exporter = NULL;
+  exporter = Exporter::GetExporter(filename);
+  exporter->SetWireframe();
+  exporter->ExportKdTree(*mKdTree);
+	
+  if (mViewSpaceBox) {
+	exporter->SetForcedMaterial(RgbColor(1,0,0));
+	exporter->ExportBox(*mViewSpaceBox);
+	exporter->ResetForcedMaterial();
+  }
+	
+  exporter->SetForcedMaterial(RgbColor(0,0,1));
+  exporter->ExportBox(tree->GetBBox(leaf));
+  exporter->ResetForcedMaterial();
+	
+  VssRayContainer rays[4];
+  for (int i=0; i < leaf->rays.size(); i++) {
+	int k = leaf->rays[i].GetRayClass();
+	rays[k].push_back(leaf->rays[i].mRay);
+  }
+	
+  // SOURCE RAY
+  exporter->ExportRays(rays[0], RgbColor(1, 0, 0));
+  // TERMINATION RAY
+  exporter->ExportRays(rays[1], RgbColor(1, 1, 1));
+  // PASSING_RAY
+  exporter->ExportRays(rays[2], RgbColor(1, 1, 0));
+  // CONTAINED_RAY
+  exporter->ExportRays(rays[3], RgbColor(0, 0, 1));
+
+  delete exporter;
+  return true;
+}
+
+void
+RssPreprocessor::ExportRssTreeLeaves(RssTree *tree, const int number)
+{
+  vector<RssTreeLeaf *> leaves;
+  tree->CollectLeaves(leaves);
+
+  int num = 0;
+  int i;
+  float p = number / (float)leaves.size();
+  for (i=0; i < leaves.size(); i++) {
+	if (RandomValue(0,1) < p) {
+	  char filename[64];
+	  sprintf(filename, "rss-leaf-%04d.x3d", num);
+	  ExportRssTreeLeaf(filename, tree, leaves[i]);
+	  num++;
+	}
+	if (num >= number)
+	  break;
+  }
+}
+
+
+float
+RssPreprocessor::GetAvgPvsSize(RssTree *tree,
+							   const vector<AxisAlignedBox3> &viewcells
+							   )
+{
+  vector<AxisAlignedBox3>::const_iterator it, it_end = viewcells.end();
+
+  int sum = 0;
+  for (it = viewcells.begin(); it != it_end; ++ it)
+	sum += tree->GetPvsSize(*it);
+	
+  return sum/(float)viewcells.size();
+}
+
+
+void
+RssPreprocessor::ExportPvs(char *filename,
+						   RssTree *rssTree
+						   )
+{
+  ObjectContainer pvs;
+  if (rssTree->CollectRootPvs(pvs)) {
+	Exporter *exporter = Exporter::GetExporter(filename);
+	exporter->SetFilled();
+	exporter->ExportGeometry(pvs);
+	exporter->SetWireframe();
+	exporter->ExportBox(rssTree->bbox);
+	exporter->ExportViewpoint(rssTree->bbox.Center(), Vector3(1,0,0));
+	delete exporter;
+  }
+}
+
+
+void
+RssPreprocessor::ComputeRenderError()
+{
+  // compute rendering error
+  if (renderer) {
+	//	emit EvalPvsStat();
+	//	QMutex mutex;
+	//	mutex.lock();
+	//	renderer->mRenderingFinished.wait(&mutex);
+	//	mutex.unlock();
+
+	renderer->EvalPvsStat();
+	mStats <<
+	  "#AvgPvsRenderError\n" <<renderer->mPvsStat.GetAvgError()<<endl<<
+	  "#MaxPvsRenderError\n" <<renderer->mPvsStat.GetMaxError()<<endl<<
+	  "#ErrorFreeFrames\n" <<renderer->mPvsStat.GetErrorFreeFrames()<<endl;
+  }
+}
+
+
+
+bool
+RssPreprocessor::ComputeVisibility()
+{
+
+	Debug << "type: rss" << endl;
+
+  cout<<"Rss Preprocessor started\n"<<flush;
+  //  cout<<"Memory/ray "<<sizeof(VssRay)+sizeof(RssTreeNode::RayInfo)<<endl;
+
+  Randomize(0);
+  
+	
+  long startTime = GetTime();
+  
+  int totalSamples = 0;
+
+  mViewSpaceBox = NULL;
+
+  // if not already loaded, construct view cells from file
+  if (!mLoadViewCells) {	
+	
+	  mViewCellsManager->SetViewSpaceBox(mKdTree->GetBox());
+
+	  // construct view cells using it's own set of samples
+	  mViewCellsManager->Construct(this);
+
+	  //-- several visualizations and statistics
+	  Debug << "view cells construction finished: " << endl;
+	  mViewCellsManager->PrintStatistics(Debug);
+  }
+
+
+  int rssPass = 0;
+  int rssSamples = 0;
+  
+  if (mLoadInitialSamples) {
+	cout << "Loading samples from file ... ";
+	LoadSamples(mVssRays, mObjects);
+	cout << "finished\n" << endl;
+  } else {
+	SimpleRayContainer rays;
+
+	GenerateRays(mInitialSamples/4, SPATIAL_BOX_BASED_DISTRIBUTION, rays);
+	GenerateRays(mInitialSamples/4, OBJECT_BASED_DISTRIBUTION, rays);
+	GenerateRays(mInitialSamples/4, DIRECTION_BASED_DISTRIBUTION, rays);
+	GenerateRays(mInitialSamples/4, OBJECT_DIRECTION_BASED_DISTRIBUTION, rays);
+	
+	CastRays(rays, mVssRays);
+
+	ExportObjectRays(mVssRays, 1546);
+  }
+  
+  cout << "#totalRayStackSize=" << (int)mVssRays.size() << endl <<flush;
+  
+  rssSamples += (int)mVssRays.size();
+  totalSamples += mInitialSamples;
+  mPass++;
+  
+  if (mExportRays) {
+	
+	char filename[64];
+	sprintf(filename, "rss-rays-initial.x3d");
+	ExportRays(filename, mVssRays, mExportNumRays);
+	
+  }
+  
+  if (mStoreInitialSamples) {
+	cout << "Writing samples to file ... ";
+	ExportSamples(mVssRays);
+	cout << "finished\n" << endl;
+  }
+	
+  if (mUseViewcells) {
+
+	// evaluate contributions of the intitial rays
+	mViewCellsManager->ComputeSampleContributions(mVssRays, true, false);
+	
+	
+	mStats <<
+	  "#Pass\n" <<mPass<<endl<<
+	  "#RssPass\n" <<rssPass<<endl<<
+	  "#Time\n" << TimeDiff(startTime, GetTime())*1e-3<<endl<<
+	  "#TotalSamples\n" <<totalSamples<<endl<<
+	  "#RssSamples\n" <<rssSamples<<endl;
+
+	{
+	  VssRayContainer contributingRays;
+	  mVssRays.GetContributingRays(contributingRays, mPass);
+	  mStats<<"#NUM_CONTRIBUTING_RAYS\n"<<(int)contributingRays.size()<<endl;
+	}
+	
+	mVssRays.PrintStatistics(mStats);
+	mViewCellsManager->PrintPvsStatistics(mStats);
+	  
+	// viewcells->UpdatePVS(newVssRays);
+	Debug<<"Valid viewcells before set validity: "<<mViewCellsManager->CountValidViewcells()<<endl;
+	// cull viewcells with PVS > median (0.5f)
+	mViewCellsManager->SetValidityPercentage(0, 0.5f); 
+	Debug<<"Valid viewcells after set validity: "<<mViewCellsManager->CountValidViewcells()<<endl;
+	
+	ComputeRenderError();
+  }
+  
+  rssPass++;
+  
+  mRssTree = new RssTree;
+  mRssTree->SetPass(mPass);
+  
+  /// compute view cell contribution of rays if view cells manager already constructed
+  mViewCellsManager->ComputeSampleContributions(mVssRays, true, false);
+
+  if (mUseImportanceSampling) {
+	
+	mRssTree->Construct(mObjects, mVssRays);
+	
+	mRssTree->stat.Print(mStats);
+	cout<<"RssTree root PVS size = "<<mRssTree->GetRootPvsSize()<<endl;
+	
+	if (mExportRssTree) {
+	  ExportRssTree("rss-tree-100.x3d", mRssTree, Vector3(1,0,0));
+	  ExportRssTree("rss-tree-001.x3d", mRssTree, Vector3(0,0,1));
+	  ExportRssTree("rss-tree-101.x3d", mRssTree, Vector3(1,0,1));
+	  ExportRssTree("rss-tree-101m.x3d", mRssTree, Vector3(-1,0,-1));
+	  ExportRssTreeLeaves(mRssTree, 10);
+	}
+	
+	if (mExportPvs) {
+	  ExportPvs("rss-pvs-initial.x3d", mRssTree);
+	}
+  }
+  
+  
+  while (1) {
+	SimpleRayContainer rays;
+	VssRayContainer vssRays;
+	int castRays = 0;
+	if (mUseImportanceSampling) {
+	  VssRayContainer tmpVssRays;
+
+	  float ratios[] = {0.8f,0.1f,0.1f};
+
+	  
+	  
+	  GenerateRays(mRssSamplesPerPass*ratios[0], RSS_BASED_DISTRIBUTION, rays);
+	  CastRays(rays, tmpVssRays);
+	  castRays += rays.size();
+	  float c1 = mViewCellsManager->ComputeSampleContributions(tmpVssRays, false, true);
+	  mStats<<"#RssRelContrib"<<endl<<c1/rays.size()<<endl;
+
+	  vssRays.insert(vssRays.end(), tmpVssRays.begin(), tmpVssRays.end() );
+	  rays.clear();
+	  tmpVssRays.clear();
+
+	  if (ratios[1]!=0.0f) {
+		GenerateRays(mRssSamplesPerPass*ratios[1], SPATIAL_BOX_BASED_DISTRIBUTION, rays);
+		CastRays(rays, tmpVssRays);
+		castRays += rays.size();
+		float c2 = mViewCellsManager->ComputeSampleContributions(tmpVssRays, false, true);
+		mStats<<"#SpatialRelContrib"<<endl<<c2/rays.size()<<endl;
+		
+		vssRays.insert(vssRays.end(), tmpVssRays.begin(), tmpVssRays.end() );
+		
+		rays.clear();
+		tmpVssRays.clear();
+	  }
+	  
+	  
+	  if (ratios[2]!=0.0f) {
+		GenerateRays(mRssSamplesPerPass*ratios[2], DIRECTION_BASED_DISTRIBUTION, rays);
+		CastRays(rays, tmpVssRays);
+		castRays += rays.size();
+		float c3 = mViewCellsManager->ComputeSampleContributions(tmpVssRays, false, true);
+		mStats<<"#DirectionalRelContrib"<<endl<<c3/rays.size()<<endl;
+		
+		vssRays.insert(vssRays.end(), tmpVssRays.begin(), tmpVssRays.end() );
+		
+		rays.clear();
+		tmpVssRays.clear();
+	  }
+	  
+	  // add contributions of all rays at once...
+	  mViewCellsManager->AddSampleContributions(vssRays);
+	  
+	}
+	else {
+	  int rayType = SPATIAL_BOX_BASED_DISTRIBUTION;
+	  if (mObjectBasedSampling)
+		rayType = OBJECT_BASED_DISTRIBUTION;
+	  else
+		if (mDirectionalSampling)
+		  rayType = DIRECTION_BASED_DISTRIBUTION;
+	  
+	  GenerateRays(mRssSamplesPerPass, rayType, rays);
+	  CastRays(rays, vssRays);
+	  castRays += rays.size();
+	  if (mUseViewcells) {
+		/// compute view cell contribution of rays
+		mViewCellsManager->ComputeSampleContributions(vssRays, true, false);
+	  }
+	  	
+	  
+	}
+	totalSamples += castRays;
+	rssSamples += (int)vssRays.size();
+
+	cout<<"Generated "<<castRays<<" rays, progress "<<totalSamples/((float) mRssSamples +
+																	mInitialSamples)<<"%\n";
+	
+	
+	mStats <<
+	  "#Pass\n" <<mPass<<endl<<
+	  "#RssPass\n" <<rssPass<<endl<<
+	  "#Time\n" << TimeDiff(startTime, GetTime())*1e-3<<endl<<
+	  "#TotalSamples\n" <<totalSamples<<endl<<
+	  "#RssSamples\n" <<rssSamples<<endl;
+
+
+	if (mUseViewcells) {
+	  vssRays.PrintStatistics(mStats);
+	  mViewCellsManager->PrintPvsStatistics(mStats);
+	}
+
+	if (0 && mPass > 0) {
+	  if (mUseImportanceSampling)
+		renderer->mSnapPrefix.sprintf("snap/i-%02d-", mPass);
+	  else
+		renderer->mSnapPrefix.sprintf("snap/r-%02d-", mPass);
+	  renderer->mSnapErrorFrames = true;
+	}
+
+	ComputeRenderError();
+	
+	// epxort rays before adding them to the tree -> some of them can be deleted
+
+	if (mExportRays) {
+	  char filename[64];
+	  if (mUseImportanceSampling)
+		sprintf(filename, "rss-rays-i%04d.x3d", rssPass);
+	  else
+		sprintf(filename, "rss-rays-%04d.x3d", rssPass);
+	  
+	  ExportRays(filename, vssRays, mExportNumRays);
+
+	  // now export all contributing rays
+	  VssRayContainer contributingRays;
+	  vssRays.GetContributingRays(contributingRays, mPass);
+	  mStats<<"#NUM_CONTRIBUTING_RAYS\n"<<(int)contributingRays.size()<<endl;
+	  sprintf(filename, "rss-crays-%04d.x3d", rssPass);
+	  ExportRays(filename, contributingRays, mExportNumRays);
+	}
+
+	
+	// add rays to the tree after the viewcells have been cast to have their contributions
+	// already when adding into the tree
+	// do not add those rays which have too low or no contribution....
+	
+	if (mUseImportanceSampling) {
+	  mRssTree->AddRays(vssRays);
+	  
+	  if (mUpdateSubdivision) {
+		int updatePasses = 1;
+		if (mPass % updatePasses == 0) {
+		  int subdivided = mRssTree->UpdateSubdivision();
+		  cout<<"subdivided leafs = "<<subdivided<<endl;
+		  cout<<"#total leaves = "<<mRssTree->stat.Leaves()<<endl;
+		}
+	  }
+	}
+	
+	if (mExportPvs) {
+	  char filename[64];
+	  sprintf(filename, "rss-pvs-%04d.x3d", rssPass);
+	  ExportPvs(filename, mRssTree);
+	}
+	
+	
+	if (!mUseImportanceSampling) 
+	  CLEAR_CONTAINER(vssRays);
+	// otherwise the rays get deleted by the rss tree update according to RssTree.maxRays ....
+
+	if (totalSamples >= mRssSamples + mInitialSamples)
+	  break;
+
+	
+	rssPass++;
+	mPass++;
+	mRssTree->SetPass(mPass);
+  }
+  
+  if (mUseViewcells) {
+
+	  if(0)
+	  {
+		  VssRayContainer selectedRays;
+		  int desired = mViewCellsManager->GetVisualizationSamples();
+
+		  mVssRays.SelectRays(desired, selectedRays);
+
+		  mViewCellsManager->Visualize(mObjects, selectedRays);
+	  }
+	  
+	  // view cells after sampling
+	  mViewCellsManager->PrintStatistics(Debug);
+      
+	  //-- render simulation after merge
+	  cout << "\nevaluating bsp view cells render time after sampling ... ";
+	  
+	  mRenderSimulator->RenderScene();
+	  SimulationStatistics ss;
+	  mRenderSimulator->GetStatistics(ss);
+	  
+	  cout << " finished" << endl;
+	  cout << ss << endl;
+	  Debug << ss << endl;
+	
+  }
+  
+  Debug<<"Deleting RSS tree...\n";
+  delete mRssTree;
+  Debug<<"Done.\n";
+
+  
+  return true;
+}
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/dual_depth.cg
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/dual_depth.cg	(revision 540)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/dual_depth.cg	(revision 540)
@@ -0,0 +1,31 @@
+struct fragment
+{
+	float4 position  : POSITION;	//screen position
+	float4 color0    : COLOR0;
+	float4 depthTexCoord: TEXCOORD0;
+};
+
+
+struct pixel
+{
+	float4 color : COLOR;	
+};
+
+pixel main(fragment IN, const uniform sampler2D depthMap)
+{
+	pixel OUT;
+	OUT.color = IN.color0;
+	
+	// the depth buffer	has to be compared to the current depth
+	float4 depth = tex2D(depthMap, IN.depthTexCoord.xy);
+	float test = IN.depthTexCoord.z / IN.depthTexCoord.w;
+	
+	// reject by alpha test
+	if (test < depth.x)
+	{
+		OUT.color.w = 0;
+	//	OUT.color.y += 0.5;
+	}
+	
+	return OUT;
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp	(revision 605)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp	(revision 605)
@@ -0,0 +1,806 @@
+#include "SceneGraph.h"
+#include "KdTree.h"
+#include "VssPreprocessor.h"
+#include "X3dExporter.h"
+#include "Environment.h"
+#include "MutualVisibility.h"
+#include "Polygon3.h"
+#include "ViewCell.h"
+#include "VssRay.h"
+#include "VssTree.h"
+#include "ViewCellsManager.h"
+#include "RenderSimulator.h"
+#include "Beam.h"
+#include "GlRenderer.h"
+
+bool use2dSampling = false;
+bool useViewspacePlane = false;
+
+VssPreprocessor::VssPreprocessor():
+  mPass(0),
+  mVssRays()
+{
+  // this should increase coherence of the samples
+  environment->GetIntValue("VssPreprocessor.samplesPerPass", mSamplesPerPass);
+  environment->GetIntValue("VssPreprocessor.initialSamples", mInitialSamples);
+  environment->GetIntValue("VssPreprocessor.vssSamples", mVssSamples);
+  environment->GetIntValue("VssPreprocessor.vssSamplesPerPass", mVssSamplesPerPass);
+  environment->GetBoolValue("VssPreprocessor.useImportanceSampling", mUseImportanceSampling);
+ 
+  environment->GetBoolValue("VssPreprocessor.loadInitialSamples", mLoadInitialSamples);
+  environment->GetBoolValue("VssPreprocessor.storeInitialSamples", mStoreInitialSamples);
+  environment->GetBoolValue("VssPreprocessor.useViewSpaceBox", mUseViewSpaceBox);
+  environment->GetBoolValue("VssPreprocessor.testBeamSampling", mTestBeamSampling);
+
+  useViewspacePlane = mUseViewSpaceBox; //hack
+
+  mStats.open("stats.log");
+}
+
+VssPreprocessor::~VssPreprocessor()
+{
+  CLEAR_CONTAINER(mVssRays);
+  DEL_PTR(mViewSpaceBox);
+}
+
+void
+VssPreprocessor::SetupRay(Ray &ray,
+						  const Vector3 &point,
+						  const Vector3 &direction
+						  )
+{
+  ray.Clear();
+  // do not store anything else then intersections at the ray
+  ray.Init(point, direction, Ray::LOCAL_RAY);
+}
+
+
+void
+VssPreprocessor::CastRays(
+						  SimpleRayContainer &rays,
+						  VssRayContainer &vssRays
+						  )
+{
+  for (int i=0; i < rays.size(); i++)
+	CastRay(rays[i].mOrigin, rays[i].mDirection, vssRays);
+}
+
+
+int
+VssPreprocessor::CastRay(
+						 Vector3 &viewPoint,
+						 Vector3 &direction,
+						 VssRayContainer &vssRays
+						 )
+{
+
+    int hits = 0;
+  static Ray ray;
+  AxisAlignedBox3 box =  mViewSpaceBox ? *mViewSpaceBox : mKdTree->GetBox();
+
+  AxisAlignedBox3 sbox = box;
+  sbox.Enlarge(Vector3(-Limits::Small));
+  if (!sbox.IsInside(viewPoint))
+	return 0;
+	
+  SetupRay(ray, viewPoint, direction);
+  // cast ray to KD tree to find intersection with other objects
+  Intersectable *objectA, *objectB;
+  Vector3 pointA, pointB;
+  float bsize = Magnitude(box.Size());
+
+
+	if (!mDetectEmptyViewSpace)
+	  ray.mFlags &= ~Ray::CULL_BACKFACES;
+	else
+	  ray.mFlags |= Ray::CULL_BACKFACES;
+
+  if (mKdTree->CastRay(ray)) {
+	objectA = ray.intersections[0].mObject;
+	pointA = ray.Extrap(ray.intersections[0].mT);
+  } else {
+	objectA = NULL;
+	// compute intersection with the scene bounding box
+	float tmin, tmax;
+	if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
+	  pointA = ray.Extrap(tmax);
+	else
+	  return 0;
+  }
+
+	
+  if (mDetectEmptyViewSpace) {
+	SetupRay(ray, pointA, -direction);
+  } else
+	SetupRay(ray, viewPoint, -direction);
+  
+  if (!mDetectEmptyViewSpace)
+	ray.mFlags &= ~Ray::CULL_BACKFACES;
+  else
+	 ray.mFlags |= Ray::CULL_BACKFACES;
+
+  if (mKdTree->CastRay(ray)) {
+	objectB = ray.intersections[0].mObject;
+	pointB = ray.Extrap(ray.intersections[0].mT);
+  } else {
+	objectB = NULL;
+	float tmin, tmax;
+	if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
+	  pointB = ray.Extrap(tmax);
+	else
+	  return 0;
+  }
+  
+  //  if (objectA == NULL && objectB != NULL) {
+  if (mDetectEmptyViewSpace) {
+	// cast again to ensure that there is no objectA
+	SetupRay(ray, pointB, direction);
+	  ray.mFlags |= Ray::CULL_BACKFACES;
+	if (mKdTree->CastRay(ray)) {
+	  objectA = ray.intersections[0].mObject;
+	  pointA = ray.Extrap(ray.intersections[0].mT);
+	}
+  }
+
+  
+  VssRay *vssRay  = NULL;
+
+  bool validSample = (objectA != objectB);
+  if (0 && mDetectEmptyViewSpace) {   // consider all samples valid
+	// check if the viewpoint lies on the line segment AB
+	if (Distance(pointA, pointB) <
+		Distance(viewPoint, pointA) + Distance(viewPoint, pointB) - Limits::Small) {
+	  validSample = false;
+	}
+  }
+	
+  if (validSample) {
+	if (objectA) {
+	  vssRay = new VssRay(pointB,
+						  pointA,
+						  objectB,
+						  objectA,
+						  mPass
+						  );
+	  vssRays.push_back(vssRay);
+	  hits ++;
+	}
+	
+	if (objectB) {
+	  vssRay = new VssRay(pointA,
+						  pointB,
+						  objectA,
+						  objectB,
+						  mPass
+						  );
+	  vssRays.push_back(vssRay);
+	  hits ++;
+	}
+  }
+	
+  return hits;
+}
+
+
+Vector3
+VssPreprocessor::GetViewpoint(AxisAlignedBox3 *viewSpaceBox)
+{
+  AxisAlignedBox3 box;
+
+  if (viewSpaceBox)
+	box =*viewSpaceBox;
+  else
+	box = mKdTree->GetBox();
+
+  // shrink the box in the y direction
+  return box.GetRandomPoint();
+}
+
+Vector3
+VssPreprocessor::GetDirection(const Vector3 &viewpoint,
+							  AxisAlignedBox3 *viewSpaceBox
+							  )
+{
+  Vector3 point;
+  if (!use2dSampling) 
+  {
+	  if (0) 
+	  {
+		  Vector3 normal;
+		  int i = Random((int)mObjects.size());
+		  Intersectable *object = mObjects[i];
+		  object->GetRandomSurfacePoint(point, normal);
+	  } 
+	  else
+		  point = mKdTree->GetBox().GetRandomPoint();
+	//	  point = viewpoint + UniformRandomVector();
+  } 
+  else 
+  {
+	  AxisAlignedBox3 box;
+
+	  if (viewSpaceBox)
+		  box =*viewSpaceBox;
+	  else
+		  box = mKdTree->GetBox();
+
+	  point = box.GetRandomPoint();
+	  point.y = viewpoint.y;
+  }
+
+  return point - viewpoint;
+}
+
+int
+VssPreprocessor::GenerateImportanceRays(VssTree *vssTree,
+										const int desiredSamples,
+										SimpleRayContainer &rays
+										)
+{
+  int num;
+  if (0) {
+	float minRayContribution;
+	float maxRayContribution;
+	float avgRayContribution;
+
+	vssTree->GetRayContributionStatistics(minRayContribution,
+										  maxRayContribution,
+										  avgRayContribution);
+
+	cout<<
+	  "#MIN_RAY_CONTRIB\n"<<minRayContribution<<endl<<
+	  "#MAX_RAY_CONTRIB\n"<<maxRayContribution<<endl<<
+	  "#AVG_RAY_CONTRIB\n"<<avgRayContribution<<endl;
+
+	float p = desiredSamples/(float)(avgRayContribution*vssTree->stat.Leaves());
+	num = vssTree->GenerateRays(p, rays);
+  } else {
+	int leaves = vssTree->stat.Leaves();
+	num = vssTree->GenerateRays(desiredSamples, leaves, rays);
+  }
+
+  cout<<"Generated "<<num<<" rays."<<endl;
+
+  return num;
+}
+
+
+bool
+VssPreprocessor::ExportRays(const char *filename,
+							const VssRayContainer &vssRays,
+							const int number
+							)
+{
+  cout<<"Exporting vss rays..."<<endl<<flush;
+
+  Exporter *exporter = NULL;
+  exporter = Exporter::GetExporter(filename);
+  //	exporter->SetWireframe();
+  //	exporter->ExportKdTree(*mKdTree);
+  exporter->SetFilled();
+  exporter->ExportScene(mSceneGraph->mRoot);
+  exporter->SetWireframe();
+
+  if (mViewSpaceBox) {
+	exporter->SetForcedMaterial(RgbColor(1,0,1));
+	exporter->ExportBox(*mViewSpaceBox);
+	exporter->ResetForcedMaterial();
+  }
+
+  VssRayContainer rays;
+  vssRays.SelectRays(number, rays);
+  
+  exporter->ExportRays(rays, RgbColor(1, 0, 0));
+
+  delete exporter;
+
+  cout<<"done."<<endl<<flush;
+
+  return true;
+}
+
+
+bool
+VssPreprocessor::ExportVssTree(char *filename,
+							   VssTree *tree,
+							   const Vector3 &dir
+							   )
+{
+  Exporter *exporter = Exporter::GetExporter(filename);
+  exporter->SetFilled();
+  exporter->ExportScene(mSceneGraph->mRoot);
+  //  exporter->SetWireframe();
+  bool result = exporter->ExportVssTree2( *tree, dir );
+  delete exporter;
+  return result;
+}
+
+bool
+VssPreprocessor::ExportVssTreeLeaf(char *filename,
+								   VssTree *tree,
+								   VssTreeLeaf *leaf)
+{
+  Exporter *exporter = NULL;
+  exporter = Exporter::GetExporter(filename);
+  exporter->SetWireframe();
+  exporter->ExportKdTree(*mKdTree);
+
+  if (mViewSpaceBox) {
+	exporter->SetForcedMaterial(RgbColor(1,0,0));
+	exporter->ExportBox(*mViewSpaceBox);
+	exporter->ResetForcedMaterial();
+  }
+
+  exporter->SetForcedMaterial(RgbColor(0,0,1));
+  exporter->ExportBox(tree->GetBBox(leaf));
+  exporter->ResetForcedMaterial();
+
+  VssRayContainer rays[4];
+  for (int i=0; i < leaf->rays.size(); i++) {
+	int k = leaf->rays[i].GetRayClass();
+	rays[k].push_back(leaf->rays[i].mRay);
+  }
+
+  // SOURCE RAY
+  exporter->ExportRays(rays[0], RgbColor(1, 0, 0));
+  // TERMINATION RAY
+  exporter->ExportRays(rays[1], RgbColor(1, 1, 1));
+  // PASSING_RAY
+  exporter->ExportRays(rays[2], RgbColor(1, 1, 0));
+  // CONTAINED_RAY
+  exporter->ExportRays(rays[3], RgbColor(0, 0, 1));
+
+  delete exporter;
+  return true;
+}
+
+void
+VssPreprocessor::ExportVssTreeLeaves(VssTree *tree, const int number)
+{
+  vector<VssTreeLeaf *> leaves;
+  tree->CollectLeaves(leaves);
+
+  int num = 0;
+  int i;
+  float p = number / (float)leaves.size();
+  for (i=0; i < leaves.size(); i++) {
+	if (RandomValue(0,1) < p) {
+	  char filename[64];
+	  sprintf(filename, "vss-leaf-%04d.x3d", num);
+	  ExportVssTreeLeaf(filename, tree, leaves[i]);
+	  num++;
+	}
+	if (num >= number)
+	  break;
+  }
+}
+#include "ViewCellBsp.h"
+
+void VssPreprocessor::TestBeamCasting(VssTree *tree, 
+									  ViewCellsManager *vm, 
+									  const ObjectContainer &objects)
+{
+	//debuggerWidget = new GlDebuggerWidget(renderer);
+	//  renderer->resize(640, 480);
+	//debuggerWidget->resize(640, 480);
+
+	vector<VssTreeLeaf *> leaves;
+	tree->CollectLeaves(leaves);
+
+	Exporter *exporter = Exporter::GetExporter("shafts.x3d");
+
+	exporter->SetWireframe();
+	exporter->ExportGeometry(objects);
+	exporter->SetFilled();
+	//Randomize();
+	debuggerWidget = new GlDebuggerWidget(renderer);
+
+	/*debuggerWidget->mBeam = beam;
+	debuggerWidget->mSourceObject = sourceObj;
+	debuggerWidget->mSamples = 10000;
+	
+	Debug << "showing window" << endl;
+	debuggerWidget->show();*/
+	
+	renderer->makeCurrent();
+
+	for (int i = 0; i < 10; ++ i)
+	{
+		Beam beam;
+		Intersectable *sourceObj = mObjects[5];
+
+		const int index = (int)RandomValue(0, (Real)((int)leaves.size() - 1));
+		VssTreeLeaf *leaf = leaves[index];
+
+		AxisAlignedBox3 dirBox = tree->GetDirBBox(leaf);
+		AxisAlignedBox3 box = tree->GetBBox(leaf);
+		
+		beam.Construct(box, dirBox);
+
+		// collect kd leaves and view cells
+		mKdTree->CastBeam(beam);
+		vm->CastBeam(beam);
+
+		Debug << "found " << (int)beam.mViewCells.size() << " view cells and " 
+			  << (int)beam.mKdNodes.size() << " kd nodes" << endl;
+
+		BeamSampleStatistics stats;
+
+		renderer->SampleBeamContributions(sourceObj,
+										  beam,
+										  200000,
+										  stats);
+
+		char s[64]; sprintf(s, "shaft%04d.png", i);
+
+		QImage image = renderer->toImage();
+		image.save(s, "PNG");
+		Debug << "beam statistics: " << stats << endl << endl;
+
+		if (1)
+		{
+			AxisAlignedBox3 sbox = mSceneGraph->GetBox();
+			Vector3 bmin = sbox.Min() - 150.0f;
+			Vector3 bmax = sbox.Max() + 150.0f;
+			AxisAlignedBox3 vbox(bmin, bmax);
+		
+			exporter->ExportBeam(beam, vbox);
+		}
+
+		bool exportViewCells = false;
+		
+		if (exportViewCells)
+		{
+			ViewCellContainer::const_iterator it, it_end = beam.mViewCells.end();
+			
+			for (it = beam.mViewCells.begin(); it != beam.mViewCells.end(); ++ it)
+			{
+				BspNodeGeometry geom;
+				AxisAlignedBox3 vbox;
+				vbox.Initialize();
+				vbox.Include((*it)->GetMesh());
+			
+				exporter->SetWireframe();
+				exporter->ExportBox(vbox);
+				exporter->SetFilled();
+				exporter->ExportViewCell(*it);
+			}
+
+			/*vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
+			
+			for (it = beam.mKdNodes.begin(); it != beam.mKdNodes.end(); ++ it)
+			{
+				exporter->ExportBox(mKdTree->GetBox((*it)));
+			}*/
+		}
+	}
+	/*while (1)
+	{ debuggerWidget->repaint();
+	};*/
+	delete exporter;
+}
+
+
+float
+VssPreprocessor::GetAvgPvsSize(VssTree *tree,
+							   const vector<AxisAlignedBox3> &viewcells
+							   )
+{
+  vector<AxisAlignedBox3>::const_iterator it, it_end = viewcells.end();
+
+  int sum = 0;
+  for (it = viewcells.begin(); it != it_end; ++ it)
+	sum += tree->GetPvsSize(*it);
+
+  return sum/(float)viewcells.size();
+}
+
+bool
+VssPreprocessor::ComputeVisibility()
+{
+	Debug << "type: vss" << endl;
+
+  long startTime = GetTime();
+
+  int totalSamples = 0;
+
+
+  AxisAlignedBox3 *box = new AxisAlignedBox3(mKdTree->GetBox());
+  
+  if (!useViewspacePlane) {
+	float size = 0.05f;
+	float s = 0.5f - size;
+	float olds = Magnitude(box->Size());
+	box->Enlarge(box->Size()*Vector3(-s));
+	Vector3 translation = Vector3(-olds*0.1f, 0, 0);
+	box->SetMin(box->Min() + translation);
+	box->SetMax(box->Max() + translation);
+  } else {
+
+	// sample city like heights
+	box->SetMin(1, box->Min(1) + box->Size(1)*0.2f);
+	box->SetMax(1, box->Min(1) + box->Size(1)*0.3f);
+  }
+
+  if (use2dSampling)
+	box->SetMax(1, box->Min(1));
+
+  cout<<"mUseViewSpaceBox="<<mUseViewSpaceBox<<endl;
+  Debug << "use view space box=" << mUseViewSpaceBox << endl;
+
+  if (mUseViewSpaceBox)
+  {
+	  if (0)
+		  mViewSpaceBox = box;
+	  else
+	  {
+		// HACK: enlarge in y directon
+		mViewSpaceBox = new AxisAlignedBox3(mKdTree->GetBox());
+		//Vector3 pmin = mViewSpaceBox->Min();
+		Vector3 size = mViewSpaceBox->Size();
+		//size[1] *= 1.25;
+		Vector3 enlarge(size[0] * 0.25f, size[1] * 0.0f, size[2] * 0.25f);
+
+		mViewSpaceBox->Enlarge(enlarge);
+	  }
+
+	  //Debug << "view space box: " << *mViewSpaceBox << endl;
+  }
+  else
+  {
+	  mViewSpaceBox = NULL;
+  }
+  
+  AxisAlignedBox3 vbox = mViewSpaceBox ? *mViewSpaceBox : mKdTree->GetBox();
+
+  mSceneGraph->CollectObjects(&mObjects);
+
+  //-- load view cells from file if requested
+  if (!mLoadViewCells)
+  {
+	  mViewCellsManager->SetViewSpaceBox(vbox);
+	  // construct view cells using it's own set of samples
+	  mViewCellsManager->Construct(this);
+
+	  //-- several visualizations and statistics
+	  Debug << "view cells construction finished: " << endl;
+	  mViewCellsManager->PrintStatistics(Debug);
+  }
+  else
+  {
+	 
+	  VssRayContainer dummies;
+	  mViewCellsManager->Visualize(mObjects, dummies);
+	  mViewCellsManager->ExportViewCells("test.xml");
+  }
+  VssTree *vssTree = NULL;
+
+  
+
+  long initialTime = GetTime();
+
+  if (mLoadInitialSamples)
+  {
+	  cout << "Loading samples from file ... ";
+	  LoadSamples(mVssRays, mObjects);
+	  cout << "finished\n" << endl;
+	  totalSamples = (int)mVssRays.size();
+  }
+  else
+  {
+	
+	while (totalSamples < mInitialSamples) {
+		int passContributingSamples = 0;
+		int passSampleContributions = 0;
+		int passSamples = 0;
+
+		int index = 0;
+
+		int sampleContributions;
+
+		int s = Min(mSamplesPerPass, mInitialSamples);
+		for (int k=0; k < s; k++) {
+			// changed by matt
+			Vector3 viewpoint; 
+			//			viewpoint = GetViewpoint(mViewSpaceBox);
+			mViewCellsManager->GetViewPoint(viewpoint);
+			Vector3 direction = GetDirection(viewpoint, mViewSpaceBox);
+
+			sampleContributions = CastRay(viewpoint, direction, mVssRays);
+
+			if (sampleContributions) {
+				passContributingSamples ++;
+				passSampleContributions += sampleContributions;
+			}
+			passSamples++;
+			totalSamples++;
+		}
+
+		mPass++;
+		int pvsSize = 0;
+		float avgRayContrib = (passContributingSamples > 0) ?
+			passSampleContributions/(float)passContributingSamples : 0;
+
+		cout << "#Pass " << mPass << " : t = " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
+		cout << "#TotalSamples=" << totalSamples/1000
+			<< "k   #SampleContributions=" << passSampleContributions << " ("
+			<< 100*passContributingSamples/(float)passSamples<<"%)" << " avgPVS="
+			<< pvsSize/(float)mObjects.size() << endl
+			<< "avg ray contrib=" << avgRayContrib << endl;
+
+		mStats <<
+			"#Pass\n" <<mPass<<endl<<
+			"#Time\n" << TimeDiff(startTime, GetTime())*1e-3 << endl<<
+			"#TotalSamples\n" << totalSamples<< endl<<
+			"#SampleContributions\n" << passSampleContributions << endl <<
+			"#PContributingSamples\n"<<100*passContributingSamples/(float)passSamples<<endl <<
+			"#AvgPVS\n"<< pvsSize/(float)mObjects.size() << endl <<
+			"#AvgRayContrib\n" << avgRayContrib << endl;
+	  }
+ 
+	  cout << "#totalPvsSize=" << mKdTree->CollectLeafPvs() << endl;
+
+
+	  
+  }
+ 
+
+  cout << "#totalRayStackSize=" << (int)mVssRays.size() << endl << flush;
+  Debug << (int)mVssRays.size() << " rays generated in " 
+	    << TimeDiff(initialTime, GetTime()) * 1e-3 << " seconds" << endl;
+
+  if (mStoreInitialSamples)
+  {
+	  cout << "Writing " << (int)mVssRays.size() << " samples to file ... ";
+	  ExportSamples(mVssRays);
+	  cout << "finished\n" << endl;
+
+	  /*VssRayContainer dummyRays;
+	  LoadSamples(dummyRays, mObjects);
+	  Debug << "rays " << (int)mVssRays.size() << " " << dummyRays.size() << endl;
+
+	  for (int i = 0; i < (int)mVssRays.size(); ++ i)
+	  {
+		  Debug << mVssRays[i]->GetOrigin() << " " << mVssRays[i]->GetTermination() << " " << mVssRays[i]->mOriginObject << " " << mVssRays[i]->mTerminationObject << endl;
+		  Debug << dummyRays[i]->GetOrigin() << " " << dummyRays[i]->GetTermination() << " " << dummyRays[i]->mOriginObject << " " << dummyRays[i]->mTerminationObject << endl << endl;
+	  }*/
+  }
+
+  
+  //int numExportRays = 5000;
+  int numExportRays = 0;
+
+  if (numExportRays) {
+	char filename[64];
+	sprintf(filename, "vss-rays-initial.x3d");
+	ExportRays(filename, mVssRays, numExportRays);
+  }
+
+  vssTree = new VssTree;
+  // viewcells = Construct(mVssRays);
+
+  vssTree->Construct(mVssRays, mViewSpaceBox);
+  cout<<"VssTree root PVS size = "<<vssTree->GetRootPvsSize()<<endl;
+
+  if (0)
+  {
+	  ExportVssTree("vss-tree-100.x3d", vssTree, Vector3(1,0,0));
+	  ExportVssTree("vss-tree-001.x3d", vssTree, Vector3(0,0,1));
+	  ExportVssTree("vss-tree-101.x3d", vssTree, Vector3(1,0,1));
+	  ExportVssTree("vss-tree-101m.x3d", vssTree, Vector3(-1,0,-1));
+	  ExportVssTreeLeaves(vssTree, 10);
+  }
+
+  // viewcells->UpdatePVS(newVssRays);
+  // get viewcells as kd tree boxes
+  vector<AxisAlignedBox3> kdViewcells;
+  if (0) {
+	vector<KdLeaf *> leaves;
+	mKdTree->CollectLeaves(leaves);
+	vector<KdLeaf *>::const_iterator it;
+	int targetLeaves = 50;
+	float prob = targetLeaves/(float)leaves.size();
+	for (it = leaves.begin(); it != leaves.end(); ++it)
+	  if (RandomValue(0.0f,1.0f) < prob)
+		kdViewcells.push_back(mKdTree->GetBox(*it));
+
+	float avgPvs = GetAvgPvsSize(vssTree, kdViewcells);
+	cout<<"Initial average PVS size = "<<avgPvs<<endl;
+  }
+
+
+  int samples = 0;
+  int pass = 0;
+
+  
+  // cast view cell samples
+  while (samples < mVssSamples) 
+  {
+	
+	int num = mVssSamplesPerPass;
+	SimpleRayContainer rays;
+	VssRayContainer vssRays;
+
+	if (!mUseImportanceSampling) {
+	  for (int j=0; j < num; j++) {
+	    // changed by matt
+		//Vector3 viewpoint = GetViewpoint(mViewSpaceBox);
+		Vector3 viewpoint; 
+		mViewCellsManager->GetViewPoint(viewpoint);
+		Vector3 direction = GetDirection(viewpoint, mViewSpaceBox);
+		rays.push_back(SimpleRay(viewpoint, direction));
+	  }
+	} else {
+	  num = GenerateImportanceRays(vssTree, num, rays);
+	}
+
+	for (int i=0; i < rays.size(); i++)
+	  CastRay(rays[i].mOrigin, rays[i].mDirection, vssRays);
+
+	vssTree->AddRays(vssRays);
+
+	if (0) {
+	  int subdivided = vssTree->UpdateSubdivision();
+	  cout<<"subdivided leafs = "<<subdivided<<endl;
+	}
+
+	float avgPvs = GetAvgPvsSize(vssTree, kdViewcells);
+	cout<<"Average PVS size = "<<avgPvs<<endl;
+
+	/// compute view cell contribution of rays
+	mViewCellsManager->ComputeSampleContributions(vssRays, true, false);
+	
+	if (numExportRays) {
+	  char filename[64];
+	  if (mUseImportanceSampling)
+		sprintf(filename, "vss-rays-i%04d.x3d", pass);
+	  else
+		sprintf(filename, "vss-rays-%04d.x3d", pass);
+
+	  ExportRays(filename, vssRays, numExportRays);
+	}
+
+	samples+=num;
+	float pvs = vssTree->GetAvgPvsSize();
+	cout<<"*****************************\n";
+	cout<<samples<<" avgPVS ="<<pvs<<endl;
+	cout<<"VssTree root PVS size = "<<vssTree->GetRootPvsSize()<<endl;
+	cout<<"*****************************\n";
+//	if (samples >= mVssSamples) break;
+	pass ++;
+  }
+
+  if (mTestBeamSampling && mUseGlRenderer)
+  {	
+	  TestBeamCasting(vssTree, mViewCellsManager, mObjects);
+  }
+
+  if (0)
+	  Debug << vssTree->stat << endl;
+
+  if (0)
+  {
+	VssRayContainer viewCellRays;
+  
+	// compute rays used for view cells construction
+	const int numRays = mViewCellsManager->GetVisualizationSamples();
+
+	vssTree->CollectRays(viewCellRays, numRays);
+  }
+
+  //-- render simulation after merge
+  cout << "\nevaluating bsp view cells render time after sampling ... ";
+  Debug << "\nStatistics after sampling: " << endl;
+
+  mRenderSimulator->RenderScene();
+  SimulationStatistics ss;
+  mRenderSimulator->GetStatistics(ss);
+  
+  cout << " finished" << endl;
+  cout << ss << endl;
+  Debug << ss << endl;
+
+  delete vssTree;
+  
+  return true;
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h	(revision 512)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h	(revision 512)
@@ -0,0 +1,537 @@
+#ifndef _KdTree_H__
+#define _KdTree_H__
+
+#include <functional>
+using namespace std;
+
+#include "Containers.h"
+#include "AxisAlignedBox3.h"
+#include "Ray.h"
+#include "Pvs.h"
+#include "Viewcell.h"
+  
+class KdNode;
+class KdLeaf;
+class KdInterior;
+class Intersectable;
+//class KdViewCell;
+class Beam;
+
+// --------------------------------------------------------------
+// Static statistics for kd-tree search
+// --------------------------------------------------------------
+class KdTreeStatistics 
+{
+public:  
+  // total number of nodes
+  int nodes;
+  // number of splits along each of the axes
+  int splits[7];
+  // totals number of rays
+  int rays;
+  // total number of query domains
+  int queryDomains;
+  // total number of ray references
+  int rayRefs;
+  // refs in non empty leafs
+  int rayRefsNonZeroQuery;
+  // total number of query references
+  int objectRefs;
+  // nodes with zero queries
+  int zeroQueryNodes;
+  // max depth nodes
+  int maxDepthNodes;
+  // max depth nodes
+  int minCostNodes;
+  // max number of rays per node
+  int maxObjectRefs;
+  // number of dynamically added ray refs
+  int addedRayRefs;
+  // number of dynamically removed ray refs
+  int removedRayRefs;
+  
+  // Constructor
+  KdTreeStatistics() {
+    Reset();
+  }
+
+  int Nodes() const {return nodes;}
+  int Interior() const { return nodes/2; }
+  int Leaves() const { return (nodes/2) + 1; }
+
+  void Reset() {
+    nodes = 0;
+    for (int i=0; i<7; i++)
+      splits[i] = 0;
+    rays = queryDomains = 0;
+    rayRefs = rayRefsNonZeroQuery = objectRefs = 0;
+    zeroQueryNodes = 0;
+    maxDepthNodes = 0;
+    minCostNodes = 0;
+    maxObjectRefs = 0;
+    addedRayRefs = removedRayRefs = 0;
+  }
+
+  void
+  Print(ostream &app) const;
+
+  friend ostream &operator<<(ostream &s, const KdTreeStatistics &stat) {
+    stat.Print(s);
+    return s;
+  }
+  
+};
+
+  
+class KdInterior;
+/** Abstract class for kd-tree node */
+class KdNode {
+public:
+  static int mailID;
+  int mailbox;
+  
+  void Mail() { mailbox = mailID; }
+  static void NewMail() { mailID++; }
+  bool Mailed() const { return mailbox == mailID; }
+
+
+  KdNode(KdInterior *parent);
+
+  /** Determines whether this node is a leaf or interior node
+      @return true if leaf
+  */
+  virtual bool IsLeaf() const = 0;
+
+  /** Determines whether this node is the root of the tree
+      @return true if root
+  */
+  virtual bool IsRoot() const {
+    return mParent == NULL;
+  }
+
+  /** Parent of the node - the parent is a little overhead for maintanance of the tree,
+      but allows various optimizations of tree traversal algorithms */
+  KdInterior *mParent;
+  int mDepth;
+};
+
+/** Implementation of the kd-tree interior node */
+class KdInterior : public KdNode {
+
+public:
+    
+  KdInterior(KdInterior *parent):KdNode(parent), mBack(NULL), mFront(NULL) {}
+
+  /** \sa KdNode::IsLeaf() */
+  virtual bool IsLeaf() const { return false; }
+
+  /** splitting axis */
+  int mAxis;
+  /** splitting position, absolute position within the bounding box of this node */
+  float mPosition;
+  /** bounding box of interior node */
+  AxisAlignedBox3 mBox;
+
+  /** back node */
+  KdNode *mBack;
+  /** front node */
+  KdNode *mFront;
+
+  void SetupChildLinks(KdNode *b, KdNode *f) {
+    mBack = b;
+    mFront = f;
+    b->mParent = f->mParent = this;
+  }
+  
+  void ReplaceChildLink(KdNode *oldChild, KdNode *newChild) {
+    if (mBack == oldChild)
+      mBack = newChild;
+    else
+      mFront = newChild;
+  }
+  
+  
+};
+  
+  
+/** Implementation of the kd-tree leaf node */
+class KdLeaf : public KdNode {
+public:
+  KdLeaf(KdInterior *parent, const int objects):
+	  KdNode(parent), mViewCell(NULL) {
+    mObjects.reserve(objects);
+  }
+  
+  void AddPassingRay(const Ray &ray, const int contributions) {
+    mPassingRays.AddRay(ray, contributions);
+		//		Debug << "adding passing ray" << endl;
+  }
+
+	
+	void AddPassingRay2(const Ray &ray,
+						const int objects,
+						const int viewcells
+						) {
+    mPassingRays.AddRay2(ray, objects, viewcells);
+		//		Debug << "adding passing ray" << endl;
+  }
+
+  /** \sa KdNode::IsLeaf() */
+  virtual bool IsLeaf() const { return true; }
+
+
+  /** pointers to occluders contained in this node */
+  ObjectContainer mObjects;
+  
+  /** Ray set description of the rays passing through this node */
+  PassingRaySet mPassingRays;
+	
+  /** PVS consisting of visible KdTree nodes */
+  KdPvs mKdPvs;
+	
+  /** pointer to view cell.
+  */
+  KdViewCell *mViewCell;
+};
+
+  
+
+/** KdTree for indexing scene entities - occluders/occludees/viewcells */
+class KdTree {
+
+protected:
+  struct TraversalData
+  {  
+    KdNode *mNode;
+    AxisAlignedBox3 mBox;
+    int mDepth;
+    float mPriority;
+    
+    TraversalData() {}
+
+    TraversalData(KdNode *n, const float p):
+      mNode(n), mPriority(p)
+    {}
+    
+    TraversalData(KdNode *n,
+		   const AxisAlignedBox3 &b,
+		   const int d):
+      mNode(n), mBox(b), mDepth(d) {}
+    
+
+    bool operator<(
+		   const TraversalData &b) const {
+      KdLeaf *leafa = (KdLeaf *) mNode;
+      KdLeaf *leafb = (KdLeaf *) b.mNode;
+      return 
+	leafa->mObjects.size()*mBox.SurfaceArea()
+	<
+	leafb->mObjects.size()*b.mBox.SurfaceArea();
+    }
+
+
+    // comparator for the 
+    struct less_priority : public
+    binary_function<const TraversalData, const TraversalData, bool> {
+      
+      bool operator()(const TraversalData a, const TraversalData b) {
+				return a.mPriority < b.mPriority;
+      }
+      
+    };
+
+  };
+
+  
+
+public:
+
+  enum {SPLIT_OBJECT_MEDIAN,
+	SPLIT_SPATIAL_MEDIAN,
+	SPLIT_SAH};
+  
+  KdTree();
+  
+    
+  /** Insert view cell into the tree */
+  virtual void InsertViewCell(ViewCell *viewCell) {
+    //      mRoot->mViewcells.push_back(viewCell);
+  }
+
+  virtual bool Construct();
+
+  /** Check whether subdivision criteria are met for the given subtree.
+      If not subdivide the leafs of the subtree. The criteria are specified in
+      the environment as well as the subdivision method. By default surface area
+      heuristics is used.
+	
+      @param subtree root of the subtree
+
+      @return true if subdivision was performed, false if subdivision criteria
+      were already met
+  */
+  virtual KdNode *Subdivide(const TraversalData &tdata);
+
+  /** Get the root of the tree */
+  KdNode *GetRoot() const {
+    return mRoot;
+  }
+
+
+  AxisAlignedBox3 GetBox() const { return mBox; }
+
+  int
+  CastRay(
+		  Ray &ray
+		  );
+  
+
+  int
+  CastBeam(
+		   Beam &beam
+		   );
+  
+  
+  /** Casts line segment into tree.
+	  @returns intersected view cells.
+  */
+  int CastLineSegment(const Vector3 &origin,
+					  const Vector3 &termination,
+					  vector<ViewCell *> &viewcells);
+
+
+  const KdTreeStatistics &GetStatistics() const {
+    return mStat;
+  }
+
+  void
+  CollectObjects(KdNode *n, ObjectContainer &objects);
+	
+  void
+  CollectLeaves(vector<KdLeaf *> &leaves);
+	
+  /** If the kd tree is used as view cell container, this
+	  methods creates the view cells.
+	  @returns the newly created view cells in a view cell container
+  */
+  void
+  CreateAndCollectViewCells(ViewCellContainer &viewCells) const;
+
+  AxisAlignedBox3 GetBox(const KdNode *node) const {
+    KdInterior *parent = node->mParent;
+    if (parent == NULL)
+      return mBox;
+    
+    if (!node->IsLeaf())
+      return ((KdInterior *)node)->mBox;
+    
+    AxisAlignedBox3 box(parent->mBox);
+    if (parent->mFront == node)
+      box.SetMin(parent->mAxis, parent->mPosition);
+    else
+      box.SetMax(parent->mAxis, parent->mPosition);
+    return box;
+  }
+	
+  KdNode *
+  FindRandomNeighbor(KdNode *n,
+					 bool onlyUnmailed
+					 );
+  
+  KdNode *
+  KdTree::GetRandomLeaf(const Plane3 &halfspace);
+
+	KdNode *
+	GetRandomLeaf(const bool onlyUnmailed = false);
+
+  int
+  FindNeighbors(KdNode *n,
+		vector<KdNode *> &neighbors,
+		bool onlyUnmailed
+		);
+
+  int
+  CollectLeafPvs();
+
+protected:
+
+  struct RayData {
+    // pointer to the actual ray
+    Ray *ray;
+    
+    // endpoints  - do we need them?
+#if USE_FIXEDPOINT_T
+    short tmin, tmax;
+#else
+    float tmin, tmax;
+#endif
+
+    RayData():ray(NULL) {}
+    RayData(Ray *r):ray(r), tmin(0),
+
+#if USE_FIXEDPOINT_T
+#define FIXEDPOINT_ONE 0x7FFE
+			  //			  tmax(0xFFFF)
+			  tmax(FIXEDPOINT_ONE)
+#else
+      tmax(1.0f)
+#endif
+    {}
+
+    RayData(Ray *r,
+	    const float _min,
+	    const float _max
+	    ):ray(r) {
+      SetTMin(_min);
+      SetTMax(_max);
+    }
+
+    RayData(Ray *r,
+	    const short _min,
+	    const float _max
+	    ):ray(r), tmin(_min) {
+      SetTMax(_max);
+    }
+
+    RayData(Ray *r,
+	    const float _min,
+	    const short _max
+	    ):ray(r), tmax(_max) {
+      SetTMin(_min);
+    }
+
+    friend bool operator<(const RayData &a, const RayData &b) {
+      return a.ray < b.ray;
+    }
+    
+    
+    float ExtrapOrigin(const int axis) const {
+      return ray->GetLoc(axis) + GetTMin()*ray->GetDir(axis);
+    }
+    
+    float ExtrapTermination(const int axis) const {
+      return ray->GetLoc(axis) + GetTMax()*ray->GetDir(axis);
+    }
+    
+#if USE_FIXEDPOINT_T
+    float GetTMin () const { return tmin/(float)(FIXEDPOINT_ONE); }
+    float GetTMax () const { return tmax/(float)(FIXEDPOINT_ONE); }
+
+    void SetTMin (const float t) {
+      tmin = (short) (t*(float)(FIXEDPOINT_ONE));
+    }
+    
+    void SetTMax (const float t) {
+      tmax = (short) (t*(float)(FIXEDPOINT_ONE));
+      tmax++;
+      //      if (tmax!=0xFFFF)
+      //	tmax++;
+    }
+#else
+    float GetTMin () const { return tmin; }
+    float GetTMax () const { return tmax; }
+
+    void SetTMin (const float t) { tmin = t; }
+    void SetTMax (const float t) { tmax = t; }
+#endif 
+  };
+
+  struct RayTraversalData {
+    KdNode *mNode;
+    Vector3 mExitPoint;
+    float mMaxT;
+    
+    RayTraversalData() {}
+    RayTraversalData(KdNode *n,
+		     const Vector3 &p,
+		     const float maxt):
+      mNode(n), mExitPoint(p), mMaxT(maxt) {}
+  };
+
+  // --------------------------------------------------------------
+  // For sorting objects
+  // --------------------------------------------------------------
+  struct  SortableEntry
+  {
+    enum {
+      BOX_MIN,
+      BOX_MAX
+    };
+    
+    int type;
+    float value;
+    Intersectable *intersectable;
+    
+    SortableEntry() {}
+    SortableEntry(const int t, const float v, Intersectable *i):type(t),
+								value(v),
+								intersectable(i) {}
+    
+    bool operator<(const SortableEntry &b) const {
+      return value < b.value;
+    }
+    
+  };
+  
+  // reusable array of split candidates
+  vector<SortableEntry> *splitCandidates;
+
+  float
+  BestCostRatio(
+		KdLeaf *node,
+		const AxisAlignedBox3 &box,
+		const int axis,
+		float &position,
+		int &objectsBack,
+		int &objectsFront
+		);
+
+  void
+  SortSplitCandidates(
+		      KdLeaf *node,
+		      const int axis
+		      );
+
+  void
+  EvaluateLeafStats(const TraversalData &data);
+
+  KdNode *
+  SubdivideNode(
+		KdLeaf *leaf,
+		const AxisAlignedBox3 &box,
+		AxisAlignedBox3 &backBBox,
+		AxisAlignedBox3 &frontBBox
+		);
+
+  bool
+  TerminationCriteriaMet(const KdLeaf *leaf);
+  
+  int
+  SelectPlane(KdLeaf *leaf,
+	      const AxisAlignedBox3 &box,
+	      float &position
+	      );
+
+
+
+  float mSplitBorder;
+  int mTermMaxDepth;
+  int mTermMinCost;
+  float mMaxCostRatio;
+  float mCt_div_ci;
+  int mSplitMethod;
+  bool mSahUseFaces;
+  /// root of the tree
+  KdNode *mRoot;
+  /// bounding box of the tree root
+  AxisAlignedBox3 mBox;
+  KdTreeStatistics mStat;
+  
+};
+  
+
+
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 574)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 574)
@@ -0,0 +1,124 @@
+#include "SamplingPreprocessor.h"
+#include "VssPreprocessor.h"
+#include "RssPreprocessor.h"
+#include "ExactPreprocessor.h"
+#include "Parser.h"
+#include "UnigraphicsParser.h"
+#include "X3dParser.h"
+#include "Environment.h"
+#include "Camera.h"
+#include "MeshKdTree.h"
+#include "Exporter.h"
+#include "X3dExporter.h" // delete later
+#include "ViewCell.h"
+#include "SceneGraph.h"
+#include "PreprocessorThread.h"
+
+#include <QApplication>
+#include <QtOpenGL>
+#include "GlRenderer.h"
+
+#define USE_EXE_PATH false
+
+#include <crtdbg.h>
+
+
+
+int
+main(int argc, char **argv)
+{
+	
+//Now just call this function at the start of your program and if you're
+//compiling in debug mode (F5), any leaks will be displayed in the Output
+//window when the program shuts down. If you're not in debug mode this will
+//be ignored. Use it as you will!
+//note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() {
+    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
+    _CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE);
+    _CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR); 
+
+  Debug.open("debug.log");
+  environment = new Environment;
+  environment->Parse(argc, argv, USE_EXE_PATH);
+  MeshKdTree::ParseEnvironment();
+  
+  char buff[128];
+  environment->GetStringValue("Preprocessor.type", buff);
+  string preprocessorType(buff);
+	
+  Preprocessor *p;
+
+  if (preprocessorType == "vss")
+	p = new VssPreprocessor();
+  else
+	if (preprocessorType == "rss")
+	  p = new RssPreprocessor();
+	else
+	  if (preprocessorType == "exact")
+		p = new ExactPreprocessor();
+	  else
+		if (preprocessorType == "sampling")
+		  p = new SamplingPreprocessor();
+		else {
+		  cerr<<"Unknown preprocessor type"<<endl;
+		  Debug<<"Unknown preprocessor type"<<endl;
+		  exit(1);
+		}
+
+  QApplication *app = NULL;
+
+  if (p->mUseGlRenderer) {
+	// create a qt application first (must be created before any opengl widget...
+	app = new QApplication(argc, argv);
+	
+	if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) {
+	  QMessageBox::information(0, "OpenGL pbuffers", 
+							   "This system does not support OpenGL/pbuffers.",
+							   QMessageBox::Ok);
+	  return -1;
+	}
+  }
+  
+  preprocessor = p;
+  
+  environment->GetStringValue("Scene.filename", buff);
+  string filename(buff);
+  p->LoadScene(filename);
+  
+  p->BuildKdTree();
+  p->KdTreeStatistics(cout);
+  
+  // parse view cells related options
+  p->PrepareViewCells();
+  
+
+  // create a preprocessor thread
+  PreprocessorThread *pt = new PreprocessorThread(p, app);
+
+  //  p->mSceneGraph->Export("soda.x3d");
+  if (0) {
+    p->Export(filename + "-out.x3d", true, false, false);
+    p->Export(filename + "-kdtree.x3d", false, true, false);	
+  }
+
+  if (p->mUseGlRenderer) {
+	
+	rendererWidget = new GlRendererWidget(p->mSceneGraph, p->mViewCellsManager, p->mKdTree);
+	//  renderer->resize(640, 480);
+	rendererWidget->resize(640, 480);
+	rendererWidget->show();
+	pt->start(QThread::LowPriority);
+  } else{
+	// just call the mail method -> will be executed in the main thread
+	pt->Main();
+  }
+  
+  // clean up
+  //  DEL_PTR(p);
+  //  DEL_PTR(environment);
+  if (app)
+	return app->exec();
+  
+  return 0;
+}
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingPreprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SamplingPreprocessor.h	(revision 469)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SamplingPreprocessor.h	(revision 469)
@@ -0,0 +1,97 @@
+#ifndef _SamplingPreprocessor_H__
+#define _SamplingPreprocessor_H__
+
+#include <fstream>
+using namespace std;
+
+#include "Preprocessor.h"
+#include "VssRay.h"
+
+class Exporter;
+
+/** Sampling based visibility preprocessing. The implementation is based on heuristical
+    sampling of view space */
+class SamplingPreprocessor : public Preprocessor {
+public:
+		
+  SamplingPreprocessor();
+  ~SamplingPreprocessor();
+
+  virtual bool ComputeVisibility();
+
+
+protected:
+	/** Sets up ray for sampling.
+	*/
+  void
+  SetupRay(Ray &ray, 
+		   const Vector3 &point, 
+		   const Vector3 &direction,
+		   const int type,
+		   const Ray::Intersection &source);
+  
+  /** Refined sampling for finding "holes", i.e., difficult visibility.
+   */
+  void
+  HoleSamplingPass();
+  
+  /** Casts a bundle of sample rays into the scene.
+		@param sampleContributions the number of sample contributions
+		@param contributingSamples the number of samples contributing
+	*/
+	void
+	CastRays(const RayContainer &rays);
+	
+	/** Casts a single ray into the scene.
+		@returns sample contributions
+	*/
+	int CastRay(Ray &ray);
+	
+	/** Verify if the exact visibility for this object was established.
+	*/
+	void
+	VerifyVisibility(Intersectable *object);
+
+	/** Sample the shiluette of objects in order to find visibility changes
+		along the visibility skeleton.
+	*/
+	int 
+	CastEdgeSamples(
+					Intersectable *object,
+					const Vector3 &point,
+					MeshInstance *mi,
+					const int samples
+					);
+
+	/** Processes the view cells during a pass.
+		@param newRays the newly cast rays
+		@param sampleContributions returns the accumulated contribution of the samples
+		@param contributingSamples returns the samples contributing to pvs
+	*/
+	
+	void ProcessViewCells(const RayContainer &newRays,
+						  const ObjectContainer &objects,
+						  int &sampleContributions,
+						  int &contributingSamples);
+
+	/**
+		Returns random node as target for the current sample ray.
+	*/
+	KdNode *GetNodeToSample(Intersectable *object);
+
+
+protected:
+
+
+	int mPass;
+	int mSamplesPerPass;
+	int mTotalSamples;
+	
+	ofstream mStats;
+	ObjectContainer mObjects;
+
+	RayContainer mSampleRays;
+	VssRayContainer mVssSampleRays;
+};
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VssRay.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VssRay.cpp	(revision 492)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VssRay.cpp	(revision 492)
@@ -0,0 +1,258 @@
+#include "VssRay.h"
+#include "AxisAlignedBox3.h"
+
+// Static variables
+int
+VssRay::mailID = 0;
+
+
+bool
+VssRay::ComputeMinMaxT(const AxisAlignedBox3 &box,
+					   float &tmin,
+					   float &tmax) const
+{
+	
+  float minx, maxx, miny, maxy, minz, maxz;
+  Vector3 dir = GetDir();
+  
+  if (fabs(dir.x) < 0.001) {
+    if (box.Min().x < GetOrigin().x && box.Max().x > GetOrigin().x) {
+      minx = -MAXFLOAT;
+      maxx = MAXFLOAT;
+    }
+    else
+      return false;
+  }
+  else {
+    float t1 = (box.Min().x - GetOrigin().x) / dir.x;
+    float t2 = (box.Max().x - GetOrigin().x) / dir.x;
+    if (t1 < t2) {
+      minx = t1;
+      maxx = t2;
+    }
+    else {
+      minx = t2;
+      maxx = t1;
+    }
+    if (maxx < 0)
+      return false;
+  }
+
+  if (fabs(dir.y) < 0.001) {
+    if (box.Min().y < GetOrigin().y && box.Max().y > GetOrigin().y) {
+      miny = -MAXFLOAT;
+      maxy = MAXFLOAT;
+    }
+    else
+      return false;
+  }
+  else {
+    float t1 = (box.Min().y - GetOrigin().y) / dir.y;
+    float t2 = (box.Max().y - GetOrigin().y) / dir.y;
+    if (t1 < t2) {
+      miny = t1;
+      maxy = t2;
+    }
+    else {
+      miny = t2;
+      maxy = t1;
+    }
+    if (maxy < 0.0)
+      return false;
+  }
+	
+  if (fabs(dir.z) < 0.001) {
+    if (box.Min().z < GetOrigin().z && box.Max().z > GetOrigin().z) {
+      minz = -MAXFLOAT;
+      maxz = MAXFLOAT;
+    }
+    else
+      return false;
+  }
+  else {
+    float t1 = (box.Min().z - GetOrigin().z) / dir.z;
+    float t2 = (box.Max().z - GetOrigin().z) / dir.z;
+    if (t1 < t2) {
+      minz = t1;
+      maxz = t2;
+    }
+    else {
+      minz = t2;
+      maxz = t1;
+    }
+    if (maxz < 0.0)
+      return false;
+  }
+
+  tmin = minx;
+  if (miny > tmin)
+    tmin = miny;
+  if (minz > tmin)
+    tmin = minz;
+
+  tmax = maxx;
+  if (maxy < tmax)
+    tmax = maxy;
+  if (maxz < tmax)
+    tmax = maxz;
+
+  return 1; // yes, intersection was found
+}
+
+
+
+bool
+VssRay::Intersects(const AxisAlignedBox3 &box,
+													float &tmin,
+													float &tmax) const
+{
+  if (!ComputeMinMaxT(box, tmin, tmax))
+    return false;
+	
+  if ( tmax < tmin)
+    return false; // the ray passes outside the box
+  
+  if ( tmax < 0.0f)
+    return false; // the intersection is not on the positive halfline
+  
+  return true; // ray hits the box .. origin can be outside or inside the box
+}
+
+
+bool
+VssRay::IntersectsSphere(const Vector3 &center,
+																const float sqrRadius,
+																Vector3 &point,
+																float &t) const
+{
+  // compute ray/plane intersection
+  Vector3 dir = GetDir();
+	
+  t = -DotProd(GetOrigin() - center, dir)*sqr(GetInvSize());
+	
+  if (t < 0.0f)
+    t = 0.0f;
+  else
+    if (t > 1.0f)
+      t = 1.0f;
+  
+  point = GetOrigin() + t*dir;
+  
+  return ::SqrDistance(point, center) < sqrRadius;
+}
+
+
+float
+VssRay::GetDirParam(const int axis, const Vector3 dir)
+{
+  return (axis == 0) ? atan2(dir.x, dir.z) : asin(dir.y);
+}
+
+float
+VssRay::GetDirParametrization(const int axis) const
+{
+  Vector3 dir = GetNormalizedDir();
+  return GetDirParam(axis, dir);
+}
+
+float
+VssRay::GetOpositeDirParametrization(const int axis) const
+{
+  Vector3 dir = -GetNormalizedDir();
+  return GetDirParam(axis, dir);
+}
+
+
+void
+GenerateExtendedConvexCombinationWeights2(float &w1,
+										  float &w2,
+										  const float overlap
+										  )
+{
+  w1 = RandomValue(-overlap, 1.0f + overlap);
+  w2 = 1.0f - w1;
+}
+
+void
+GenerateExtendedConvexCombinationWeights(float &w1,
+										 float &w2,
+										 float &w3,
+										 const float overlap
+										 )
+{
+
+  while (1) {
+	w1 = RandomValue(-overlap, 1.0f + overlap);
+	w2 = RandomValue(-overlap, 1.0f + overlap);
+	w3 = 1.0f + overlap - w1 - w2;
+	if (w3 >= -overlap && w3 <= 1.0f + overlap)
+	  break;
+	/*
+	w3 = RandomValue(0.0f, 1.0f + overlap);
+	
+	float sum = w1 + w2 + w3;
+	if (sum>0.0f) {
+	  w1/=sum;
+	  w2/=sum;
+	  w3/=sum;
+	  break;
+	}
+	*/
+  }
+}
+
+
+void
+VssRayContainer::PrintStatistics(ostream &s)
+{
+
+  VssRayContainer::const_iterator it = begin(), it_end = end();
+  int sumContributions = 0;
+  float sumRelContributions = 0.0f;
+  
+  for (; it != it_end; ++it) {
+	VssRay *ray = *it;
+	sumContributions += ray->mPvsContribution;
+	sumRelContributions += ray->mRelativePvsContribution;
+  }
+  
+  s<<"##### VSS RAY STAT ##########\n";
+  s<<"#RAYS\n"<<(int)size()<<endl;
+  s<<"#AVG_RAY_PVS_CONTRIBUTION\n"<<sumContributions/(float)size()<<endl;
+  s<<"#AVG_RAY_RELATIVE_PVS_CONTRIBUTION\n"<<sumRelContributions/
+	(float)size()<<endl;
+  
+}
+
+
+int
+VssRayContainer::SelectRays(const int number,
+							VssRayContainer &selected) const
+{
+  float p = number/(float)size();
+  VssRayContainer::const_iterator it = begin();
+  
+  for (; it != end(); it++)
+	if (Random(1.0f) < p)
+	  selected.push_back(*it);
+  
+  return selected.size();
+}
+
+
+int
+VssRayContainer::GetContributingRays(VssRayContainer &selected,
+									 const int minPass
+									 ) const
+{
+  VssRayContainer::const_iterator it = begin();
+  
+  for (; it != end(); it++) {
+	VssRay *ray = *it;
+	if (ray->mPass >= minPass && ray->mPvsContribution > 0)
+	  selected.push_back(ray);
+  }
+  return selected.size();
+}
+
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.cpp	(revision 580)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.cpp	(revision 580)
@@ -0,0 +1,1299 @@
+#include <stack>
+#include "common.h"
+#include "SceneGraph.h"
+#include "X3dExporter.h"
+#include "Mesh.h"
+#include "KdTree.h"
+#include "ViewCellBsp.h"
+#include "ViewCell.h"
+#include "Polygon3.h"
+#include "VssRay.h"
+#include "VspKdTree.h"
+#include "VssTree.h"
+#include "VspBspTree.h"
+#include "RssTree.h"
+#include "Beam.h"
+
+
+X3dExporter::X3dExporter(const string filename):Exporter(filename)
+{
+  stream.open(mFilename.c_str());
+  stream<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
+  stream<<"<X3D>"<<endl;
+  stream<<"<Scene>"<<endl;
+  
+}
+
+X3dExporter::~X3dExporter()
+{
+  stream<<"</Scene>"<<endl;
+  stream<<"</X3D>"<<endl;
+  stream.close();
+}
+
+
+//  bool
+//  X3dExporter::ExportRays(const vector<Ray> &rays,
+//  												const float length,
+//  												const RgbColor &color)
+//  {
+//    vector<Ray>::const_iterator ri = rays.begin();
+//    stream<<"<Shape>"<<endl;
+//    stream<<"<Appearance>"<<endl;
+//    stream<<"<Material ambientColor=\""<<color.r<<" "<<color.g<<" "<<color.b<<
+//      "\" />"<<endl;
+//    stream<<"</Appearance>"<<endl;
+  
+//    stream<<"<IndexedLineSet coordIndex=\""<<endl;
+
+//    int index = 0;
+//    for (; ri != rays.end(); ri++) {
+//      stream<<index<<" "<<index+1<<" -1\n";
+//      index+=2;
+//    }
+  
+//    stream<<"\" >"<<endl;
+  
+//    stream<<"<Coordinate  point=\""<<endl;
+  
+//    ri = rays.begin();
+//    for (; ri != rays.end(); ri++) {
+//      Vector3 a = (*ri).GetLoc();
+    
+//      Vector3 b;
+//      if (length < 0)
+//        b = (*ri).GetLoc() - length*(*ri).GetDir();
+//      else
+//        if ((*ri).intersections.size()==0)
+//  	b = (*ri).GetLoc() + length*(*ri).GetDir();
+//        else
+//  	b = (*ri).Extrap((*ri).intersections[0].mT);
+    
+//      stream<<a.x<<" "<<a.y<<" "<<a.z<<" ,";
+//      stream<<b.x<<" "<<b.y<<" "<<b.z<<" ,\n";
+//    }
+  
+//    stream<<"\" >"<<endl;
+//    stream<<"</Coordinate>"<<endl;
+//    stream<<"</IndexedLineSet>"<<endl;
+//    stream<<"</Shape>"<<endl;
+//    return true;
+//  }
+
+
+bool
+X3dExporter::ExportRays(const RayContainer &rays,
+						const float length,
+						const RgbColor &color)
+{
+  RayContainer::const_iterator ri = rays.begin();
+
+  stream<<"<Shape>"<<endl;
+  stream<<"<Appearance>"<<endl;
+  stream<<"<Material diffuseColor=\""<<color.r<<" "<<color.g<<" "<<color.b<<
+    "\" />"<<endl;
+  stream<<"</Appearance>"<<endl;
+  
+  stream<<"<IndexedLineSet coordIndex=\""<<endl;
+
+  int index = 0;
+  for (; ri != rays.end(); ri++) {
+    stream<<index<<" "<<index+1<<" -1\n";
+    index+=2;
+  }
+  
+  stream<<"\" >"<<endl;
+  
+  stream<<"<Coordinate  point=\""<<endl;
+  
+  ri = rays.begin();
+  for (; ri != rays.end(); ri++) {
+    Vector3 a = (*ri)->GetLoc();
+    
+    Vector3 b;
+    if (length < 0)
+      b = (*ri)->GetLoc() - length*(*ri)->GetDir();
+    else
+      if ((*ri)->intersections.size()==0)
+		b = (*ri)->GetLoc() + length*(*ri)->GetDir();
+      else
+		b = (*ri)->Extrap((*ri)->intersections[0].mT);
+    
+    stream<<a.x<<" "<<a.y<<" "<<a.z<<" ,";
+    stream<<b.x<<" "<<b.y<<" "<<b.z<<" ,\n";
+  }
+  
+  stream<<"\" >"<<endl;
+  stream<<"</Coordinate>"<<endl;
+  stream<<"</IndexedLineSet>"<<endl;
+  stream<<"</Shape>"<<endl;
+
+  return true;
+}
+
+bool
+X3dExporter::ExportRays(const VssRayContainer &rays,
+						const RgbColor &color)
+{
+  VssRayContainer::const_iterator ri = rays.begin();
+
+  stream<<"<Shape>"<<endl;
+  stream<<"<Appearance>"<<endl;
+  stream<<"<Material diffuseColor=\""<<color.r<<" "<<color.g<<" "<<color.b<<
+    "\" />"<<endl;
+  stream<<"</Appearance>"<<endl;
+  
+  stream<<"<IndexedLineSet coordIndex=\""<<endl;
+
+  int index = 0;
+  for (; ri != rays.end(); ri++) {
+    stream<<index<<" "<<index+1<<" -1\n";
+    index+=2;
+  }
+  
+  stream<<"\" >"<<endl;
+  
+  stream<<"<Coordinate  point=\""<<endl;
+  
+  ri = rays.begin();
+  for (; ri != rays.end(); ri++) {
+    const Vector3 a = (*ri)->GetOrigin();
+	//const Vector3 b = (*ri)->mTerminationObject ? (*ri)->GetTermination() : a + 1000 * Normalize((*ri)->GetDir());
+	const Vector3 b = (*ri)->GetTermination(); // matt: change again!!
+
+    stream<<a.x<<" "<<a.y<<" "<<a.z<<" ,";
+	stream<<b.x<<" "<<b.y<<" "<<b.z<<" ,\n";
+  }
+  
+  stream<<"\" >"<<endl;
+  stream<<"</Coordinate>"<<endl;
+  stream<<"</IndexedLineSet>"<<endl;
+  stream<<"</Shape>"<<endl;
+	
+  return true;
+}
+
+void
+X3dExporter::ExportSceneNode(SceneGraphNode *node)
+{
+  stream<<"<Group>"<<endl;
+
+  SceneGraphNodeContainer::iterator ni = node->mChildren.begin();
+  for (; ni != node->mChildren.end(); ni++)
+    ExportSceneNode(*ni);
+  
+  
+  ObjectContainer::const_iterator mi = node->mGeometry.begin();
+  for (; mi != node->mGeometry.end(); mi++) {
+    // export the transform...
+    ExportIntersectable(*mi);
+  }
+  
+  stream<<"</Group>"<<endl;
+
+}
+void
+X3dExporter::ExportIntersectable(Intersectable *object)
+{
+  switch (object->Type()) {
+  case Intersectable::MESH_INSTANCE:
+  case Intersectable::TRANSFORMED_MESH_INSTANCE:
+    ExportMeshInstance((MeshInstance *)object);
+	break;
+  case Intersectable::VIEW_CELL:
+	ExportViewCell((ViewCell *)object);
+    break;
+  default:
+    cerr<<"Sorry the export for object not yet defined"<<endl;
+    break;
+  }
+}
+
+void
+X3dExporter::ExportMeshInstance(MeshInstance *object)
+{
+  // $$JB$$
+  // in the future check whether the mesh was not already exported
+  // and use a reference to the that mesh instead
+  ExportMesh(object->GetMesh());
+}
+
+void 
+X3dExporter::ExportViewCells(const ViewCellContainer &viewCells)
+{
+	ViewCellContainer::const_iterator it, it_end = viewCells.end();
+
+	for (it = viewCells.begin(); it != it_end; ++ it)
+		ExportViewCell(*it);
+}
+
+void 
+X3dExporter::ExportBspLeaves(const BspTree &tree, const int maxPvs)
+{
+	stack<pair<BspNode *, BspNodeGeometry *> > tStack;
+	ViewCell::NewMail();
+
+	BspNodeGeometry *geom = new BspNodeGeometry();
+	tree.ConstructGeometry(tree.GetRoot(), *geom);
+
+	tStack.push(pair<BspNode *, BspNodeGeometry *>(tree.GetRoot(), geom));
+
+	if (maxPvs > 0)
+		mUseForcedMaterial = true;
+
+	while (!tStack.empty()) 
+	{
+		BspNode *node = tStack.top().first;
+		BspNodeGeometry *cell = tStack.top().second;
+		tStack.pop();
+
+		if (!node->IsLeaf()) 
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+								
+			BspNodeGeometry *front = new BspNodeGeometry();
+			BspNodeGeometry *back = new BspNodeGeometry();
+
+			cell->SplitGeometry(*front, 
+								*back, 
+								interior->GetPlane(), 
+								tree.GetBoundingBox(), 
+								tree.GetEpsilon());
+
+			tStack.push(pair<BspNode *, BspNodeGeometry *>(interior->GetFront(), front));
+			tStack.push(pair<BspNode *, BspNodeGeometry *>(interior->GetBack(), back));
+		}
+		else
+		{
+			if (maxPvs > 0)
+			{
+				BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+
+				mForcedMaterial.mDiffuseColor.b = 1.0f;
+  				float importance = (float)leaf->GetViewCell()->GetPvs().GetSize() / (float)maxPvs;
+
+				mForcedMaterial.mDiffuseColor.r = importance;
+				mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r;
+			}
+
+			ExportPolygons(cell->mPolys);
+		}
+		
+		DEL_PTR(cell);
+	}
+}
+
+void
+X3dExporter::ExportViewCell(ViewCell *viewCell)
+{
+	if (viewCell->GetMesh())
+		ExportMesh(viewCell->GetMesh());
+}
+
+void
+X3dExporter::ExportMesh(Mesh *mesh)
+{
+
+  stream<<"<Shape>"<<endl;
+  stream<<"<Appearance>"<<endl;
+  
+  // $$ tmp -> random material
+  
+  float r, g, b;
+
+  if (mUseForcedMaterial) {
+    r = mForcedMaterial.mDiffuseColor.r;
+    g = mForcedMaterial.mDiffuseColor.g;
+    b = mForcedMaterial.mDiffuseColor.b;
+    
+  } else
+    if (mesh->mMaterial) {
+      r = mesh->mMaterial->mDiffuseColor.r;
+      g = mesh->mMaterial->mDiffuseColor.g;
+      b = mesh->mMaterial->mDiffuseColor.b;
+    } else {
+      r = RandomValue(0.5, 1.0);
+      g = RandomValue(0.5, 1.0);
+      b = RandomValue(0.5, 1.0);
+    }
+  stream<<"<Material diffuseColor=\""<<r<<" "<<g<<" "<<b<<
+    "\" specularColor=\"0.0 0.0 0.0\"/>"<<endl;
+  stream<<"</Appearance>"<<endl;
+
+
+  if (mWireframe)
+    stream<<"<IndexedLineSet coordIndex=\""<<endl;
+  else
+    //stream<<"<IndexedFaceSet ccw=\"TRUE\" coordIndex=\""<<endl;
+	stream << "<IndexedFaceSet coordIndex=\"" << endl;
+
+  FaceContainer::const_iterator fi = mesh->mFaces.begin();
+
+  int index = 0;
+  
+  for (; fi != mesh->mFaces.end(); fi++) {
+    Face *face = *fi;
+    VertexIndexContainer::const_iterator vi = face->mVertexIndices.begin();
+    for (; vi != face->mVertexIndices.end(); vi++)
+      stream<<*vi<<" ";
+	if (mWireframe) // final line to finish polygon
+		stream << (*face->mVertexIndices.begin()) << " ";
+
+    stream<<"-1"<<endl;
+  }
+  stream<<"\" >"<<endl;
+
+  stream<<"<Coordinate  point=\""<<endl;
+  
+  VertexContainer::const_iterator vi = mesh->mVertices.begin();
+  for (; vi != mesh->mVertices.end(); vi++) {
+    stream<<(*vi).x<<" "<<(*vi).y<<" "<<(*vi).z;
+    stream<<","<<endl;
+  }
+  
+  stream<<"\" >"<<endl;
+  stream<<"</Coordinate>"<<endl;
+
+  if (mWireframe)
+    stream<<"</IndexedLineSet>"<<endl;
+  else
+    stream<<"</IndexedFaceSet>"<<endl;
+  
+  stream<<"</Shape>"<<endl;
+
+}
+
+
+void X3dExporter::ExportPolygon(Polygon3 *poly)
+{
+	stream << "<Shape>" << endl;
+	stream << "<Appearance>" << endl;
+  
+	// $$ tmp -> random material
+  
+	float r, g, b;
+
+	if (mUseForcedMaterial) 
+	{
+		r = mForcedMaterial.mDiffuseColor.r;
+		g = mForcedMaterial.mDiffuseColor.g;
+		b = mForcedMaterial.mDiffuseColor.b;
+	} 
+	else if (poly->mMaterial) 
+	{
+		r = poly->mMaterial->mDiffuseColor.r;
+		g = poly->mMaterial->mDiffuseColor.g;
+		b = poly->mMaterial->mDiffuseColor.b;
+	} else 
+	{
+		r = RandomValue(0.5, 1.0);
+		g = RandomValue(0.5, 1.0);
+		b = RandomValue(0.5, 1.0);
+	}
+
+	stream << "<Material diffuseColor=\"" << r << " " << g << " " << b 
+		   << "\" specularColor=\"0.0 0.0 0.0\"/>" << endl;
+
+    stream << "</Appearance>" << endl;
+
+
+	//-- create and write indices
+	if (mWireframe)
+		stream<<"<IndexedLineSet coordIndex=\""<<endl;
+	else
+		//stream << "<IndexedFaceSet ccw=\"TRUE\" coordIndex=\"" << endl;
+		stream << "<IndexedFaceSet coordIndex=\"" << endl;
+	int index = 0;
+	
+	VertexContainer::const_iterator vi;  
+	
+	for (index = 0; index < (int)poly->mVertices.size(); ++ index) 
+		stream << index << " ";
+	
+	if (mWireframe) // final line to finish polygon
+		stream << "0 ";
+
+	stream << "-1" << endl;
+	stream << "\" >" << endl;
+	
+	stream << "<Coordinate  point=\"" << endl;
+  
+  	for (vi = poly->mVertices.begin(); vi != poly->mVertices.end(); ++vi) 
+	{
+		stream << (*vi).x << " " << (*vi).y << " " << (*vi).z;
+		stream << "," << endl;
+	}
+  
+	stream << "\" >" << endl;
+	stream << "</Coordinate>" << endl;
+
+	if (mWireframe)
+		stream << "</IndexedLineSet>" << endl;
+	else
+		stream << "</IndexedFaceSet>" << endl;
+  
+	stream << "</Shape>" << endl;
+}
+
+void X3dExporter::ExportPolygons(const PolygonContainer &polys)
+{
+  	stream << "<Shape>" << endl;
+	stream << "<Appearance>" << endl;
+  
+	// $$ tmp -> random material
+  
+	float r, g, b;
+
+	if (mUseForcedMaterial) 
+	{
+		r = mForcedMaterial.mDiffuseColor.r;
+		g = mForcedMaterial.mDiffuseColor.g;
+		b = mForcedMaterial.mDiffuseColor.b;
+	} 
+	else 
+	{
+		r = RandomValue(0.5, 1.0);
+		g = RandomValue(0.5, 1.0);
+		b = RandomValue(0.5, 1.0);
+	}
+
+	stream << "<Material diffuseColor=\"" << r << " " << g << " " << b 
+		   << "\" specularColor=\"0.0 0.0 0.0\"/>" << endl;
+
+    stream << "</Appearance>" << endl;
+
+
+	//-- create and write indices
+	if (mWireframe)
+		stream<<"<IndexedLineSet coordIndex=\""<<endl;
+	else
+		//stream << "<IndexedFaceSet ccw=\"TRUE\" coordIndex=\"" << endl;
+		stream << "<IndexedFaceSet coordIndex=\"" << endl;
+
+	int index = 0;
+	
+	PolygonContainer::const_iterator pit;
+
+    VertexContainer::const_iterator vi;  
+	
+	for (pit = polys.begin(); pit != polys.end(); ++pit)
+	{
+		Polygon3 *poly = *pit;
+		int startIdx = index;
+		for (vi = poly->mVertices.begin(); vi != poly->mVertices.end(); ++vi) 
+		{
+			stream << index ++ << " ";
+		}
+
+		stream << startIdx << " ";// finish line
+		stream << "-1" << endl;
+	}
+
+	stream << "\" >" << endl;
+	
+	stream << "<Coordinate  point=\"" << endl;
+	for (pit = polys.begin(); pit != polys.end(); ++ pit)
+	{
+		Polygon3 *poly = *pit;
+        for (vi = poly->mVertices.begin(); vi != poly->mVertices.end(); ++vi) 
+		{
+			stream << (*vi).x << " " << (*vi).y << " " << (*vi).z;
+			stream << "," << endl;
+		}
+	}
+	stream << "\" >" << endl;
+	stream << "</Coordinate>" << endl;
+
+	if (mWireframe)
+		stream << "</IndexedLineSet>" << endl;
+	else
+		stream << "</IndexedFaceSet>" << endl;
+  
+	stream << "</Shape>" << endl;
+}
+
+bool
+X3dExporter::ExportBox(const AxisAlignedBox3 &box)
+{
+  Mesh *mesh = new Mesh;
+  // add 8 vertices of the box
+  int index = (int)mesh->mVertices.size();
+  for (int i=0; i < 8; i++) {
+    Vector3 v;
+    box.GetVertex(i, v);
+    mesh->mVertices.push_back(v);
+  }
+  
+  mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) );
+  mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) );
+  mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) );
+  
+  mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) );
+  mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) );
+  mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) );
+  
+  ExportMesh(mesh);
+  delete mesh;
+  return true;
+}
+
+bool
+X3dExporter::ExportBspTree(const BspTree &tree)
+{
+	if (mExportRayDensity) 
+	{
+		return ExportBspTreeRayDensity(tree);
+	}
+  
+	bool savedWireframe = mWireframe;
+
+	SetWireframe();
+	
+	ExportBox(tree.GetBoundingBox());
+	
+	if (!savedWireframe)
+		SetFilled();
+
+	// export view cells
+	ExportBspLeaves(tree);	
+
+	return true;
+}
+
+bool X3dExporter::ExportVspKdTree(const VspKdTree &tree, const int maxPvs)
+{
+	stack<VspKdNode *> tStack;
+
+	tStack.push(tree.GetRoot());
+
+	//Mesh *mesh = new Mesh;
+  
+	if (maxPvs > 0)
+		mUseForcedMaterial = true;
+
+	while (!tStack.empty()) 
+	{
+		VspKdNode *node = tStack.top();
+    
+		tStack.pop();
+
+		if (node->IsLeaf())
+		{
+			AxisAlignedBox3 box = tree.GetBBox(node);
+
+			Mesh *mesh = new Mesh;
+
+			// add 6 vertices of the box
+			int index = (int)mesh->mVertices.size();
+
+			for (int i=0; i < 8; ++ i) 
+			{
+				Vector3 v;
+				box.GetVertex(i, v);
+				mesh->mVertices.push_back(v);
+			}
+
+			mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) );
+			mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) );
+			mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) );
+
+			mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) );
+			mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) );
+			mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) );
+
+			if (maxPvs > 0)
+			{
+				VspKdLeaf *leaf = dynamic_cast<VspKdLeaf *>(node);
+
+				mForcedMaterial.mDiffuseColor.b = 1.0f;
+				
+				leaf->UpdatePvsSize();
+			
+				const float importance = (float)leaf->GetPvsSize() / (float)maxPvs;
+				mForcedMaterial.mDiffuseColor.r = importance;
+				mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r;
+			}
+
+			ExportMesh(mesh);
+			DEL_PTR(mesh);
+		}
+		else  
+		{
+			VspKdInterior *interior = dynamic_cast<VspKdInterior *>(node);
+			tStack.push(interior->GetFront());
+			tStack.push(interior->GetBack());
+		}
+	}
+  
+	//ExportMesh(mesh);
+	//DEL_PTR(mesh);
+
+	return true;
+}
+
+
+bool X3dExporter::ExportKdTree(const KdTree &tree)
+{
+	 if (mExportRayDensity) {
+    return ExportKdTreeRayDensity(tree);
+  }
+  
+  stack<KdNode *> tStack;
+
+  tStack.push(tree.GetRoot());
+
+  Mesh *mesh = new Mesh;
+  
+  while (!tStack.empty()) {
+    KdNode *node = tStack.top();
+    tStack.pop();
+    AxisAlignedBox3 box = tree.GetBox(node);
+    // add 6 vertices of the box
+    int index = (int)mesh->mVertices.size();
+    for (int i=0; i < 8; i++) {
+      Vector3 v;
+      box.GetVertex(i, v);
+      mesh->mVertices.push_back(v);
+    }
+    mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) );
+    mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) );
+    mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) );
+
+    mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) );
+    mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) );
+    mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) );
+
+    if (!node->IsLeaf()) {
+      KdInterior *interior = (KdInterior *)node;
+      tStack.push(interior->mFront);
+      tStack.push(interior->mBack);
+    }
+  }
+  
+  ExportMesh(mesh);
+  delete mesh;
+  return true;
+	// TODO
+	return true;
+}
+
+
+
+
+bool
+X3dExporter::ExportVssTree(const VssTree &tree
+						   )
+{
+  stack<VssTreeNode *> tStack;
+	
+  tStack.push(tree.GetRoot());
+	
+  Mesh *mesh = new Mesh;
+  VssRayContainer rays;
+	
+  while (!tStack.empty()) {
+
+		VssTreeNode *node = tStack.top();
+    tStack.pop();
+
+			
+    if (!node->IsLeaf()) {
+      VssTreeInterior *interior = (VssTreeInterior *)node;
+      tStack.push(interior->front);
+      tStack.push(interior->back);
+    } else {
+			VssTreeLeaf *leaf = (VssTreeLeaf *)node;
+			AxisAlignedBox3 box;
+			box = tree.GetBBox(leaf);
+			box.AddBoxToMesh(mesh);
+
+			if (tree.ValidLeaf(leaf)) {
+				
+				Vector3 origin = box.Center();
+				box = tree.GetDirBBox(leaf);
+				VssRay *ray;
+				
+				const indices[][2] = {{0,0}, {0,1}, {1,1}, {1,0}}; 
+				MeshInstance dummy(mesh);
+				for (int i=0; i < 4; i++) {
+					//				Vector3 v = box.GetVertex(indices[i][0], indices[i][1], 0);
+					Vector3 v = box.Center();
+					
+					Vector3 direction = VssRay::GetDirection(v.x, v.y);
+					if (Magnitude(direction) > Limits::Small)
+					  direction.Normalize();
+					else
+					  direction = Vector3(0, 1, 0);
+					float k = 100.0f*leaf->GetImportance();
+					// get 4 corners of the ray directions
+					
+					ray = new VssRay(origin, origin + (direction*k), NULL, &dummy);
+					rays.push_back(ray);
+				}
+			}
+		}
+  }
+
+  ExportMesh(mesh);
+  ExportRays(rays);
+  CLEAR_CONTAINER(rays);
+  delete mesh;
+  return true;
+}
+
+bool
+X3dExporter::ExportVssTree2(const VssTree &tree,
+							const Vector3 direction
+							)
+{
+  stack<VssTreeNode *> tStack;
+	
+
+  mUseForcedMaterial = true;
+
+  Vector3 dirParam;
+
+  dirParam.x = VssRay::GetDirParam(0, Normalize(direction));
+  dirParam.y = VssRay::GetDirParam(1, Normalize(direction));
+
+  float maxImportance = 0.0f;
+  tStack.push(tree.GetRoot());
+  while (!tStack.empty()) {
+	
+	VssTreeNode *node = tStack.top();
+    tStack.pop();
+	
+    if (!node->IsLeaf()) {
+      VssTreeInterior *interior = (VssTreeInterior *)node;
+	  if (interior->axis < 3) {
+		tStack.push(interior->front);
+		tStack.push(interior->back);
+	  } else {
+		if (dirParam[interior->axis-3] < interior->position)
+		  tStack.push(interior->back);
+		else
+		  tStack.push(interior->front);
+	  }
+    } else {
+	  VssTreeLeaf *leaf = (VssTreeLeaf *)node;
+	  if (tree.ValidLeaf(leaf)) {
+		float i = leaf->GetImportance();
+		if (i > maxImportance)
+		  maxImportance = i;
+	  }
+	}
+  }
+
+  tStack.push(tree.GetRoot());
+  while (!tStack.empty()) {
+
+	VssTreeNode *node = tStack.top();
+    tStack.pop();
+	
+			
+    if (!node->IsLeaf()) {
+      VssTreeInterior *interior = (VssTreeInterior *)node;
+	  if (interior->axis < 3) {
+		tStack.push(interior->front);
+		tStack.push(interior->back);
+	  } else {
+		if (dirParam[interior->axis-3] < interior->position)
+		  tStack.push(interior->back);
+		else
+		  tStack.push(interior->front);
+	  }
+    } else {
+	  VssTreeLeaf *leaf = (VssTreeLeaf *)node;
+	  if (tree.ValidLeaf(leaf)) {
+		AxisAlignedBox3 box;
+		box = tree.GetBBox(leaf);
+		Mesh *mesh = new Mesh;
+		box.AddBoxToMesh(mesh);
+		
+		// get 4 corners of the ray directions
+		
+		mForcedMaterial.mDiffuseColor.b = 1.0f;
+		mForcedMaterial.mDiffuseColor.r = leaf->GetImportance()/maxImportance;
+		mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r;
+		
+		ExportMesh(mesh);
+		delete mesh;
+	  }
+	}
+  }
+
+  mUseForcedMaterial = false;
+
+  return true;
+}
+
+bool
+X3dExporter::ExportBspTreeRayDensity(const BspTree &tree)
+{
+	stack<BspNode *> tStack;
+
+	tStack.push(tree.GetRoot());
+
+	bool fm = mUseForcedMaterial;
+	
+	mUseForcedMaterial = true;
+	
+	mForcedMaterial.mDiffuseColor.g = 1.0f;
+  	mForcedMaterial.mDiffuseColor.b = 1.0f;
+  
+	while (!tStack.empty()) 
+	{
+		BspNode *node = tStack.top();
+		tStack.pop();
+
+		if (node->IsLeaf()) 
+		{
+			ViewCell *vc = dynamic_cast<BspLeaf *>(node)->GetViewCell();
+#if 0     
+			// set the mesh material according to the ray density
+			if (vc->mPassingRays.mRays) 
+			{
+				float importance = 
+				  vc->mPassingRays.mContributions / (float)vc->mPassingRays.mRays;
+				
+				mForcedMaterial.mDiffuseColor.r = importance;
+				mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r;
+				ExportViewCell(vc);
+
+			}
+#endif
+		} 
+		else 
+		{
+			BspInterior *interior = (BspInterior *)node;
+			tStack.push(interior->GetFront());
+			tStack.push(interior->GetBack());
+		}
+	}
+  
+	// restore the state of forced material
+	mUseForcedMaterial = fm;
+
+	return true;
+}
+
+bool
+X3dExporter::ExportKdTreeRayDensity(const KdTree &tree)
+{
+  stack<KdNode *> tStack;
+
+  tStack.push(tree.GetRoot());
+
+  bool fm = mUseForcedMaterial;
+  mUseForcedMaterial = true;
+  mForcedMaterial.mDiffuseColor.g = 1.0f;
+  mForcedMaterial.mDiffuseColor.b = 1.0f;
+  while (!tStack.empty()) {
+    KdNode *node = tStack.top();
+    tStack.pop();
+    if (node->IsLeaf()) {
+      AxisAlignedBox3 box = tree.GetBox(node);
+      Mesh *mesh = new Mesh;
+      
+      // add 6 vertices of the box
+      int index = (int)mesh->mVertices.size();
+      for (int i=0; i < 8; i++) {
+	Vector3 v;
+	box.GetVertex(i, v);
+	mesh->mVertices.push_back(v);
+      }
+      mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) );
+      mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) );
+      mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) );
+      
+      mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) );
+      mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) );
+      mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) );
+
+
+      // set the mesh material according to the ray density
+      KdLeaf *leaf = (KdLeaf *) node;
+      if (leaf->mPassingRays.mRays) {
+	float importance = leaf->mPassingRays.mContributions/(float)leaf->mPassingRays.mRays;
+	//	float importance = leaf->mPassingRays.mContributions/1000.0f;
+	//	float importance = leaf->mPassingRays.mRays/1000.0f;
+	///(float)leaf->mPassingRays.mRays;
+	// mForcedMaterial.mDiffuseColor.r = log10(leaf->mPassingRays.mRays)/3.0f;
+	mForcedMaterial.mDiffuseColor.r = importance;
+	mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r;
+	ExportMesh(mesh);
+      }
+      delete mesh;
+    } else {
+      KdInterior *interior = (KdInterior *)node;
+      tStack.push(interior->mFront);
+      tStack.push(interior->mBack);
+    }
+  }
+  // restore the state of forced material
+  mUseForcedMaterial = fm;
+  return true;
+}
+
+
+struct BspSplitData
+{
+	/// the current node
+	BspNode *mNode;
+
+	vector<Plane3> mPlanes;
+	vector<bool> mSides;
+	bool mIsFront;
+	int mDepth;
+
+	BspSplitData(BspNode *node): 
+	mNode(node), mIsFront(false), mDepth(0)
+	{};	
+
+	BspSplitData(BspNode *node, 
+				vector<Plane3> planes, 
+				vector<bool> sides, 
+				const bool isFront,
+				const int depth): 
+	mNode(node), mPlanes(planes), mSides(sides), 
+	mIsFront(isFront), mDepth(depth)
+	{};
+};
+
+void X3dExporter::ExportLeavesGeometry(const BspTree &tree, 
+									   const vector<BspLeaf *> &leaves)
+{
+	vector<BspLeaf *>::const_iterator it, it_end = leaves.end();
+
+	for (it = leaves.begin(); it != it_end; ++ it)
+	{
+		BspNodeGeometry geom;
+		tree.ConstructGeometry(*it, geom);
+		
+		ExportPolygons(geom.mPolys);
+	}
+}
+
+void X3dExporter::ExportBspNodeSplits(BspNode *root,
+									  const AxisAlignedBox3 &box, 
+									  const bool exportDepth,
+									  const bool epsilon)
+{
+	std::stack<BspSplitData> tStack;
+
+	BspSplitData tData(root);
+	tStack.push(tData);
+  
+	PolygonContainer polys;
+	vector <int> depths;
+
+	int maxDepth = 0;
+
+	while (!tStack.empty())
+	{
+		// filter polygons donw the tree
+		BspSplitData tData = tStack.top();
+	    tStack.pop();	
+		
+		if (tData.mNode->IsLeaf())
+		{
+			if (tData.mDepth > maxDepth)
+				maxDepth = tData.mDepth;
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(tData.mNode);
+
+			// add current side of split plane
+			if (tData.mNode != root)
+				tData.mSides.push_back(tData.mIsFront);
+
+			// bounded plane is added to the polygons
+			Polygon3 *planePoly = 
+				box.CrossSection(interior->GetPlane());
+		
+			// do all the splits with the previous planes
+			for (int i = 0; i < (int)tData.mPlanes.size(); ++ i)
+			{				
+				if (planePoly->ClassifyPlane(tData.mPlanes[i], epsilon) 
+					== Polygon3::SPLIT)
+				{
+					Polygon3 *frontPoly = new Polygon3();
+					Polygon3 *backPoly = new Polygon3();
+
+					planePoly->Split(tData.mPlanes[i], 
+									 *frontPoly, 
+									 *backPoly,
+									 epsilon);
+
+					DEL_PTR(planePoly);
+
+					if(tData.mSides[i] == true)
+					{
+						planePoly = frontPoly;
+						DEL_PTR(backPoly);
+					}
+					else
+					{
+						planePoly = backPoly;
+						DEL_PTR(frontPoly);
+					}
+				}
+			}
+
+			tData.mPlanes.push_back(interior->GetPlane()); // add plane to split planes
+
+			if (planePoly->Valid(epsilon))
+			{
+				polys.push_back(planePoly);
+				depths.push_back(tData.mDepth);
+			}
+			else
+				DEL_PTR(planePoly);
+			
+			// push the children on the stack
+			tStack.push(BspSplitData(interior->GetFront(), tData.mPlanes, 
+				                     tData.mSides, true, tData.mDepth + 1));
+			tStack.push(BspSplitData(interior->GetBack(), tData.mPlanes, 
+				                     tData.mSides, false, tData.mDepth + 1));
+		}
+	}
+
+	if (maxDepth > 0)
+	{	
+		mUseForcedMaterial = true;
+			
+		for (int i = 0; i < (int)polys.size(); ++ i)
+		{
+			mForcedMaterial.mDiffuseColor.b = 1.0f;
+			float importance =  (float)depths[i]/ (float)maxDepth;
+            
+			mForcedMaterial.mDiffuseColor.r = importance;
+			mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r;
+
+			ExportPolygon(polys[i]);
+		}
+	}
+	else
+	{
+		ExportPolygons(polys);
+	}
+
+	CLEAR_CONTAINER(polys);
+}
+
+void X3dExporter::ExportBspSplits(const BspTree &tree,
+								  const bool exportDepth)
+{
+	ExportBspNodeSplits(tree.GetRoot(), 
+						tree.GetBoundingBox(), 
+						exportDepth, 
+						tree.GetEpsilon());
+}
+
+void X3dExporter::ExportBspSplits(const VspBspTree &tree,
+								  const bool exportDepth)
+{
+	ExportBspNodeSplits(tree.GetRoot(), 
+						tree.GetBoundingBox(), 
+						exportDepth, 
+						tree.GetEpsilon());
+}
+
+void X3dExporter::ExportBspSplitPlanes(const BspTree &tree)
+{
+	std::stack<BspNode *> tStack;
+
+	tStack.push(tree.GetRoot());
+  
+	PolygonContainer polys;
+
+	while (!tStack.empty())
+	{
+		// filter polygons donw the tree
+		BspNode *node = tStack.top();
+	    tStack.pop();	
+		
+		if (!node->IsLeaf())
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			// bounded plane is added to the polygons
+			polys.push_back(tree.GetBoundingBox().CrossSection(interior->GetPlane()));
+		
+			// push the children on the stack
+			tStack.push(interior->GetBack());
+			tStack.push(interior->GetFront());
+		}
+	}
+
+	ExportPolygons(polys);
+	CLEAR_CONTAINER(polys);
+}
+
+
+void X3dExporter::ExportGeometry(const ObjectContainer &objects)
+{
+	for (int j = 0; j < objects.size(); ++ j)
+		ExportIntersectable(objects[j]);
+}
+
+
+bool
+X3dExporter::ExportRssTree2(const RssTree &tree,
+							const Vector3 direction
+							)
+{
+  stack<RssTreeNode *> tStack;
+  
+  
+  mUseForcedMaterial = true;
+
+  Vector3 dirParam;
+
+  dirParam.x = VssRay::GetDirParam(0, Normalize(direction));
+  dirParam.y = VssRay::GetDirParam(1, Normalize(direction));
+
+  float maxImportance = 0.0f;
+  tStack.push(tree.GetRoot());
+  while (!tStack.empty()) {
+	
+	RssTreeNode *node = tStack.top();
+    tStack.pop();
+	
+    if (!node->IsLeaf()) {
+      RssTreeInterior *interior = (RssTreeInterior *)node;
+	  if (interior->axis < 3) {
+		tStack.push(interior->front);
+		tStack.push(interior->back);
+	  } else {
+		if (dirParam[interior->axis-3] < interior->position)
+		  tStack.push(interior->back);
+		else
+		  tStack.push(interior->front);
+	  }
+    } else {
+	  RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+	  if (tree.ValidLeaf(leaf)) {
+		float i = leaf->GetImportance();
+		if (i > maxImportance)
+		  maxImportance = i;
+	  }
+	}
+  }
+
+  tStack.push(tree.GetRoot());
+  while (!tStack.empty()) {
+
+	RssTreeNode *node = tStack.top();
+    tStack.pop();
+	
+			
+    if (!node->IsLeaf()) {
+      RssTreeInterior *interior = (RssTreeInterior *)node;
+	  if (interior->axis < 3) {
+		tStack.push(interior->front);
+		tStack.push(interior->back);
+	  } else {
+		if (dirParam[interior->axis-3] < interior->position)
+		  tStack.push(interior->back);
+		else
+		  tStack.push(interior->front);
+	  }
+    } else {
+	  RssTreeLeaf *leaf = (RssTreeLeaf *)node;
+	  if (tree.ValidLeaf(leaf)) {
+		AxisAlignedBox3 box;
+		box = tree.GetShrankedBBox(leaf);
+		Mesh *mesh = new Mesh;
+		box.AddBoxToMesh(mesh);
+		
+		// get 4 corners of the ray directions
+		
+		mForcedMaterial.mDiffuseColor.b = 1.0f;
+		mForcedMaterial.mDiffuseColor.r = leaf->GetImportance()/maxImportance;
+		mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r;
+		
+		ExportMesh(mesh);
+		delete mesh;
+	  }
+	}
+  }
+
+  mUseForcedMaterial = false;
+
+  return true;
+}
+
+
+void
+X3dExporter::ExportViewpoint(const Vector3 &point,
+							 const Vector3 &direction)
+{
+  stream<<"<Viewpoint "<<endl;
+  
+  stream<<"position=\""<<point.x<<" "<<point.y<<" "<<point.z<<"\""<<endl;
+  //  stream<<"orientation "<<direction.x<<direction.y<<direction.z<<endl;
+  
+  stream<<">"<<endl;
+  stream<<"</Viewpoint>"<<endl;
+
+}
+
+
+
+void X3dExporter::ExportBeam(const Beam &beam, const AxisAlignedBox3 &box)
+{
+	if (beam.mMesh)
+	{
+		ExportMesh(beam.mMesh);
+		return;
+	}
+
+	PolygonContainer polys;
+	//ExportBox(beam.mBox);
+
+	const float zfar = 2.0f * Magnitude(box.Diagonal());
+
+	// box should not never remove part of beam polygons
+	Vector3 bmin = beam.mBox.Min() - Vector3(zfar * 2.0f);
+	Vector3 bmax = beam.mBox.Max() + Vector3(zfar * 2.0f);
+
+	AxisAlignedBox3 bbox(bmin, bmax);
+	Plane3 fplane;
+	fplane.mNormal = -beam.mPlanes[0].mNormal;
+
+	fplane.mD = beam.mPlanes[0].mD - zfar - 1.0f; 
+	
+	vector<Plane3> planes = beam.mPlanes;
+	planes.push_back(fplane);
+
+	for (int i = 0; i < planes.size(); ++ i)
+	{
+		Polygon3 *poly = bbox.CrossSection(planes[i]);
+		if (!poly->Valid(Limits::Small))
+			DEL_PTR(poly);
+		
+		for (int j = 0; (j < planes.size()) && poly; ++ j)
+		{
+			if (j != i)
+			{
+				Polygon3 *front = new Polygon3();
+				Polygon3 *back = new Polygon3();
+				
+				poly->Split(planes[j], *front, *back, Limits::Small);
+				DEL_PTR(poly);
+				DEL_PTR(front);
+
+				if (!back->Valid(Limits::Small))
+					DEL_PTR(back);
+				poly = back;
+			}
+		}
+		if (poly)
+			polys.push_back(poly);
+	}
+
+	ExportPolygons(polys);
+	CLEAR_CONTAINER(polys);
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/common.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/common.cpp	(revision 542)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/common.cpp	(revision 542)
@@ -0,0 +1,286 @@
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "common.h"
+
+#ifdef _X_WINDOW_
+#include "xwindow.h"
+#endif
+
+#ifndef _MSC_VER
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/resource.h>
+#else
+#include <windows.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#endif
+
+
+
+// global file streams
+ofstream Debug;
+
+int CGlobals::Special=0;
+
+
+// Puts the specified number of spaces out to cout.  Used for
+// indentation during CObject3D::Describe().
+void
+indent(ostream &app, int ind)
+{
+  int i;
+
+  for (i = 0; i < ind; i++)
+    app << ' ';
+}
+
+
+
+Real Limits::Threshold = 1e-6f;
+Real Limits::Small = 0.01f;
+Real Limits::Infinity = 1e20;
+
+
+
+
+Real
+Random(Real max)
+{
+#ifdef __UNIX__
+  return (random()*max/0x7FFFFFFF);
+#else
+  return (((Real)rand())/RAND_MAX)*max;
+#endif
+  
+}
+
+int Random(int max)
+{
+  return rand()%max;
+}
+
+void Randomize()
+{
+  time_t t;
+  srand((unsigned) time(&t));
+}
+
+void
+Randomize(const unsigned int seed)
+{
+  srand(seed);
+}
+
+void GetKey(char *s)
+{
+#ifdef _X_WINDOW_
+XWaitForButton(s);
+#else
+getch();
+#endif
+}
+
+#ifdef  _MSC_VER
+static bool hasHRTimer = false;
+static LARGE_INTEGER hrFreq;
+#endif
+
+
+void
+InitTiming()
+{
+#ifdef  _MSC_VER
+  hasHRTimer = (bool) QueryPerformanceFrequency(&hrFreq);
+#endif
+}
+
+long
+GetTime()
+{
+#ifndef  _MSC_VER
+  static struct rusage r;
+  getrusage(RUSAGE_SELF,&r);
+  return r.ru_utime.tv_usec+1000000*r.ru_utime.tv_sec;
+#else
+  if (hasHRTimer) {
+    LARGE_INTEGER counter;
+    QueryPerformanceCounter(&counter);
+    // return in usec
+    return (long) (1000000*counter.QuadPart/(hrFreq.QuadPart));
+  } else {
+    static struct _timeb mtime;
+    _ftime(&mtime);
+    
+    return 1000*(1000*mtime.time + mtime.millitm);
+  }
+#endif
+}
+
+
+long
+GetRealTime()
+{
+#ifndef  _MSC_VER
+  static struct timeval _tstart;
+  static struct timezone tz;
+  gettimeofday(&_tstart,&tz);
+  return (long)(1000000*_tstart.tv_sec + _tstart.tv_usec);
+#else
+  if (hasHRTimer) {
+    LARGE_INTEGER counter;
+    QueryPerformanceCounter(&counter);
+    // return in usec
+    return (long) (1000000*counter.QuadPart/(hrFreq.QuadPart));
+  } else {
+    static struct _timeb mtime;
+    _ftime(&mtime);
+    return 1000*(1000*mtime.time + mtime.millitm);
+  }
+#endif
+}
+
+// return time diff. in ms
+Real
+TimeDiff(long time1,long time2) // in ms
+{
+  const Real clk=1.0e-3f; // ticks per second
+  long t=time2-time1;
+  
+  return ((t<0)?-t:t)*clk;
+}
+
+char *
+TimeString()
+{
+  time_t t;
+  time(&t);
+  return ctime(&t);
+}
+
+char *
+GetAbsPath(char *name)
+{
+  //  char *url = new char[strlen(name)+1];
+  //  strcpy(url,name);
+
+  // get the absolute path
+  int c = strlen(name);
+  int i = c-1;
+  bool wasDot = false;
+  // search for double dot
+  for (;i>=0;i--) 
+    if (name[i]=='.') {
+      if (wasDot)
+   break;
+      wasDot = true;
+    } else
+      wasDot = false;
+
+  if (i>0)
+    i+=3;
+  if (i<0)
+    i=0;
+  
+  char *url = new char[c-i+1];
+  int j=0;
+  for (;i<c;i++,j++)
+    url[j] = name[i];
+  url[j]=0;
+  
+  return url;
+}
+
+char *
+GetPath(const char *s)
+{
+  int i=strlen(s);
+  for (; i>0; i--) {
+    if (s[i]=='/' || s[i]=='\\')
+      break;
+  }
+  
+  char *path = new char[i+1];
+  int j=0;
+  for (; j<i; j++)
+    path[j] = s[j];
+  path[j] = 0;
+  return path;
+}
+
+
+char *
+strdup(char *a)
+{
+  if (a) {
+    char *s = new char[strlen(a)+1];
+    strcpy(s,a);
+    return s;
+  } else
+    return NULL;
+}
+
+bool
+FileExists(char *filename)
+{
+  FILE *f;
+
+  f = fopen(filename,"r");
+  if (f) {
+    fclose(f);
+    return true;
+  }
+  return false;
+}
+
+
+#if 0
+bool
+CreateDir(char *dir)
+{
+#ifdef _MSC_VER
+  HANDLE fFile; // File Handle
+  WIN32_FIND_DATA fileinfo; // File Information Structure
+  int n = strlen(dir) - 1;
+  
+  if (dir[n] == '\\' || dir[n] == '/')
+    dir[n]=0;
+  
+  fFile = FindFirstFile(dir, &fileinfo);
+  
+  // if the file exists and it is a directory
+  if (fileinfo.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) {
+    // Directory Exists close file and return
+    FindClose(fFile);
+    return true;
+  }
+  
+  FindClose(fFile);
+
+  // Now lets cycle through the String Array and create each directory in turn
+  if (CreateDirectory(dir, 0)) {
+    SetFileAttributes(dir, FILE_ATTRIBUTE_NORMAL);
+    return true;
+  } else {
+    char *temp = GetPath(dir);
+
+    if (strcmp(temp, dir)!=0) {
+      CreateDir(temp);
+      if (CreateDirectory(dir, 0)) {
+   SetFileAttributes(dir, FILE_ATTRIBUTE_NORMAL);
+   return true;
+      }
+    }
+    delete temp;
+  }
+  Debug << "cannot create directory " << dir << endl;
+#endif
+  return false;
+}
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h	(revision 556)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h	(revision 556)
@@ -0,0 +1,85 @@
+#ifndef __INTERSECTABLE_H
+#define __INTERSECTABLE_H
+
+#include "AxisAlignedBox3.h"
+#include "Pvs.h"
+
+struct VssRayContainer;
+
+class Intersectable {
+public:
+	// last mail id -> warning not thread safe!
+	// both mailId and mailbox should be unique for each thread!!!
+	static int sMailId;
+	static int sReservedMailboxes;
+	int mMailbox;
+	
+	// unique object Id
+	int mId;
+
+	// universal counter
+	int mCounter;
+	
+	// object based pvs
+	KdPvs mKdPvs;
+  
+  enum { MESH_INSTANCE, TRANSFORMED_MESH_INSTANCE, SPHERE, VIEW_CELL };
+  
+  Intersectable():mMailbox(0) {}
+
+	void SetId(const int id) { mId = id; }
+	int GetId() { return mId; }
+	
+
+	static void NewMail(const int reserve = 1) {
+		sMailId += sReservedMailboxes;
+		sReservedMailboxes = reserve;
+	}
+	
+	void Mail() { mMailbox = sMailId; }
+  bool Mailed() const { return mMailbox == sMailId; }
+
+	void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
+	bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
+
+	int IncMail() { return ++mMailbox - sMailId; }
+
+
+	
+  virtual AxisAlignedBox3 GetBox() = 0;
+  
+  virtual int CastRay(Ray &ray) = 0;
+  
+  virtual bool IsConvex() = 0;
+  virtual bool IsWatertight() = 0;
+  virtual float IntersectionComplexity() = 0;
+  
+  virtual int NumberOfFaces() const = 0;
+
+  virtual int Type() const = 0;
+  
+  virtual int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal) = 0;
+  
+  virtual int
+  GetRandomVisibleSurfacePoint(Vector3 &point,
+							   Vector3 &normal,
+							   const Vector3 &viewpoint,
+															 const int maxTries
+							   ) = 0;
+  
+  virtual ostream &Describe(ostream &s) = 0;
+  
+  virtual int GenerateSilhouetteRays(const int nrays,
+									 const AxisAlignedBox3 &originBox,
+									 const AxisAlignedBox3 &directionBox,
+									 VssRayContainer &rays
+									 ) {return 0;}
+
+  static bool GreaterCounter(const Intersectable *a,
+							 const Intersectable *b) {
+	return a->mCounter > b->mCounter;
+  }
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParserXerces.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParserXerces.h	(revision 590)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParserXerces.h	(revision 590)
@@ -0,0 +1,160 @@
+#ifndef _X3D_PARSER_XERCES__H
+#define _X3D_PARSER_XERCES__H
+
+// ---------------------------------------------------------------------------
+//  Includes
+// ---------------------------------------------------------------------------
+#include <xercesc/sax/HandlerBase.hpp>
+#include "Mesh.h"
+
+XERCES_CPP_NAMESPACE_USE
+XERCES_CPP_NAMESPACE_BEGIN
+class AttributeList;
+XERCES_CPP_NAMESPACE_END
+
+class VspBspTree;
+class VspKdTree;
+class BspTree;
+class ViewCellsManager;
+
+class ViewCellsParseHandlers: public HandlerBase
+{
+public:
+  // -----------------------------------------------------------------------
+  //  Constructors and Destructor
+  // -----------------------------------------------------------------------
+  ViewCellsParseHandlers(ObjectContainer *objects);
+  ~ViewCellsParseHandlers();
+  
+  
+  // -----------------------------------------------------------------------
+  //  Getter methods
+  // -----------------------------------------------------------------------
+  unsigned int GetElementCount()
+  {
+    return mElementCount;
+  }
+  
+  unsigned int GetAttrCount()
+  {
+    return mAttrCount;
+  }
+  
+  unsigned int GetCharacterCount()
+  {
+    return mCharacterCount;
+  }
+  
+  unsigned int GetSpaceCount()
+  {
+    return mSpaceCount;
+  }
+
+
+  // -----------------------------------------------------------------------
+  //  Handlers for the SAX DocumentHandler interface
+  // -----------------------------------------------------------------------
+  void endElement(const XMLCh* const name);
+  void startElement(const XMLCh* const name, AttributeList& attributes);
+  void characters(const XMLCh* const chars, const unsigned int length);
+  void ignorableWhitespace(const XMLCh* const chars, const unsigned int length);
+  void resetDocument();
+
+  void CreateViewCellsManager(const char *name);
+
+
+  VspBspTree *mVspBspTree;
+  VspKdTree *mVspKdTree;
+  BspTree *mBspTree;
+  
+  BspNode *mCurrentBspNode;
+  ViewCellContainer mViewCells;
+  ViewCellsManager *mViewCellsManager;
+  ObjectContainer *mObjects;
+
+  AxisAlignedBox3 mViewSpaceBox;
+
+  // Handlers for X3D
+  void StartBspLeaf(AttributeList& attributes);
+  void StartBspInterior(AttributeList& attributes);
+  void EndBspInterior();
+ 
+  void StartViewCell(AttributeList&  attributes);
+  void EndViewCells();
+
+  void StartHierarchy(AttributeList& attributes);
+
+  void startBspElement(string element, AttributeList& attributes);
+  void StartViewSpaceBox(AttributeList&  attributes);
+  // -----------------------------------------------------------------------
+  //  Handlers for the SAX ErrorHandler interface
+  // -----------------------------------------------------------------------
+  void warning(const SAXParseException& exc);
+  void error(const SAXParseException& exc);
+  void fatalError(const SAXParseException& exc);
+  
+  
+private:
+  // -----------------------------------------------------------------------
+  //  Private data members
+  //
+  //  fAttrCount
+  //  fCharacterCount
+  //  fElementCount
+  //  fSpaceCount
+  //      These are just counters that are run upwards based on the input
+  //      from the document handlers.
+  // -----------------------------------------------------------------------
+  unsigned int    mAttrCount;
+  unsigned int    mCharacterCount;
+  unsigned int    mElementCount;
+  unsigned int    mSpaceCount;
+};
+
+// ---------------------------------------------------------------------------
+//  This is a simple class that lets us do easy (though not terribly efficient)
+//  trancoding of XMLCh data to local code page for display.
+// ---------------------------------------------------------------------------
+class StrX
+{
+public :
+  // -----------------------------------------------------------------------
+  //  Constructors and Destructor
+  // -----------------------------------------------------------------------
+  StrX(const XMLCh* const toTranscode)
+  {
+	  // Call the private transcoding method
+	  mLocalForm = XMLString::transcode(toTranscode);
+  }
+  
+  ~StrX()
+  {
+	  XMLString::release(&mLocalForm);
+  }
+  
+  // -----------------------------------------------------------------------
+  //  Getter methods
+  // -----------------------------------------------------------------------
+  const char* LocalForm() const
+  {
+    return mLocalForm;
+  }
+  
+private :
+  // -----------------------------------------------------------------------
+  //  Private data members
+  //
+  //  fLocalForm
+  //      This is the local code page form of the string.
+  // -----------------------------------------------------------------------
+  char*   mLocalForm;
+};
+
+inline XERCES_STD_QUALIFIER ostream&
+operator<<(XERCES_STD_QUALIFIER ostream& target, const StrX& toDump)
+{
+  target << toDump.LocalForm();
+  return target;
+}
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/default.env
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/default.env	(revision 608)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/default.env	(revision 608)
@@ -0,0 +1,349 @@
+#############################################################################
+# ERS default configuration file
+# Jiri Bittner 2003
+#############################################################################
+
+Scene {
+
+# filename ../data/glasgow/glasgow1.x3d
+#	filename vienna.x3d
+# filename ../data/vienna/vienna-simple.x3d
+#filename ../data/vienna/vienna-buildings.x3d
+#filename ../data/vienna/vienna-buildings.x3d;../data/vienna/vienna-roofs.x3d
+#;../data/vienna/vienna-plane.x3d
+# filename ../data/vienna/viewcells-25-sel.x3d
+#filename ../data/atlanta/atlanta2.x3d
+#filename ../data/soda/soda.dat
+filename ../data/soda/soda5.dat
+}
+
+Preprocessor {
+	# stored sample rays
+	samplesFilename rays.out
+	useGlRenderer true
+#	type sampling
+#	type vss
+	type rss
+	detectEmptyViewSpace true
+	pvsRenderErrorSamples 10000
+	quitOnFinish false
+}
+
+
+VssPreprocessor {
+	samplesPerPass  100000
+	initialSamples 500000
+	vssSamples 2000000
+	vssSamplesPerPass 200000
+	useImportanceSampling true
+	loadInitialSamples  false
+	storeInitialSamples false
+}
+
+
+VssTree {
+	useRss    false
+	epsilon		1e-6
+
+	maxDepth 	40
+	minPvs		30
+	minRays		100
+	minSize		0.001
+ 	maxCostRatio	1.5
+	maxRayContribution 0.5
+	
+	maxTotalMemory	200
+	maxStaticMemory	100
+
+#	splitType regular
+#	splitType heuristic
+	splitType hybrid
+	splitUseOnlyDrivingAxis true
+
+	interleaveDirSplits	true
+    dirSplitDepth 0
+
+	numberOfEndPointDomains	10000
+	ct_div_ci	0.0
+	randomize	false
+
+	refDirBoxMaxSize	0.1
+}
+
+RssPreprocessor {
+	samplesPerPass 500
+	initialSamples 100
+	vssSamples 100
+	vssSamplesPerPass 100
+	useImportanceSampling true
+
+	directionalSampling true
+	objectBasedSampling false
+
+	Export {
+		pvs false
+		rssTree false
+		rays true
+		numRays 5000
+	}
+
+	useViewcells true
+	updateSubdivision true
+	loadInitialSamples false
+	storeInitialSamples false
+}
+
+
+RssTree {
+	epsilon		1e-6
+	perObjectTree false
+
+	maxDepth 	40
+	minPvs		1
+	minRays		50
+	minSize		0.001
+ 	maxCostRatio 1.0
+	maxRayContribution 0.5
+	maxRays		2000000
+	maxTotalMemory	200
+	maxStaticMemory	100
+
+#	splitType regular
+#	splitType heuristic
+	splitType hybrid
+	splitUseOnlyDrivingAxis false
+	importanceBasedCost false
+
+	interleaveDirSplits	true
+    dirSplitDepth 0
+
+	ct_div_ci	0.0
+}
+
+Limits {
+
+       threshold	1e-6
+       small		1e-6
+       infinity		1e9
+}
+
+Unigraphics {
+		meshGrouping 1
+}
+
+KdTree {
+	sahUseFaces true
+	Termination {
+		minCost 1
+		maxDepth 18
+		maxCostRatio 0.9
+		ct_div_ci 0.5
+	}
+
+#	splitMethod spatialMedian
+	splitMethod SAH
+	splitBorder 0.01
+}
+
+MeshKdTree {
+	Termination {
+		minCost 1
+		maxDepth 18
+		maxCostRatio 0.9
+		ct_div_ci 0.5
+	}
+
+#	splitMethod spatialMedian
+	splitMethod SAH
+	splitBorder 0.01
+}
+
+
+SamplingPreprocessor {
+	totalSamples 10000000
+	samplesPerPass  3
+}
+
+
+ViewCells {
+	# samples used for view cell construction
+	Construction {
+		samples 600000
+		samplesPerPass 200000
+	}
+
+	#number of active view cells
+	active 10000
+	maxStaticMemory	40
+
+	exportToFile false
+	loadFromFile false
+
+	#type kdTree
+	#type vspKdTree
+	#type bspTree
+	type vspBspTree
+	
+	#type sceneDependent
+	
+	height 5.0
+	maxViewCells 100000
+
+	#percentage of total visible objects where pvs is considered invalid
+	maxPvsRatio 1.0
+		
+	pruneEmptyViewCells false
+	processOnlyValidViewCells false
+	
+	PostProcess {
+		# how much samples are used for post processing
+		samples 300000
+		renderCostWeight 1.0
+		maxCostRatio 0.1
+		minViewCells 1
+		avgCostMaxDeviation 0.8
+		maxMergesPerPass 500 
+		useRaysForMerge false
+		refine false
+		compress false
+		merge true
+	}
+
+	Visualization {
+		# how much samples we use for visualization
+		samples 100000
+		#colorCode PVS
+		#colorCode MergedLeaves
+		#colorCode MergedTreeDiff
+		colorCode Random
+		exportRays true
+		exportGeometry true
+		exportMergedViewCells false
+		useCuttingPlane false
+		cuttingPlaneAxis 1
+	}
+	
+#	filename ../data/atlanta/atlanta_viewcells_large.x3d
+#	filename ../data/vienna/viewcells-25-sel.x3d
+#	filename ../data/vienna/viewcells-25.x3d
+#	filename ../data/vienna/viewcells-large-sel.x3d
+#	filename ../scripts/viewcells_vienna.xml
+	filename ../scripts/viewcells_atlanta.xml
+}
+
+
+Simulation {
+	objRenderCost 1.0
+	vcOverhead 1.0
+	# always between 0 and 1
+	moveSpeed 0.0001
+}
+
+
+
+VspKdTree {
+	epsilon		1e-6
+
+	Construction {
+		samples 300000
+	}
+	
+	Termination {
+		maxDepth	 	40
+		minPvs			50
+		minRays			300
+		minSize			0.001
+		maxCostRatio		0.9
+		missTolerance		4
+		maxRayContribution 	0.5
+	}
+	
+	maxTotalMemory	100
+	maxStaticMemory	50
+
+	splitType 	regular
+	#splitType 	heuristics
+	splitUseOnlyDrivingAxis true
+	ct_div_ci	0.0
+	
+	# maximal cost for merging a view cell
+	PostProcess {
+		maxCostRatio 0.005
+		minViewCells 200
+		maxPvsSize   50000
+	}
+	
+	
+	Visualization {
+	}
+}
+
+
+
+VspBspTree {
+	Construction {
+		samples 1000000
+		epsilon 0.005
+		randomize false
+		renderCostWeight 1.0
+	}
+
+
+	# random polygon       = 1
+	# axis aligned         = 2
+	# least ray splits     = 256
+	# balanced rays        = 512
+	# pvs                  = 1024
+	
+	splitPlaneStrategy 1024
+	
+	# maximal candidates for split planes
+	maxPolyCandidates 0
+
+	
+	# maximal tested rays for split cost heuristics
+	maxTests 10000
+	
+	maxTotalMemory	50
+	maxStaticMemory	50
+	
+	# factors for evaluating split plane costs
+	Factor {
+		leastRaySplits 1.0
+	  	balancedRays 1.0
+	  	pvs 1.0
+	}
+	
+	Termination {
+		# parameters used for autopartition
+		minRays 		-150
+		minPolygons 		-1
+		maxDepth		30
+		minPvs 			-10
+		#minProbability		0.0001
+		minProbability 		-1
+#		maxRayContribution	0.3
+		maxRayContribution	2.3
+#		maxCostRatio		0.9
+		maxCostRatio		3.9
+		missTolerance		3
+
+		
+		maxViewCells		50000
+		
+		# used for pvs criterium
+		ct_div_ci 0.0
+		
+		AxisAligned {
+			minRays 		1
+			maxRayContribution	9.9
+		}
+	}
+	
+	splitUseOnlyDrivingAxis true
+	
+	Visualization {
+		# x3d visualization of the split planes
+		exportSplits true
+	}
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h	(revision 599)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h	(revision 599)
@@ -0,0 +1,183 @@
+#ifndef _Preprocessor_H__
+#define _Preprocessor_H__
+
+#include <string>
+using namespace std;
+#include "Containers.h"
+#include "Mesh.h"
+#include "KdTree.h"
+
+#include <QObject>
+
+class RenderSimulator;
+class SceneGraph;
+class Exporter;
+class ViewCellsManager;
+class BspTree;
+class VspKdTree;
+class VspBspTree;
+class RenderSimulator;
+struct VssRayContainer;
+
+class GlRendererBuffer;
+
+/** Namespace for the external visibility preprocessor
+
+    This namespace includes all classes which are created by the VUT (Vienna University
+    of Technology) for the External Visibility Preprocessor of the GTP (GameTools Project)
+    (www.gametools.org).
+*/
+  
+  /** Main class of the visibility preprocessor. Responsible for loading and
+      saving of the input and output files. Initiates construction of the kD-tree,
+      viewcell loading/generation and the visibility computation itself.
+  */
+class Preprocessor : public QObject {
+  Q_OBJECT
+
+public:
+	/** Default constructor initialising e.g., KD tree and BSP tree.
+	*/
+	Preprocessor();
+
+   virtual ~Preprocessor();
+
+  /** Load the input scene. 
+      @param filename file to load
+	@return true on success
+  */
+  virtual bool LoadScene(const string filename);
+  
+  /** Export all preprocessed data in a XML format understandable by the
+      PreprocessingInterface of the GtpVisibilityPreprocessor Module. The file can be compressed depending
+      on the environement settings.
+      @return true on successful export
+  */
+  virtual bool ExportPreprocessedData(const string filename);
+  
+  /** Build the KdTree of currently loaded occluders/occludees/viewcells. The construction
+      is driven by the environment settings, which also sais which of the three types of
+      entities should be used to drive the heuristical construction (only occluders by default)
+  */
+  virtual bool BuildKdTree();
+
+  /** Compute visibility method. This method has to be reimplemented by the actual
+      Preprocessor implementation (e.g. SamplingPreprocessor, ExactPreprocessor,
+      GlobalSamplingpreprocessor)
+    */
+  virtual bool ComputeVisibility() = 0;
+  
+  /** View cells are either loaded or prepared for generation, according to the chosen environment
+      object. Important evironment options are, e.g, the view cell type.
+      Should be done after scene loading (i.e., some options are based on scene type).
+  */
+  bool PrepareViewCells();
+  
+  bool
+  Export( const string filename,
+	  const bool scene,
+	  const bool kdtree,
+	  const bool bsptree
+	  );
+  
+  
+  virtual void KdTreeStatistics(ostream &s);
+  virtual void BspTreeStatistics(ostream &s);
+
+  /** Loads samples from file.
+	  @param samples returns the stored sample rays
+	  @param objects needed to associate the objects ids
+	  @returns true if samples were loaded successfully
+  */
+  bool LoadSamples(VssRayContainer &samples,
+				   ObjectContainer &objects) const;
+
+  /** Exports samples to file.
+	  @returns true if samples were written successfully
+  */
+  bool ExportSamples(const VssRayContainer &samples) const;
+
+  /** Get Sample rays of particular type, returns false if this
+	  type of rays is not supported by the preprocessor
+  */
+  enum {
+	OBJECT_BASED_DISTRIBUTION,
+	DIRECTION_BASED_DISTRIBUTION,
+	DIRECTION_BOX_BASED_DISTRIBUTION,
+	SPATIAL_BOX_BASED_DISTRIBUTION,
+	RSS_BASED_DISTRIBUTION,
+	RSS_SILHOUETTE_BASED_DISTRIBUTION,
+	VSS_BASED_DISTRIBUTION,
+	OBJECT_DIRECTION_BASED_DISTRIBUTION
+  };
+  
+  virtual bool
+  GenerateRays(
+			   const int number,
+			   const int raysType,
+			   SimpleRayContainer &rays
+			   );
+  
+  virtual void CastRays(SimpleRayContainer &rays,
+	  VssRayContainer &vssRays) {};
+
+  ViewCellsManager *CreateViewCellsManager(const char *name);
+
+  /// scene graph loaded from file
+  SceneGraph *mSceneGraph;
+
+  /// raw array of objects
+  ObjectContainer mObjects;
+  
+  /// kD-tree organizing the scene graph (occluders + occludees) + viewcells
+  KdTree *mKdTree;
+  
+  /// View space partition bsp tree
+  VspBspTree *mVspBspTree;
+  /// list of all loaded occluders
+  ObjectContainer mOccluders;
+  /// list of all loaded occludees
+  ObjectContainer mOccludees;
+   
+  /// BSP tree representing the viewcells
+  BspTree *mBspTree;
+
+  ViewCellsManager *mViewCellsManager;
+
+  /** Kd tree inducing a coarse partition of view space that are the building
+	  blocks for view cells.
+  */
+  VspKdTree *mVspKdTree;
+
+  bool mUseGlRenderer;
+  bool mUseGlDebugger;
+
+  bool mLoadViewCells;
+  
+  bool mDetectEmptyViewSpace;
+
+  bool mQuitOnFinish;
+protected:
+
+  /////////////////////////
+
+  /// samples used for construction of the BSP view cells tree.
+  int mBspConstructionSamples;
+   /// samples used for construction of the VSP KD tree.
+  int mVspKdConstructionSamples;
+  /** Simulates rendering of the scene.
+  */
+  RenderSimulator *mRenderSimulator;
+
+  GlRendererBuffer *renderer;
+  
+  signals:
+  void EvalPvsStat();
+
+};
+
+
+
+extern Preprocessor *preprocessor;
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Rectangle3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Rectangle3.h	(revision 245)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Rectangle3.h	(revision 245)
@@ -0,0 +1,66 @@
+#ifndef __RECTANGLE3_H
+#define __RECTANGLE3_H
+#include <iostream>
+using namespace std;
+#include "Vector3.h"
+
+/// rectangle vertices
+//   3 2
+//   0 1
+class Rectangle3 {
+public:
+  Vector3 mVertices[4];
+
+  Vector3 GetVertex(const int i) const { return mVertices[i]; }
+  Rectangle3() {}
+  
+  Rectangle3(const Vector3 &v0,
+	     const Vector3 &v1,
+	     const Vector3 &v2,
+	     const Vector3 &v3) {
+    mVertices[0] = v0;
+    mVertices[1] = v1;
+    mVertices[2] = v2;
+    mVertices[3] = v3;
+  }
+  
+  Vector3 GetNormal() const {
+    return Normalize(CrossProd(mVertices[0]-mVertices[1],
+			       mVertices[2]-mVertices[1]
+			       ));
+  }
+  
+  Vector3 GetCenter() const {
+    return (mVertices[0] + mVertices[1] + mVertices[2] + mVertices[3])/4.0f;
+  }
+
+  int DominantAxis() const {
+    if (SqrMagnitude(mVertices[0] - mVertices[1]) >  SqrMagnitude(mVertices[0] - mVertices[3]))
+      return 0;
+    else
+      return 1;
+  }
+      
+  float GetArea() const {
+    Vector3 v = CrossProd(mVertices[3], mVertices[0]);
+    
+    for (int i=0; i < 3; i++)
+      v += CrossProd(mVertices[i], mVertices[i+1]);
+    
+    return 0.5f*abs(DotProd(GetNormal(), v));
+  }
+  
+  void
+  Split(const int axis,
+	Rectangle3 &r1,
+	Rectangle3 &r2
+	) const;
+
+  friend ostream& operator<< (ostream &s, const Rectangle3 &r) {
+    return s<<"Rectangle3:"<<r.mVertices[0]<<r.mVertices[1]<<r.mVertices[2]<<r.mVertices[3];
+  }
+
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Triangle3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Triangle3.h	(revision 544)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Triangle3.h	(revision 544)
@@ -0,0 +1,48 @@
+#ifndef __TRIANGLE3_H
+#define __TRIANGLE3_H
+
+#include "Vector3.h"
+
+struct Triangle3 {
+  
+  Vector3 mVertices[3];
+  
+  Triangle3() {}
+  Triangle3(const Vector3 &a,
+		 const Vector3 &b,
+		 const Vector3 &c
+		 ) {
+    Init(a, b, c);
+  }
+
+  void
+  Init(const Vector3 &a,
+       const Vector3 &b,
+       const Vector3 &c
+       ) {
+    mVertices[0] = a;
+    mVertices[1] = b;
+    mVertices[2] = c;
+    
+  }
+
+  Vector3 GetNormal() const {
+    Vector3 v1=mVertices[0]-mVertices[1], v2=mVertices[2]-mVertices[1];
+    return Normalize(CrossProd(v2,v1));
+  }
+
+  Vector3 GetCenter() const {
+    return (mVertices[0] + mVertices[1] + mVertices[2])/3.0f;
+  }
+
+  float GetSpatialAngle(const Vector3 &point) const;
+
+  float GetArea() const {
+	  Vector3 v1=mVertices[0]-mVertices[1], v2=mVertices[2]-mVertices[1];
+	  return 0.5f * Magnitude(CrossProd(v2, v1));
+  }
+};
+
+
+#endif
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h	(revision 608)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h	(revision 608)
@@ -0,0 +1,319 @@
+#ifndef __RENDERER_H
+#define __RENDERER_H
+
+#include <QtOpenGL>
+#include <QWaitCondition>
+//#include <QGLPixelBuffer>
+
+#include "Vector3.h"
+#include "Containers.h"
+#include "Halton.h"
+#include "Renderer.h"
+#include "Beam.h"
+
+class SceneGraph;
+class ViewCellsManager;
+class Mesh;
+class MeshInstance;
+class Intersectable;
+class Material;
+class Beam;
+class KdTree;
+class QWidget;
+class GlRendererBuffer;
+class BeamSampleStatistics;
+
+struct VssRayContainer;
+
+struct PvsRenderStatistics {
+  
+  float maxError;
+  float sumError;
+  int frames;
+  int errorFreeFrames;
+
+  PvsRenderStatistics() { Reset(); }
+  
+  void Reset() {
+	maxError = 0.0f;
+	sumError = 0.0f;
+	frames = 0;
+	errorFreeFrames = 0;
+  }
+
+  float GetMaxError() { return maxError; }
+  float GetAvgError() { return sumError/frames; }
+  float GetErrorFreeFrames() { return errorFreeFrames/(float)frames; }
+  
+};
+
+
+/** Class encapsulating gl rendering for the scene.
+	There is no gl context binding so the binding is performed in the
+	derived classes
+*/
+
+class GlRenderer: public Renderer
+{
+
+public:
+  ObjectContainer mObjects;
+   
+  Vector3 mViewPoint;
+  Vector3 mViewDirection;
+
+  int timerId;
+  bool mUseFalseColors;
+
+  HaltonSequence halton;
+  
+  int mFrame;
+  bool mWireFrame;
+  
+bool mDetectEmptyViewSpace;
+  bool mSnapErrorFrames;
+  QString mSnapPrefix;
+
+  KdTree *mKdTree;
+
+  QWaitCondition mRenderingFinished;
+  
+  
+  GlRenderer(SceneGraph *sceneGraph,
+			 ViewCellsManager *viewcells,
+			 KdTree *tree);
+  
+  ~GlRenderer();
+
+
+  void SetupFalseColor(const int id);
+  void RenderIntersectable(Intersectable *);
+  void RenderViewCell(ViewCell *vc);
+  void RenderMeshInstance(MeshInstance *mi);
+  void RenderMesh(Mesh *m);
+  void SetupMaterial(Material *m);
+  virtual void SetupCamera();
+  
+  bool
+  RenderScene();
+
+
+  virtual void
+  SetupProjection(const int w, const int h);
+
+  
+  
+
+  void InitGL();
+
+  virtual int GetWidth() const = 0;
+  virtual int GetHeight() const = 0;
+
+  int GetId(int r, int g, int b) const;
+};
+
+
+class GlRendererBuffer : public QGLPixelBuffer, public GlRenderer
+{
+public:
+	GlRendererBuffer(const int w,
+					 const int h,
+					 SceneGraph *sceneGraph,
+					 ViewCellsManager *viewcells,
+					 KdTree *tree);
+
+  
+  void
+  EvalPvsStat();
+
+  void
+  ClearErrorBuffer();
+  
+
+  virtual int GetWidth() const { return width(); }
+  virtual int GetHeight() const { return height(); }
+
+
+  void RandomViewPoint();
+  void SampleBeamContributions(
+							   Intersectable *sourceObject,
+							   Beam &beam,
+							   const int samples,
+							   BeamSampleStatistics &stat
+							   );
+
+  void
+  SampleViewpointContributions(
+							   Intersectable *sourceObject,
+							   const Vector3 viewPoint,
+							   Beam &beam,
+							   const int desiredSamples,
+							   BeamSampleStatistics &stat
+							   );
+
+  void InitGL();
+
+  /** Computes rays from information gained with hw sampling-
+  */
+  void ComputeRays(Intersectable *sourceObj, VssRayContainer &rays);
+
+  int ComputePvs() const;
+
+  float
+  GetPixelError();
+
+  int ComputePvs(ObjectContainer &objects, ObjectContainer &pvs) const;
+
+  PvsRenderStatistics mPvsStat;
+   
+  int mPvsStatFrames;
+  vector<float> mPvsErrorBuffer;
+private:
+	
+	static void GenQueries(const int numQueries);
+	
+	void SetupProjectionForViewPoint(const Vector3 &viewPoint, 
+									 const Beam &beam, 
+									 Intersectable *sourceObject);
+};
+
+
+class RendererControlWidget : public QWidget
+{
+  Q_OBJECT
+public:
+  RendererControlWidget(QWidget * parent = 0, Qt::WFlags f = 0);
+
+  signals:
+  
+  SetViewCellGranularity(int);
+  SetSceneCut(int);
+  SetTopDistance(int);
+
+  SetShowViewCells(bool);
+  SetTopView(bool);
+  SetCutViewCells(bool);
+  SetCutScene(bool);
+
+};
+
+class GlRendererWidget : public QGLWidget, public GlRenderer
+{
+  Q_OBJECT
+public:
+
+  // point of the last mouse click used for movement in the scene
+  Vector3 mousePoint;
+
+  bool mTopView;
+  bool mRenderViewCells;
+  bool mCutViewCells;
+  bool mCutScene;
+  
+  Plane3 mSceneCutPlane;
+  float mTopDistance;
+  
+  GlRendererWidget(SceneGraph *sceneGraph,
+				   ViewCellsManager *viewcells,
+				   KdTree *tree,
+				   QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WFlags f = 0
+				   );
+
+
+  virtual void SetupCamera();
+
+  void initializeGL() {
+	InitGL();
+  }
+  void resizeGL(int w, int h);
+  void paintGL();
+  void timerEvent(QTimerEvent *) {
+	  update();
+  }
+
+  void mousePressEvent(QMouseEvent *);
+  void mouseReleaseEvent(QMouseEvent *);
+  void mouseMoveEvent(QMouseEvent *);
+
+  void keyPressEvent ( QKeyEvent * e ) ;
+  
+  float
+  RenderErrors();
+  void
+  RenderInfo();
+
+  virtual int GetWidth() const { return width(); }
+  virtual int GetHeight() const { return height(); }
+
+  virtual void
+  SetupProjection(const int w, const int h);
+
+  void
+  RenderViewCells();
+
+ public slots:
+ void
+ SetViewCellGranularity(int number);
+
+ void
+ SetSceneCut(int cut);
+
+ void
+ SetTopDistance(int dist);
+
+  void SetShowViewCells(bool b) {
+	mRenderViewCells = b;
+	updateGL();
+  }
+  
+  void SetTopView(bool b) {
+	mTopView = b;
+	updateGL();
+  }
+
+  void SetCutViewCells(bool b) {
+	mCutViewCells = b;
+	updateGL();
+  }
+  void SetCutScene(bool b) {
+	mCutScene = b;
+	updateGL();
+  }
+
+};
+
+
+extern GlRendererWidget *rendererWidget;
+
+class GlDebuggerWidget : public QGLWidget
+{
+	Q_OBJECT
+public:
+    GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent = NULL);
+    ~GlDebuggerWidget();
+    void initializeGL();
+    void resizeGL(int w, int h);
+    void paintGL();
+    void timerEvent(QTimerEvent *) { update(); }
+    void mousePressEvent(QMouseEvent *) { killTimer(timerId); }
+    void mouseReleaseEvent(QMouseEvent *) { timerId = startTimer(20); }
+
+    void initCommon();
+    void initPbuffer();
+
+  
+	 GlRendererBuffer *mRenderBuffer;
+
+	 Beam mBeam;
+	 int mSamples;
+	 Intersectable *mSourceObject;
+
+private:
+    GLuint dynamicTexture;
+    int timerId;
+};
+
+extern GlDebuggerWidget *debuggerWidget;
+
+#endif
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Material.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Material.cpp	(revision 608)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Material.cpp	(revision 608)
@@ -0,0 +1,24 @@
+#include "common.h"
+#include "Material.h"
+
+
+Material
+RandomMaterial()
+{
+  float a = 0.1f;
+  float b = 0.9f;
+
+  Material m;
+  m.mDiffuseColor = RandomColor(a, b);
+
+  return m;
+}
+
+
+RgbColor
+RandomColor(const float a, const float b)
+{
+  return RgbColor(a + Random(b),
+				  a + Random(b),
+				  a + Random(b));
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/MeshKdTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/MeshKdTree.h	(revision 177)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/MeshKdTree.h	(revision 177)
@@ -0,0 +1,270 @@
+#ifndef _MeshKdTree_H__
+#define _MeshKdTree_H__
+
+#include <functional>
+using namespace std;
+
+#include "Containers.h"
+#include "AxisAlignedBox3.h"
+#include "Ray.h"
+
+  
+class MeshKdNode;
+class MeshKdLeaf;
+class MeshKdInterior;
+  
+/** Abstract class for kd-tree node */
+class MeshKdNode {
+public:
+  MeshKdNode() {}
+  
+  /** Determines whether this node is a leaf or interior node
+      @return true if leaf
+  */
+  virtual bool IsLeaf() const = 0;
+  virtual ~MeshKdNode() {}
+};
+
+/** Implementation of the kd-tree interior node */
+class MeshKdInterior : public MeshKdNode {
+  
+public:
+  MeshKdInterior():MeshKdNode(),
+		   mBack(NULL), mFront(NULL) {}
+  
+  /** \sa KdNode::IsLeaf() */
+  virtual bool IsLeaf() const { return false; }
+
+  /** splitting axis */
+  int mAxis;
+  /** splitting position, absolute position within the bounding box of this node */
+  float mPosition;
+  
+  /** back node */
+  MeshKdNode *mBack;
+  /** front node */
+  MeshKdNode *mFront;
+
+  void SetupChildLinks(MeshKdNode *b, MeshKdNode *f) {
+    mBack = b;
+    mFront = f;
+  }
+  
+  void ReplaceChildLink(MeshKdNode *oldChild, MeshKdNode *newChild) {
+    if (mBack == oldChild)
+      mBack = newChild;
+    else
+      mFront = newChild;
+  }
+  
+  ~MeshKdInterior() {
+    delete mBack;
+    delete mFront;
+  }
+};
+  
+  
+/** Implementation of the kd-tree leaf node */
+class MeshKdLeaf : public MeshKdNode {
+public:
+  MeshKdLeaf():MeshKdNode() {
+  }
+
+  MeshKdLeaf(const vector<int> &faces):MeshKdNode() {
+    mFaces = faces;
+  }
+  
+  /** \sa KdNode::IsLeaf() */
+  virtual bool IsLeaf() const { return true; }
+  
+  /** indices of contained faces */
+  vector<int> mFaces;
+  
+};
+
+
+
+/** KdTree for indexing scene entities - occluders/occludees/viewcells */
+class MeshKdTree {
+  
+protected:
+  struct TraversalData
+  {  
+    MeshKdNode *mNode;
+    MeshKdInterior *mParent;
+    AxisAlignedBox3 mBox;
+    int mDepth;
+    float mPriority;
+    
+    TraversalData() {}
+    
+    TraversalData(MeshKdNode *n, const float p):
+      mNode(n), mPriority(p)
+    {}
+    
+    TraversalData(MeshKdNode *n,
+		  MeshKdInterior *p,
+		  const AxisAlignedBox3 &b,
+		  const int d):
+      mNode(n), mParent(p), mBox(b), mDepth(d) {}
+    
+    
+    bool operator<(
+		   const TraversalData &b) const {
+      MeshKdLeaf *leafa = (MeshKdLeaf *) mNode;
+      MeshKdLeaf *leafb = (MeshKdLeaf *) b.mNode;
+      return 
+	leafa->mFaces.size()*mBox.SurfaceArea()
+	<
+	leafb->mFaces.size()*b.mBox.SurfaceArea();
+    }
+    
+  };
+
+  
+
+public:
+
+  enum {SPLIT_OBJECT_MEDIAN,
+	SPLIT_SPATIAL_MEDIAN,
+	SPLIT_SAH};
+  
+
+  MeshKdTree(Mesh *mesh);
+  ~MeshKdTree() {
+    if (mSplitCandidates)
+      delete mSplitCandidates;
+    
+    if (mRoot)
+      delete mRoot;
+  }
+  
+  virtual bool Construct();
+
+  /** Check whether subdivision criteria are met for the given subtree.
+      If not subdivide the leafs of the subtree. The criteria are specified in
+      the environment as well as the subdivision method. By default surface area
+      heuristics is used.
+	
+      @param subtree root of the subtree
+
+      @return true if subdivision was performed, false if subdivision criteria
+      were already met
+  */
+  virtual MeshKdNode *Subdivide(const TraversalData &tdata);
+  
+  /** Get the root of the tree */
+  MeshKdNode *GetRoot() const {
+    return mRoot;
+  }
+  
+  AxisAlignedBox3 GetBox() const { return mMesh->mBox; }
+
+  int
+  CastRay(
+	  Ray &ray,
+	  MeshInstance *instance
+	  );
+
+
+protected:
+  
+  struct RayTraversalData {
+    MeshKdNode *mNode;
+    Vector3 mExitPoint;
+    float mMaxT;
+    
+    RayTraversalData() {}
+    RayTraversalData(MeshKdNode *n,
+		     const Vector3 &p,
+		     const float maxt):
+      mNode(n), mExitPoint(p), mMaxT(maxt) {}
+  };
+
+  // --------------------------------------------------------------
+  // For sorting objects
+  // --------------------------------------------------------------
+  struct  SortableEntry
+  {
+    enum {
+      FACE_MIN,
+      FACE_MAX
+    };
+    
+    int type;
+    float value;
+    int face;
+    
+    SortableEntry() {}
+    SortableEntry(const int t, const float v, const int f):type(t),
+							   value(v),
+							   face(f) {}
+    
+    bool operator<(const SortableEntry &b) const {
+      return value < b.value;
+    }
+    
+  };
+  
+
+  float
+  BestCostRatio(
+		MeshKdLeaf *node,
+		const AxisAlignedBox3 &box,
+		const int axis,
+		float &position,
+		int &objectsBack,
+		int &objectsFront
+		);
+
+  void
+  SortSplitCandidates(
+		      MeshKdLeaf *node,
+		      const int axis
+		      );
+
+  MeshKdNode *
+  SubdivideNode(
+		MeshKdLeaf *leaf,
+		MeshKdInterior *parent,
+		const AxisAlignedBox3 &box,
+		const int depth,
+		AxisAlignedBox3 &backBBox,
+		AxisAlignedBox3 &frontBBox
+		);
+
+  bool
+  TerminationCriteriaMet(const MeshKdLeaf *leaf, const int depth);
+  
+  int
+  SelectPlane(MeshKdLeaf *leaf,
+	      const AxisAlignedBox3 &box,
+	      float &position
+	      );
+
+  /// pointer to the mesh owning the tree
+  Mesh *mMesh;
+  
+  /// root of the tree
+  MeshKdNode *mRoot;
+  
+  /// reusable array of split candidates
+  vector<SortableEntry> *mSplitCandidates;
+
+public:
+  static void ParseEnvironment();
+  static float mSplitBorder;
+  static int mTermMaxDepth;
+  static int mTermMinCost;
+  static float mMaxCostRatio;
+  static float mCt_div_ci;
+  static int mSplitMethod;
+
+};
+  
+
+
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Matrix4x4.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Matrix4x4.cpp	(revision 245)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Matrix4x4.cpp	(revision 245)
@@ -0,0 +1,647 @@
+#include "Matrix4x4.h"
+#include "Vector3.h"
+
+// standard headers
+#include <iomanip>
+using namespace std;
+
+
+Matrix4x4::Matrix4x4(const Vector3 &a, const Vector3 &b, const Vector3 &c)
+{
+  // first index is column [x], the second is row [y]
+  x[0][0] = a.x;
+  x[1][0] = b.x;
+  x[2][0] = c.x;
+  x[3][0] = 0.0f;
+
+  x[0][1] = a.y;
+  x[1][1] = b.y;
+  x[2][1] = c.y;
+  x[3][1] = 0.0f;
+
+  x[0][2] = a.z;
+  x[1][2] = b.z;
+  x[2][2] = c.z;
+  x[3][2] = 0.0f;
+
+  x[0][3] = 0.0f;
+  x[1][3] = 0.0f;
+  x[2][3] = 0.0f;
+  x[3][3] = 1.0f;
+
+}
+
+void
+Matrix4x4::SetColumns(const Vector3 &a, const Vector3 &b, const Vector3 &c)
+{
+  // first index is column [x], the second is row [y]
+  x[0][0] = a.x;
+  x[1][0] = a.y;
+  x[2][0] = a.z;
+  x[3][0] = 0.0f;
+
+  x[0][1] = b.x;
+  x[1][1] = b.y;
+  x[2][1] = b.z;
+  x[3][1] = 0.0f;
+
+  x[0][2] = c.x;
+  x[1][2] = c.y;
+  x[2][2] = c.z;
+  x[3][2] = 0.0f;
+
+  x[0][3] = 0.0f;
+  x[1][3] = 0.0f;
+  x[2][3] = 0.0f;
+  x[3][3] = 1.0f;
+}
+
+// full constructor
+Matrix4x4::Matrix4x4(float x11, float x12, float x13, float x14,
+		     float x21, float x22, float x23, float x24,
+		     float x31, float x32, float x33, float x34,
+		     float x41, float x42, float x43, float x44)
+{
+  // first index is column [x], the second is row [y]
+  x[0][0] = x11;
+  x[1][0] = x12;
+  x[2][0] = x13;
+  x[3][0] = x14;
+
+  x[0][1] = x21;
+  x[1][1] = x22;
+  x[2][1] = x23;
+  x[3][1] = x24;
+
+  x[0][2] = x31;
+  x[1][2] = x32;
+  x[2][2] = x33;
+  x[3][2] = x34;
+
+  x[0][3] = x41;
+  x[1][3] = x42;
+  x[2][3] = x43;
+  x[3][3] = x44;
+}
+
+// inverse matrix computation gauss_jacobiho method .. from N.R. in C
+// if matrix is regular = computatation successfull = returns 0
+// in case of singular matrix returns 1
+int
+Matrix4x4::Invert()
+{
+  int indxc[4],indxr[4],ipiv[4];
+  int i,icol,irow,j,k,l,ll,n;
+  float big,dum,pivinv,temp;
+  // satisfy the compiler
+  icol = irow = 0;
+
+  // the size of the matrix
+  n = 4;
+
+  for ( j = 0 ; j < n ; j++) /* zero pivots */
+    ipiv[j] = 0;
+
+  for ( i = 0; i < n; i++)
+  {
+    big = 0.0;
+    for (j = 0 ; j < n ; j++)
+      if (ipiv[j] != 1)
+        for ( k = 0 ; k<n ; k++)
+        {
+          if (ipiv[k] == 0)
+	  {
+	    if (fabs(x[k][j]) >= big)
+            {
+	      big = fabs(x[k][j]);
+              irow = j;
+              icol = k;
+            }
+          }
+          else
+            if (ipiv[k] > 1)
+	      return 1; /* singular matrix */
+        }
+    ++(ipiv[icol]);
+    if (irow != icol)
+    {
+      for ( l = 0 ; l<n ; l++)
+      {
+        temp = x[l][icol];
+        x[l][icol] = x[l][irow];
+        x[l][irow] = temp;
+      }
+    }
+    indxr[i] = irow;
+    indxc[i] = icol;
+    if (x[icol][icol] == 0.0)
+      return 1; /* singular matrix */
+
+    pivinv = 1.0 / x[icol][icol];
+    x[icol][icol] = 1.0 ;
+    for ( l = 0 ; l<n ; l++)
+      x[l][icol] = x[l][icol] * pivinv ;
+    
+    for (ll = 0 ; ll < n ; ll++)
+      if (ll != icol)
+      {
+        dum = x[icol][ll];
+	x[icol][ll] = 0.0;
+        for ( l = 0 ; l<n ; l++)
+	  x[l][ll] = x[l][ll] - x[l][icol] * dum ;
+      }
+  }
+  for ( l = n; l--; )
+  {
+    if (indxr[l] != indxc[l])
+      for ( k = 0; k<n ; k++)
+      {
+        temp = x[indxr[l]][k];
+	x[indxr[l]][k] = x[indxc[l]][k];
+	x[indxc[l]][k] = temp;
+      }
+  }
+
+  return 0 ; // matrix is regular .. inversion has been succesfull
+}
+
+// Invert the given matrix using the above inversion routine.
+Matrix4x4
+Invert(const Matrix4x4& M)
+{
+  Matrix4x4 InvertMe = M;
+  InvertMe.Invert();
+  return InvertMe;
+}
+
+
+// Transpose the matrix.
+void
+Matrix4x4::Transpose()
+{
+  for (int i = 0; i < 4; i++)
+    for (int j = i; j < 4; j++)
+      if (i != j) {
+	float temp = x[i][j];
+	x[i][j] = x[j][i];
+	x[j][i] = temp;
+      }
+}
+
+// Transpose the given matrix using the transpose routine above.
+Matrix4x4
+Transpose(const Matrix4x4& M)
+{
+  Matrix4x4 TransposeMe = M;
+  TransposeMe.Transpose();
+  return TransposeMe;
+}
+
+// Construct an identity matrix.
+Matrix4x4
+IdentityMatrix()
+{
+  Matrix4x4 M;
+
+  for (int i = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++)
+      M.x[i][j] = (i == j) ? 1.0 : 0.0;
+  return M;
+}
+
+// Construct a zero matrix.
+Matrix4x4
+ZeroMatrix()
+{
+  Matrix4x4 M;
+  for (int i = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++)
+      M.x[i][j] = 0;
+  return M;
+}
+
+// Construct a translation matrix given the location to translate to.
+Matrix4x4
+TranslationMatrix(const Vector3& Location)
+{
+  Matrix4x4 M = IdentityMatrix();
+  M.x[3][0] = Location.x;
+  M.x[3][1] = Location.y;
+  M.x[3][2] = Location.z;
+  return M;
+}
+
+// Construct a rotation matrix.  Rotates Angle radians about the
+// X axis.
+Matrix4x4
+RotationXMatrix(float Angle)
+{
+  Matrix4x4 M = IdentityMatrix();
+  float Cosine = cos(Angle);
+  float Sine = sin(Angle);
+  M.x[1][1] = Cosine;
+  M.x[2][1] = -Sine;
+  M.x[1][2] = Sine;
+  M.x[2][2] = Cosine;
+  return M;
+}
+
+// Construct a rotation matrix.  Rotates Angle radians about the
+// Y axis.
+Matrix4x4
+RotationYMatrix(float Angle)
+{
+  Matrix4x4 M = IdentityMatrix();
+  float Cosine = cos(Angle);
+  float Sine = sin(Angle);
+  M.x[0][0] = Cosine;
+  M.x[2][0] = -Sine;
+  M.x[0][2] = Sine;
+  M.x[2][2] = Cosine;
+  return M;
+}
+
+// Construct a rotation matrix.  Rotates Angle radians about the
+// Z axis.
+Matrix4x4
+RotationZMatrix(float Angle)
+{
+  Matrix4x4 M = IdentityMatrix();
+  float Cosine = cos(Angle);
+  float Sine = sin(Angle);
+  M.x[0][0] = Cosine;
+  M.x[1][0] = -Sine;
+  M.x[0][1] = Sine;
+  M.x[1][1] = Cosine;
+  return M;
+}
+
+// Construct a yaw-pitch-roll rotation matrix.	Rotate Yaw
+// radians about the XY axis, rotate Pitch radians in the
+// plane defined by the Yaw rotation, and rotate Roll radians
+// about the axis defined by the previous two angles.
+Matrix4x4
+RotationYPRMatrix(float Yaw, float Pitch, float Roll)
+{
+  Matrix4x4 M;
+  float ch = cos(Yaw);
+  float sh = sin(Yaw);
+  float cp = cos(Pitch);
+  float sp = sin(Pitch);
+  float cr = cos(Roll);
+  float sr = sin(Roll);
+
+  M.x[0][0] = ch * cr + sh * sp * sr;
+  M.x[1][0] = -ch * sr + sh * sp * cr;
+  M.x[2][0] = sh * cp;
+  M.x[0][1] = sr * cp;
+  M.x[1][1] = cr * cp;
+  M.x[2][1] = -sp;
+  M.x[0][2] = -sh * cr - ch * sp * sr;
+  M.x[1][2] = sr * sh + ch * sp * cr;
+  M.x[2][2] = ch * cp;
+  for (int i = 0; i < 4; i++)
+    M.x[3][i] = M.x[i][3] = 0;
+  M.x[3][3] = 1;
+
+  return M;
+}
+
+// Construct a rotation of a given angle about a given axis.
+// Derived from Eric Haines's SPD (Standard Procedural 
+// Database).
+Matrix4x4
+RotationAxisMatrix(const Vector3& axis, float angle)
+{
+  Matrix4x4 M;
+  double cosine = cos(angle);
+  double sine = sin(angle);
+  double one_minus_cosine = 1 - cosine;
+
+  M.x[0][0] = axis.x * axis.x + (1.0 - axis.x * axis.x) * cosine;
+  M.x[0][1] = axis.x * axis.y * one_minus_cosine + axis.z * sine;
+  M.x[0][2] = axis.x * axis.z * one_minus_cosine - axis.y * sine;
+  M.x[0][3] = 0;
+
+  M.x[1][0] = axis.x * axis.y * one_minus_cosine - axis.z * sine;
+  M.x[1][1] = axis.y * axis.y + (1.0 - axis.y * axis.y) * cosine;
+  M.x[1][2] = axis.y * axis.z * one_minus_cosine + axis.x * sine;
+  M.x[1][3] = 0;
+
+  M.x[2][0] = axis.x * axis.z * one_minus_cosine + axis.y * sine;
+  M.x[2][1] = axis.y * axis.z * one_minus_cosine - axis.x * sine;
+  M.x[2][2] = axis.z * axis.z + (1.0 - axis.z * axis.z) * cosine;
+  M.x[2][3] = 0;
+
+  M.x[3][0] = 0;
+  M.x[3][1] = 0;
+  M.x[3][2] = 0;
+  M.x[3][3] = 1;
+
+  return M;
+}
+
+
+// Constructs the rotation matrix that rotates 'vec1' to 'vec2'
+Matrix4x4
+RotationVectorsMatrix(const Vector3 &vecStart,
+		      const Vector3 &vecTo)
+{
+  Vector3 vec = CrossProd(vecStart, vecTo);
+  
+  if (Magnitude(vec) > Limits::Small) {
+    // vector exist, compute angle
+    float angle = acos(DotProd(vecStart, vecTo));
+    // normalize for sure
+    vec.Normalize();
+    return RotationAxisMatrix(vec, angle);
+  }
+
+  // opposite or colinear vectors
+  Matrix4x4 ret = IdentityMatrix();
+  if (DotProd(vecStart, vecTo) < 0.0)
+    ret *= -1.0; // opposite vectors
+
+  return ret;
+}
+
+
+// Construct a scale matrix given the X, Y, and Z parameters
+// to scale by.  To scale uniformly, let X==Y==Z.
+Matrix4x4
+ScaleMatrix(float X, float Y, float Z)
+{
+  Matrix4x4 M = IdentityMatrix();
+
+  M.x[0][0] = X;
+  M.x[1][1] = Y;
+  M.x[2][2] = Z;
+
+  return M;
+}
+
+// Construct a rotation matrix that makes the x, y, z axes
+// correspond to the vectors given.
+Matrix4x4
+GenRotation(const Vector3 &x, const Vector3 &y, const Vector3 &z)
+{
+  Matrix4x4 M = IdentityMatrix();
+
+#if 1
+  //  x  y
+  M.x[0][0] = x.x;
+  M.x[1][0] = x.y;
+  M.x[2][0] = x.z;
+
+  M.x[0][1] = y.x;
+  M.x[1][1] = y.y;
+  M.x[2][1] = y.z;
+
+  M.x[0][2] = z.x;
+  M.x[1][2] = z.y;
+  M.x[2][2] = z.z;
+#else
+  //  x  y -- old version
+  M.x[0][0] = x.x;
+  M.x[0][1] = x.y;
+  M.x[0][2] = x.z;
+
+  M.x[1][0] = y.x;
+  M.x[1][1] = y.y;
+  M.x[1][2] = y.z;
+
+  M.x[2][0] = z.x;
+  M.x[2][1] = z.y;
+  M.x[2][2] = z.z;
+#endif
+
+  return M;
+}
+
+// Construct a quadric matrix.	After Foley et al. pp. 528-529.
+Matrix4x4
+QuadricMatrix(float a, float b, float c, float d, float e,
+	      float f, float g, float h, float j, float k)
+{
+  Matrix4x4 M;
+
+  M.x[0][0] = a;  M.x[0][1] = d;  M.x[0][2] = f;  M.x[0][3] = g;
+  M.x[1][0] = d;  M.x[1][1] = b;  M.x[1][2] = e;  M.x[1][3] = h;
+  M.x[2][0] = f;  M.x[2][1] = e;  M.x[2][2] = c;  M.x[2][3] = j;
+  M.x[3][0] = g;  M.x[3][1] = h;  M.x[3][2] = j;  M.x[3][3] = k;
+
+  return M;
+}
+
+// Construct various "mirror" matrices, which flip coordinate
+// signs in the various axes specified.
+Matrix4x4
+MirrorX()
+{
+  Matrix4x4 M = IdentityMatrix();
+  M.x[0][0] = -1;
+  return M;
+}
+
+Matrix4x4
+MirrorY()
+{
+  Matrix4x4 M = IdentityMatrix();
+  M.x[1][1] = -1;
+  return M;
+}
+
+Matrix4x4
+MirrorZ()
+{
+  Matrix4x4 M = IdentityMatrix();
+  M.x[2][2] = -1;
+  return M;
+}
+
+Matrix4x4
+RotationOnly(const Matrix4x4& x)
+{
+  Matrix4x4 M = x;
+  M.x[3][0] = M.x[3][1] = M.x[3][2] = 0;
+  return M;
+}
+
+// Add corresponding elements of the two matrices.
+Matrix4x4&
+Matrix4x4::operator+= (const Matrix4x4& A)
+{
+  for (int i = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++)
+      x[i][j] += A.x[i][j];
+  return *this;
+}
+
+// Subtract corresponding elements of the matrices.
+Matrix4x4&
+Matrix4x4::operator-= (const Matrix4x4& A)
+{
+  for (int i = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++)
+      x[i][j] -= A.x[i][j];
+  return *this;
+}
+
+// Scale each element of the matrix by A.
+Matrix4x4&
+Matrix4x4::operator*= (float A)
+{
+  for (int i = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++)
+      x[i][j] *= A;
+  return *this;
+}
+
+// Multiply two matrices.
+Matrix4x4&
+Matrix4x4::operator*= (const Matrix4x4& A)
+{
+  Matrix4x4 ret = *this;
+
+  for (int i = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++) {
+      float subt = 0;
+      for (int k = 0; k < 4; k++)
+	subt += ret.x[i][k] * A.x[k][j];
+      x[i][j] = subt;
+    }
+  return *this;
+}
+
+// Add corresponding elements of the matrices.
+Matrix4x4
+operator+ (const Matrix4x4& A, const Matrix4x4& B)
+{
+  Matrix4x4 ret;
+
+  for (int i = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++)
+      ret.x[i][j] = A.x[i][j] + B.x[i][j];
+  return ret;
+}
+
+// Subtract corresponding elements of the matrices.
+Matrix4x4
+operator- (const Matrix4x4& A, const Matrix4x4& B)
+{
+  Matrix4x4 ret;
+
+  for (int i = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++)
+      ret.x[i][j] = A.x[i][j] - B.x[i][j];
+  return ret;
+}
+
+// Multiply matrices.
+Matrix4x4
+operator* (const Matrix4x4& A, const Matrix4x4& B)
+{
+  Matrix4x4 ret;
+
+  for (int i = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++) {
+      float subt = 0;
+      for (int k = 0; k < 4; k++)
+	subt += A.x[i][k] * B.x[k][j];
+      ret.x[i][j] = subt;
+    }
+  return ret;
+}
+
+// Transform a vector by a matrix.
+Vector3
+operator* (const Matrix4x4& M, const Vector3& v)
+{
+  Vector3 ret;
+  float denom;
+
+  ret.x = v.x * M.x[0][0] + v.y * M.x[1][0] + v.z * M.x[2][0] + M.x[3][0];
+  ret.y = v.x * M.x[0][1] + v.y * M.x[1][1] + v.z * M.x[2][1] + M.x[3][1];
+  ret.z = v.x * M.x[0][2] + v.y * M.x[1][2] + v.z * M.x[2][2] + M.x[3][2];
+  denom = M.x[0][3] + M.x[1][3] + M.x[2][3] + M.x[3][3];
+  if (denom != 1.0)
+    ret /= denom;
+  return ret;
+}
+
+// Apply the rotation portion of a matrix to a vector.
+Vector3
+RotateOnly(const Matrix4x4& M, const Vector3& v)
+{
+  Vector3 ret;
+  float denom;
+
+  ret.x = v.x * M.x[0][0] + v.y * M.x[1][0] + v.z * M.x[2][0];
+  ret.y = v.x * M.x[0][1] + v.y * M.x[1][1] + v.z * M.x[2][1];
+  ret.z = v.x * M.x[0][2] + v.y * M.x[1][2] + v.z * M.x[2][2];
+  denom = M.x[0][3] + M.x[1][3] + M.x[2][3] + M.x[3][3];
+  if (denom != 1.0)
+    ret /= denom;
+  return ret;
+}
+
+// Scale each element of the matrix by B.
+Matrix4x4
+operator* (const Matrix4x4& A, float B)
+{
+  Matrix4x4 ret;
+
+  for (int i = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++)
+      ret.x[i][j] = A.x[i][j] * B;
+  return ret;
+}
+
+// Overloaded << for C++-style output.
+ostream&
+operator<< (ostream& s, const Matrix4x4& M)
+{
+  for (int i = 0; i < 4; i++) { // y
+    for (int j = 0; j < 4; j++) { // x
+                                          //  x  y 
+      s << setprecision(4) << setw(10) << M.x[j][i];
+    }
+    s << '\n';
+  }
+  return s;
+}
+
+// Rotate a direction vector...
+Vector3
+PlaneRotate(const Matrix4x4& tform, const Vector3& p)
+{
+  // I sure hope that matrix is invertible...
+  Matrix4x4 use = Transpose(Invert(tform));
+
+  return RotateOnly(use, p);
+}
+
+// Transform a normal
+Vector3
+TransformNormal(const Matrix4x4& tform, const Vector3& n)
+{
+  Matrix4x4 use = NormalTransformMatrix(tform);
+
+  return RotateOnly(use, n);
+}
+ 
+Matrix4x4 
+NormalTransformMatrix(const Matrix4x4 &tform)
+{
+  Matrix4x4 m = tform;
+  // for normal translation vector must be zero!
+  m.x[3][0] = m.x[3][1] = m.x[3][2] = 0.0; 
+  // I sure hope that matrix is invertible...
+  return Transpose(Invert(m));
+}
+
+Vector3
+GetTranslation(const Matrix4x4 &M)
+{
+  return Vector3(M.x[3][0], M.x[3][1], M.x[3][2]);
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro	(revision 563)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro	(revision 563)
@@ -0,0 +1,47 @@
+TEMPLATE = app
+
+TARGET = preprocessor
+
+#win32:INCLUDEPATH += c:/STLport-4.6.2/stlport
+win32:INCLUDEPATH += "d:/Programs/NVIDIA Corporation/Cg/include"
+
+unix:INCLUDEPATH += ../support/src/xerces-c-src_2_7_0/include
+
+INCLUDEPATH += ../src  ../support/xerces/include  ../support/zlib/include ../support/boost ../support/devil/include
+
+
+win32:LIBPATH += ../support/xerces/lib ../support/devil/lib "d:/Programs/NVIDIA Corporation/Cg/lib"
+unix:LIBPATH += ../support/src/xerces-c-src_2_7_0/lib ../support/devil/lib /usr/lib/qt3/lib64
+
+#win32:LIBPATH += c:/STLport-4.6.2/lib
+
+# debuc config
+CONFIG		+= console warn_off thread release qt
+
+# RELEASE CONFIG
+#CONFIG		+= windows warn_on thread release
+
+# DEPENDPATH	= ../../include
+
+QT += opengl
+
+win32:LIBS += xerces-c_2.lib devil.lib ilu.lib ilut.lib cg.lib cgGL.lib
+unix:LIBS += -lxerces-c -lIL -lILU -lILUT
+
+# Input
+HEADERS += Halton.h VssRay.h VssPreprocessor.h RssTree.h GlRenderer.h \
+PreprocessorThread.h Preprocessor.h Beam.h
+
+
+SOURCES += \
+Preprocessor.cpp SamplingPreprocessor.cpp ExactPreprocessor.cpp \
+KdTree.cpp Environment.cpp gzstream.cpp common.cpp \
+UnigraphicsParser.cpp X3dExporter.cpp SceneGraph.cpp Material.cpp \
+Matrix4x4.cpp Vector3.cpp AxisAlignedBox3.cpp Ray.cpp main.cpp Mesh.cpp \
+Exporter.cpp Camera.cpp X3dParser.cpp MeshKdTree.cpp Pvs.cpp \
+MutualVisibility.cpp Triangle3.cpp Rectangle3.cpp Plane3.cpp Polygon3.cpp \
+ViewCell.cpp ViewCellBsp.cpp Halton.cpp VssRay.cpp VssTree.cpp VssPreprocessor.cpp \
+RenderSimulator.cpp VspKdTree.cpp RayInfo.cpp RssTree.cpp RssPreprocessor.cpp \
+ViewCellsManager.cpp VspBspTree.cpp GlRenderer.cpp \
+PreprocessorThread.cpp Renderer.cpp Beam.cpp ViewCellsParser.cpp Tetrahedron3.cpp
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Renderer.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Renderer.cpp	(revision 497)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Renderer.cpp	(revision 497)
@@ -0,0 +1,21 @@
+#include "Renderer.h"
+
+
+Renderer::Renderer():
+mViewCellsManager(NULL)
+{
+}
+
+Renderer::Renderer(SceneGraph *sceneGraph, ViewCellsManager *vcm):
+mSceneGraph(sceneGraph), mViewCellsManager(vcm)
+{
+}
+
+Renderer::~Renderer()
+{}
+
+void Renderer::SetViewCellsManager(ViewCellsManager *vcm)
+{
+	mViewCellsManager = vcm;
+}
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RayInfo.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RayInfo.cpp	(revision 508)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RayInfo.cpp	(revision 508)
@@ -0,0 +1,163 @@
+#include "RayInfo.h"
+#include "Ray.h"
+#include "VssRay.h"
+#include "Plane3.h"
+
+RayInfo::RayInfo(): mRay(NULL), mMinT(0),
+#if USE_FIXEDPOINT_T
+#define FIXEDPOINT_ONE 0x7FFE
+	// mMaxT(0xFFFF)
+	mMaxT(FIXEDPOINT_ONE)
+#else
+	mMaxT(1.0f)
+#endif
+{}
+		
+RayInfo::RayInfo(VssRay *r):mRay(r), mMinT(0),
+#if USE_FIXEDPOINT_T
+#define FIXEDPOINT_ONE 0x7FFE
+	// mMaxT(0xFFFF)
+	mMaxT(FIXEDPOINT_ONE)
+#else
+	mMaxT(1.0f)
+#endif
+{}
+		
+RayInfo::RayInfo(VssRay *r,	const float _min, const float _max):
+mRay(r) 
+{
+	SetMinT(_min);
+	SetMaxT(_max);
+}
+		
+RayInfo::RayInfo(VssRay *r, const short _min, const float _max):
+mRay(r), mMinT(_min) 
+{
+	SetMaxT(_max);
+}
+		
+RayInfo::RayInfo(VssRay *r,	const float _min, const short _max): 
+mRay(r), mMaxT(_max) 
+{
+	SetMinT(_min);
+}
+		
+float RayInfo::ExtrapOrigin(const int axis) const 
+{
+	return mRay->GetOrigin(axis) + GetMinT() * mRay->GetDir(axis);
+}
+		
+float RayInfo::ExtrapTermination(const int axis) const 
+{
+	return mRay->GetOrigin(axis) + GetMaxT() * mRay->GetDir(axis);
+}
+
+Vector3 RayInfo::ExtrapOrigin() const 
+{
+	return mRay->GetOrigin() + GetMinT() * mRay->GetDir();
+}
+		
+Vector3 RayInfo::ExtrapTermination() const 
+{
+	return mRay->GetOrigin() + GetMaxT() * mRay->GetDir();
+}
+
+#if USE_FIXEDPOINT_T
+	float RayInfo::GetMinT () const 
+	{ 
+		return mMinT/(float)(FIXEDPOINT_ONE); 
+	}
+
+	float RayInfo::GetMaxT() const 
+	{ 
+		return mMaxT / (float)(FIXEDPOINT_ONE); 
+	}
+		
+	void RayInfo::SetMinT (const float t) 
+	{
+		mMinT = (short) (t * (float)(FIXEDPOINT_ONE));
+	}
+		
+	void RayInfo::SetMaxT (const float t) 
+	{
+		mMaxT = (short) (t*(float)(FIXEDPOINT_ONE));
+		++ mMaxT;
+		//      if (mMaxT!=0xFFFF)
+		//	mMaxT++;
+	}
+#else
+	float RayInfo::GetMinT () const 
+	{ 
+		return mMinT; 
+	}
+	
+	float RayInfo::GetMaxT () const 
+	{ 
+		return mMaxT; 
+	}
+		
+	void RayInfo::SetMinT (const float t) 
+	{ 
+		mMinT = t; 
+	}
+	
+	void RayInfo::SetMaxT (const float t) 
+	{ 
+		mMaxT = t; 
+	}
+	
+#endif 
+
+int RayInfo::ComputeRayIntersection(const int axis, const float position, float &t) const
+{		
+	// intersect the ray with the plane
+	const float denom = mRay->GetDir(axis);
+
+	if (fabs(denom) < 1e-20)
+		//if (denom == 0.0f)
+		return (mRay->GetOrigin(axis) > position) ? 1 : -1;
+
+	t = (position - mRay->GetOrigin(axis)) / denom;
+
+	if (t < GetMinT())
+		return (denom > 0) ? 1 : -1;
+
+	if (t > GetMaxT())
+		return (denom > 0) ? -1 : 1;
+
+	return 0;
+}
+
+
+int RayInfo::ComputeRayIntersection(const Plane3 &splitPlane, float &t) const
+{	
+	t = splitPlane.FindT(mRay->GetOrigin(), mRay->GetTermination());
+//	Debug << "t: " << t << " mint " << GetMinT() << " maxt " << GetMaxT() << 
+//	" orig: " << mRay->GetOrigin() << " term " << mRay->GetTermination() << endl;
+
+	// NOTE: if plane equals end point of ray, the ray should be classified
+	// non-intersecting, otherwise polygon-plane intersections of bsp tree
+	// approaches are not eliminating any rays intersecting the polygon!
+#if 1
+	if (t >= GetMaxT() - 1e-20)
+		return splitPlane.Side(ExtrapOrigin());
+	if (t <= GetMinT() + 1e-20)
+		return splitPlane.Side(ExtrapTermination());
+#else
+	if (t > GetMaxT())
+		return splitPlane.Side(ExtrapOrigin());
+	else if (t < GetMinT())
+		return splitPlane.Side(ExtrapTermination());
+#endif
+	return 0;
+}
+
+float RayInfo::SegmentLength() const
+{
+	return Distance(ExtrapOrigin(), ExtrapTermination());
+}
+
+float RayInfo::SqrSegmentLength() const
+{
+	return SqrDistance(ExtrapOrigin(), ExtrapTermination());
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp	(revision 469)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp	(revision 469)
@@ -0,0 +1,8 @@
+#include <iostream>
+#include "Pvs.h"
+
+int
+KdPvs::Compress()
+{
+	return 0; // TODO
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Polygon3.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Polygon3.cpp	(revision 574)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Polygon3.cpp	(revision 574)
@@ -0,0 +1,567 @@
+#include "Polygon3.h"
+#include "Mesh.h"
+#include "AxisAlignedBox3.h"
+#include "Ray.h"
+#include "Triangle3.h"
+
+Polygon3::Polygon3(): 
+mMaterial(NULL), mParent(NULL), mPiercingRays(0)
+{
+	// mostly there will be triangles
+	//mVertices.reserve(3);
+}
+
+Polygon3::Polygon3(const VertexContainer &vertices): 
+mMaterial(NULL), mParent(NULL), mPiercingRays(0)
+{
+	mVertices.reserve(vertices.size());
+	mVertices = vertices;
+}
+
+
+Polygon3::Polygon3(MeshInstance *parent): 
+mMaterial(NULL), mParent(parent), mPiercingRays(0)
+{}
+
+
+Polygon3::Polygon3(Face *face, Mesh *parentMesh):
+mMaterial(NULL), mParent(NULL), mPiercingRays(0)
+{	
+	mVertices.reserve(face->mVertexIndices.size());
+	
+	VertexIndexContainer::iterator it = face->mVertexIndices.begin();
+	for (; it != face->mVertexIndices.end();  ++it)
+	{
+		mVertices.push_back(parentMesh->mVertices[*it]);
+	}
+
+	mMaterial = parentMesh->mMaterial;
+}
+
+
+Plane3 Polygon3::GetSupportingPlane() const
+{
+	return Plane3(mVertices[0], mVertices[1], mVertices[2]);
+}
+
+
+Vector3 Polygon3::GetNormal() const 
+{
+    return Normalize(CrossProd(mVertices[2] - mVertices[1],
+							   mVertices[0] - mVertices[1]));
+}
+
+void Polygon3::Split(const Plane3 &partition, 
+					 Polygon3 &front, 
+					 Polygon3 &back,
+					 const float epsilon)
+{
+	Vector3 ptA = mVertices.back();
+	
+	int sideA = partition.Side(ptA, epsilon);
+	
+	VertexContainer::const_iterator it;
+	
+	Vector3 lastSplit;
+
+	bool foundSplit = false;
+
+	//-- find line - plane intersections
+	for (it = mVertices.begin(); it != mVertices.end(); ++ it)
+	{
+		Vector3 ptB = *it;
+		int sideB = partition.Side(ptB, epsilon);
+	
+		// vertices on different sides => split
+	    if (sideB > 0)
+		{
+			if (sideA < 0)
+			{
+				//-- plane - line intersection
+				Vector3 splitPt = partition.FindIntersection(ptA, ptB);
+			
+				// test if split point not too close to previous split point
+				if (!foundSplit || (!EpsilonEqualV3(splitPt, lastSplit, epsilon)))
+				{
+					// add vertex to both polygons
+					front.mVertices.push_back(splitPt);
+					back.mVertices.push_back(splitPt);
+					
+					lastSplit = splitPt;
+					foundSplit = true;
+				}
+			}
+			front.mVertices.push_back(ptB);
+		}
+		else if (sideB < 0)
+		{
+			if (sideA > 0)
+			{
+				//-- plane - line intersection
+				Vector3 splitPt = partition.FindIntersection(ptA, ptB);
+				// test if split point not too close to other split point
+					// test if split point not too close to previous split point
+				if (!foundSplit || (!EpsilonEqualV3(splitPt, lastSplit, epsilon)))
+				{
+					// add vertex to both polygons
+					front.mVertices.push_back(splitPt);
+					back.mVertices.push_back(splitPt);
+
+					lastSplit = splitPt;
+					foundSplit = true;
+				}	
+			}
+			back.mVertices.push_back(ptB);
+		}
+		else
+		{
+			// vertex on plane => add vertex to both polygons
+			front.mVertices.push_back(ptB);
+			back.mVertices.push_back(ptB); 
+		}
+	
+		ptA = ptB;
+		sideA = sideB;
+	}
+}
+
+
+float Polygon3::GetArea() const
+{
+	Vector3 v = CrossProd(mVertices.back(), mVertices.front());
+    
+    for (int i=0; i < mVertices.size() - 1; ++i)
+		v += CrossProd(mVertices[i], mVertices[i+1]);
+    
+    return 0.5f * fabs(DotProd(GetNormal(), v));
+}
+
+
+int Polygon3::Side(const Plane3 &plane, 
+				   const float epsilon) const
+{
+	int classification = ClassifyPlane(plane, epsilon);
+	
+	if (classification == BACK_SIDE)
+		return -1;
+	else if (classification == FRONT_SIDE)
+		return 1;
+	// plane splits polygon
+	return 0;
+}
+
+
+int Polygon3::ClassifyPlane(const Plane3 &plane, 
+							const float epsilon) const
+{
+	VertexContainer::const_iterator it, it_end = mVertices.end();
+
+	bool onFrontSide = false;
+	bool onBackSide = false;
+	
+	int count = 0;
+	// find possible line-plane intersections
+	for (it = mVertices.begin(); it != it_end; ++ it)
+	{
+		const int side = plane.Side(*it, epsilon);
+		
+		if (side > 0)
+			onFrontSide = true;
+		else if (side < 0)
+			onBackSide = true;
+		
+		//TODO: check if split goes through vertex
+		if (onFrontSide && onBackSide) // split 
+		{
+			return SPLIT;
+		}
+		// 3 vertices enough to decide coincident
+		else if (((++ count) >= 3) && !onFrontSide && !onBackSide)
+		{   
+			return COINCIDENT; 
+		}
+	}
+
+	if (onBackSide)
+	{
+		return BACK_SIDE;
+	}
+	else if (onFrontSide)
+	{
+		return FRONT_SIDE;
+	}
+	
+	return COINCIDENT; // plane and polygon are coincident
+}
+
+
+Vector3
+Polygon3::Center() const
+{
+	int i;
+	Vector3 sum = mVertices[0];
+	for (i=1; i < mVertices.size(); i++)
+		sum += mVertices[i];
+	
+	return sum/(float)i;
+}
+
+
+void
+Polygon3::Scale(const float scale)
+{
+	int i;
+	Vector3 center = Center();
+	for (i=0; i < mVertices.size(); i++) {
+		mVertices[i] = center + scale*(mVertices[i] - center);
+	}
+}
+
+bool Polygon3::Valid(const float epsilon) const
+{
+	if (mVertices.size() < 3)
+		return false;
+
+	//TODO: remove for performance
+#if 0
+	if (1)
+	{
+		// check if area exceeds certain size
+		if (GetArea() < AREA_LIMIT)
+		{
+			Debug << "area too small: " << GetArea() << endl;
+			return false;
+		}
+	}
+	else
+	{
+		Vector3 vtx = mVertices.back();
+		VertexContainer::const_iterator it, it_end = mVertices.end();
+
+		for (it = mVertices.begin(); it != it_end; ++it)
+		{
+			if (!(EpsilonEqualV3(vtx, *it)))
+			{
+				//Debug << "Malformed vertices:\n" << *this << endl;
+				return false;
+			}
+			vtx = *it;
+		}
+	}
+#endif
+
+	return true;
+}
+
+
+void Polygon3::IncludeInBox(const PolygonContainer &polys, AxisAlignedBox3 &box)
+{
+	PolygonContainer::const_iterator it, it_end = polys.end();
+
+	for (it = polys.begin(); it != it_end; ++ it)
+		box.Include(*(*it));
+}
+
+
+// int_lineseg returns 1 if the given line segment intersects a 2D
+// ray travelling in the positive X direction.	This is used in the
+// Jordan curve computation for polygon intersection.
+inline int
+int_lineseg(float px,
+	    float py,
+	    float u1,
+	    float v1,
+	    float u2,
+	    float v2)
+{
+	float t;
+	float ydiff;
+
+	u1 -= px; u2 -= px; 	  // translate line
+	v1 -= py; v2 -= py;
+
+	if ((v1 > 0 && v2 > 0) ||
+		(v1 < 0 && v2 < 0) ||
+		(u1 < 0 && u2 < 0))
+	return 0;
+
+	if (u1 > 0 && u2 > 0)
+	return 1;
+
+	ydiff = v2 - v1;
+
+	if (fabs(ydiff) < Limits::Small) 
+	{	  // denominator near 0
+		if (((fabs(v1) > Limits::Small) || (u1 > 0) || (u2 > 0)))
+			return 0;
+		return 1;
+	}
+
+	t = -v1 / ydiff;		  // Compute parameter
+
+	return (u1 + t * (u2 - u1)) > 0;
+}
+
+
+int Polygon3::CastRay(const Ray &ray, float &t, const float nearestT)
+{
+	Plane3 plane = GetSupportingPlane();
+	float dot = DotProd(plane.mNormal, ray.GetDir());
+
+	// Watch for near-zero denominator
+	// ONLY single sided polygons!!!!!
+	if (dot > -Limits::Small)
+	//  if (fabs(dot) < Limits::Small)
+	return Ray::NO_INTERSECTION;
+
+	t = (-plane.mD - DotProd(plane.mNormal, ray.GetLoc())) / dot;
+
+	if (t <= Limits::Small)
+	return Ray::INTERSECTION_OUT_OF_LIMITS;
+
+	if (t >= nearestT) {
+	return Ray::INTERSECTION_OUT_OF_LIMITS; // no intersection was found
+	}
+
+	int count = 0;
+	float u, v, u1, v1, u2, v2;
+	int i;
+
+	int paxis = plane.mNormal.DrivingAxis();
+
+	// Project the intersection point onto the coordinate plane
+	// specified by which.
+	ray.Extrap(t).ExtractVerts(&u, &v, paxis);
+
+	int size = (int)mVertices.size();
+
+	mVertices.back().ExtractVerts(&u1, &v1, paxis );
+
+	if (0 && size <= 4) 
+	{
+		// assume a convex face
+		for (i = 0; i < size; i++) 
+		{
+      		mVertices[i].ExtractVerts(&u2, &v2, paxis);
+	    
+			// line u1, v1, u2, v2
+	    
+			if ((v2 - v1)*(u1 - u) > (u2 - u1)*(v1 - v))
+				return Ray::NO_INTERSECTION;
+
+			u1 = u2;
+			v1 = v2;
+	}
+
+	return Ray::INTERSECTION;
+	}
+
+	// We're stuck with the Jordan curve computation.  Count number
+	// of intersections between the line segments the polygon comprises
+	// with a ray originating at the point of intersection and
+	// travelling in the positive X direction.
+	for (i = 0; i < size; i++) 
+	{
+		mVertices[i].ExtractVerts(&u2, &v2, paxis);
+
+		count += (int_lineseg(u, v, u1, v1, u2, v2) != 0);
+
+		u1 = u2;
+		v1 = v2;
+	}
+
+	// We hit polygon if number of intersections is odd.
+	return (count & 1) ? Ray::INTERSECTION : Ray::NO_INTERSECTION;
+}
+
+
+void Polygon3::InheritRays(Polygon3 &front_piece, 
+					       Polygon3 &back_piece) const
+{
+	if (mPiercingRays.empty())
+		return;
+
+	RayContainer::const_iterator it, 
+		it_end = mPiercingRays.end();
+
+	for (it = mPiercingRays.begin(); it != it_end; ++ it)
+	{
+		switch((*it)->GetId())
+		{
+		case Ray::BACK:
+			back_piece.mPiercingRays.push_back(*it);
+			break;
+		case Ray::FRONT:
+			front_piece.mPiercingRays.push_back(*it);
+			break;
+		case Ray::FRONT_BACK:
+			back_piece.mPiercingRays.push_back(*it);
+			break;
+		case Ray::BACK_FRONT:
+			front_piece.mPiercingRays.push_back(*it);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+
+int Polygon3::ClassifyPlane(const PolygonContainer &polys, 
+							const Plane3 &plane,
+							const float epsilon)
+{
+	PolygonContainer::const_iterator it;
+
+	bool onFrontSide = false;
+	bool onBackSide = false;
+	
+	// find intersections
+	for (it = polys.begin(); it != polys.end(); ++ it)
+	{
+        const int cf = (*it)->ClassifyPlane(plane, epsilon);
+		
+        if (cf == FRONT_SIDE)
+			onFrontSide = true;
+		else if (cf == BACK_SIDE)
+			onBackSide = true;
+		
+		if ((cf == SPLIT) || (cf == COINCIDENT) || (onFrontSide && onBackSide))
+		{
+			return SPLIT;
+		}
+	}
+
+	if (onBackSide)
+	{
+		return BACK_SIDE;
+	}
+	else if (onFrontSide)
+	{
+		return FRONT_SIDE;
+	}
+	
+	return SPLIT;
+}
+
+
+int Polygon3::ParentObjectsSize(const PolygonContainer &polys)
+{
+	int count = 0;
+
+	PolygonContainer::const_iterator it, it_end = polys.end();
+
+	MeshInstance::NewMail();
+
+	for (it = polys.begin(); it != it_end; ++ it)
+	{
+		if ((*it)->mParent && !(*it)->mParent->Mailed())
+		{
+			++ count;
+			(*it)->mParent->Mail();
+		}
+	}
+	return count;
+}
+
+
+float Polygon3::GetArea(const PolygonContainer &cell)
+{
+	float area = 0;
+	PolygonContainer::const_iterator pit;
+
+	for (pit = cell.begin(); pit != cell.end(); ++ pit)
+	{
+		area += (*pit)->GetArea();
+	}
+
+	return area;
+}
+
+
+Polygon3 *Polygon3::CreateReversePolygon() const
+{
+	Polygon3 *revPoly = new Polygon3();
+
+	VertexContainer::const_reverse_iterator rit, 
+			rit_end = mVertices.rend();
+
+	for(rit = mVertices.rbegin(); rit != rit_end; ++ rit)
+		revPoly->mVertices.push_back(*rit);
+
+	return revPoly;
+}
+
+
+void Polygon3::Triangulate(vector<Triangle3> &triangles)
+{
+	int i = 1;
+	int j = 0;
+	int k = (int)mVertices.size() - 1;
+	int count = 0;
+
+	while (i < k)
+	{
+		triangles.push_back(Triangle3(mVertices[i], mVertices[j], mVertices[k]));
+
+		if ((count ++) % 2)
+			j = i ++;
+		else
+			j = k --;
+	}
+}
+
+
+void Polygon3::Triangulate(VertexIndexContainer &indices)
+{
+	int i = 1;
+	int j = 0;
+	int k = (int)mVertices.size() - 1;
+
+	int count = 0;
+
+	while (i < k)
+	{
+		indices.push_back(k);
+		indices.push_back(j);
+		indices.push_back(i);
+
+		if ((count ++) % 2)
+			j = i ++;
+		else
+			j = k --;
+	}
+}
+
+
+void Polygon3::AddToMesh(Mesh &mesh)
+{
+	const int n = (int)mesh.mVertices.size();
+
+    //-- add the vertices
+    VertexContainer::const_iterator vit, vit_end = mVertices.end();
+	for (vit = mVertices.begin(); vit != vit_end; ++ vit)
+	{
+		mesh.mVertices.push_back(*vit);
+	}
+
+	// one quad => no triangulation necessary
+	if ((int)mVertices.size() == 4)
+	{
+		mesh.AddFace(new Face(n, n + 1, n + 2, n + 3));
+	}
+	else
+	{
+		VertexIndexContainer indices;
+		Triangulate(indices);
+
+		// add indices of triangle strip
+		for (int i = 0; i < (int)indices.size(); i += 3)
+		{
+			Face *face = new Face(n + indices[i], 
+								  n + indices[i + 1], 
+								  n + indices[i + 2]);
+			mesh.AddFace(face);
+		}
+	}
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Containers.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Containers.h	(revision 503)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Containers.h	(revision 503)
@@ -0,0 +1,49 @@
+#ifndef _Container_H__
+#define _Container_H__
+
+#include <vector>
+#include <queue>
+
+using namespace std;
+
+class ViewCell;
+class HierarchyNode;
+class SceneGraphNode;
+class Intersectable;
+class Polygon3;
+class Ray;
+class Mesh;
+
+/** Container storing polygons used during BSP tree construction.
+*/
+typedef vector<Polygon3 *> PolygonContainer;
+
+/** Container storing a bundle of rays.
+*/
+typedef vector<Ray *> RayContainer;
+
+/** Container for Mesh pointers primarily for the use within the kDTree and
+    BSP hierarchies */
+typedef vector<Intersectable *> ObjectContainer;
+
+/** Container for ViewCell pointers primarily for the use within the kDTree and
+    BSP hierarchies */
+
+typedef vector<ViewCell *> ViewCellContainer;
+
+/** Container for ViewCell pointers primarily for the use within the kDTree and
+    BSP hierarchies */
+//typedef vector<MeshInstance *> MeshInstanceContainer;
+
+/** Container for HierarchyNodes pointers primarily for the use within the kDTree and
+    BSP hierarchies */
+
+typedef vector<HierarchyNode *> NodeContainer;
+
+typedef vector<SceneGraphNode *> SceneGraphNodeContainer;
+
+typedef vector<Mesh *> MeshContainer;
+
+
+#endif // _Container_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.cpp	(revision 590)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.cpp	(revision 590)
@@ -0,0 +1,632 @@
+// ---------------------------------------------------------------------------
+//  Includes for all the program files to see
+// ---------------------------------------------------------------------------
+#include <string.h>
+#include <stdlib.h>
+#include <iostream>
+using namespace std;
+#include <xercesc/util/PlatformUtils.hpp>
+
+// ---------------------------------------------------------------------------
+//  Includes
+// ---------------------------------------------------------------------------
+#include <xercesc/framework/StdInInputSource.hpp>
+#include <xercesc/parsers/SAXParser.hpp>
+#include <xercesc/util/OutOfMemoryException.hpp>
+
+// ---------------------------------------------------------------------------
+//  Includes
+// ---------------------------------------------------------------------------
+#include <xercesc/sax/AttributeList.hpp>
+#include <xercesc/sax/SAXParseException.hpp>
+#include <xercesc/sax/SAXException.hpp>
+
+#include "ViewCellsParser.h"
+
+#include "ViewCellsParserXerces.h"
+#include "Mesh.h"
+#include "VspBspTree.h"
+#include "ViewCellBsp.h"
+#include "VspKdTree.h"
+#include "ViewCellsManager.h"
+
+// ---------------------------------------------------------------------------
+//  Local data
+//
+//  doNamespaces
+//      Indicates whether namespace processing should be enabled or not.
+//      The default is no, but -n overrides that.
+//
+//  doSchema
+//      Indicates whether schema processing should be enabled or not.
+//      The default is no, but -s overrides that.
+//
+//  schemaFullChecking
+//      Indicates whether full schema constraint checking should be enabled or not.
+//      The default is no, but -s overrides that.
+//
+//  valScheme
+//      Indicates what validation scheme to use. It defaults to 'auto', but
+//      can be set via the -v= command.
+// ---------------------------------------------------------------------------
+static bool     doNamespaces       = false;
+static bool     doSchema           = false;
+static bool     schemaFullChecking = false;
+static SAXParser::ValSchemes    valScheme       = SAXParser::Val_Auto;
+
+
+
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Constructors and Destructor
+// ---------------------------------------------------------------------------
+ViewCellsParseHandlers::ViewCellsParseHandlers(ObjectContainer *objects):
+  mElementCount(0)
+  , mAttrCount(0)
+  , mCharacterCount(0)
+  , mSpaceCount(0)
+  , mViewCellsManager(NULL)
+  , mVspBspTree(NULL)
+  , mBspTree(NULL)
+{
+	mObjects = objects;
+}
+
+
+ViewCellsParseHandlers::~ViewCellsParseHandlers()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Implementation of the SAX DocumentHandler interface
+// ---------------------------------------------------------------------------
+
+
+void ViewCellsParseHandlers::endElement(const XMLCh* const name)
+{
+  StrX lname(name);
+  string element(lname.LocalForm());
+  if (element == "Interior")
+	  EndBspInterior();
+  if (element == "ViewCells")
+	  EndViewCells();
+}
+
+
+void ViewCellsParseHandlers::EndBspInterior()
+{
+	// go one up in the tree
+	if (mCurrentBspNode->GetParent())
+	{	cout << "]";
+		mCurrentBspNode = mCurrentBspNode->GetParent();
+	}
+}
+
+
+inline bool vlt(ViewCell *v1, ViewCell *v2)
+{
+	return v1->mId < v2->mId;
+}
+
+
+void ViewCellsParseHandlers::EndViewCells()
+{
+	// sort view cells to help associating view cells according to their id
+	stable_sort(mViewCells.begin(), mViewCells.end(), vlt);
+}
+
+
+
+void ViewCellsParseHandlers::StartHierarchy(AttributeList&  attributes)
+{
+	int len = attributes.getLength();
+  
+	for (int i = 0; i < len; ++ i) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+		
+		if (attrName == "name") 
+		{
+			StrX attrValue(attributes.getValue(i));
+			
+			const char *ptr = attrValue.LocalForm();
+			
+			CreateViewCellsManager(ptr);
+		}
+	}
+}
+
+
+void ViewCellsParseHandlers::startBspElement(string element,
+											 AttributeList& attributes)
+{
+	if (element == "Interior") 
+	{
+		cout << "[";
+		StartBspInterior(attributes);
+	}
+
+	if (element == "Leaf") 
+	{
+		StartBspLeaf(attributes);
+	}
+}
+
+
+void ViewCellsParseHandlers::startElement(const XMLCh* const name,
+										  AttributeList& attributes)
+{
+	StrX lname(name);
+	string element(lname.LocalForm());
+
+	// decides the used view cell hierarchy
+	if (element == "Hierarchy")
+	{
+		cout << "h";
+		StartHierarchy(attributes);
+	}
+	
+	// decides the used view cell hierarchy
+	if (element == "ViewSpaceBox")
+	{
+		cout << "vsb";
+		StartViewSpaceBox(attributes);
+	}
+
+	if (element == "ViewCell")
+	{
+		cout << "v";
+		StartViewCell(attributes);
+	}
+
+	// use different methods for the given view cell hierarchy types
+	if (mViewCellsManager)
+	{
+		switch (mViewCellsManager->GetType())
+		{
+		case ViewCellsManager::BSP:
+		case ViewCellsManager::VSP_BSP:
+			startBspElement(element, attributes);
+			break;
+	
+		default:
+			Debug << "not implemented" << endl;
+			break;
+		}
+	}
+
+	++ mElementCount;
+	mAttrCount += attributes.getLength();
+}
+
+
+inline bool ilt(Intersectable *obj1, Intersectable *obj2)
+{
+	return obj1->mId < obj2->mId;
+}
+
+
+void ViewCellsParseHandlers::StartViewCell(AttributeList&  attributes)
+{
+	int len = attributes.getLength();
+	vector<int> objIndices;
+  
+//hack!!
+	
+	ViewCell *viewCell = new ViewCellInterior();//mViewCellsManager->GenerateViewCell();
+	viewCell->mIsActive = true;
+
+	mViewCells.push_back(viewCell);
+	
+	for (int i = 0; i < len; ++ i) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+		
+		if (attrName == "pvs") 
+		{
+			StrX attrValue(attributes.getValue(i));
+			
+			// handle coordIndex
+			objIndices.clear();
+			const char *ptr = attrValue.LocalForm();
+			char *endptr;
+			
+			while (1)
+			{
+				int index = strtol(ptr, &endptr, 10);
+
+				if (ptr == endptr)
+					break;
+
+				objIndices.push_back(index);
+
+				ptr = endptr;
+			}
+
+			//TODO: find objects and add them to pvs
+			// TODO: get view cell with specified id
+			MeshInstance dummyInst(NULL);
+
+			vector<int>::const_iterator it, it_end = objIndices.end();
+			for (it = objIndices.begin(); it != it_end; ++ it)
+			{
+				const int objId = *it;	
+				dummyInst.SetId(objId);
+
+				ObjectContainer::iterator oit =
+				  lower_bound(mObjects->begin(), mObjects->end(), &dummyInst, ilt);
+				
+				Intersectable *obj = *oit;
+				
+				if (obj->GetId() == objId)
+				{
+				  // $$JB we should store a float a per object which corresponds
+				  // to sumof pdfs, i.e. its relative visibility
+				  // temporarily set to 1.0f
+					viewCell->GetPvs().AddSample(obj, 1.0f);
+				}
+				else
+				{
+					Debug << "error: object does not exist" << endl;
+				}
+			}
+		}
+		else if (attrName == "id") 
+		{
+			StrX attrValue(attributes.getValue(i));
+			
+			const char *ptr = attrValue.LocalForm();
+			char *endptr = NULL;
+			const int id = strtol(ptr, &endptr, 10);
+
+			viewCell->SetId(id);
+		}
+	}
+}
+
+
+void ViewCellsParseHandlers::StartViewSpaceBox(AttributeList& attributes)
+{
+	int len = attributes.getLength();
+
+	Vector3 bmin, bmax;
+
+	for (int i = 0; i < len; ++ i) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+		StrX attrValue(attributes.getValue(i));
+		const char *ptr = attrValue.LocalForm();
+
+		if (attrName == "min") 
+		{
+			sscanf(ptr, "%f %f %f",
+				   &bmin.x, &bmin.y, &bmin.z);
+		}
+		else if (attrName == "max") 
+		{
+			sscanf(ptr, "%f %f %f",
+				   &bmax.x, &bmax.y, &bmax.z);
+		}
+	}
+
+	mViewSpaceBox = AxisAlignedBox3(bmin, bmax);
+
+	Debug << "view space box: " << mViewSpaceBox << endl;
+}
+
+
+void ViewCellsParseHandlers::StartBspLeaf(AttributeList& attributes)
+{
+	BspLeaf * leaf = 
+		new BspLeaf(dynamic_cast<BspInterior *>(mCurrentBspNode), NULL);
+
+	if (mCurrentBspNode) // replace front or (if not NULL) back child
+	{
+		dynamic_cast<BspInterior *>(mCurrentBspNode)->ReplaceChildLink(NULL, leaf);
+	}
+	else
+	{
+		if (mViewCellsManager->GetType() == ViewCellsManager::BSP)
+		{
+			mBspTree->mRoot = leaf;
+		}
+		else if (mViewCellsManager->GetType() == ViewCellsManager::VSP_BSP)
+		{
+			mVspBspTree->mRoot = leaf;
+		}
+	}
+
+	//-- find associated view cell
+	int viewCellId;
+	
+	int len = attributes.getLength();
+	  
+	for (int i = 0; i < len; ++ i) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+		StrX attrValue(attributes.getValue(i));
+
+		const char *ptr = attrValue.LocalForm();
+		char *endptr = NULL;
+
+		if (attrName == "viewCellId") 
+		{
+			viewCellId = strtol(ptr, &endptr, 10);
+		}
+	}
+
+	
+	if (viewCellId >= 0) // valid view cell
+	{
+		// TODO: get view cell with specified id
+		ViewCellInterior dummyVc;
+		dummyVc.SetId(viewCellId);
+
+		ViewCellContainer::iterator vit =
+			lower_bound(mViewCells.begin(), mViewCells.end(), &dummyVc, vlt);
+			
+		ViewCellInterior *viewCell = dynamic_cast<ViewCellInterior *>(*vit);
+
+		// giant hack!!
+		BspViewCell *l = dynamic_cast<BspViewCell *>(mViewCellsManager->GenerateViewCell());
+		viewCell->SetupChildLink(l);
+
+		if (viewCell->GetId() == viewCellId)
+		{
+			leaf->SetViewCell(l);
+			l->mLeaf = leaf;
+		}
+		else
+		{
+			Debug << "error: view cell does not exist" << endl;
+		}
+	}
+	else
+	{
+		if (mViewCellsManager->GetType() == ViewCellsManager::VSP_BSP)
+		{
+			leaf->SetViewCell(mVspBspTree->GetOrCreateOutOfBoundsCell());
+			leaf->SetTreeValid(false);
+			mVspBspTree->PropagateUpValidity(leaf);
+		}
+	}
+}
+
+
+void ViewCellsParseHandlers::StartBspInterior(AttributeList& attributes)
+{
+	Plane3 plane;
+	int len = attributes.getLength();
+
+	for (int i = 0; i < len; ++ i) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+		StrX attrValue(attributes.getValue(i));
+		const char *ptr = attrValue.LocalForm();
+
+		if (attrName == "plane") 
+		{
+			sscanf(ptr, "%f %f %f %f",
+				   &plane.mNormal.x, &plane.mNormal.y, &plane.mNormal.z, &plane.mD);
+		}
+	}
+
+	BspInterior* interior = new BspInterior(plane);
+	
+	if (mCurrentBspNode) // replace NULL child of parent with current node
+	{
+		BspInterior *current = dynamic_cast<BspInterior *>(mCurrentBspNode);
+
+		current->ReplaceChildLink(NULL, interior);
+		interior->SetParent(current);
+	}
+	else
+	{
+		if (mViewCellsManager->GetType() == ViewCellsManager::BSP)
+		{
+			mBspTree->mRoot = interior;
+		}
+		else
+		{
+			mVspBspTree->mRoot = interior;
+		}
+	}
+
+	mCurrentBspNode = interior;
+}
+
+
+
+void ViewCellsParseHandlers::CreateViewCellsManager(const char *name)
+{
+	if (strcmp(name, "bspTree") == 0)
+	{
+		Debug << "view cell type: Bsp" << endl;
+
+		mBspTree = new BspTree();
+		mBspTree->mBox = mViewSpaceBox;
+		mCurrentBspNode = mBspTree->GetRoot();
+
+		mViewCellsManager = new BspViewCellsManager(mBspTree);
+	}
+	else if (strcmp(name, "vspBspTree") == 0)
+	{
+		Debug << "view cell type: VspBsp" << endl;
+
+		mVspBspTree = new VspBspTree();
+		mCurrentBspNode = mVspBspTree->GetRoot();
+
+		mViewCellsManager = new VspBspViewCellsManager(mVspBspTree);
+
+		mVspBspTree->mBox = mViewSpaceBox;
+		Debug << "creating vsp bsp view cells manager" << endl;
+	}
+	else if (strcmp(name, "vspKdTree") == 0)
+	{
+		// TODO
+		mVspKdTree = new VspKdTree();	
+		mViewCellsManager = new VspKdViewCellsManager(mVspKdTree);
+	}
+	else
+	{
+		cerr<<"Wrong view cells type" << name << endl;
+		exit(1);
+	}
+
+	mViewCellsManager->SetViewSpaceBox(mViewSpaceBox);
+}
+
+
+void ViewCellsParseHandlers::characters(const XMLCh* const chars,
+										const unsigned int length)
+{
+	mCharacterCount += length;
+}
+
+
+void ViewCellsParseHandlers::ignorableWhitespace(const XMLCh* const chars,
+												 const unsigned int length)
+{
+	mSpaceCount += length;
+}
+
+
+void ViewCellsParseHandlers::resetDocument()
+{
+	mAttrCount = 0;
+	mCharacterCount = 0;
+	mElementCount = 0;
+	mSpaceCount = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Overrides of the SAX ErrorHandler interface
+// ---------------------------------------------------------------------------
+void
+ViewCellsParseHandlers::error(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nError at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+void
+ViewCellsParseHandlers::fatalError(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nFatal Error at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+void
+ViewCellsParseHandlers::warning(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nWarning at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+
+bool ViewCellsParser::ParseFile(const string filename, 
+								ViewCellsManager **viewCells,
+								ObjectContainer *objects)
+{
+  // Initialize the XML4C system
+  try {
+    XMLPlatformUtils::Initialize();
+  }
+  
+  catch (const XMLException& toCatch)
+    {
+      XERCES_STD_QUALIFIER cerr << "Error during initialization! Message:\n"
+				<< StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl;
+      return false;
+    }
+  
+  
+  //
+  //  Create a SAX parser object. Then, according to what we were told on
+  //  the command line, set the options.
+  //
+  SAXParser* parser = new SAXParser;
+  parser->setValidationScheme(valScheme);
+  parser->setDoNamespaces(doNamespaces);
+  parser->setDoSchema(doSchema);
+  parser->setValidationSchemaFullChecking(schemaFullChecking);
+  
+
+  //
+  //  Create our SAX handler object and install it on the parser, as the
+  //  document and error handler. We are responsible for cleaning them
+  //  up, but since its just stack based here, there's nothing special
+  //  to do.
+  //
+  ViewCellsParseHandlers handler(objects);
+  parser->setDocumentHandler(&handler);
+  parser->setErrorHandler(&handler);
+  
+  unsigned long duration;
+  int errorCount = 0;
+  // create a faux scope so that 'src' destructor is called before
+  // XMLPlatformUtils::Terminate
+  {
+    //
+    //  Kick off the parse and catch any exceptions. Create a standard
+    //  input input source and tell the parser to parse from that.
+    //
+    //    StdInInputSource src;
+    try
+      {
+	const unsigned long startMillis = XMLPlatformUtils::getCurrentMillis();
+	parser->parse(filename.c_str());
+	const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis();
+	duration = endMillis - startMillis;
+	errorCount = parser->getErrorCount();
+      }
+    catch (const OutOfMemoryException&)
+      {
+	XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
+	errorCount = 2;
+	return false;
+      }
+    catch (const XMLException& e)
+      {
+	XERCES_STD_QUALIFIER cerr << "\nError during parsing: \n"
+				  << StrX(e.getMessage())
+				  << "\n" << XERCES_STD_QUALIFIER endl;
+	errorCount = 1;
+	return false;
+      }
+
+    
+    // Print out the stats that we collected and time taken
+    if (!errorCount) {
+      XERCES_STD_QUALIFIER cout << filename << ": " << duration << " ms ("
+				<< handler.GetElementCount() << " elems, "
+				<< handler.GetAttrCount() << " attrs, "
+				<< handler.GetSpaceCount() << " spaces, "
+				<< handler.GetCharacterCount() << " chars)" << XERCES_STD_QUALIFIER endl;
+    }
+  }
+  
+  //
+  //  Delete the parser itself.  Must be done prior to calling Terminate, below.
+  //
+  delete parser;
+  
+  XMLPlatformUtils::Terminate();
+  
+   // assign new view cells manager
+  *viewCells = handler.mViewCellsManager;
+
+  if (errorCount > 0)
+    return false;
+  else
+    return true;
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspKdTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspKdTree.h	(revision 587)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspKdTree.h	(revision 587)
@@ -0,0 +1,895 @@
+// ================================================================
+// $Id$
+// ****************************************************************
+// 
+// Initial coding by
+/**
+   @author Jiri Bittner
+*/
+
+#ifndef __VSPKDTREE_H__
+#define __VSPKDTREE_H__
+
+// Standard headers
+#include <iomanip>
+#include <vector>
+#include <functional>
+#include <stack>
+
+
+// User headers
+#include "VssRay.h"
+#include "AxisAlignedBox3.h"
+
+
+#define USE_KDNODE_VECTORS 1
+#define _RSS_STATISTICS
+#define _RSS_TRAVERSAL_STATISTICS
+
+
+#include "Statistics.h"
+#include "Ray.h"
+
+#include "RayInfo.h"
+#include "Containers.h"
+#include "ViewCell.h"
+
+class VspKdLeaf;
+class ViewCellsManager;
+class ViewCellsStatistics;
+
+
+/**
+	Candidate for leaf merging based on priority.
+*/
+class VspKdMergeCandidate
+{  
+public:
+
+	VspKdMergeCandidate(VspKdLeaf *l1, VspKdLeaf *l2);
+
+	/** Computes PVS difference between the leaves.
+	*/
+	//int ComputePvsDifference() const;
+
+	/** If this merge pair is still valid.
+	*/
+	bool Valid() const;
+
+	/** Sets this merge candidate to be valid.
+	*/
+	void SetValid();
+
+	friend bool operator<(const VspKdMergeCandidate &leafa, const VspKdMergeCandidate &leafb)
+	{
+		return leafb.GetMergeCost() < leafa.GetMergeCost();
+	}
+
+	void SetLeaf1(VspKdLeaf *l);
+	void SetLeaf2(VspKdLeaf *l);
+
+	VspKdLeaf *GetLeaf1();
+	VspKdLeaf *GetLeaf2();
+
+	/** Merge cost of this candidate pair.
+	*/
+	float GetMergeCost() const;
+
+	/** Returns cost of leaf 1.
+	*/
+	float GetLeaf1Cost() const;
+	/** Returns cost of leaf 2.
+	*/
+	float GetLeaf2Cost() const;
+
+	/// maximal pvs size
+	static int sMaxPvsSize;
+	/// overall cost used to normalize cost ratio
+	static float sOverallCost;
+
+protected:
+	
+	/** Evaluates the merge costs of the leaves.
+	*/
+	void EvalMergeCost();
+
+	int mLeaf1Id;
+	int mLeaf2Id;
+
+	float mMergeCost;
+	
+	VspKdLeaf *mLeaf1;
+	VspKdLeaf *mLeaf2;
+};
+
+
+
+/**
+	Static statistics for vsp kd-tree search
+*/
+class VspKdStatistics:  public StatisticsBase
+{
+public:  
+	// total number of nodes
+	int nodes;
+	// number of splits along each of the axes
+	int splits[3];
+	// totals number of rays
+	int rays;
+	// initial size of the pvs
+	int initialPvsSize;
+	// total number of query domains
+	int queryDomains;
+	// total number of ray references
+	int rayRefs;
+
+	// max depth nodes
+	int maxDepthNodes;
+	// max depth nodes
+	int minPvsNodes;
+	// nodes with minimum PVS
+	int minRaysNodes;
+	// max ray contribution nodes
+	int maxRayContribNodes;
+	// max depth nodes
+	int minSizeNodes;
+	
+	// max number of rays per node
+	int maxRayRefs;
+	// maximal PVS size / leaf
+	int maxPvsSize;
+
+	// max cost ratio
+	int maxCostNodes;
+
+	// number of dynamically added ray refs
+	int addedRayRefs;
+	// number of dynamically removed ray refs
+	int removedRayRefs;
+  
+	/// for average pvs
+	int accPvsSize;
+
+	/** Default constructor.
+	*/
+	VspKdStatistics() {	Reset(); }
+	int Nodes() const { return nodes; }
+	int Interior() const { return nodes / 2; }
+	int Leaves() const { return (nodes / 2) + 1; }
+
+	void Reset() 
+	{
+		nodes = 0;
+
+		for (int i=0; i<3; i++)
+			splits[i] = 0;
+
+		rays = queryDomains = 0;
+		rayRefs = 0;
+		
+		maxDepthNodes = 0;
+		minPvsNodes = 0;
+		minRaysNodes = 0;
+		maxRayContribNodes = 0;
+		minSizeNodes = 0;
+		maxCostNodes = 0;
+
+		maxRayRefs = 0;
+		addedRayRefs = removedRayRefs = 0;
+		
+		initialPvsSize = 0;
+		maxPvsSize = 0;
+		accPvsSize = 0;
+	}
+
+	void Print(ostream &app) const;
+	friend ostream &operator<<(ostream &s, const VspKdStatistics &stat) 
+	{
+	    stat.Print(s);
+	    return s;
+	}  
+};
+
+
+class VspKdInterior;
+
+
+/** Abstract superclass of Vsp-Kd-Tree nodes.
+*/
+class VspKdNode
+{
+public:
+
+	friend class VspKdTree;
+
+	enum {EInterior, EIntermediate, ELeaf};
+
+	/** Constructs new interior node from the parent node.
+	*/
+	inline VspKdNode(VspKdNode *p);
+
+	/** Destroys this node and the subtree.
+	*/
+	virtual ~VspKdNode();
+
+	/** Type of the node (Einterior or ELeaf)
+	*/
+	virtual int Type() const = 0;
+ 
+	/** Returns true if this node is a leaf.
+	*/
+	bool IsLeaf() const;
+	
+	/** Prints node stats.
+	*/
+	virtual void Print(ostream &s) const = 0;
+
+	/** Returns time needed to access this node.
+		@NOTE: don't really know how it is used!
+	*/
+	virtual int GetAccessTime(); 
+
+	/** Returns parent node.
+	*/
+	VspKdNode *GetParent() const;
+
+	/** Sets parent node.
+	*/
+	void SetParent(VspKdNode *p);
+
+protected:
+	/////////////////////////////////
+	// The actual data goes here
+  
+	/// link to the parent
+	VspKdNode *mParent;
+
+	enum {SPLIT_X = 0, SPLIT_Y, SPLIT_Z};
+  
+	/// splitting axis
+	char mAxis;
+	
+	/// depth
+	unsigned char mDepth;
+};
+
+// --------------------------------------------------------------
+// KD-tree node - interior node
+// --------------------------------------------------------------
+class VspKdInterior: public VspKdNode
+{
+public:
+	friend class VspKdTree;
+
+	/** Constructs new interior node from parent node.
+	*/
+	VspKdInterior(VspKdInterior *p);
+			
+	virtual int GetAccessTime();
+	
+	virtual int Type() const;
+  
+	virtual ~VspKdInterior();
+    
+	virtual void Print(ostream &s) const;
+
+	/** Returns back child.
+	*/
+	inline VspKdNode *GetBack() const;
+	/** Returns front child.
+	*/
+	inline VspKdNode *GetFront() const;
+
+protected:
+
+	/** Sets pointers to back child and front child.
+	*/
+	void SetupChildLinks(VspKdNode *b, VspKdNode *f);
+	/** Replaces the pointer to oldChild with a pointer to newChild.
+	*/
+	void ReplaceChildLink(VspKdNode *oldChild, VspKdNode *newChild);
+	/** Computes intersection of the ray with the node boundaries.
+	*/
+	int ComputeRayIntersection(const RayInfo &rayData, float &t);
+
+	// plane in local modelling coordinates
+	float mPosition;
+
+	// pointers to children
+	VspKdNode *mBack;
+	VspKdNode *mFront;
+
+	// the bbox of the node
+	AxisAlignedBox3 mBox;
+
+	// data for caching
+	long mAccesses;
+	long mLastAccessTime;
+};
+
+
+/**
+	Node type just before leaf holding abitrary split plane
+*/
+class VspKdIntermediate: public VspKdNode
+{
+public:
+	friend class VspKdTree;
+
+	/** Constructs new interior node from parent node.
+	*/
+	VspKdIntermediate(VspKdInterior *p);
+			
+	//virtual int GetAccessTime();
+	
+	virtual int Type() const;
+  
+	virtual ~VspKdIntermediate();
+    
+	virtual void Print(ostream &s) const;
+
+	/** Returns back child.
+	*/
+	inline VspKdLeaf *GetBack() const;
+	/** Returns front child.
+	*/
+	inline VspKdLeaf *GetFront() const;
+
+protected:
+
+	/** Sets pointers to back child and front child.
+	*/
+	void SetupChildLinks(VspKdLeaf *b, VspKdLeaf *f);
+	/** Computes intersection of the ray with the node boundaries.
+	*/
+	int ComputeRayIntersection(const RayInfo &rayData, float &t);
+
+	// plane in local modelling coordinates
+	Plane3 mSplitPlane;
+
+	// pointers to children
+	VspKdLeaf *mBack;
+	VspKdLeaf *mFront;
+
+	// the bbox of the node
+	AxisAlignedBox3 mBox;
+
+	// data for caching
+	long mAccesses;
+	long mLastAccessTime;
+};
+
+// --------------------------------------------------------------
+// KD-tree node - leaf node
+// --------------------------------------------------------------
+class VspKdLeaf: public VspKdNode
+{
+public:
+
+	friend class VspKdTree;
+
+	/** Constructs leaf from parent node.
+		@param p the parent node
+		@param nRays preallocates memory to store this number of rays
+		@parma maxMisses how many times the max cost ratio was missed on the path to the leaf
+	*/
+	VspKdLeaf(VspKdNode *p,	const int nRays, const int maxCostMisses = 0);
+	
+	virtual ~VspKdLeaf();
+
+	virtual int Type() const;  
+
+	virtual void Print(ostream &s) const;
+  
+	/** Adds a ray to the leaf ray container.
+	*/
+	void AddRay(const RayInfo &data);
+	/** Returns size of the leaf PVS as induced by the rays
+		@note returns precomputed PVS size, which may not be valid
+		anymore. Run UpdatePvsSize to get a valid PVS.
+	*/
+	int GetPvsSize() const;
+
+	/** If PVS is not valid, this function recomputes the leaf 
+		PVS as induced by the rays.
+	*/
+	void UpdatePvsSize();
+
+	/** Returns stored rays.
+	*/
+	RayInfoContainer &GetRays();
+
+	/** Returns rays into this ray container.
+	*/
+	void GetRays(VssRayContainer &rays);
+	/** Returns average contribution of a ray to the PVS
+	*/
+	inline float GetAvgRayContribution() const;
+	/** Returns square of average contribution of a ray.
+	*/
+	inline float GetSqrRayContribution() const;
+
+	/** Extracts PVS from ray set.
+	*/
+	void ExtractPvs(ObjectContainer &objects) const;
+
+	//-- mailing options
+	void Mail();
+
+	bool Mailed() const;
+  
+	/** Returns true if mail equals the leaf mail box.
+	*/
+	bool Mailed(const int mail) const;
+
+	void SetViewCell(VspKdViewCell *viewCell);
+
+	/** Returns mail box of this leaf.
+	*/
+	int GetMailbox() const;
+
+	/** Returns view cell associated with this leaf.
+	*/
+	VspKdViewCell *GetViewCell();
+
+	/** Returns number of times the max cost ratio was missed until
+		this leaf.
+	*/
+	int GetMaxCostMisses();
+
+	////////////////////////////////////////////
+	
+	static void NewMail();
+	static int sMailId;
+
+	ObjectPvs *mPvs;
+	float mVolume;
+
+protected:
+
+	/** Manually sets PVS size.
+		@param s the PVS size
+	*/
+	void SetPvsSize(const int s);
+
+	int mMailbox;
+  
+	/// rays intersecting this leaf.
+	RayInfoContainer mRays;
+	/// true if mPvsSize is valid => PVS does not have to be updated
+	bool mValidPvs;
+	/// the view cell associated with this leaf
+	VspKdViewCell *mViewCell;
+	/// number of times the max cost ratio was missed on the way to the leaf.
+	int mMaxCostMisses;
+
+//private:
+	/// stores PVS size so we have to evaluate PVS size only once
+	int mPvsSize;
+};
+
+
+// ---------------------------------------------------------------
+// Main LSDS search class
+// ---------------------------------------------------------------
+class VspKdTree
+{
+	// --------------------------------------------------------------
+	// For sorting rays
+	// -------------------------------------------------------------
+	struct SortableEntry
+	{
+		enum EType 
+		{
+			ERayMin,
+			ERayMax
+		};
+
+		int type;
+		float value;
+		VssRay *ray;
+  
+		SortableEntry() {}
+		SortableEntry(const int t, const float v, VssRay *r): type(t),
+					  value(v), ray(r) 
+		{
+		}
+		
+		friend bool operator<(const SortableEntry &a, const SortableEntry &b) 
+		{
+			return a.value < b.value;
+		}
+	};
+
+	struct TraversalData
+	{  
+		VspKdNode *mNode;
+		AxisAlignedBox3 mBox;
+		//TODO PolygonContainer *mPolys;
+
+		int mDepth;
+		//float mPriority;
+        
+		TraversalData() {}
+
+		TraversalData(VspKdNode *n, const float p):
+		mNode(n)//, mPriority(p)
+		{}
+
+		TraversalData(VspKdNode *n,	const AxisAlignedBox3 &b, const int d):
+		mNode(n), mBox(b), mDepth(d) {}
+    
+		// comparator for the priority queue
+		/*struct less_priority : public binary_function<const TraversalData, const TraversalData, bool> 
+		{
+			bool operator()(const TraversalData a, const TraversalData b) {			
+			return a.mPriority < b.mPriority;		}	};*/
+
+		//    ~TraversalData() {}
+		//    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
+    
+        friend bool operator<(const TraversalData &a, const TraversalData &b) 
+		{
+			// return a.node->queries.size() < b.node->queries.size();
+			VspKdLeaf *leafa = dynamic_cast<VspKdLeaf *>(a.mNode);
+			VspKdLeaf *leafb = dynamic_cast<VspKdLeaf *>(b.mNode);
+#if 0
+			return
+				leafa->rays.size() * a.mBox.GetVolume()
+				<
+				leafb->rays.size() * b.mBox.GetVolume();
+#endif
+#if 0
+			return
+				leafa->GetPvsSize() * a.mBox.GetVolume()
+				<
+				leafb->GetPvsSize() * b.mBox.GetVolume();
+#endif
+#if 0
+			return
+				leafa->GetPvsSize()
+				<
+				leafb->GetPvsSize();
+#endif
+#if 0
+			return
+				leafa->GetPvsSize() / (float)(leafa->rays.size() + Limits::Small())
+				>
+				leafb->GetPvsSize() / (float)(leafb->rays.size() + Limits::Small());
+#endif
+#if 0
+			return
+				leafa->GetPvsSize() * (float)leafa->rays.size()
+				<
+				leafb->GetPvsSize() * (float)leafb->rays.size();
+#endif
+#if 1
+			return a.mDepth > b.mDepth;
+#endif
+		}
+	};
+  
+	/** Simplified data for ray traversal only.
+	*/
+	struct RayTraversalData 
+	{
+		RayInfo mRayData;
+		VspKdNode *mNode;
+
+		RayTraversalData() {}
+	  
+		RayTraversalData(VspKdNode *n, const RayInfo &data):
+		mRayData(data), mNode(n) {}
+	};
+	
+	struct LineTraversalData 
+	{
+		VspKdNode *mNode;
+		Vector3 mExitPoint;
+		
+		float mMaxT;
+    
+		LineTraversalData () {}
+		LineTraversalData (VspKdNode *n,
+								  const Vector3 &p,
+								  const float maxt):
+		mNode(n), mExitPoint(p), mMaxT(maxt) {}
+	};
+
+public:
+
+	VspKdTree();
+	virtual ~VspKdTree();
+
+	virtual void Construct(const VssRayContainer &rays,
+						   AxisAlignedBox3 *forcedBoundingBox = NULL);
+
+	/** Returns bounding box of the specified node.
+	*/
+	AxisAlignedBox3 GetBBox(VspKdNode *node) const;
+
+	const VspKdStatistics &GetStatistics() const;
+
+	/** Get the root of the tree.
+	*/
+	VspKdNode *GetRoot() const;
+
+	/** Returns average PVS size in tree.
+	*/
+	float GetAvgPvsSize();
+
+	/** Returns memory usage in MB.
+	*/
+	float GetMemUsage() const;
+	//?
+	float GetRayMemUsage() const;
+
+	/** Collects leaves of this tree.
+	*/
+	void CollectLeaves(vector<VspKdLeaf *> &leaves) const;
+
+	/** Merges view cells created with this tree according to 
+		some (global) cost heuristics.
+	*/
+	int MergeViewCells(const VssRayContainer &rays);
+
+	/** Finds neighbours of this node.
+		@param n the input node
+		@param neighbours the neighbors of the input node
+		@param onlyUnmailed if only unmailed neighbors are collected
+	*/
+	int FindNeighbors(VspKdLeaf *n, 
+					  vector<VspKdLeaf *> &neighbors, 
+					  bool onlyUnmailed);
+
+	
+	/** Sets pointer to view cells manager.
+	*/
+	void SetViewCellsManager(ViewCellsManager *vcm);
+
+	/** A ray is cast possible intersecting the tree.
+		@param the ray that is cast.
+		@returns the number of intersections with objects stored in the tree.
+	*/
+	int CastLineSegment(const Vector3 &origin,
+						const Vector3 &termination,
+						vector<ViewCell *> &viewcells);
+
+	/** Collects view cells generated by this tree.
+	*/
+	void CollectViewCells(ViewCellContainer &viewCells) const;
+	
+	/** Refines view cells using shuffling, i.e., border leaves 
+		of two view cells are exchanged if the resulting view cells
+		are tested to be "better" than the old ones.
+		@returns number of refined view cells
+	*/
+	int RefineViewCells(const VssRayContainer &rays);
+
+	/** Collects candidates for the merge in the merge queue.
+	*/
+	void CollectMergeCandidates();
+
+	/** Collapses the tree with respect to the view cell partition.
+		@returns number of collapsed nodes
+	*/
+	int CollapseTree();
+
+protected:
+
+	/** Collapses the tree with respect to the view cell partition,
+		i.e. leaves having the same view cell are collapsed.
+		@param node the root of the subtree to be collapsed
+		@param collapsed returns the number of collapsed nodes
+		@returns node of type leaf if the node could be collapsed, 
+		this node otherwise
+	*/
+	VspKdNode *CollapseTree(VspKdNode *node, int &collapsed);
+
+	// incremental construction
+	virtual void UpdateRays(VssRayContainer &remove, VssRayContainer &add);
+
+	virtual void AddRays(VssRayContainer &add);
+
+	VspKdNode *Locate(const Vector3 &v);
+	
+	VspKdNode *SubdivideNode(VspKdLeaf *leaf,
+				 				 const AxisAlignedBox3 &box,
+								 AxisAlignedBox3 &backBox,
+								 AxisAlignedBox3 &frontBox);
+	
+	VspKdNode *Subdivide(const TraversalData &tdata);
+	
+	int SelectPlane(VspKdLeaf *leaf,
+					const AxisAlignedBox3 &box,
+					float &position,
+					int &raysBack,
+					int &raysFront,
+					int &pvsBack,
+					int &pvsFront);
+
+	void SortSplitCandidates(VspKdLeaf *node,
+							 const int axis);	
+  
+	float BestCostRatioHeuristic(VspKdLeaf *node,
+								 const AxisAlignedBox3 &box,
+								 int &axis,
+								 float &position,
+								 int &raysBack,
+								 int &raysFront,
+								 int &pvsBack,
+								 int &pvsFront);
+
+	float BestCostRatioRegular(VspKdLeaf *node,
+							   const AxisAlignedBox3 &box,
+							   int &axis,
+							   float &position,
+							   int &raysBack,
+							   int &raysFront,
+							   int &pvsBack,
+							   int &pvsFront);
+	
+	float EvalCostRatio(VspKdLeaf *node,
+						const AxisAlignedBox3 &box,
+						const int axis,
+						const float position,
+						int &raysBack,
+						int &raysFront,
+						int &pvsBack,
+						int &pvsFront);
+
+
+	VspKdNode * SubdivideLeaf(VspKdLeaf *leaf,
+								  const float SAThreshold);
+
+	void RemoveRay(VssRay *ray,
+				   vector<VspKdLeaf *> *affectedLeaves,
+				   const bool removeAllScheduledRays);
+
+	void AddRay(VssRay *ray);
+	
+	void TraverseInternalNode(RayTraversalData &data,
+							 stack<RayTraversalData> &tstack);
+
+	void EvaluateLeafStats(const TraversalData &data);
+
+
+	int	GetRootPvsSize() const;
+	
+	int	GetPvsSize(VspKdNode *node, const AxisAlignedBox3 &box) const;
+
+	void GetRayContributionStatistics(float &minRayContribution,
+									  float &maxRayContribution,
+									  float &avgRayContribution);
+
+	int GenerateRays(const float ratioPerLeaf,
+					 SimpleRayContainer &rays);
+
+	/** Collapses this subtree and releases the memory.
+		@returns number of collapsed rays.
+	*/
+	int CollapseSubtree(VspKdNode *sroot, const int time);
+	
+	int ReleaseMemory(const int time);
+
+	bool TerminationCriteriaMet(const VspKdLeaf *leaf, 
+								const AxisAlignedBox3 &box) const;
+
+	/** Computes PVS size of this node given a global ray set.
+		@returns PVS size of the intersection of this node bounding box with the rays.
+	*/
+	int ComputePvsSize(VspKdNode *node, 
+					   const RayInfoContainer &globalRays) const;
+
+
+	/** Generates view cell for this leaf taking the ray contributions.
+	*/
+	void GenerateViewCell(VspKdLeaf *leaf);
+
+	/** Merges view cells of the two leaves.
+	*/
+	bool MergeViewCells(VspKdLeaf *l1, VspKdLeaf *l2);
+	
+	/** Helper function revalidating the view cell leaf list after merge.
+	*/
+	void RepairViewCellsLeafLists();
+
+	/** Shuffles the leaves, i.e., tests if exchanging
+		the view cells the leaves belong to helps in improving the view cells.
+	*/
+	bool ShuffleLeaves(VspKdLeaf *leaf1, VspKdLeaf *leaf2) const;
+
+	/** Shuffles, i.e. takes border leaf from view cell 1 and adds it 
+		to view cell 2.
+	*/
+	void ShuffleLeaf(VspKdLeaf *leaf,
+					 VspKdViewCell *vc1, 
+					 VspKdViewCell *vc2) const;
+protected:
+	
+
+	/////////////////////////////
+	// The core pointer
+	VspKdNode *mRoot;
+  
+	/////////////////////////////
+	// Basic properties
+
+	// total number of nodes of the tree
+	int mNumNodes;
+	
+	// axis aligned bounding box of the scene
+	AxisAlignedBox3 mBox;
+
+	// epsilon used for the construction
+	float mEpsilon;
+
+	// ratio between traversal and intersection costs
+	float mCtDivCi;
+	
+	// type of the splitting to use for the tree construction
+	enum {ESplitRegular, ESplitHeuristic};
+	int splitType;
+	
+	// maximum alovable memory in MB
+	float mMaxTotalMemory;
+
+	// maximum alovable memory for static kd tree in MB
+	float mMaxStaticMemory;
+
+	// this is used during the construction depending
+	// on the type of the tree and queries...
+	float mMaxMemory;
+
+	// minimal acess time for collapse
+	int mAccessTimeThreshold;
+
+	// minimal depth at which to perform collapse
+	int mMinCollapseDepth;
+	
+	// reusable array of split candidates
+	vector<SortableEntry> *mSplitCandidates;
+	
+	ViewCellsManager *mViewCellsManager;
+
+	priority_queue<VspKdMergeCandidate> mMergeQueue;
+
+
+	/////////////////////////////
+	// Construction parameters
+
+	/// max depth of the tree
+	int mTermMaxDepth;
+	/// minimal ratio of the volume of the cell and the query volume
+	float mTermMinSize;
+	/// minimal pvs per node to still get subdivided
+	int mTermMinPvs;
+	/// minimal ray number per node to still get subdivided
+	int mTermMinRays;
+	/// maximal acceptable cost ratio to continue subdivision
+	float mTermMaxCostRatio;
+	/// maximal contribution per ray to subdivide the node
+	float mTermMaxRayContribution;
+	/// tolerance value indicating how often the max cost ratio can be failed
+	int mTermMissTolerance;
+
+	/// maximal numbers of view cells
+	int mMaxViewCells;
+
+	/// maximal cost ratio of a merge
+	float mMergeMaxCostRatio;
+	
+	/// minimal number of view cells
+	int mMergeMinViewCells;
+
+	/// if only the "driving axis", i.e., the axis with the biggest extent
+	/// should be used for subdivision
+	bool mOnlyDrivingAxis;
+
+	/////////////////////////////
+	VspKdStatistics mStat;	
+};
+
+
+#endif // __VSP_KDTREE_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.cpp	(revision 599)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.cpp	(revision 599)
@@ -0,0 +1,57 @@
+#include <QApplication>
+
+#include "PreprocessorThread.h"
+#include "Camera.h"
+#include "KdTree.h"
+#include "SceneGraph.h"
+#include "Preprocessor.h"
+
+
+
+PreprocessorThread::PreprocessorThread(Preprocessor *p,
+									   QObject *parent):QThread(parent)
+{
+  mPreprocessor = p;
+  if (p->mQuitOnFinish)
+	connect(this, SIGNAL(finished()), qApp, SLOT(closeAllWindows(void)));
+}
+
+void
+PreprocessorThread::Main()
+{
+     
+  if (1) {
+    mPreprocessor->ComputeVisibility();
+	//	mPreprocessor->ExportPreprocessedData("scene.vis");
+  }
+  
+  Camera camera;
+
+  if (0) {
+    // camera.LookAtBox(mPreprocessor->mKdTree->GetBox());
+	//	camera.LookInBox(mPreprocessor->mKdTree->GetBox());
+	camera.SetPosition(Vector3(3473, 6.778, -1699));
+	camera.SetDirection(Vector3(-0.2432, 0, 0.97));
+    camera.SnapImage("camera.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph);
+  }
+  if (0) {
+    camera.LookInBox(mPreprocessor->mKdTree->GetBox());
+    camera.SetPosition(camera.mPosition + Vector3(-250,0,-550));
+    camera.SnapImage("camera2.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph);
+  }
+
+  if (0) {
+    camera.SetPosition( mPreprocessor->mKdTree->GetBox().Center() - Vector3(0,-100,0) );
+	camera.SetDirection(Vector3(1, 0, 0));
+	camera.SnapImage("camera3.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph);
+  }
+
+
+  cerr<<"Preprocessor main finished...\n";
+  
+}
+
+PreprocessorThread::~PreprocessorThread()
+{
+  cerr<<"Preprocessor thread destructor...\n";
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.h	(revision 490)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.h	(revision 490)
@@ -0,0 +1,22 @@
+#ifndef __X3DPARSER_H
+#define __X3DPARSER_H
+
+#include "Parser.h"
+#include "Containers.h"
+
+class ViewCellsManager;
+
+class X3dParser : public Parser
+{
+public:
+  X3dParser():Parser(), mViewCellHeight(5.0f) {}
+  
+  bool ParseFile(const string filename, SceneGraphNode **root);
+  bool ParseFile(const string filename, ViewCellsManager &viewCells);
+  
+  /// height of a loaded view cell
+  float mViewCellHeight;
+};
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingPreprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SamplingPreprocessor.cpp	(revision 574)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SamplingPreprocessor.cpp	(revision 574)
@@ -0,0 +1,448 @@
+#include "SceneGraph.h"
+#include "KdTree.h"
+#include "SamplingPreprocessor.h"
+#include "X3dExporter.h"
+#include "Environment.h"
+#include "MutualVisibility.h"
+#include "Polygon3.h"
+#include "ViewCell.h"
+#include "ViewCellsManager.h"
+#include "RenderSimulator.h"
+
+SamplingPreprocessor::SamplingPreprocessor(): mPass(0)
+{
+  // this should increase coherence of the samples
+  environment->GetIntValue("Sampling.samplesPerPass", mSamplesPerPass);
+  environment->GetIntValue("Sampling.totalSamples", mTotalSamples);
+ 
+  mStats.open("stats.log");
+}
+
+SamplingPreprocessor::~SamplingPreprocessor()
+{
+	CLEAR_CONTAINER(mSampleRays);
+	CLEAR_CONTAINER(mVssSampleRays);
+}
+
+void
+SamplingPreprocessor::SetupRay(Ray &ray, 
+							   const Vector3 &point, 
+							   const Vector3 &direction,
+							   const int type,
+							   const Ray::Intersection &origin)
+{
+  ray.Clear();
+  
+	ray.mFlags |= Ray::STORE_KDLEAVES | Ray::STORE_BSP_INTERSECTIONS;
+	//  cout<<point<<" "<<direction<<endl;
+
+	ray.Init(point, direction, type);
+	ray.sourceObject = origin;
+}
+
+void
+SamplingPreprocessor::HoleSamplingPass()
+{
+  vector<KdLeaf *> leaves;
+  mKdTree->CollectLeaves(leaves);
+  
+  // go through all the leaves and evaluate their passing contribution
+  for (int i=0 ; i < leaves.size(); i++) {
+    KdLeaf *leaf = leaves[i];
+    cout<<leaf->mPassingRays<<endl;
+  }
+}
+
+ 
+void
+SamplingPreprocessor::CastRays(const RayContainer &rays)
+{ 	
+  // cast ray to KD tree to find intersection with other objects
+  RayContainer::const_iterator it, it_end = rays.end();
+
+  VssRayContainer vssRays;
+  for (it = rays.begin(); it != it_end; ++it) {
+	mKdTree->CastRay(*(*it));
+	vssRays.push_back(new VssRay(*(*it)));
+  }
+  
+  mViewCellsManager->ComputeSampleContributions(vssRays, true, false);
+  CLEAR_CONTAINER(vssRays);
+}
+
+int
+SamplingPreprocessor::CastRay(Ray &ray)
+{
+	// cast ray to KD tree to find intersection with other objects
+	mKdTree->CastRay(ray);
+	VssRay vssRay(ray);
+
+	mViewCellsManager->ComputeSampleContributions(vssRay, true, false);
+	
+	return vssRay.mPvsContribution;
+}
+
+//  void
+//  SamplingPreprocessor::AvsGenerateRandomRay(Ray &ray)
+//  {
+//    int objId = RandomValue(0, mObjects.size());
+//    Intersectable *object = objects[objId];
+//    object->GetRandomSurfacePoint(point, normal);
+//    direction = UniformRandomVector(normal);
+//    SetupRay(ray, point, direction);
+//  }
+
+//  void
+//  SamplingPreprocessor::AvsHandleRay(Ray &ray)
+//  {
+//    int sampleContributions = 0;
+
+//    mKdTree->CastRay(ray);
+  
+//    if (ray.leaves.size()) {
+//      sampleContributions += AddNodeSamples(object, ray, pass);
+    
+//      if (ray.intersections.size()) {
+//        sampleContributions += AddNodeSamples(ray.intersections[0].mObject, ray, pass);
+//      }
+//    }
+//  }
+
+//  void
+//  SamplingPreprocessor::AvsBorderSampling(Ray &ray)
+//  {
+  
+
+//  }
+
+//  void
+//  SamplingPreprocessor::AvsPass()
+//  {
+//    Ray ray;
+//    while (1) {
+//      AvsGenerateRay(ray);
+//      HandleRay(ray);
+//      while ( !mRayQueue.empty() ) {
+//        Ray ray = mRayQueue.pop();
+//        mRayQueue.pop();
+//        AdaptiveBorderSampling(ray);
+//      }
+//    }
+  
+  
+
+//  }
+
+
+int
+SamplingPreprocessor::CastEdgeSamples(
+									  Intersectable *object,
+									  const Vector3 &point,
+									  MeshInstance *mi,
+									  const int samples
+									  )
+{
+	Ray ray;
+	int maxTries = samples*10;
+	int i;
+	int rays = 0;
+	int edgeSamplesContributions = 0;
+	for (i=0; i < maxTries && rays < samples; i++) {
+		// pickup a random face of each mesh 
+		Mesh *mesh = mi->GetMesh();
+		int face = (int)RandomValue(0, (Real)((int)mesh->mFaces.size() - 1));
+		
+		Polygon3 poly(mesh->mFaces[face], mesh);
+		poly.Scale(1.001f);
+		// now extend a random edge of the face
+		int edge = (int)RandomValue(0, (Real)((int)poly.mVertices.size() - 1));
+		float t = RandomValue(0.0f, 1.0f);
+		Vector3 target = t*poly.mVertices[edge] + (1.0f-t)*poly.mVertices[(edge + 1)%
+			poly.mVertices.size()];
+		SetupRay(ray, point, target - point, Ray::LOCAL_RAY, Ray::Intersection(0, object, 0));
+		if (!mesh->CastRay(ray, mi)) {
+			// the rays which intersect the mesh have been discarded since they are not tangent
+			// to the mesh
+			rays++;
+			edgeSamplesContributions += CastRay(ray);
+		}
+	}
+	return edgeSamplesContributions;
+}
+
+KdNode *
+SamplingPreprocessor::GetNodeToSample(Intersectable *object)
+{
+	int pvsSize = object->mKdPvs.GetSize();
+	KdNode *nodeToSample = NULL;
+	
+	bool samplePvsBoundary = false;
+	if (pvsSize && samplePvsBoundary) {
+		// this samples the nodes from the boundary of the current PVS
+		// mail all nodes from the pvs
+		Intersectable::NewMail();
+		KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
+		
+		for (; i != object->mKdPvs.mEntries.end(); i++) {
+			KdNode *node = (*i).first;
+			node->Mail();
+		}
+		
+		int maxTries = 2*pvsSize;
+		Debug << "Finding random neighbour" << endl;	
+		for (int tries = 0; tries < 10; tries++) {
+			int index = (int)RandomValue(0, (Real)(pvsSize - 1));
+			KdPvsData data;
+			KdNode *node;
+			object->mKdPvs.GetData(index, node, data);
+			nodeToSample = mKdTree->FindRandomNeighbor(node, true);
+			if (nodeToSample)
+				break;
+		}
+	} else {
+		// just pickup a random node
+		//		nodeToSample = mKdTree->GetRandomLeaf(Plane3(normal, point));
+		nodeToSample = mKdTree->GetRandomLeaf();
+	}
+	return nodeToSample;
+}
+
+void
+SamplingPreprocessor::VerifyVisibility(Intersectable *object)
+{
+	// mail all nodes from the pvs
+	Intersectable::NewMail();
+	KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
+	for (; i != object->mKdPvs.mEntries.end(); i++) {
+		KdNode *node = (*i).first;
+		node->Mail();
+	}
+	Debug << "Get all neighbours from PVS" << endl;
+	vector<KdNode *> invisibleNeighbors;
+	// get all neighbors of all PVS nodes
+	i = object->mKdPvs.mEntries.begin();
+	for (; i != object->mKdPvs.mEntries.end(); i++) {
+		KdNode *node = (*i).first;
+		mKdTree->FindNeighbors(node, invisibleNeighbors, true);
+		AxisAlignedBox3 box = object->GetBox();
+		for (int j=0; j < invisibleNeighbors.size(); j++) {
+			int visibility = ComputeBoxVisibility(mSceneGraph,
+							      mKdTree,
+							      box,
+							      mKdTree->GetBox(invisibleNeighbors[j]),
+							      1e-6f);
+			//	      exit(0);
+		}
+		// now rank all the neighbors according to probability that a new
+		// sample creates some contribution
+	}
+}
+
+bool
+SamplingPreprocessor::ComputeVisibility()
+{
+  
+  /// rays per pass
+  RayContainer passRays;
+
+
+  mViewCellsManager->SetViewSpaceBox(mKdTree->GetBox());
+  
+  Vector3 point, normal, direction;
+  //Ray ray;
+
+  long startTime = GetTime();
+  
+  int i;
+  int totalSamples = 0;
+
+  int pvsSize = 0;
+
+  while (totalSamples < mTotalSamples) {
+		int passContributingSamples = 0;
+		int passSampleContributions = 0;
+		int passSamples = 0;
+		int index = 0;
+		
+		int reverseSamples = 0;
+		
+		for (i = 0; i < mObjects.size(); i++) {
+						
+			KdNode *nodeToSample = NULL;
+			Intersectable *object = mObjects[i];
+		
+			int pvsSize = 0;
+			
+			if (0 && pvsSize && mPass == 1000 ) {
+				VerifyVisibility(object);
+			}
+			
+			int faceIndex = object->GetRandomSurfacePoint(point, normal);
+			
+			bool viewcellSample = true;
+			//int sampleContributions;
+			bool debug = false; //(object->GetId() >= 2199);
+			if (viewcellSample) {
+				//mKdTree->GetRandomLeaf(Plane3(normal, point));
+
+				nodeToSample = GetNodeToSample(object);
+
+				for (int k=0; k < mSamplesPerPass; k++) {
+					bool reverseSample = false;
+				
+					if (nodeToSample) {
+						AxisAlignedBox3 box = mKdTree->GetBox(nodeToSample);
+						Vector3 pointToSample = box.GetRandomPoint();
+						//						pointToSample.y = 0.9*box.Min().y + 0.1*box.Max().y;
+						if (object->GetRandomVisibleSurfacePoint( point, normal, pointToSample, 3 )) {
+							direction = pointToSample - point;
+						} else {
+							reverseSamples++;
+							reverseSample = true;
+							direction = point - pointToSample;
+							point = pointToSample;
+							//Debug << "point: " << pointToSample << endl;
+						}
+					}
+					else {
+						direction = UniformRandomVector(normal);
+					}
+					
+					Ray *ray = new Ray();
+
+					// construct a ray
+					SetupRay(*ray, point, direction, Ray::LOCAL_RAY, 
+							 Ray::Intersection(0, reverseSample ? NULL : object, faceIndex));
+
+					passRays.push_back(ray);
+					
+					//-- CORR matt: put block inside loop
+					/*if (sampleContributions) {
+						passContributingSamples ++;
+						passSampleContributions += sampleContributions;
+					}*/
+				}
+			} else {
+				// edge samples
+				// get random visible mesh
+				//				object->GetRandomVisibleMesh(Plane3(normal, point));
+			}
+	
+			// CORR matt: must add all samples
+			passSamples += mSamplesPerPass;
+		}
+	
+		//-------------------
+		// cast rays for view cells construction
+		ProcessViewCells(passRays,
+						 mObjects,
+						 passSampleContributions,
+						 passContributingSamples);
+
+		CLEAR_CONTAINER(passRays);
+		
+		totalSamples += passSamples; 
+		
+		//    if (pass>10)
+		//      HoleSamplingPass();
+    
+		mPass ++;
+        
+		pvsSize += passSampleContributions;
+		
+		float avgRayContrib = (passContributingSamples > 0) ? 
+			passSampleContributions / (float)passContributingSamples : 0;
+
+		cout << "#Pass " << mPass << " : t = " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
+		cout << "#TotalSamples=" << totalSamples/1000 
+				 << "k   #SampleContributions=" << passSampleContributions << " (" 
+				 << 100*passContributingSamples/(float)passSamples<<"%)" << " avgPVS="
+				 << (float)pvsSize /(float)mObjects.size() << endl 
+				 << "avg ray contrib=" << avgRayContrib << endl
+				 << "reverse samples [%]" << reverseSamples/(float)passSamples*100.0f << endl;
+
+		mStats <<
+			"#Pass\n" <<mPass<<endl<<
+			"#Time\n" << TimeDiff(startTime, GetTime())*1e-3 << endl<<
+			"#TotalSamples\n" << totalSamples<< endl<<
+			"#SampleContributions\n" << passSampleContributions << endl << 
+			"#PContributingSamples\n"<<100*passContributingSamples/(float)passSamples<<endl <<
+			"#AvgPVS\n"<< pvsSize/(float)mObjects.size() << endl <<
+			"#AvgRayContrib\n" << avgRayContrib << endl;
+	}
+	
+	//cout << "#totalKdPvsSize=" << mKdTree->CollectLeafPvs() << endl;
+	
+  //  HoleSamplingPass();
+	if (0) {
+		Exporter *exporter = Exporter::GetExporter("ray-density.x3d"); 
+		exporter->SetExportRayDensity(true);
+		exporter->ExportKdTree(*mKdTree);
+		delete exporter;
+	}
+	
+	// construct view cells if not already constructed
+	if (!mViewCellsManager->ViewCellsConstructed())
+	  mViewCellsManager->ConstructSubdivision(mObjects, mVssSampleRays);
+
+	// $$JB temporary removed
+	//	mViewCellsManager->PostProcess(objects, mSampleRays);
+	
+	//-- several visualizations and statistics
+	Debug << "view cells after post processing: " << endl;
+	mViewCellsManager->PrintStatistics(Debug);
+
+	//-- render simulation after merge
+	cout << "\nevaluating bsp view cells render time after merge ... ";
+	
+	 mRenderSimulator->RenderScene();
+	 SimulationStatistics ss;
+	 mRenderSimulator->GetStatistics(ss);
+	 
+	 cout << " finished" << endl;
+	 cout << ss << endl;
+	 Debug << ss << endl;
+	
+	// $$JB temporary removed
+	//mViewCellsManager->Visualize(objects, mSampleRays);	
+   
+	return true;
+}
+
+void SamplingPreprocessor::ProcessViewCells(const RayContainer &newRays,
+											const ObjectContainer &objects,
+											int &sampleContributions,
+											int &contributingSamples)
+{
+  // cast rays to view cells
+  CastRays(newRays);
+
+  // save rays for view cells construction
+  if (!mViewCellsManager->ViewCellsConstructed())
+	{
+	  if ((int)mVssSampleRays.size() < mViewCellsManager->GetConstructionSamples())
+		{
+		  RayContainer::const_iterator it, it_end = newRays.end();
+		  
+		  for (it = newRays.begin(); it != it_end; ++ it)
+			mVssSampleRays.push_back(new VssRay(*(*it)));
+		}
+	  else
+		{
+		  // construct view cells
+		  mViewCellsManager->ConstructSubdivision(objects, mVssSampleRays);
+		  
+		  // throw away samples 
+		  //CLEAR_CONTAINER(mVssSampleRays);
+		}
+	}
+  // Need rays (with ordered intersections) for post processing => collect new rays
+  if (((int)mSampleRays.size() < mViewCellsManager->GetPostProcessSamples()) ||
+	  ((int)mSampleRays.size() < mViewCellsManager->GetVisualizationSamples()))
+	{
+	  RayContainer::const_iterator it, it_end = newRays.end();
+	  
+	  for (it = newRays.begin(); it != it_end; ++ it)
+		mSampleRays.push_back(new Ray(*(*it)));
+	}
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GL/glut.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GL/glut.h	(revision 498)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GL/glut.h	(revision 498)
@@ -0,0 +1,743 @@
+#ifndef __glut_h__
+#define __glut_h__
+
+/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998, 2000. */
+
+/* This program is freely distributable without licensing fees  and is
+   provided without guarantee or warrantee expressed or  implied. This
+   program is -not- in the public domain. */
+
+#ifdef _WIN32
+
+/* GLUT 3.7 now tries to avoid including <windows.h>
+   to avoid name space pollution, but Win32's <GL/gl.h> 
+   needs APIENTRY and WINGDIAPI defined properly. */
+# if 0
+   /* This would put tons of macros and crap in our clean name space. */
+#  define  WIN32_LEAN_AND_MEAN
+#  include <windows.h>
+# else
+   /* XXX This is from Win32's <windef.h> */
+#  ifndef APIENTRY
+#   define GLUT_APIENTRY_DEFINED
+    /* Cygwin and MingW32 are two free GNU-based Open Source compilation
+       environments for Win32.  Note that __CYGWIN32__ is deprecated
+       in favor of simply __CYGWIN__. */
+#   if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
+#    ifdef i386
+#     define APIENTRY __attribute__ ((stdcall)) 
+#    else
+#     define APIENTRY
+#    endif
+#   else
+#    if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
+#     define APIENTRY    __stdcall
+#    else
+#     define APIENTRY
+#    endif
+#   endif
+#  endif
+   /* XXX This is from Win32's <winnt.h> */
+#  ifndef CALLBACK
+#   if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
+#    define CALLBACK __attribute__ ((stdcall)) 
+#   else
+#    if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
+#     define CALLBACK __stdcall
+#    else
+#     define CALLBACK
+#    endif
+#   endif
+#  endif
+   /* XXX This is from Win32's <wingdi.h> and <winnt.h> */
+#  ifndef WINGDIAPI
+#   define GLUT_WINGDIAPI_DEFINED
+#   if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
+#    define WINGDIAPI
+#   else
+#    define WINGDIAPI __declspec(dllimport)
+#   endif
+#  endif
+#  if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
+    /* Rely on Cygwin32/MingW32 <stddef.h> to set wchar_t. */
+    /* XXX Warning.  The Cygwin32/MingW32 definition for wchar_t
+       is an "int" instead of the "short" used by Windows. */
+#   include <stddef.h>
+#  else
+    /* XXX This is from Win32's <ctype.h> */
+#   ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#    define _WCHAR_T_DEFINED
+#   endif
+#  endif
+# endif
+
+/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA
+   in your compile preprocessor options. */
+# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA)
+#  pragma comment (lib, "winmm.lib")      /* link with Windows MultiMedia lib */
+/* To enable automatic SGI OpenGL for Windows library usage for GLUT,
+   define GLUT_USE_SGI_OPENGL in your compile preprocessor options.  */
+#  ifdef GLUT_USE_SGI_OPENGL
+#   pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */
+#   pragma comment (lib, "glu.lib")    /* link with SGI OpenGL Utility lib */
+#   pragma comment (lib, "glut.lib")   /* link with Win32 GLUT for SGI OpenGL lib */
+#  else
+#   pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */
+#   pragma comment (lib, "glu32.lib")    /* link with Microsoft OpenGL Utility lib */
+#   pragma comment (lib, "glut32.lib")   /* link with Win32 GLUT lib */
+#  endif
+# endif
+
+/* To disable supression of annoying warnings about floats being promoted
+   to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor
+   options. */
+# if defined(_MSC_VER) && !defined(GLUT_NO_WARNING_DISABLE)
+#  pragma warning (disable:4244)  /* Disable bogus VC++ 4.2 conversion warnings. */
+#  pragma warning (disable:4305)  /* VC++ 5.0 version of above warning. */
+# endif
+
+/* Win32 has an annoying issue where there are multiple C run-time
+   libraries (CRTs).  If the executable is linked with a different CRT
+   from the GLUT DLL, the GLUT DLL will not share the same CRT static
+   data seen by the executable.  In particular, atexit callbacks registered
+   in the executable will not be called if GLUT calls its (different)
+   exit routine).  GLUT is typically built with the
+   "/MD" option (the CRT with multithreading DLL support), but the Visual
+   C++ linker default is "/ML" (the single threaded CRT).
+
+   One workaround to this issue is requiring users to always link with
+   the same CRT as GLUT is compiled with.  That requires users supply a
+   non-standard option.  GLUT 3.7 has its own built-in workaround where
+   the executable's "exit" function pointer is covertly passed to GLUT.
+   GLUT then calls the executable's exit function pointer to ensure that
+   any "atexit" calls registered by the application are called if GLUT
+   needs to exit.
+
+   Note that the __glut*WithExit routines should NEVER be called directly.
+   To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */
+
+/* XXX This is from Win32's <process.h> */
+# if !defined(_MSC_VER) && !defined(__cdecl)
+   /* Define __cdecl for non-Microsoft compilers. */
+#  define __cdecl
+#  define GLUT_DEFINED___CDECL
+# endif
+# ifndef _CRTIMP
+#  ifdef _NTSDK
+    /* Definition compatible with NT SDK */
+#   define _CRTIMP
+#  else
+    /* Current definition */
+#   ifdef _DLL
+#    define _CRTIMP __declspec(dllimport)
+#   else
+#    define _CRTIMP
+#   endif
+#  endif
+#  define GLUT_DEFINED__CRTIMP
+# endif
+
+/* GLUT API entry point declarations for Win32. */
+# ifdef GLUT_BUILDING_LIB
+#  define GLUTAPI __declspec(dllexport)
+# else
+#  ifdef _DLL
+#   define GLUTAPI __declspec(dllimport)
+#  else
+#   define GLUTAPI extern
+#  endif
+# endif
+
+/* GLUT callback calling convention for Win32. */
+# define GLUTCALLBACK __cdecl
+
+#endif  /* _WIN32 */
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+# ifndef GLUT_BUILDING_LIB
+#if     _MSC_VER >= 1200
+extern _CRTIMP __declspec(noreturn) void   __cdecl exit(int);
+#else
+extern _CRTIMP void   __cdecl exit(int);
+#endif
+//extern _CRTIMP void __cdecl exit(int);
+# endif
+#else
+/* non-Win32 case. */
+/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */
+# define APIENTRY
+# define GLUT_APIENTRY_DEFINED
+# define CALLBACK
+/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */
+# define GLUTAPI extern
+# define GLUTCALLBACK
+/* Prototype exit for the non-Win32 case (see above). */
+extern void exit(int);
+#endif
+
+/**
+ GLUT API revision history:
+ 
+ GLUT_API_VERSION is updated to reflect incompatible GLUT
+ API changes (interface changes, semantic changes, deletions,
+ or additions).
+ 
+ GLUT_API_VERSION=1  First public release of GLUT.  11/29/94
+
+ GLUT_API_VERSION=2  Added support for OpenGL/GLX multisampling,
+ extension.  Supports new input devices like tablet, dial and button
+ box, and Spaceball.  Easy to query OpenGL extensions.
+
+ GLUT_API_VERSION=3  glutMenuStatus added.
+
+ GLUT_API_VERSION=4  glutInitDisplayString, glutWarpPointer,
+ glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic
+ video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc,
+ glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat,
+ glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!).
+**/
+#ifndef GLUT_API_VERSION  /* allow this to be overriden */
+#define GLUT_API_VERSION		3
+#endif
+
+/**
+ GLUT implementation revision history:
+ 
+ GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT
+ API revisions and implementation revisions (ie, bug fixes).
+
+ GLUT_XLIB_IMPLEMENTATION=1  mjk's first public release of
+ GLUT Xlib-based implementation.  11/29/94
+
+ GLUT_XLIB_IMPLEMENTATION=2  mjk's second public release of
+ GLUT Xlib-based implementation providing GLUT version 2 
+ interfaces.
+
+ GLUT_XLIB_IMPLEMENTATION=3  mjk's GLUT 2.2 images. 4/17/95
+
+ GLUT_XLIB_IMPLEMENTATION=4  mjk's GLUT 2.3 images. 6/?/95
+
+ GLUT_XLIB_IMPLEMENTATION=5  mjk's GLUT 3.0 images. 10/?/95
+
+ GLUT_XLIB_IMPLEMENTATION=7  mjk's GLUT 3.1+ with glutWarpPoitner.  7/24/96
+
+ GLUT_XLIB_IMPLEMENTATION=8  mjk's GLUT 3.1+ with glutWarpPoitner
+ and video resize.  1/3/97
+
+ GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines.
+
+ GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release.
+
+ GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling.
+
+ GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support.
+
+ GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface.
+
+ GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa <GL/glut.h>
+
+ GLUT_XLIB_IMPLEMENTATION=16 mjk's GLUT 3.8 
+**/
+#ifndef GLUT_XLIB_IMPLEMENTATION  /* Allow this to be overriden. */
+#define GLUT_XLIB_IMPLEMENTATION	16
+#endif
+
+/* Display mode bit masks. */
+#define GLUT_RGB			0
+#define GLUT_RGBA			GLUT_RGB
+#define GLUT_INDEX			1
+#define GLUT_SINGLE			0
+#define GLUT_DOUBLE			2
+#define GLUT_ACCUM			4
+#define GLUT_ALPHA			8
+#define GLUT_DEPTH			16
+#define GLUT_STENCIL			32
+#if (GLUT_API_VERSION >= 2)
+#define GLUT_MULTISAMPLE		128
+#define GLUT_STEREO			256
+#endif
+#if (GLUT_API_VERSION >= 3)
+#define GLUT_LUMINANCE			512
+#endif
+
+/* Mouse buttons. */
+#define GLUT_LEFT_BUTTON		0
+#define GLUT_MIDDLE_BUTTON		1
+#define GLUT_RIGHT_BUTTON		2
+
+/* Mouse button  state. */
+#define GLUT_DOWN			0
+#define GLUT_UP				1
+
+#if (GLUT_API_VERSION >= 2)
+/* function keys */
+#define GLUT_KEY_F1			1
+#define GLUT_KEY_F2			2
+#define GLUT_KEY_F3			3
+#define GLUT_KEY_F4			4
+#define GLUT_KEY_F5			5
+#define GLUT_KEY_F6			6
+#define GLUT_KEY_F7			7
+#define GLUT_KEY_F8			8
+#define GLUT_KEY_F9			9
+#define GLUT_KEY_F10			10
+#define GLUT_KEY_F11			11
+#define GLUT_KEY_F12			12
+/* directional keys */
+#define GLUT_KEY_LEFT			100
+#define GLUT_KEY_UP			101
+#define GLUT_KEY_RIGHT			102
+#define GLUT_KEY_DOWN			103
+#define GLUT_KEY_PAGE_UP		104
+#define GLUT_KEY_PAGE_DOWN		105
+#define GLUT_KEY_HOME			106
+#define GLUT_KEY_END			107
+#define GLUT_KEY_INSERT			108
+#endif
+
+/* Entry/exit  state. */
+#define GLUT_LEFT			0
+#define GLUT_ENTERED			1
+
+/* Menu usage  state. */
+#define GLUT_MENU_NOT_IN_USE		0
+#define GLUT_MENU_IN_USE		1
+
+/* Visibility  state. */
+#define GLUT_NOT_VISIBLE		0
+#define GLUT_VISIBLE			1
+
+/* Window status  state. */
+#define GLUT_HIDDEN			0
+#define GLUT_FULLY_RETAINED		1
+#define GLUT_PARTIALLY_RETAINED		2
+#define GLUT_FULLY_COVERED		3
+
+/* Color index component selection values. */
+#define GLUT_RED			0
+#define GLUT_GREEN			1
+#define GLUT_BLUE			2
+
+#ifdef _WIN32
+/* Stroke font constants (use these in GLUT program). */
+#define GLUT_STROKE_ROMAN		((void*)0)
+#define GLUT_STROKE_MONO_ROMAN		((void*)1)
+
+/* Bitmap font constants (use these in GLUT program). */
+#define GLUT_BITMAP_9_BY_15		((void*)2)
+#define GLUT_BITMAP_8_BY_13		((void*)3)
+#define GLUT_BITMAP_TIMES_ROMAN_10	((void*)4)
+#define GLUT_BITMAP_TIMES_ROMAN_24	((void*)5)
+#if (GLUT_API_VERSION >= 3)
+#define GLUT_BITMAP_HELVETICA_10	((void*)6)
+#define GLUT_BITMAP_HELVETICA_12	((void*)7)
+#define GLUT_BITMAP_HELVETICA_18	((void*)8)
+#endif
+#else
+/* Stroke font opaque addresses (use constants instead in source code). */
+GLUTAPI void *glutStrokeRoman;
+GLUTAPI void *glutStrokeMonoRoman;
+
+/* Stroke font constants (use these in GLUT program). */
+#define GLUT_STROKE_ROMAN		(&glutStrokeRoman)
+#define GLUT_STROKE_MONO_ROMAN		(&glutStrokeMonoRoman)
+
+/* Bitmap font opaque addresses (use constants instead in source code). */
+GLUTAPI void *glutBitmap9By15;
+GLUTAPI void *glutBitmap8By13;
+GLUTAPI void *glutBitmapTimesRoman10;
+GLUTAPI void *glutBitmapTimesRoman24;
+GLUTAPI void *glutBitmapHelvetica10;
+GLUTAPI void *glutBitmapHelvetica12;
+GLUTAPI void *glutBitmapHelvetica18;
+
+/* Bitmap font constants (use these in GLUT program). */
+#define GLUT_BITMAP_9_BY_15		(&glutBitmap9By15)
+#define GLUT_BITMAP_8_BY_13		(&glutBitmap8By13)
+#define GLUT_BITMAP_TIMES_ROMAN_10	(&glutBitmapTimesRoman10)
+#define GLUT_BITMAP_TIMES_ROMAN_24	(&glutBitmapTimesRoman24)
+#if (GLUT_API_VERSION >= 3)
+#define GLUT_BITMAP_HELVETICA_10	(&glutBitmapHelvetica10)
+#define GLUT_BITMAP_HELVETICA_12	(&glutBitmapHelvetica12)
+#define GLUT_BITMAP_HELVETICA_18	(&glutBitmapHelvetica18)
+#endif
+#endif
+
+/* glutGet parameters. */
+#define GLUT_WINDOW_X			((GLenum) 100)
+#define GLUT_WINDOW_Y			((GLenum) 101)
+#define GLUT_WINDOW_WIDTH		((GLenum) 102)
+#define GLUT_WINDOW_HEIGHT		((GLenum) 103)
+#define GLUT_WINDOW_BUFFER_SIZE		((GLenum) 104)
+#define GLUT_WINDOW_STENCIL_SIZE	((GLenum) 105)
+#define GLUT_WINDOW_DEPTH_SIZE		((GLenum) 106)
+#define GLUT_WINDOW_RED_SIZE		((GLenum) 107)
+#define GLUT_WINDOW_GREEN_SIZE		((GLenum) 108)
+#define GLUT_WINDOW_BLUE_SIZE		((GLenum) 109)
+#define GLUT_WINDOW_ALPHA_SIZE		((GLenum) 110)
+#define GLUT_WINDOW_ACCUM_RED_SIZE	((GLenum) 111)
+#define GLUT_WINDOW_ACCUM_GREEN_SIZE	((GLenum) 112)
+#define GLUT_WINDOW_ACCUM_BLUE_SIZE	((GLenum) 113)
+#define GLUT_WINDOW_ACCUM_ALPHA_SIZE	((GLenum) 114)
+#define GLUT_WINDOW_DOUBLEBUFFER	((GLenum) 115)
+#define GLUT_WINDOW_RGBA		((GLenum) 116)
+#define GLUT_WINDOW_PARENT		((GLenum) 117)
+#define GLUT_WINDOW_NUM_CHILDREN	((GLenum) 118)
+#define GLUT_WINDOW_COLORMAP_SIZE	((GLenum) 119)
+#if (GLUT_API_VERSION >= 2)
+#define GLUT_WINDOW_NUM_SAMPLES		((GLenum) 120)
+#define GLUT_WINDOW_STEREO		((GLenum) 121)
+#endif
+#if (GLUT_API_VERSION >= 3)
+#define GLUT_WINDOW_CURSOR		((GLenum) 122)
+#endif
+#define GLUT_SCREEN_WIDTH		((GLenum) 200)
+#define GLUT_SCREEN_HEIGHT		((GLenum) 201)
+#define GLUT_SCREEN_WIDTH_MM		((GLenum) 202)
+#define GLUT_SCREEN_HEIGHT_MM		((GLenum) 203)
+#define GLUT_MENU_NUM_ITEMS		((GLenum) 300)
+#define GLUT_DISPLAY_MODE_POSSIBLE	((GLenum) 400)
+#define GLUT_INIT_WINDOW_X		((GLenum) 500)
+#define GLUT_INIT_WINDOW_Y		((GLenum) 501)
+#define GLUT_INIT_WINDOW_WIDTH		((GLenum) 502)
+#define GLUT_INIT_WINDOW_HEIGHT		((GLenum) 503)
+#define GLUT_INIT_DISPLAY_MODE		((GLenum) 504)
+#if (GLUT_API_VERSION >= 2)
+#define GLUT_ELAPSED_TIME		((GLenum) 700)
+#endif
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
+#define GLUT_WINDOW_FORMAT_ID		((GLenum) 123)
+#endif
+
+#if (GLUT_API_VERSION >= 2)
+/* glutDeviceGet parameters. */
+#define GLUT_HAS_KEYBOARD		((GLenum) 600)
+#define GLUT_HAS_MOUSE			((GLenum) 601)
+#define GLUT_HAS_SPACEBALL		((GLenum) 602)
+#define GLUT_HAS_DIAL_AND_BUTTON_BOX	((GLenum) 603)
+#define GLUT_HAS_TABLET			((GLenum) 604)
+#define GLUT_NUM_MOUSE_BUTTONS		((GLenum) 605)
+#define GLUT_NUM_SPACEBALL_BUTTONS	((GLenum) 606)
+#define GLUT_NUM_BUTTON_BOX_BUTTONS	((GLenum) 607)
+#define GLUT_NUM_DIALS			((GLenum) 608)
+#define GLUT_NUM_TABLET_BUTTONS		((GLenum) 609)
+#endif
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
+#define GLUT_DEVICE_IGNORE_KEY_REPEAT   ((GLenum) 610)
+#define GLUT_DEVICE_KEY_REPEAT          ((GLenum) 611)
+#define GLUT_HAS_JOYSTICK		((GLenum) 612)
+#define GLUT_OWNS_JOYSTICK		((GLenum) 613)
+#define GLUT_JOYSTICK_BUTTONS		((GLenum) 614)
+#define GLUT_JOYSTICK_AXES		((GLenum) 615)
+#define GLUT_JOYSTICK_POLL_RATE		((GLenum) 616)
+#endif
+
+#if (GLUT_API_VERSION >= 3)
+/* glutLayerGet parameters. */
+#define GLUT_OVERLAY_POSSIBLE           ((GLenum) 800)
+#define GLUT_LAYER_IN_USE		((GLenum) 801)
+#define GLUT_HAS_OVERLAY		((GLenum) 802)
+#define GLUT_TRANSPARENT_INDEX		((GLenum) 803)
+#define GLUT_NORMAL_DAMAGED		((GLenum) 804)
+#define GLUT_OVERLAY_DAMAGED		((GLenum) 805)
+
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+/* glutVideoResizeGet parameters. */
+#define GLUT_VIDEO_RESIZE_POSSIBLE	((GLenum) 900)
+#define GLUT_VIDEO_RESIZE_IN_USE	((GLenum) 901)
+#define GLUT_VIDEO_RESIZE_X_DELTA	((GLenum) 902)
+#define GLUT_VIDEO_RESIZE_Y_DELTA	((GLenum) 903)
+#define GLUT_VIDEO_RESIZE_WIDTH_DELTA	((GLenum) 904)
+#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA	((GLenum) 905)
+#define GLUT_VIDEO_RESIZE_X		((GLenum) 906)
+#define GLUT_VIDEO_RESIZE_Y		((GLenum) 907)
+#define GLUT_VIDEO_RESIZE_WIDTH		((GLenum) 908)
+#define GLUT_VIDEO_RESIZE_HEIGHT	((GLenum) 909)
+#endif
+
+/* glutUseLayer parameters. */
+#define GLUT_NORMAL			((GLenum) 0)
+#define GLUT_OVERLAY			((GLenum) 1)
+
+/* glutGetModifiers return mask. */
+#define GLUT_ACTIVE_SHIFT               1
+#define GLUT_ACTIVE_CTRL                2
+#define GLUT_ACTIVE_ALT                 4
+
+/* glutSetCursor parameters. */
+/* Basic arrows. */
+#define GLUT_CURSOR_RIGHT_ARROW		0
+#define GLUT_CURSOR_LEFT_ARROW		1
+/* Symbolic cursor shapes. */
+#define GLUT_CURSOR_INFO		2
+#define GLUT_CURSOR_DESTROY		3
+#define GLUT_CURSOR_HELP		4
+#define GLUT_CURSOR_CYCLE		5
+#define GLUT_CURSOR_SPRAY		6
+#define GLUT_CURSOR_WAIT		7
+#define GLUT_CURSOR_TEXT		8
+#define GLUT_CURSOR_CROSSHAIR		9
+/* Directional cursors. */
+#define GLUT_CURSOR_UP_DOWN		10
+#define GLUT_CURSOR_LEFT_RIGHT		11
+/* Sizing cursors. */
+#define GLUT_CURSOR_TOP_SIDE		12
+#define GLUT_CURSOR_BOTTOM_SIDE		13
+#define GLUT_CURSOR_LEFT_SIDE		14
+#define GLUT_CURSOR_RIGHT_SIDE		15
+#define GLUT_CURSOR_TOP_LEFT_CORNER	16
+#define GLUT_CURSOR_TOP_RIGHT_CORNER	17
+#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER	18
+#define GLUT_CURSOR_BOTTOM_LEFT_CORNER	19
+/* Inherit from parent window. */
+#define GLUT_CURSOR_INHERIT		100
+/* Blank cursor. */
+#define GLUT_CURSOR_NONE		101
+/* Fullscreen crosshair (if available). */
+#define GLUT_CURSOR_FULL_CROSSHAIR	102
+#endif
+
+/* GLUT initialization sub-API. */
+GLUTAPI void APIENTRY glutInit(int *argcp, char **argv);
+#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
+GLUTAPI void APIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int));
+#ifndef GLUT_BUILDING_LIB
+static void APIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); }
+#define glutInit glutInit_ATEXIT_HACK
+#endif
+#endif
+GLUTAPI void APIENTRY glutInitDisplayMode(unsigned int mode);
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+GLUTAPI void APIENTRY glutInitDisplayString(const char *string);
+#endif
+GLUTAPI void APIENTRY glutInitWindowPosition(int x, int y);
+GLUTAPI void APIENTRY glutInitWindowSize(int width, int height);
+GLUTAPI void APIENTRY glutMainLoop(void);
+
+/* GLUT window sub-API. */
+GLUTAPI int APIENTRY glutCreateWindow(const char *title);
+#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
+GLUTAPI int APIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int));
+#ifndef GLUT_BUILDING_LIB
+static int APIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); }
+#define glutCreateWindow glutCreateWindow_ATEXIT_HACK
+#endif
+#endif
+GLUTAPI int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height);
+GLUTAPI void APIENTRY glutDestroyWindow(int win);
+GLUTAPI void APIENTRY glutPostRedisplay(void);
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11)
+GLUTAPI void APIENTRY glutPostWindowRedisplay(int win);
+#endif
+GLUTAPI void APIENTRY glutSwapBuffers(void);
+GLUTAPI int APIENTRY glutGetWindow(void);
+GLUTAPI void APIENTRY glutSetWindow(int win);
+GLUTAPI void APIENTRY glutSetWindowTitle(const char *title);
+GLUTAPI void APIENTRY glutSetIconTitle(const char *title);
+GLUTAPI void APIENTRY glutPositionWindow(int x, int y);
+GLUTAPI void APIENTRY glutReshapeWindow(int width, int height);
+GLUTAPI void APIENTRY glutPopWindow(void);
+GLUTAPI void APIENTRY glutPushWindow(void);
+GLUTAPI void APIENTRY glutIconifyWindow(void);
+GLUTAPI void APIENTRY glutShowWindow(void);
+GLUTAPI void APIENTRY glutHideWindow(void);
+#if (GLUT_API_VERSION >= 3)
+GLUTAPI void APIENTRY glutFullScreen(void);
+GLUTAPI void APIENTRY glutSetCursor(int cursor);
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+GLUTAPI void APIENTRY glutWarpPointer(int x, int y);
+#endif
+
+/* GLUT overlay sub-API. */
+GLUTAPI void APIENTRY glutEstablishOverlay(void);
+GLUTAPI void APIENTRY glutRemoveOverlay(void);
+GLUTAPI void APIENTRY glutUseLayer(GLenum layer);
+GLUTAPI void APIENTRY glutPostOverlayRedisplay(void);
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11)
+GLUTAPI void APIENTRY glutPostWindowOverlayRedisplay(int win);
+#endif
+GLUTAPI void APIENTRY glutShowOverlay(void);
+GLUTAPI void APIENTRY glutHideOverlay(void);
+#endif
+
+/* GLUT menu sub-API. */
+GLUTAPI int APIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int));
+#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
+GLUTAPI int APIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int));
+#ifndef GLUT_BUILDING_LIB
+static int APIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); }
+#define glutCreateMenu glutCreateMenu_ATEXIT_HACK
+#endif
+#endif
+GLUTAPI void APIENTRY glutDestroyMenu(int menu);
+GLUTAPI int APIENTRY glutGetMenu(void);
+GLUTAPI void APIENTRY glutSetMenu(int menu);
+GLUTAPI void APIENTRY glutAddMenuEntry(const char *label, int value);
+GLUTAPI void APIENTRY glutAddSubMenu(const char *label, int submenu);
+GLUTAPI void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value);
+GLUTAPI void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu);
+GLUTAPI void APIENTRY glutRemoveMenuItem(int item);
+GLUTAPI void APIENTRY glutAttachMenu(int button);
+GLUTAPI void APIENTRY glutDetachMenu(int button);
+
+/* GLUT window callback sub-API. */
+GLUTAPI void APIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void));
+GLUTAPI void APIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height));
+GLUTAPI void APIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y));
+GLUTAPI void APIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y));
+GLUTAPI void APIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
+GLUTAPI void APIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
+GLUTAPI void APIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state));
+GLUTAPI void APIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state));
+GLUTAPI void APIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void));
+GLUTAPI void APIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value);
+GLUTAPI void APIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state));
+#if (GLUT_API_VERSION >= 2)
+GLUTAPI void APIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y));
+GLUTAPI void APIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z));
+GLUTAPI void APIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z));
+GLUTAPI void APIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state));
+GLUTAPI void APIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state));
+GLUTAPI void APIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value));
+GLUTAPI void APIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
+GLUTAPI void APIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y));
+#if (GLUT_API_VERSION >= 3)
+GLUTAPI void APIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y));
+GLUTAPI void APIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void));
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+GLUTAPI void APIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state));
+#endif
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
+GLUTAPI void APIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y));
+GLUTAPI void APIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y));
+GLUTAPI void APIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval);
+#endif
+#endif
+#endif
+
+/* GLUT color index sub-API. */
+GLUTAPI void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue);
+GLUTAPI GLfloat APIENTRY glutGetColor(int ndx, int component);
+GLUTAPI void APIENTRY glutCopyColormap(int win);
+
+/* GLUT state retrieval sub-API. */
+GLUTAPI int APIENTRY glutGet(GLenum type);
+GLUTAPI int APIENTRY glutDeviceGet(GLenum type);
+#if (GLUT_API_VERSION >= 2)
+/* GLUT extension support sub-API */
+GLUTAPI int APIENTRY glutExtensionSupported(const char *name);
+#endif
+#if (GLUT_API_VERSION >= 3)
+GLUTAPI int APIENTRY glutGetModifiers(void);
+GLUTAPI int APIENTRY glutLayerGet(GLenum type);
+#endif
+
+/* GLUT font sub-API */
+GLUTAPI void APIENTRY glutBitmapCharacter(void *font, int character);
+GLUTAPI int APIENTRY glutBitmapWidth(void *font, int character);
+GLUTAPI void APIENTRY glutStrokeCharacter(void *font, int character);
+GLUTAPI int APIENTRY glutStrokeWidth(void *font, int character);
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+GLUTAPI int APIENTRY glutBitmapLength(void *font, const unsigned char *string);
+GLUTAPI int APIENTRY glutStrokeLength(void *font, const unsigned char *string);
+#endif
+
+/* GLUT pre-built models sub-API */
+GLUTAPI void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks);
+GLUTAPI void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks);
+GLUTAPI void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);
+GLUTAPI void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);
+GLUTAPI void APIENTRY glutWireCube(GLdouble size);
+GLUTAPI void APIENTRY glutSolidCube(GLdouble size);
+GLUTAPI void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings);
+GLUTAPI void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings);
+GLUTAPI void APIENTRY glutWireDodecahedron(void);
+GLUTAPI void APIENTRY glutSolidDodecahedron(void);
+GLUTAPI void APIENTRY glutWireTeapot(GLdouble size);
+GLUTAPI void APIENTRY glutSolidTeapot(GLdouble size);
+GLUTAPI void APIENTRY glutWireOctahedron(void);
+GLUTAPI void APIENTRY glutSolidOctahedron(void);
+GLUTAPI void APIENTRY glutWireTetrahedron(void);
+GLUTAPI void APIENTRY glutSolidTetrahedron(void);
+GLUTAPI void APIENTRY glutWireIcosahedron(void);
+GLUTAPI void APIENTRY glutSolidIcosahedron(void);
+
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+/* GLUT video resize sub-API. */
+GLUTAPI int APIENTRY glutVideoResizeGet(GLenum param);
+GLUTAPI void APIENTRY glutSetupVideoResizing(void);
+GLUTAPI void APIENTRY glutStopVideoResizing(void);
+GLUTAPI void APIENTRY glutVideoResize(int x, int y, int width, int height);
+GLUTAPI void APIENTRY glutVideoPan(int x, int y, int width, int height);
+
+/* GLUT debugging sub-API. */
+GLUTAPI void APIENTRY glutReportErrors(void);
+#endif
+
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
+/* GLUT device control sub-API. */
+/* glutSetKeyRepeat modes. */
+#define GLUT_KEY_REPEAT_OFF		0
+#define GLUT_KEY_REPEAT_ON		1
+#define GLUT_KEY_REPEAT_DEFAULT		2
+
+/* Joystick button masks. */
+#define GLUT_JOYSTICK_BUTTON_A		1
+#define GLUT_JOYSTICK_BUTTON_B		2
+#define GLUT_JOYSTICK_BUTTON_C		4
+#define GLUT_JOYSTICK_BUTTON_D		8
+
+GLUTAPI void APIENTRY glutIgnoreKeyRepeat(int ignore);
+GLUTAPI void APIENTRY glutSetKeyRepeat(int repeatMode);
+GLUTAPI void APIENTRY glutForceJoystickFunc(void);
+
+/* GLUT game mode sub-API. */
+/* glutGameModeGet. */
+#define GLUT_GAME_MODE_ACTIVE           ((GLenum) 0)
+#define GLUT_GAME_MODE_POSSIBLE         ((GLenum) 1)
+#define GLUT_GAME_MODE_WIDTH            ((GLenum) 2)
+#define GLUT_GAME_MODE_HEIGHT           ((GLenum) 3)
+#define GLUT_GAME_MODE_PIXEL_DEPTH      ((GLenum) 4)
+#define GLUT_GAME_MODE_REFRESH_RATE     ((GLenum) 5)
+#define GLUT_GAME_MODE_DISPLAY_CHANGED  ((GLenum) 6)
+
+GLUTAPI void APIENTRY glutGameModeString(const char *string);
+GLUTAPI int APIENTRY glutEnterGameMode(void);
+GLUTAPI void APIENTRY glutLeaveGameMode(void);
+GLUTAPI int APIENTRY glutGameModeGet(GLenum mode);
+#endif
+
+#ifdef __cplusplus
+}
+
+#endif
+
+#ifdef GLUT_APIENTRY_DEFINED
+# undef GLUT_APIENTRY_DEFINED
+# undef APIENTRY
+#endif
+
+#ifdef GLUT_WINGDIAPI_DEFINED
+# undef GLUT_WINGDIAPI_DEFINED
+# undef WINGDIAPI
+#endif
+
+#ifdef GLUT_DEFINED___CDECL
+# undef GLUT_DEFINED___CDECL
+# undef __cdecl
+#endif
+
+#ifdef GLUT_DEFINED__CRTIMP
+# undef GLUT_DEFINED__CRTIMP
+# undef _CRTIMP
+#endif
+
+#endif                  /* __glut_h__ */
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GL/glew.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GL/glew.h	(revision 498)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GL/glew.h	(revision 498)
@@ -0,0 +1,9113 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2004, 2003, 2002, Milan Ikits <milan ikits[at]ieee org>
+** Copyright (C) 2004, 2003, 2002, Marcelo E. Magallon <mmagallo[at]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** All rights reserved.
+** 
+** Redistribution and use in source and binary forms, with or without 
+** modification, are permitted provided that the following conditions are met:
+** 
+** * Redistributions of source code must retain the above copyright notice, 
+**   this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright notice, 
+**   this list of conditions and the following disclaimer in the documentation 
+**   and/or other materials provided with the distribution.
+** * The name of the author may be used to endorse or promote products 
+**   derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+** THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+** 
+** http://oss.sgi.com/projects/FreeB
+** 
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+** 
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+** 
+** Additional Notice Provisions: This software was created using the
+** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has
+** not been independently verified as being compliant with the OpenGL(R)
+** version 1.2.1 Specification.
+*/
+
+#ifndef __glew_h__
+#define __glew_h__
+#define __GLEW_H__
+
+#if defined(__gl_h_) || defined(__GL_H__)
+#error gl.h included before glew.h
+#endif
+#if defined(__glext_h_) || defined(__GLEXT_H_)
+#error glext.h included before glew.h
+#endif
+#if defined(__gl_ATI_h_)
+#error glATI.h included before glew.h
+#endif
+
+#define __gl_h_
+#define __GL_H__
+#define __glext_h_
+#define __GLEXT_H_
+#define __gl_ATI_h_
+#define __GLX_glx_h__
+
+#if defined(_WIN32)
+
+/*
+ * GLEW does not include <windows.h> to avoid name space pollution.
+ * GL needs GLAPI and GLAPIENTRY, GLU needs APIENTRY, CALLBACK, and wchar_t
+ * defined properly.
+ */
+/* <windef.h> */
+#ifndef APIENTRY
+#define GLEW_APIENTRY_DEFINED
+#  if defined(__CYGWIN__) || defined(__MINGW32__)
+#    define APIENTRY __stdcall
+#  elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
+#    define APIENTRY __stdcall
+#  else
+#    define APIENTRY
+#  endif
+#endif
+#ifndef GLAPI
+#  if defined(__CYGWIN__) || defined(__MINGW32__)
+#    define GLAPI extern
+#  endif
+#endif
+/* <winnt.h> */
+#ifndef CALLBACK
+#define GLEW_CALLBACK_DEFINED
+#  if defined(__CYGWIN__) || defined(__MINGW32__)
+#    define CALLBACK __attribute__ ((__stdcall__))
+#  elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
+#    define CALLBACK __stdcall
+#  else
+#    define CALLBACK
+#  endif
+#endif
+/* <wingdi.h> and <winnt.h> */
+#ifndef WINGDIAPI
+#define GLEW_WINGDIAPI_DEFINED
+#define WINGDIAPI __declspec(dllimport)
+#endif
+/* <ctype.h> */
+#if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED)
+typedef unsigned short wchar_t;
+#  define _WCHAR_T_DEFINED
+#endif
+/* <stddef.h> */
+#if !defined(_W64)
+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+#    define _W64 __w64
+#  else
+#    define _W64
+#  endif
+#endif
+#if !defined(_PTRDIFF_T_DEFINED) && !defined(_PTRDIFF_T_)
+#  ifdef _WIN64
+typedef __int64 ptrdiff_t;
+#  else
+typedef _W64 int ptrdiff_t;
+#  endif
+#  define _PTRDIFF_T_DEFINED
+#  define _PTRDIFF_T_
+#endif
+
+#ifndef GLAPI
+#  if defined(__CYGWIN__) || defined(__MINGW32__)
+#    define GLAPI extern
+#  else
+#    define GLAPI WINGDIAPI
+#  endif
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY APIENTRY
+#endif
+
+/*
+ * GLEW_STATIC needs to be set when using the static version.
+ * GLEW_BUILD is set when building the DLL version.
+ */
+#ifdef GLEW_STATIC
+#  define GLEWAPI extern
+#else
+#  ifdef GLEW_BUILD
+#    define GLEWAPI extern __declspec(dllexport)
+#  else
+#    define GLEWAPI extern __declspec(dllimport)
+#  endif
+#endif
+
+#else /* _UNIX */
+
+/*
+ * Needed for ptrdiff_t in turn needed by VBO.  This is defined by ISO
+ * C.  On my system, this amounts to _3 lines_ of included code, all of
+ * them pretty much harmless.  If you know of a way of detecting 32 vs
+ * 64 _targets_ at compile time you are free to replace this with
+ * something that's portable.  For now, _this_ is the portable solution.
+ * (mem, 2004-01-04)
+ */
+
+#include <stddef.h>
+
+#define GLEW_APIENTRY_DEFINED
+#define APIENTRY
+#define GLEWAPI extern
+
+/* <glu.h> */
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+#ifndef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#endif /* _WIN32 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----------------------------- GL_VERSION_1_1 ---------------------------- */
+
+#ifndef GL_VERSION_1_1
+#define GL_VERSION_1_1 1
+
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef signed char GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef int GLsizei;
+typedef unsigned char GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef float GLfloat;
+typedef float GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void GLvoid;
+
+#define GL_ACCUM 0x0100
+#define GL_LOAD 0x0101
+#define GL_RETURN 0x0102
+#define GL_MULT 0x0103
+#define GL_ADD 0x0104
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+#define GL_CURRENT_BIT 0x00000001
+#define GL_POINT_BIT 0x00000002
+#define GL_LINE_BIT 0x00000004
+#define GL_POLYGON_BIT 0x00000008
+#define GL_POLYGON_STIPPLE_BIT 0x00000010
+#define GL_PIXEL_MODE_BIT 0x00000020
+#define GL_LIGHTING_BIT 0x00000040
+#define GL_FOG_BIT 0x00000080
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_ACCUM_BUFFER_BIT 0x00000200
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_VIEWPORT_BIT 0x00000800
+#define GL_TRANSFORM_BIT 0x00001000
+#define GL_ENABLE_BIT 0x00002000
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_HINT_BIT 0x00008000
+#define GL_EVAL_BIT 0x00010000
+#define GL_LIST_BIT 0x00020000
+#define GL_TEXTURE_BIT 0x00040000
+#define GL_SCISSOR_BIT 0x00080000
+#define GL_ALL_ATTRIB_BITS 0x000fffff
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_QUADS 0x0007
+#define GL_QUAD_STRIP 0x0008
+#define GL_POLYGON 0x0009
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_TRUE 1
+#define GL_FALSE 0
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_2_BYTES 0x1407
+#define GL_3_BYTES 0x1408
+#define GL_4_BYTES 0x1409
+#define GL_DOUBLE 0x140A
+#define GL_NONE 0
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_LEFT 0x0406
+#define GL_RIGHT 0x0407
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_AUX0 0x0409
+#define GL_AUX1 0x040A
+#define GL_AUX2 0x040B
+#define GL_AUX3 0x040C
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_2D 0x0600
+#define GL_3D 0x0601
+#define GL_3D_COLOR 0x0602
+#define GL_3D_COLOR_TEXTURE 0x0603
+#define GL_4D_COLOR_TEXTURE 0x0604
+#define GL_PASS_THROUGH_TOKEN 0x0700
+#define GL_POINT_TOKEN 0x0701
+#define GL_LINE_TOKEN 0x0702
+#define GL_POLYGON_TOKEN 0x0703
+#define GL_BITMAP_TOKEN 0x0704
+#define GL_DRAW_PIXEL_TOKEN 0x0705
+#define GL_COPY_PIXEL_TOKEN 0x0706
+#define GL_LINE_RESET_TOKEN 0x0707
+#define GL_EXP 0x0800
+#define GL_EXP2 0x0801
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+#define GL_COEFF 0x0A00
+#define GL_ORDER 0x0A01
+#define GL_DOMAIN 0x0A02
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_CURRENT_RASTER_COLOR 0x0B04
+#define GL_CURRENT_RASTER_INDEX 0x0B05
+#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define GL_CURRENT_RASTER_POSITION 0x0B07
+#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_STIPPLE 0x0B24
+#define GL_LINE_STIPPLE_PATTERN 0x0B25
+#define GL_LINE_STIPPLE_REPEAT 0x0B26
+#define GL_LIST_MODE 0x0B30
+#define GL_MAX_LIST_NESTING 0x0B31
+#define GL_LIST_BASE 0x0B32
+#define GL_LIST_INDEX 0x0B33
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_STIPPLE 0x0B42
+#define GL_EDGE_FLAG 0x0B43
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_LIGHTING 0x0B50
+#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_SHADE_MODEL 0x0B54
+#define GL_COLOR_MATERIAL_FACE 0x0B55
+#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_FOG 0x0B60
+#define GL_FOG_INDEX 0x0B61
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_START 0x0B63
+#define GL_FOG_END 0x0B64
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_COLOR 0x0B66
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_ACCUM_CLEAR_VALUE 0x0B80
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_NORMALIZE 0x0BA1
+#define GL_VIEWPORT 0x0BA2
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_DITHER 0x0BD0
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND 0x0BE2
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_INDEX_LOGIC_OP 0x0BF1
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_AUX_BUFFERS 0x0C00
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_READ_BUFFER 0x0C02
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_INDEX_CLEAR_VALUE 0x0C20
+#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_INDEX_MODE 0x0C30
+#define GL_RGBA_MODE 0x0C31
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_STEREO 0x0C33
+#define GL_RENDER_MODE 0x0C40
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_FOG_HINT 0x0C54
+#define GL_TEXTURE_GEN_S 0x0C60
+#define GL_TEXTURE_GEN_T 0x0C61
+#define GL_TEXTURE_GEN_R 0x0C62
+#define GL_TEXTURE_GEN_Q 0x0C63
+#define GL_PIXEL_MAP_I_TO_I 0x0C70
+#define GL_PIXEL_MAP_S_TO_S 0x0C71
+#define GL_PIXEL_MAP_I_TO_R 0x0C72
+#define GL_PIXEL_MAP_I_TO_G 0x0C73
+#define GL_PIXEL_MAP_I_TO_B 0x0C74
+#define GL_PIXEL_MAP_I_TO_A 0x0C75
+#define GL_PIXEL_MAP_R_TO_R 0x0C76
+#define GL_PIXEL_MAP_G_TO_G 0x0C77
+#define GL_PIXEL_MAP_B_TO_B 0x0C78
+#define GL_PIXEL_MAP_A_TO_A 0x0C79
+#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAP_COLOR 0x0D10
+#define GL_MAP_STENCIL 0x0D11
+#define GL_INDEX_SHIFT 0x0D12
+#define GL_INDEX_OFFSET 0x0D13
+#define GL_RED_SCALE 0x0D14
+#define GL_RED_BIAS 0x0D15
+#define GL_ZOOM_X 0x0D16
+#define GL_ZOOM_Y 0x0D17
+#define GL_GREEN_SCALE 0x0D18
+#define GL_GREEN_BIAS 0x0D19
+#define GL_BLUE_SCALE 0x0D1A
+#define GL_BLUE_BIAS 0x0D1B
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_ALPHA_BIAS 0x0D1D
+#define GL_DEPTH_SCALE 0x0D1E
+#define GL_DEPTH_BIAS 0x0D1F
+#define GL_MAX_EVAL_ORDER 0x0D30
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_INDEX_BITS 0x0D51
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_ACCUM_RED_BITS 0x0D58
+#define GL_ACCUM_GREEN_BITS 0x0D59
+#define GL_ACCUM_BLUE_BITS 0x0D5A
+#define GL_ACCUM_ALPHA_BITS 0x0D5B
+#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_AUTO_NORMAL 0x0D80
+#define GL_MAP1_COLOR_4 0x0D90
+#define GL_MAP1_INDEX 0x0D91
+#define GL_MAP1_NORMAL 0x0D92
+#define GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define GL_MAP1_VERTEX_3 0x0D97
+#define GL_MAP1_VERTEX_4 0x0D98
+#define GL_MAP2_COLOR_4 0x0DB0
+#define GL_MAP2_INDEX 0x0DB1
+#define GL_MAP2_NORMAL 0x0DB2
+#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define GL_MAP2_VERTEX_3 0x0DB7
+#define GL_MAP2_VERTEX_4 0x0DB8
+#define GL_MAP1_GRID_DOMAIN 0x0DD0
+#define GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define GL_MAP2_GRID_DOMAIN 0x0DD2
+#define GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+#define GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define GL_SELECTION_BUFFER_SIZE 0x0DF4
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_BORDER 0x1005
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+#define GL_LIGHT0 0x4000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+#define GL_AMBIENT 0x1200
+#define GL_DIFFUSE 0x1201
+#define GL_SPECULAR 0x1202
+#define GL_POSITION 0x1203
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_QUADRATIC_ATTENUATION 0x1209
+#define GL_COMPILE 0x1300
+#define GL_COMPILE_AND_EXECUTE 0x1301
+#define GL_CLEAR 0x1500
+#define GL_AND 0x1501
+#define GL_AND_REVERSE 0x1502
+#define GL_COPY 0x1503
+#define GL_AND_INVERTED 0x1504
+#define GL_NOOP 0x1505
+#define GL_XOR 0x1506
+#define GL_OR 0x1507
+#define GL_NOR 0x1508
+#define GL_EQUIV 0x1509
+#define GL_INVERT 0x150A
+#define GL_OR_REVERSE 0x150B
+#define GL_COPY_INVERTED 0x150C
+#define GL_OR_INVERTED 0x150D
+#define GL_NAND 0x150E
+#define GL_SET 0x150F
+#define GL_EMISSION 0x1600
+#define GL_SHININESS 0x1601
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+#define GL_COLOR_INDEXES 0x1603
+#define GL_MODELVIEW 0x1700
+#define GL_PROJECTION 0x1701
+#define GL_TEXTURE 0x1702
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+#define GL_COLOR_INDEX 0x1900
+#define GL_STENCIL_INDEX 0x1901
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_RED 0x1903
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_BITMAP 0x1A00
+#define GL_POINT 0x1B00
+#define GL_LINE 0x1B01
+#define GL_FILL 0x1B02
+#define GL_RENDER 0x1C00
+#define GL_FEEDBACK 0x1C01
+#define GL_SELECT 0x1C02
+#define GL_FLAT 0x1D00
+#define GL_SMOOTH 0x1D01
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+#define GL_S 0x2000
+#define GL_T 0x2001
+#define GL_R 0x2002
+#define GL_Q 0x2003
+#define GL_MODULATE 0x2100
+#define GL_DECAL 0x2101
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_ENV_COLOR 0x2201
+#define GL_TEXTURE_ENV 0x2300
+#define GL_EYE_LINEAR 0x2400
+#define GL_OBJECT_LINEAR 0x2401
+#define GL_SPHERE_MAP 0x2402
+#define GL_TEXTURE_GEN_MODE 0x2500
+#define GL_OBJECT_PLANE 0x2501
+#define GL_EYE_PLANE 0x2502
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_CLAMP 0x2900
+#define GL_REPEAT 0x2901
+#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_R3_G3_B2 0x2A10
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB8 0x8051
+#define GL_RGB10 0x8052
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_TEXTURE_PRIORITY 0x8066
+#define GL_TEXTURE_RESIDENT 0x8067
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_COLOR_ARRAY 0x8076
+#define GL_INDEX_ARRAY 0x8077
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_EDGE_FLAG_ARRAY 0x8079
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_INDEX_ARRAY_TYPE 0x8085
+#define GL_INDEX_ARRAY_STRIDE 0x8086
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_INDEX_ARRAY_POINTER 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define GL_V2F 0x2A20
+#define GL_V3F 0x2A21
+#define GL_C4UB_V2F 0x2A22
+#define GL_C4UB_V3F 0x2A23
+#define GL_C3F_V3F 0x2A24
+#define GL_N3F_V3F 0x2A25
+#define GL_C4F_N3F_V3F 0x2A26
+#define GL_T2F_V3F 0x2A27
+#define GL_T4F_V4F 0x2A28
+#define GL_T2F_C4UB_V3F 0x2A29
+#define GL_T2F_C3F_V3F 0x2A2A
+#define GL_T2F_N3F_V3F 0x2A2B
+#define GL_T2F_C4F_N3F_V3F 0x2A2C
+#define GL_T4F_C4F_N3F_V4F 0x2A2D
+#define GL_LOGIC_OP GL_INDEX_LOGIC_OP
+#define GL_TEXTURE_COMPONENTS GL_TEXTURE_INTERNAL_FORMAT
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+
+GLAPI void GLAPIENTRY glAccum (GLenum op, GLfloat value);
+GLAPI void GLAPIENTRY glAlphaFunc (GLenum func, GLclampf ref);
+GLAPI GLboolean GLAPIENTRY glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences);
+GLAPI void GLAPIENTRY glArrayElement (GLint i);
+GLAPI void GLAPIENTRY glBegin (GLenum mode);
+GLAPI void GLAPIENTRY glBindTexture (GLenum target, GLuint texture);
+GLAPI void GLAPIENTRY glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+GLAPI void GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GLAPI void GLAPIENTRY glCallList (GLuint list);
+GLAPI void GLAPIENTRY glCallLists (GLsizei n, GLenum type, const GLvoid *lists);
+GLAPI void GLAPIENTRY glClear (GLbitfield mask);
+GLAPI void GLAPIENTRY glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GLAPI void GLAPIENTRY glClearDepth (GLclampd depth);
+GLAPI void GLAPIENTRY glClearIndex (GLfloat c);
+GLAPI void GLAPIENTRY glClearStencil (GLint s);
+GLAPI void GLAPIENTRY glClipPlane (GLenum plane, const GLdouble *equation);
+GLAPI void GLAPIENTRY glColor3b (GLbyte red, GLbyte green, GLbyte blue);
+GLAPI void GLAPIENTRY glColor3bv (const GLbyte *v);
+GLAPI void GLAPIENTRY glColor3d (GLdouble red, GLdouble green, GLdouble blue);
+GLAPI void GLAPIENTRY glColor3dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue);
+GLAPI void GLAPIENTRY glColor3fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glColor3i (GLint red, GLint green, GLint blue);
+GLAPI void GLAPIENTRY glColor3iv (const GLint *v);
+GLAPI void GLAPIENTRY glColor3s (GLshort red, GLshort green, GLshort blue);
+GLAPI void GLAPIENTRY glColor3sv (const GLshort *v);
+GLAPI void GLAPIENTRY glColor3ub (GLubyte red, GLubyte green, GLubyte blue);
+GLAPI void GLAPIENTRY glColor3ubv (const GLubyte *v);
+GLAPI void GLAPIENTRY glColor3ui (GLuint red, GLuint green, GLuint blue);
+GLAPI void GLAPIENTRY glColor3uiv (const GLuint *v);
+GLAPI void GLAPIENTRY glColor3us (GLushort red, GLushort green, GLushort blue);
+GLAPI void GLAPIENTRY glColor3usv (const GLushort *v);
+GLAPI void GLAPIENTRY glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+GLAPI void GLAPIENTRY glColor4bv (const GLbyte *v);
+GLAPI void GLAPIENTRY glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+GLAPI void GLAPIENTRY glColor4dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void GLAPIENTRY glColor4fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glColor4i (GLint red, GLint green, GLint blue, GLint alpha);
+GLAPI void GLAPIENTRY glColor4iv (const GLint *v);
+GLAPI void GLAPIENTRY glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha);
+GLAPI void GLAPIENTRY glColor4sv (const GLshort *v);
+GLAPI void GLAPIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+GLAPI void GLAPIENTRY glColor4ubv (const GLubyte *v);
+GLAPI void GLAPIENTRY glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+GLAPI void GLAPIENTRY glColor4uiv (const GLuint *v);
+GLAPI void GLAPIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha);
+GLAPI void GLAPIENTRY glColor4usv (const GLushort *v);
+GLAPI void GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GLAPI void GLAPIENTRY glColorMaterial (GLenum face, GLenum mode);
+GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+GLAPI void GLAPIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void GLAPIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void GLAPIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void GLAPIENTRY glCullFace (GLenum mode);
+GLAPI void GLAPIENTRY glDeleteLists (GLuint list, GLsizei range);
+GLAPI void GLAPIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GLAPI void GLAPIENTRY glDepthFunc (GLenum func);
+GLAPI void GLAPIENTRY glDepthMask (GLboolean flag);
+GLAPI void GLAPIENTRY glDepthRange (GLclampd zNear, GLclampd zFar);
+GLAPI void GLAPIENTRY glDisable (GLenum cap);
+GLAPI void GLAPIENTRY glDisableClientState (GLenum array);
+GLAPI void GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GLAPI void GLAPIENTRY glDrawBuffer (GLenum mode);
+GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+GLAPI void GLAPIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glEdgeFlag (GLboolean flag);
+GLAPI void GLAPIENTRY glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glEdgeFlagv (const GLboolean *flag);
+GLAPI void GLAPIENTRY glEnable (GLenum cap);
+GLAPI void GLAPIENTRY glEnableClientState (GLenum array);
+GLAPI void GLAPIENTRY glEnd (void);
+GLAPI void GLAPIENTRY glEndList (void);
+GLAPI void GLAPIENTRY glEvalCoord1d (GLdouble u);
+GLAPI void GLAPIENTRY glEvalCoord1dv (const GLdouble *u);
+GLAPI void GLAPIENTRY glEvalCoord1f (GLfloat u);
+GLAPI void GLAPIENTRY glEvalCoord1fv (const GLfloat *u);
+GLAPI void GLAPIENTRY glEvalCoord2d (GLdouble u, GLdouble v);
+GLAPI void GLAPIENTRY glEvalCoord2dv (const GLdouble *u);
+GLAPI void GLAPIENTRY glEvalCoord2f (GLfloat u, GLfloat v);
+GLAPI void GLAPIENTRY glEvalCoord2fv (const GLfloat *u);
+GLAPI void GLAPIENTRY glEvalMesh1 (GLenum mode, GLint i1, GLint i2);
+GLAPI void GLAPIENTRY glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+GLAPI void GLAPIENTRY glEvalPoint1 (GLint i);
+GLAPI void GLAPIENTRY glEvalPoint2 (GLint i, GLint j);
+GLAPI void GLAPIENTRY glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer);
+GLAPI void GLAPIENTRY glFinish (void);
+GLAPI void GLAPIENTRY glFlush (void);
+GLAPI void GLAPIENTRY glFogf (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glFogfv (GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glFogi (GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glFogiv (GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glFrontFace (GLenum mode);
+GLAPI void GLAPIENTRY glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI GLuint GLAPIENTRY glGenLists (GLsizei range);
+GLAPI void GLAPIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GLAPI void GLAPIENTRY glGetBooleanv (GLenum pname, GLboolean *params);
+GLAPI void GLAPIENTRY glGetClipPlane (GLenum plane, GLdouble *equation);
+GLAPI void GLAPIENTRY glGetDoublev (GLenum pname, GLdouble *params);
+GLAPI GLenum GLAPIENTRY glGetError (void);
+GLAPI void GLAPIENTRY glGetFloatv (GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetIntegerv (GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetLightiv (GLenum light, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetMapdv (GLenum target, GLenum query, GLdouble *v);
+GLAPI void GLAPIENTRY glGetMapfv (GLenum target, GLenum query, GLfloat *v);
+GLAPI void GLAPIENTRY glGetMapiv (GLenum target, GLenum query, GLint *v);
+GLAPI void GLAPIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetMaterialiv (GLenum face, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetPixelMapfv (GLenum map, GLfloat *values);
+GLAPI void GLAPIENTRY glGetPixelMapuiv (GLenum map, GLuint *values);
+GLAPI void GLAPIENTRY glGetPixelMapusv (GLenum map, GLushort *values);
+GLAPI void GLAPIENTRY glGetPointerv (GLenum pname, GLvoid* *params);
+GLAPI void GLAPIENTRY glGetPolygonStipple (GLubyte *mask);
+GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name);
+GLAPI void GLAPIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params);
+GLAPI void GLAPIENTRY glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetTexGeniv (GLenum coord, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+GLAPI void GLAPIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glHint (GLenum target, GLenum mode);
+GLAPI void GLAPIENTRY glIndexMask (GLuint mask);
+GLAPI void GLAPIENTRY glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glIndexd (GLdouble c);
+GLAPI void GLAPIENTRY glIndexdv (const GLdouble *c);
+GLAPI void GLAPIENTRY glIndexf (GLfloat c);
+GLAPI void GLAPIENTRY glIndexfv (const GLfloat *c);
+GLAPI void GLAPIENTRY glIndexi (GLint c);
+GLAPI void GLAPIENTRY glIndexiv (const GLint *c);
+GLAPI void GLAPIENTRY glIndexs (GLshort c);
+GLAPI void GLAPIENTRY glIndexsv (const GLshort *c);
+GLAPI void GLAPIENTRY glIndexub (GLubyte c);
+GLAPI void GLAPIENTRY glIndexubv (const GLubyte *c);
+GLAPI void GLAPIENTRY glInitNames (void);
+GLAPI void GLAPIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer);
+GLAPI GLboolean GLAPIENTRY glIsEnabled (GLenum cap);
+GLAPI GLboolean GLAPIENTRY glIsList (GLuint list);
+GLAPI GLboolean GLAPIENTRY glIsTexture (GLuint texture);
+GLAPI void GLAPIENTRY glLightModelf (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glLightModelfv (GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glLightModeli (GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glLightModeliv (GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glLightf (GLenum light, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glLighti (GLenum light, GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glLightiv (GLenum light, GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glLineStipple (GLint factor, GLushort pattern);
+GLAPI void GLAPIENTRY glLineWidth (GLfloat width);
+GLAPI void GLAPIENTRY glListBase (GLuint base);
+GLAPI void GLAPIENTRY glLoadIdentity (void);
+GLAPI void GLAPIENTRY glLoadMatrixd (const GLdouble *m);
+GLAPI void GLAPIENTRY glLoadMatrixf (const GLfloat *m);
+GLAPI void GLAPIENTRY glLoadName (GLuint name);
+GLAPI void GLAPIENTRY glLogicOp (GLenum opcode);
+GLAPI void GLAPIENTRY glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+GLAPI void GLAPIENTRY glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+GLAPI void GLAPIENTRY glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+GLAPI void GLAPIENTRY glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+GLAPI void GLAPIENTRY glMapGrid1d (GLint un, GLdouble u1, GLdouble u2);
+GLAPI void GLAPIENTRY glMapGrid1f (GLint un, GLfloat u1, GLfloat u2);
+GLAPI void GLAPIENTRY glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+GLAPI void GLAPIENTRY glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+GLAPI void GLAPIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glMateriali (GLenum face, GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glMaterialiv (GLenum face, GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glMatrixMode (GLenum mode);
+GLAPI void GLAPIENTRY glMultMatrixd (const GLdouble *m);
+GLAPI void GLAPIENTRY glMultMatrixf (const GLfloat *m);
+GLAPI void GLAPIENTRY glNewList (GLuint list, GLenum mode);
+GLAPI void GLAPIENTRY glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz);
+GLAPI void GLAPIENTRY glNormal3bv (const GLbyte *v);
+GLAPI void GLAPIENTRY glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz);
+GLAPI void GLAPIENTRY glNormal3dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz);
+GLAPI void GLAPIENTRY glNormal3fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glNormal3i (GLint nx, GLint ny, GLint nz);
+GLAPI void GLAPIENTRY glNormal3iv (const GLint *v);
+GLAPI void GLAPIENTRY glNormal3s (GLshort nx, GLshort ny, GLshort nz);
+GLAPI void GLAPIENTRY glNormal3sv (const GLshort *v);
+GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI void GLAPIENTRY glPassThrough (GLfloat token);
+GLAPI void GLAPIENTRY glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values);
+GLAPI void GLAPIENTRY glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values);
+GLAPI void GLAPIENTRY glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values);
+GLAPI void GLAPIENTRY glPixelStoref (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glPixelStorei (GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glPixelTransferf (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glPixelTransferi (GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glPixelZoom (GLfloat xfactor, GLfloat yfactor);
+GLAPI void GLAPIENTRY glPointSize (GLfloat size);
+GLAPI void GLAPIENTRY glPolygonMode (GLenum face, GLenum mode);
+GLAPI void GLAPIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GLAPI void GLAPIENTRY glPolygonStipple (const GLubyte *mask);
+GLAPI void GLAPIENTRY glPopAttrib (void);
+GLAPI void GLAPIENTRY glPopClientAttrib (void);
+GLAPI void GLAPIENTRY glPopMatrix (void);
+GLAPI void GLAPIENTRY glPopName (void);
+GLAPI void GLAPIENTRY glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+GLAPI void GLAPIENTRY glPushAttrib (GLbitfield mask);
+GLAPI void GLAPIENTRY glPushClientAttrib (GLbitfield mask);
+GLAPI void GLAPIENTRY glPushMatrix (void);
+GLAPI void GLAPIENTRY glPushName (GLuint name);
+GLAPI void GLAPIENTRY glRasterPos2d (GLdouble x, GLdouble y);
+GLAPI void GLAPIENTRY glRasterPos2dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glRasterPos2f (GLfloat x, GLfloat y);
+GLAPI void GLAPIENTRY glRasterPos2fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glRasterPos2i (GLint x, GLint y);
+GLAPI void GLAPIENTRY glRasterPos2iv (const GLint *v);
+GLAPI void GLAPIENTRY glRasterPos2s (GLshort x, GLshort y);
+GLAPI void GLAPIENTRY glRasterPos2sv (const GLshort *v);
+GLAPI void GLAPIENTRY glRasterPos3d (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void GLAPIENTRY glRasterPos3dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glRasterPos3f (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glRasterPos3fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glRasterPos3i (GLint x, GLint y, GLint z);
+GLAPI void GLAPIENTRY glRasterPos3iv (const GLint *v);
+GLAPI void GLAPIENTRY glRasterPos3s (GLshort x, GLshort y, GLshort z);
+GLAPI void GLAPIENTRY glRasterPos3sv (const GLshort *v);
+GLAPI void GLAPIENTRY glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void GLAPIENTRY glRasterPos4dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void GLAPIENTRY glRasterPos4fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glRasterPos4i (GLint x, GLint y, GLint z, GLint w);
+GLAPI void GLAPIENTRY glRasterPos4iv (const GLint *v);
+GLAPI void GLAPIENTRY glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void GLAPIENTRY glRasterPos4sv (const GLshort *v);
+GLAPI void GLAPIENTRY glReadBuffer (GLenum mode);
+GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+GLAPI void GLAPIENTRY glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+GLAPI void GLAPIENTRY glRectdv (const GLdouble *v1, const GLdouble *v2);
+GLAPI void GLAPIENTRY glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+GLAPI void GLAPIENTRY glRectfv (const GLfloat *v1, const GLfloat *v2);
+GLAPI void GLAPIENTRY glRecti (GLint x1, GLint y1, GLint x2, GLint y2);
+GLAPI void GLAPIENTRY glRectiv (const GLint *v1, const GLint *v2);
+GLAPI void GLAPIENTRY glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+GLAPI void GLAPIENTRY glRectsv (const GLshort *v1, const GLshort *v2);
+GLAPI GLint GLAPIENTRY glRenderMode (GLenum mode);
+GLAPI void GLAPIENTRY glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void GLAPIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glScaled (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void GLAPIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void GLAPIENTRY glSelectBuffer (GLsizei size, GLuint *buffer);
+GLAPI void GLAPIENTRY glShadeModel (GLenum mode);
+GLAPI void GLAPIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GLAPI void GLAPIENTRY glStencilMask (GLuint mask);
+GLAPI void GLAPIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GLAPI void GLAPIENTRY glTexCoord1d (GLdouble s);
+GLAPI void GLAPIENTRY glTexCoord1dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glTexCoord1f (GLfloat s);
+GLAPI void GLAPIENTRY glTexCoord1fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glTexCoord1i (GLint s);
+GLAPI void GLAPIENTRY glTexCoord1iv (const GLint *v);
+GLAPI void GLAPIENTRY glTexCoord1s (GLshort s);
+GLAPI void GLAPIENTRY glTexCoord1sv (const GLshort *v);
+GLAPI void GLAPIENTRY glTexCoord2d (GLdouble s, GLdouble t);
+GLAPI void GLAPIENTRY glTexCoord2dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glTexCoord2f (GLfloat s, GLfloat t);
+GLAPI void GLAPIENTRY glTexCoord2fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glTexCoord2i (GLint s, GLint t);
+GLAPI void GLAPIENTRY glTexCoord2iv (const GLint *v);
+GLAPI void GLAPIENTRY glTexCoord2s (GLshort s, GLshort t);
+GLAPI void GLAPIENTRY glTexCoord2sv (const GLshort *v);
+GLAPI void GLAPIENTRY glTexCoord3d (GLdouble s, GLdouble t, GLdouble r);
+GLAPI void GLAPIENTRY glTexCoord3dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glTexCoord3f (GLfloat s, GLfloat t, GLfloat r);
+GLAPI void GLAPIENTRY glTexCoord3fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glTexCoord3i (GLint s, GLint t, GLint r);
+GLAPI void GLAPIENTRY glTexCoord3iv (const GLint *v);
+GLAPI void GLAPIENTRY glTexCoord3s (GLshort s, GLshort t, GLshort r);
+GLAPI void GLAPIENTRY glTexCoord3sv (const GLshort *v);
+GLAPI void GLAPIENTRY glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void GLAPIENTRY glTexCoord4dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void GLAPIENTRY glTexCoord4fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glTexCoord4i (GLint s, GLint t, GLint r, GLint q);
+GLAPI void GLAPIENTRY glTexCoord4iv (const GLint *v);
+GLAPI void GLAPIENTRY glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void GLAPIENTRY glTexCoord4sv (const GLshort *v);
+GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glTexGend (GLenum coord, GLenum pname, GLdouble param);
+GLAPI void GLAPIENTRY glTexGendv (GLenum coord, GLenum pname, const GLdouble *params);
+GLAPI void GLAPIENTRY glTexGenf (GLenum coord, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glTexGeniv (GLenum coord, GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTranslated (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glVertex2d (GLdouble x, GLdouble y);
+GLAPI void GLAPIENTRY glVertex2dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glVertex2f (GLfloat x, GLfloat y);
+GLAPI void GLAPIENTRY glVertex2fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glVertex2i (GLint x, GLint y);
+GLAPI void GLAPIENTRY glVertex2iv (const GLint *v);
+GLAPI void GLAPIENTRY glVertex2s (GLshort x, GLshort y);
+GLAPI void GLAPIENTRY glVertex2sv (const GLshort *v);
+GLAPI void GLAPIENTRY glVertex3d (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void GLAPIENTRY glVertex3dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glVertex3f (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glVertex3fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glVertex3i (GLint x, GLint y, GLint z);
+GLAPI void GLAPIENTRY glVertex3iv (const GLint *v);
+GLAPI void GLAPIENTRY glVertex3s (GLshort x, GLshort y, GLshort z);
+GLAPI void GLAPIENTRY glVertex3sv (const GLshort *v);
+GLAPI void GLAPIENTRY glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void GLAPIENTRY glVertex4dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void GLAPIENTRY glVertex4fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w);
+GLAPI void GLAPIENTRY glVertex4iv (const GLint *v);
+GLAPI void GLAPIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void GLAPIENTRY glVertex4sv (const GLshort *v);
+GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define GLEW_VERSION_1_1 GLEW_GET_VAR(__GLEW_VERSION_1_1)
+
+#endif /* GL_VERSION_1_1 */
+
+/* ---------------------------------- GLU ---------------------------------- */
+
+/* this is where we can safely include GLU */
+#if defined(__APPLE__) && defined(__MACH__)
+#include <OpenGL/glu.h>
+#else
+#include <GL/glu.h>
+#endif
+
+/* ----------------------------- GL_VERSION_1_2 ---------------------------- */
+
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+
+#define glCopyTexSubImage3D GLEW_GET_FUN(__glewCopyTexSubImage3D)
+#define glDrawRangeElements GLEW_GET_FUN(__glewDrawRangeElements)
+#define glTexImage3D GLEW_GET_FUN(__glewTexImage3D)
+#define glTexSubImage3D GLEW_GET_FUN(__glewTexSubImage3D)
+
+#define GLEW_VERSION_1_2 GLEW_GET_VAR(__GLEW_VERSION_1_2)
+
+#endif /* GL_VERSION_1_2 */
+
+/* ----------------------------- GL_VERSION_1_3 ---------------------------- */
+
+#ifndef GL_VERSION_1_3
+#define GL_VERSION_1_3 1
+
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_SUBTRACT 0x84E7
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#define GL_MULTISAMPLE_BIT 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLvoid *img);
+typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble m[16]);
+typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
+
+#define glActiveTexture GLEW_GET_FUN(__glewActiveTexture)
+#define glClientActiveTexture GLEW_GET_FUN(__glewClientActiveTexture)
+#define glCompressedTexImage1D GLEW_GET_FUN(__glewCompressedTexImage1D)
+#define glCompressedTexImage2D GLEW_GET_FUN(__glewCompressedTexImage2D)
+#define glCompressedTexImage3D GLEW_GET_FUN(__glewCompressedTexImage3D)
+#define glCompressedTexSubImage1D GLEW_GET_FUN(__glewCompressedTexSubImage1D)
+#define glCompressedTexSubImage2D GLEW_GET_FUN(__glewCompressedTexSubImage2D)
+#define glCompressedTexSubImage3D GLEW_GET_FUN(__glewCompressedTexSubImage3D)
+#define glGetCompressedTexImage GLEW_GET_FUN(__glewGetCompressedTexImage)
+#define glLoadTransposeMatrixd GLEW_GET_FUN(__glewLoadTransposeMatrixd)
+#define glLoadTransposeMatrixf GLEW_GET_FUN(__glewLoadTransposeMatrixf)
+#define glMultTransposeMatrixd GLEW_GET_FUN(__glewMultTransposeMatrixd)
+#define glMultTransposeMatrixf GLEW_GET_FUN(__glewMultTransposeMatrixf)
+#define glMultiTexCoord1d GLEW_GET_FUN(__glewMultiTexCoord1d)
+#define glMultiTexCoord1dv GLEW_GET_FUN(__glewMultiTexCoord1dv)
+#define glMultiTexCoord1f GLEW_GET_FUN(__glewMultiTexCoord1f)
+#define glMultiTexCoord1fv GLEW_GET_FUN(__glewMultiTexCoord1fv)
+#define glMultiTexCoord1i GLEW_GET_FUN(__glewMultiTexCoord1i)
+#define glMultiTexCoord1iv GLEW_GET_FUN(__glewMultiTexCoord1iv)
+#define glMultiTexCoord1s GLEW_GET_FUN(__glewMultiTexCoord1s)
+#define glMultiTexCoord1sv GLEW_GET_FUN(__glewMultiTexCoord1sv)
+#define glMultiTexCoord2d GLEW_GET_FUN(__glewMultiTexCoord2d)
+#define glMultiTexCoord2dv GLEW_GET_FUN(__glewMultiTexCoord2dv)
+#define glMultiTexCoord2f GLEW_GET_FUN(__glewMultiTexCoord2f)
+#define glMultiTexCoord2fv GLEW_GET_FUN(__glewMultiTexCoord2fv)
+#define glMultiTexCoord2i GLEW_GET_FUN(__glewMultiTexCoord2i)
+#define glMultiTexCoord2iv GLEW_GET_FUN(__glewMultiTexCoord2iv)
+#define glMultiTexCoord2s GLEW_GET_FUN(__glewMultiTexCoord2s)
+#define glMultiTexCoord2sv GLEW_GET_FUN(__glewMultiTexCoord2sv)
+#define glMultiTexCoord3d GLEW_GET_FUN(__glewMultiTexCoord3d)
+#define glMultiTexCoord3dv GLEW_GET_FUN(__glewMultiTexCoord3dv)
+#define glMultiTexCoord3f GLEW_GET_FUN(__glewMultiTexCoord3f)
+#define glMultiTexCoord3fv GLEW_GET_FUN(__glewMultiTexCoord3fv)
+#define glMultiTexCoord3i GLEW_GET_FUN(__glewMultiTexCoord3i)
+#define glMultiTexCoord3iv GLEW_GET_FUN(__glewMultiTexCoord3iv)
+#define glMultiTexCoord3s GLEW_GET_FUN(__glewMultiTexCoord3s)
+#define glMultiTexCoord3sv GLEW_GET_FUN(__glewMultiTexCoord3sv)
+#define glMultiTexCoord4d GLEW_GET_FUN(__glewMultiTexCoord4d)
+#define glMultiTexCoord4dv GLEW_GET_FUN(__glewMultiTexCoord4dv)
+#define glMultiTexCoord4f GLEW_GET_FUN(__glewMultiTexCoord4f)
+#define glMultiTexCoord4fv GLEW_GET_FUN(__glewMultiTexCoord4fv)
+#define glMultiTexCoord4i GLEW_GET_FUN(__glewMultiTexCoord4i)
+#define glMultiTexCoord4iv GLEW_GET_FUN(__glewMultiTexCoord4iv)
+#define glMultiTexCoord4s GLEW_GET_FUN(__glewMultiTexCoord4s)
+#define glMultiTexCoord4sv GLEW_GET_FUN(__glewMultiTexCoord4sv)
+#define glSampleCoverage GLEW_GET_FUN(__glewSampleCoverage)
+
+#define GLEW_VERSION_1_3 GLEW_GET_VAR(__GLEW_VERSION_1_3)
+
+#endif /* GL_VERSION_1_3 */
+
+/* ----------------------------- GL_VERSION_1_4 ---------------------------- */
+
+#ifndef GL_VERSION_1_4
+#define GL_VERSION_1_4 1
+
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_COLOR_SUM 0x8458
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+
+typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVPROC) (const GLdouble *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVPROC) (const GLfloat *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVPROC) (const GLint *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVPROC) (const GLshort *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVPROC) (const GLdouble *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVPROC) (const GLfloat *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVPROC) (const GLint *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVPROC) (const GLshort *p);
+
+#define glBlendColor GLEW_GET_FUN(__glewBlendColor)
+#define glBlendEquation GLEW_GET_FUN(__glewBlendEquation)
+#define glBlendFuncSeparate GLEW_GET_FUN(__glewBlendFuncSeparate)
+#define glFogCoordPointer GLEW_GET_FUN(__glewFogCoordPointer)
+#define glFogCoordd GLEW_GET_FUN(__glewFogCoordd)
+#define glFogCoorddv GLEW_GET_FUN(__glewFogCoorddv)
+#define glFogCoordf GLEW_GET_FUN(__glewFogCoordf)
+#define glFogCoordfv GLEW_GET_FUN(__glewFogCoordfv)
+#define glMultiDrawArrays GLEW_GET_FUN(__glewMultiDrawArrays)
+#define glMultiDrawElements GLEW_GET_FUN(__glewMultiDrawElements)
+#define glPointParameterf GLEW_GET_FUN(__glewPointParameterf)
+#define glPointParameterfv GLEW_GET_FUN(__glewPointParameterfv)
+#define glSecondaryColor3b GLEW_GET_FUN(__glewSecondaryColor3b)
+#define glSecondaryColor3bv GLEW_GET_FUN(__glewSecondaryColor3bv)
+#define glSecondaryColor3d GLEW_GET_FUN(__glewSecondaryColor3d)
+#define glSecondaryColor3dv GLEW_GET_FUN(__glewSecondaryColor3dv)
+#define glSecondaryColor3f GLEW_GET_FUN(__glewSecondaryColor3f)
+#define glSecondaryColor3fv GLEW_GET_FUN(__glewSecondaryColor3fv)
+#define glSecondaryColor3i GLEW_GET_FUN(__glewSecondaryColor3i)
+#define glSecondaryColor3iv GLEW_GET_FUN(__glewSecondaryColor3iv)
+#define glSecondaryColor3s GLEW_GET_FUN(__glewSecondaryColor3s)
+#define glSecondaryColor3sv GLEW_GET_FUN(__glewSecondaryColor3sv)
+#define glSecondaryColor3ub GLEW_GET_FUN(__glewSecondaryColor3ub)
+#define glSecondaryColor3ubv GLEW_GET_FUN(__glewSecondaryColor3ubv)
+#define glSecondaryColor3ui GLEW_GET_FUN(__glewSecondaryColor3ui)
+#define glSecondaryColor3uiv GLEW_GET_FUN(__glewSecondaryColor3uiv)
+#define glSecondaryColor3us GLEW_GET_FUN(__glewSecondaryColor3us)
+#define glSecondaryColor3usv GLEW_GET_FUN(__glewSecondaryColor3usv)
+#define glSecondaryColorPointer GLEW_GET_FUN(__glewSecondaryColorPointer)
+#define glWindowPos2d GLEW_GET_FUN(__glewWindowPos2d)
+#define glWindowPos2dv GLEW_GET_FUN(__glewWindowPos2dv)
+#define glWindowPos2f GLEW_GET_FUN(__glewWindowPos2f)
+#define glWindowPos2fv GLEW_GET_FUN(__glewWindowPos2fv)
+#define glWindowPos2i GLEW_GET_FUN(__glewWindowPos2i)
+#define glWindowPos2iv GLEW_GET_FUN(__glewWindowPos2iv)
+#define glWindowPos2s GLEW_GET_FUN(__glewWindowPos2s)
+#define glWindowPos2sv GLEW_GET_FUN(__glewWindowPos2sv)
+#define glWindowPos3d GLEW_GET_FUN(__glewWindowPos3d)
+#define glWindowPos3dv GLEW_GET_FUN(__glewWindowPos3dv)
+#define glWindowPos3f GLEW_GET_FUN(__glewWindowPos3f)
+#define glWindowPos3fv GLEW_GET_FUN(__glewWindowPos3fv)
+#define glWindowPos3i GLEW_GET_FUN(__glewWindowPos3i)
+#define glWindowPos3iv GLEW_GET_FUN(__glewWindowPos3iv)
+#define glWindowPos3s GLEW_GET_FUN(__glewWindowPos3s)
+#define glWindowPos3sv GLEW_GET_FUN(__glewWindowPos3sv)
+
+#define GLEW_VERSION_1_4 GLEW_GET_VAR(__GLEW_VERSION_1_4)
+
+#endif /* GL_VERSION_1_4 */
+
+/* ----------------------------- GL_VERSION_1_5 ---------------------------- */
+
+#ifndef GL_VERSION_1_5
+#define GL_VERSION_1_5 1
+
+#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE
+#define GL_FOG_COORD GL_FOG_COORDINATE
+#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY
+#define GL_SRC0_RGB GL_SOURCE0_RGB
+#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER
+#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE
+#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA
+#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE
+#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE
+#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA
+#define GL_SRC1_RGB GL_SOURCE1_RGB
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING
+#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA
+#define GL_SRC2_RGB GL_SOURCE2_RGB
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+
+typedef ptrdiff_t GLsizeiptr;
+typedef ptrdiff_t GLintptr;
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint params);
+typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id);
+typedef GLvoid* (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
+typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERPROC) (GLenum target);
+
+#define glBeginQuery GLEW_GET_FUN(__glewBeginQuery)
+#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer)
+#define glBufferData GLEW_GET_FUN(__glewBufferData)
+#define glBufferSubData GLEW_GET_FUN(__glewBufferSubData)
+#define glDeleteBuffers GLEW_GET_FUN(__glewDeleteBuffers)
+#define glDeleteQueries GLEW_GET_FUN(__glewDeleteQueries)
+#define glEndQuery GLEW_GET_FUN(__glewEndQuery)
+#define glGenBuffers GLEW_GET_FUN(__glewGenBuffers)
+#define glGenQueries GLEW_GET_FUN(__glewGenQueries)
+#define glGetBufferParameteriv GLEW_GET_FUN(__glewGetBufferParameteriv)
+#define glGetBufferPointerv GLEW_GET_FUN(__glewGetBufferPointerv)
+#define glGetBufferSubData GLEW_GET_FUN(__glewGetBufferSubData)
+#define glGetQueryObjectiv GLEW_GET_FUN(__glewGetQueryObjectiv)
+#define glGetQueryObjectuiv GLEW_GET_FUN(__glewGetQueryObjectuiv)
+#define glGetQueryiv GLEW_GET_FUN(__glewGetQueryiv)
+#define glIsBuffer GLEW_GET_FUN(__glewIsBuffer)
+#define glIsQuery GLEW_GET_FUN(__glewIsQuery)
+#define glMapBuffer GLEW_GET_FUN(__glewMapBuffer)
+#define glUnmapBuffer GLEW_GET_FUN(__glewUnmapBuffer)
+
+#define GLEW_VERSION_1_5 GLEW_GET_VAR(__GLEW_VERSION_1_5)
+
+#endif /* GL_VERSION_1_5 */
+
+/* ----------------------------- GL_VERSION_2_0 ---------------------------- */
+
+#ifndef GL_VERSION_2_0
+#define GL_VERSION_2_0 1
+
+#define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0)
+
+#endif /* GL_VERSION_2_0 */
+
+/* -------------------------- GL_3DFX_multisample -------------------------- */
+
+#ifndef GL_3DFX_multisample
+#define GL_3DFX_multisample 1
+
+#define GL_MULTISAMPLE_3DFX 0x86B2
+#define GL_SAMPLE_BUFFERS_3DFX 0x86B3
+#define GL_SAMPLES_3DFX 0x86B4
+#define GL_MULTISAMPLE_BIT_3DFX 0x20000000
+
+#define GLEW_3DFX_multisample GLEW_GET_VAR(__GLEW_3DFX_multisample)
+
+#endif /* GL_3DFX_multisample */
+
+/* ---------------------------- GL_3DFX_tbuffer ---------------------------- */
+
+#ifndef GL_3DFX_tbuffer
+#define GL_3DFX_tbuffer 1
+
+typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);
+
+#define glTbufferMask3DFX GLEW_GET_FUN(__glewTbufferMask3DFX)
+
+#define GLEW_3DFX_tbuffer GLEW_GET_VAR(__GLEW_3DFX_tbuffer)
+
+#endif /* GL_3DFX_tbuffer */
+
+/* -------------------- GL_3DFX_texture_compression_FXT1 ------------------- */
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_3DFX_texture_compression_FXT1 1
+
+#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
+#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
+
+#define GLEW_3DFX_texture_compression_FXT1 GLEW_GET_VAR(__GLEW_3DFX_texture_compression_FXT1)
+
+#endif /* GL_3DFX_texture_compression_FXT1 */
+
+/* ------------------------ GL_APPLE_client_storage ------------------------ */
+
+#ifndef GL_APPLE_client_storage
+#define GL_APPLE_client_storage 1
+
+#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
+
+#define GLEW_APPLE_client_storage GLEW_GET_VAR(__GLEW_APPLE_client_storage)
+
+#endif /* GL_APPLE_client_storage */
+
+/* ------------------------- GL_APPLE_element_array ------------------------ */
+
+#ifndef GL_APPLE_element_array
+#define GL_APPLE_element_array 1
+
+#define GL_ELEMENT_ARRAY_APPLE 0x8768
+#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8769
+#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x876A
+
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount);
+
+#define glDrawElementArrayAPPLE GLEW_GET_FUN(__glewDrawElementArrayAPPLE)
+#define glDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewDrawRangeElementArrayAPPLE)
+#define glElementPointerAPPLE GLEW_GET_FUN(__glewElementPointerAPPLE)
+#define glMultiDrawElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawElementArrayAPPLE)
+#define glMultiDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawRangeElementArrayAPPLE)
+
+#define GLEW_APPLE_element_array GLEW_GET_VAR(__GLEW_APPLE_element_array)
+
+#endif /* GL_APPLE_element_array */
+
+/* ----------------------------- GL_APPLE_fence ---------------------------- */
+
+#ifndef GL_APPLE_fence
+#define GL_APPLE_fence 1
+
+#define GL_DRAW_PIXELS_APPLE 0x8A0A
+#define GL_FENCE_APPLE 0x8A0B
+
+typedef void (GLAPIENTRY * PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);
+typedef void (GLAPIENTRY * PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint* fences);
+typedef GLboolean (GLAPIENTRY * PFNGLISFENCEAPPLEPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLSETFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (GLAPIENTRY * PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);
+
+#define glDeleteFencesAPPLE GLEW_GET_FUN(__glewDeleteFencesAPPLE)
+#define glFinishFenceAPPLE GLEW_GET_FUN(__glewFinishFenceAPPLE)
+#define glFinishObjectAPPLE GLEW_GET_FUN(__glewFinishObjectAPPLE)
+#define glGenFencesAPPLE GLEW_GET_FUN(__glewGenFencesAPPLE)
+#define glIsFenceAPPLE GLEW_GET_FUN(__glewIsFenceAPPLE)
+#define glSetFenceAPPLE GLEW_GET_FUN(__glewSetFenceAPPLE)
+#define glTestFenceAPPLE GLEW_GET_FUN(__glewTestFenceAPPLE)
+#define glTestObjectAPPLE GLEW_GET_FUN(__glewTestObjectAPPLE)
+
+#define GLEW_APPLE_fence GLEW_GET_VAR(__GLEW_APPLE_fence)
+
+#endif /* GL_APPLE_fence */
+
+/* ------------------------- GL_APPLE_float_pixels ------------------------- */
+
+#ifndef GL_APPLE_float_pixels
+#define GL_APPLE_float_pixels 1
+
+#define GL_HALF_APPLE 0x140B
+#define GL_RGBA_FLOAT32_APPLE 0x8814
+#define GL_RGB_FLOAT32_APPLE 0x8815
+#define GL_ALPHA_FLOAT32_APPLE 0x8816
+#define GL_INTENSITY_FLOAT32_APPLE 0x8817
+#define GL_LUMINANCE_FLOAT32_APPLE 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819
+#define GL_RGBA_FLOAT16_APPLE 0x881A
+#define GL_RGB_FLOAT16_APPLE 0x881B
+#define GL_ALPHA_FLOAT16_APPLE 0x881C
+#define GL_INTENSITY_FLOAT16_APPLE 0x881D
+#define GL_LUMINANCE_FLOAT16_APPLE 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F
+#define GL_COLOR_FLOAT_APPLE 0x8A0F
+
+#define GLEW_APPLE_float_pixels GLEW_GET_VAR(__GLEW_APPLE_float_pixels)
+
+#endif /* GL_APPLE_float_pixels */
+
+/* ------------------------ GL_APPLE_specular_vector ----------------------- */
+
+#ifndef GL_APPLE_specular_vector
+#define GL_APPLE_specular_vector 1
+
+#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+
+#define GLEW_APPLE_specular_vector GLEW_GET_VAR(__GLEW_APPLE_specular_vector)
+
+#endif /* GL_APPLE_specular_vector */
+
+/* ------------------------- GL_APPLE_texture_range ------------------------ */
+
+#ifndef GL_APPLE_texture_range
+#define GL_APPLE_texture_range 1
+
+#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7
+#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8
+#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
+#define GL_STORAGE_PRIVATE_APPLE 0x85BD
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid **params);
+typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer);
+
+#define glGetTexParameterPointervAPPLE GLEW_GET_FUN(__glewGetTexParameterPointervAPPLE)
+#define glTextureRangeAPPLE GLEW_GET_FUN(__glewTextureRangeAPPLE)
+
+#define GLEW_APPLE_texture_range GLEW_GET_VAR(__GLEW_APPLE_texture_range)
+
+#endif /* GL_APPLE_texture_range */
+
+/* ------------------------ GL_APPLE_transform_hint ------------------------ */
+
+#ifndef GL_APPLE_transform_hint
+#define GL_APPLE_transform_hint 1
+
+#define GL_TRANSFORM_HINT_APPLE 0x85B1
+
+#define GLEW_APPLE_transform_hint GLEW_GET_VAR(__GLEW_APPLE_transform_hint)
+
+#endif /* GL_APPLE_transform_hint */
+
+/* ---------------------- GL_APPLE_vertex_array_object --------------------- */
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_APPLE_vertex_array_object 1
+
+#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5
+
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);
+typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays);
+typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays);
+typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
+
+#define glBindVertexArrayAPPLE GLEW_GET_FUN(__glewBindVertexArrayAPPLE)
+#define glDeleteVertexArraysAPPLE GLEW_GET_FUN(__glewDeleteVertexArraysAPPLE)
+#define glGenVertexArraysAPPLE GLEW_GET_FUN(__glewGenVertexArraysAPPLE)
+#define glIsVertexArrayAPPLE GLEW_GET_FUN(__glewIsVertexArrayAPPLE)
+
+#define GLEW_APPLE_vertex_array_object GLEW_GET_VAR(__GLEW_APPLE_vertex_array_object)
+
+#endif /* GL_APPLE_vertex_array_object */
+
+/* ---------------------- GL_APPLE_vertex_array_range ---------------------- */
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_APPLE_vertex_array_range 1
+
+#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
+#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+
+typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer);
+
+#define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE)
+#define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE)
+#define glVertexArrayRangeAPPLE GLEW_GET_FUN(__glewVertexArrayRangeAPPLE)
+
+#define GLEW_APPLE_vertex_array_range GLEW_GET_VAR(__GLEW_APPLE_vertex_array_range)
+
+#endif /* GL_APPLE_vertex_array_range */
+
+/* --------------------------- GL_APPLE_ycbcr_422 -------------------------- */
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_APPLE_ycbcr_422 1
+
+#define GL_YCBCR_422_APPLE 0x85B9
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+
+#define GLEW_APPLE_ycbcr_422 GLEW_GET_VAR(__GLEW_APPLE_ycbcr_422)
+
+#endif /* GL_APPLE_ycbcr_422 */
+
+/* ----------------------- GL_ARB_color_buffer_float ----------------------- */
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_ARB_color_buffer_float 1
+
+#define GL_RGBA_FLOAT_MODE_ARB 0x8820
+#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B
+#define GL_CLAMP_READ_COLOR_ARB 0x891C
+#define GL_FIXED_ONLY_ARB 0x891D
+
+typedef void (GLAPIENTRY * PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);
+
+#define glClampColorARB GLEW_GET_FUN(__glewClampColorARB)
+
+#define GLEW_ARB_color_buffer_float GLEW_GET_VAR(__GLEW_ARB_color_buffer_float)
+
+#endif /* GL_ARB_color_buffer_float */
+
+/* -------------------------- GL_ARB_depth_texture ------------------------- */
+
+#ifndef GL_ARB_depth_texture
+#define GL_ARB_depth_texture 1
+
+#define GL_DEPTH_COMPONENT16_ARB 0x81A5
+#define GL_DEPTH_COMPONENT24_ARB 0x81A6
+#define GL_DEPTH_COMPONENT32_ARB 0x81A7
+#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+
+#define GLEW_ARB_depth_texture GLEW_GET_VAR(__GLEW_ARB_depth_texture)
+
+#endif /* GL_ARB_depth_texture */
+
+/* -------------------------- GL_ARB_draw_buffers -------------------------- */
+
+#ifndef GL_ARB_draw_buffers
+#define GL_ARB_draw_buffers 1
+
+#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
+#define GL_DRAW_BUFFER0_ARB 0x8825
+#define GL_DRAW_BUFFER1_ARB 0x8826
+#define GL_DRAW_BUFFER2_ARB 0x8827
+#define GL_DRAW_BUFFER3_ARB 0x8828
+#define GL_DRAW_BUFFER4_ARB 0x8829
+#define GL_DRAW_BUFFER5_ARB 0x882A
+#define GL_DRAW_BUFFER6_ARB 0x882B
+#define GL_DRAW_BUFFER7_ARB 0x882C
+#define GL_DRAW_BUFFER8_ARB 0x882D
+#define GL_DRAW_BUFFER9_ARB 0x882E
+#define GL_DRAW_BUFFER10_ARB 0x882F
+#define GL_DRAW_BUFFER11_ARB 0x8830
+#define GL_DRAW_BUFFER12_ARB 0x8831
+#define GL_DRAW_BUFFER13_ARB 0x8832
+#define GL_DRAW_BUFFER14_ARB 0x8833
+#define GL_DRAW_BUFFER15_ARB 0x8834
+
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum* bufs);
+
+#define glDrawBuffersARB GLEW_GET_FUN(__glewDrawBuffersARB)
+
+#define GLEW_ARB_draw_buffers GLEW_GET_VAR(__GLEW_ARB_draw_buffers)
+
+#endif /* GL_ARB_draw_buffers */
+
+/* ------------------------ GL_ARB_fragment_program ------------------------ */
+
+#ifndef GL_ARB_fragment_program
+#define GL_ARB_fragment_program 1
+
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
+
+#define GLEW_ARB_fragment_program GLEW_GET_VAR(__GLEW_ARB_fragment_program)
+
+#endif /* GL_ARB_fragment_program */
+
+/* --------------------- GL_ARB_fragment_program_shadow -------------------- */
+
+#ifndef GL_ARB_fragment_program_shadow
+#define GL_ARB_fragment_program_shadow 1
+
+#define GLEW_ARB_fragment_program_shadow GLEW_GET_VAR(__GLEW_ARB_fragment_program_shadow)
+
+#endif /* GL_ARB_fragment_program_shadow */
+
+/* ------------------------- GL_ARB_fragment_shader ------------------------ */
+
+#ifndef GL_ARB_fragment_shader
+#define GL_ARB_fragment_shader 1
+
+#define GL_FRAGMENT_SHADER_ARB 0x8B30
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+
+#define GLEW_ARB_fragment_shader GLEW_GET_VAR(__GLEW_ARB_fragment_shader)
+
+#endif /* GL_ARB_fragment_shader */
+
+/* ------------------------ GL_ARB_half_float_pixel ------------------------ */
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_ARB_half_float_pixel 1
+
+#define GL_HALF_FLOAT_ARB 0x140B
+
+#define GLEW_ARB_half_float_pixel GLEW_GET_VAR(__GLEW_ARB_half_float_pixel)
+
+#endif /* GL_ARB_half_float_pixel */
+
+/* ----------------------------- GL_ARB_imaging ---------------------------- */
+
+#ifndef GL_ARB_imaging
+#define GL_ARB_imaging 1
+
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_FUNC_ADD 0x8006
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_BLEND_EQUATION 0x8009
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_CONVOLUTION_1D 0x8010
+#define GL_CONVOLUTION_2D 0x8011
+#define GL_SEPARABLE_2D 0x8012
+#define GL_CONVOLUTION_BORDER_MODE 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define GL_REDUCE 0x8016
+#define GL_CONVOLUTION_FORMAT 0x8017
+#define GL_CONVOLUTION_WIDTH 0x8018
+#define GL_CONVOLUTION_HEIGHT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define GL_HISTOGRAM 0x8024
+#define GL_PROXY_HISTOGRAM 0x8025
+#define GL_HISTOGRAM_WIDTH 0x8026
+#define GL_HISTOGRAM_FORMAT 0x8027
+#define GL_HISTOGRAM_RED_SIZE 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define GL_HISTOGRAM_SINK 0x802D
+#define GL_MINMAX 0x802E
+#define GL_MINMAX_FORMAT 0x802F
+#define GL_MINMAX_SINK 0x8030
+#define GL_TABLE_TOO_LARGE 0x8031
+#define GL_COLOR_MATRIX 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define GL_COLOR_TABLE 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define GL_PROXY_COLOR_TABLE 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE 0x80D6
+#define GL_COLOR_TABLE_BIAS 0x80D7
+#define GL_COLOR_TABLE_FORMAT 0x80D8
+#define GL_COLOR_TABLE_WIDTH 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define GL_IGNORE_BORDER 0x8150
+#define GL_CONSTANT_BORDER 0x8151
+#define GL_WRAP_BORDER 0x8152
+#define GL_REPLICATE_BORDER 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR 0x8154
+
+typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (GLAPIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLRESETMINMAXPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+
+#define glColorSubTable GLEW_GET_FUN(__glewColorSubTable)
+#define glColorTable GLEW_GET_FUN(__glewColorTable)
+#define glColorTableParameterfv GLEW_GET_FUN(__glewColorTableParameterfv)
+#define glColorTableParameteriv GLEW_GET_FUN(__glewColorTableParameteriv)
+#define glConvolutionFilter1D GLEW_GET_FUN(__glewConvolutionFilter1D)
+#define glConvolutionFilter2D GLEW_GET_FUN(__glewConvolutionFilter2D)
+#define glConvolutionParameterf GLEW_GET_FUN(__glewConvolutionParameterf)
+#define glConvolutionParameterfv GLEW_GET_FUN(__glewConvolutionParameterfv)
+#define glConvolutionParameteri GLEW_GET_FUN(__glewConvolutionParameteri)
+#define glConvolutionParameteriv GLEW_GET_FUN(__glewConvolutionParameteriv)
+#define glCopyColorSubTable GLEW_GET_FUN(__glewCopyColorSubTable)
+#define glCopyColorTable GLEW_GET_FUN(__glewCopyColorTable)
+#define glCopyConvolutionFilter1D GLEW_GET_FUN(__glewCopyConvolutionFilter1D)
+#define glCopyConvolutionFilter2D GLEW_GET_FUN(__glewCopyConvolutionFilter2D)
+#define glGetColorTable GLEW_GET_FUN(__glewGetColorTable)
+#define glGetColorTableParameterfv GLEW_GET_FUN(__glewGetColorTableParameterfv)
+#define glGetColorTableParameteriv GLEW_GET_FUN(__glewGetColorTableParameteriv)
+#define glGetConvolutionFilter GLEW_GET_FUN(__glewGetConvolutionFilter)
+#define glGetConvolutionParameterfv GLEW_GET_FUN(__glewGetConvolutionParameterfv)
+#define glGetConvolutionParameteriv GLEW_GET_FUN(__glewGetConvolutionParameteriv)
+#define glGetHistogram GLEW_GET_FUN(__glewGetHistogram)
+#define glGetHistogramParameterfv GLEW_GET_FUN(__glewGetHistogramParameterfv)
+#define glGetHistogramParameteriv GLEW_GET_FUN(__glewGetHistogramParameteriv)
+#define glGetMinmax GLEW_GET_FUN(__glewGetMinmax)
+#define glGetMinmaxParameterfv GLEW_GET_FUN(__glewGetMinmaxParameterfv)
+#define glGetMinmaxParameteriv GLEW_GET_FUN(__glewGetMinmaxParameteriv)
+#define glGetSeparableFilter GLEW_GET_FUN(__glewGetSeparableFilter)
+#define glHistogram GLEW_GET_FUN(__glewHistogram)
+#define glMinmax GLEW_GET_FUN(__glewMinmax)
+#define glResetHistogram GLEW_GET_FUN(__glewResetHistogram)
+#define glResetMinmax GLEW_GET_FUN(__glewResetMinmax)
+#define glSeparableFilter2D GLEW_GET_FUN(__glewSeparableFilter2D)
+
+#define GLEW_ARB_imaging GLEW_GET_VAR(__GLEW_ARB_imaging)
+
+#endif /* GL_ARB_imaging */
+
+/* ------------------------- GL_ARB_matrix_palette ------------------------- */
+
+#ifndef GL_ARB_matrix_palette
+#define GL_ARB_matrix_palette 1
+
+#define GL_MATRIX_PALETTE_ARB 0x8840
+#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
+#define GL_MAX_PALETTE_MATRICES_ARB 0x8842
+#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843
+#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844
+#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845
+#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849
+
+typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUBVARBPROC) (GLint size, GLubyte *indices);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUIVARBPROC) (GLint size, GLuint *indices);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *indices);
+
+#define glCurrentPaletteMatrixARB GLEW_GET_FUN(__glewCurrentPaletteMatrixARB)
+#define glMatrixIndexPointerARB GLEW_GET_FUN(__glewMatrixIndexPointerARB)
+#define glMatrixIndexubvARB GLEW_GET_FUN(__glewMatrixIndexubvARB)
+#define glMatrixIndexuivARB GLEW_GET_FUN(__glewMatrixIndexuivARB)
+#define glMatrixIndexusvARB GLEW_GET_FUN(__glewMatrixIndexusvARB)
+
+#define GLEW_ARB_matrix_palette GLEW_GET_VAR(__GLEW_ARB_matrix_palette)
+
+#endif /* GL_ARB_matrix_palette */
+
+/* --------------------------- GL_ARB_multisample -------------------------- */
+
+#ifndef GL_ARB_multisample
+#define GL_ARB_multisample 1
+
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);
+
+#define glSampleCoverageARB GLEW_GET_FUN(__glewSampleCoverageARB)
+
+#define GLEW_ARB_multisample GLEW_GET_VAR(__GLEW_ARB_multisample)
+
+#endif /* GL_ARB_multisample */
+
+/* -------------------------- GL_ARB_multitexture -------------------------- */
+
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+
+typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+
+#define glActiveTextureARB GLEW_GET_FUN(__glewActiveTextureARB)
+#define glClientActiveTextureARB GLEW_GET_FUN(__glewClientActiveTextureARB)
+#define glMultiTexCoord1dARB GLEW_GET_FUN(__glewMultiTexCoord1dARB)
+#define glMultiTexCoord1dvARB GLEW_GET_FUN(__glewMultiTexCoord1dvARB)
+#define glMultiTexCoord1fARB GLEW_GET_FUN(__glewMultiTexCoord1fARB)
+#define glMultiTexCoord1fvARB GLEW_GET_FUN(__glewMultiTexCoord1fvARB)
+#define glMultiTexCoord1iARB GLEW_GET_FUN(__glewMultiTexCoord1iARB)
+#define glMultiTexCoord1ivARB GLEW_GET_FUN(__glewMultiTexCoord1ivARB)
+#define glMultiTexCoord1sARB GLEW_GET_FUN(__glewMultiTexCoord1sARB)
+#define glMultiTexCoord1svARB GLEW_GET_FUN(__glewMultiTexCoord1svARB)
+#define glMultiTexCoord2dARB GLEW_GET_FUN(__glewMultiTexCoord2dARB)
+#define glMultiTexCoord2dvARB GLEW_GET_FUN(__glewMultiTexCoord2dvARB)
+#define glMultiTexCoord2fARB GLEW_GET_FUN(__glewMultiTexCoord2fARB)
+#define glMultiTexCoord2fvARB GLEW_GET_FUN(__glewMultiTexCoord2fvARB)
+#define glMultiTexCoord2iARB GLEW_GET_FUN(__glewMultiTexCoord2iARB)
+#define glMultiTexCoord2ivARB GLEW_GET_FUN(__glewMultiTexCoord2ivARB)
+#define glMultiTexCoord2sARB GLEW_GET_FUN(__glewMultiTexCoord2sARB)
+#define glMultiTexCoord2svARB GLEW_GET_FUN(__glewMultiTexCoord2svARB)
+#define glMultiTexCoord3dARB GLEW_GET_FUN(__glewMultiTexCoord3dARB)
+#define glMultiTexCoord3dvARB GLEW_GET_FUN(__glewMultiTexCoord3dvARB)
+#define glMultiTexCoord3fARB GLEW_GET_FUN(__glewMultiTexCoord3fARB)
+#define glMultiTexCoord3fvARB GLEW_GET_FUN(__glewMultiTexCoord3fvARB)
+#define glMultiTexCoord3iARB GLEW_GET_FUN(__glewMultiTexCoord3iARB)
+#define glMultiTexCoord3ivARB GLEW_GET_FUN(__glewMultiTexCoord3ivARB)
+#define glMultiTexCoord3sARB GLEW_GET_FUN(__glewMultiTexCoord3sARB)
+#define glMultiTexCoord3svARB GLEW_GET_FUN(__glewMultiTexCoord3svARB)
+#define glMultiTexCoord4dARB GLEW_GET_FUN(__glewMultiTexCoord4dARB)
+#define glMultiTexCoord4dvARB GLEW_GET_FUN(__glewMultiTexCoord4dvARB)
+#define glMultiTexCoord4fARB GLEW_GET_FUN(__glewMultiTexCoord4fARB)
+#define glMultiTexCoord4fvARB GLEW_GET_FUN(__glewMultiTexCoord4fvARB)
+#define glMultiTexCoord4iARB GLEW_GET_FUN(__glewMultiTexCoord4iARB)
+#define glMultiTexCoord4ivARB GLEW_GET_FUN(__glewMultiTexCoord4ivARB)
+#define glMultiTexCoord4sARB GLEW_GET_FUN(__glewMultiTexCoord4sARB)
+#define glMultiTexCoord4svARB GLEW_GET_FUN(__glewMultiTexCoord4svARB)
+
+#define GLEW_ARB_multitexture GLEW_GET_VAR(__GLEW_ARB_multitexture)
+
+#endif /* GL_ARB_multitexture */
+
+/* ------------------------- GL_ARB_occlusion_query ------------------------ */
+
+#ifndef GL_ARB_occlusion_query
+#define GL_ARB_occlusion_query 1
+
+#define GL_QUERY_COUNTER_BITS_ARB 0x8864
+#define GL_CURRENT_QUERY_ARB 0x8865
+#define GL_QUERY_RESULT_ARB 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
+#define GL_SAMPLES_PASSED_ARB 0x8914
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDQUERYARBPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISQUERYARBPROC) (GLuint id);
+
+#define glBeginQueryARB GLEW_GET_FUN(__glewBeginQueryARB)
+#define glDeleteQueriesARB GLEW_GET_FUN(__glewDeleteQueriesARB)
+#define glEndQueryARB GLEW_GET_FUN(__glewEndQueryARB)
+#define glGenQueriesARB GLEW_GET_FUN(__glewGenQueriesARB)
+#define glGetQueryObjectivARB GLEW_GET_FUN(__glewGetQueryObjectivARB)
+#define glGetQueryObjectuivARB GLEW_GET_FUN(__glewGetQueryObjectuivARB)
+#define glGetQueryivARB GLEW_GET_FUN(__glewGetQueryivARB)
+#define glIsQueryARB GLEW_GET_FUN(__glewIsQueryARB)
+
+#define GLEW_ARB_occlusion_query GLEW_GET_VAR(__GLEW_ARB_occlusion_query)
+
+#endif /* GL_ARB_occlusion_query */
+
+/* ------------------------ GL_ARB_point_parameters ------------------------ */
+
+#ifndef GL_ARB_point_parameters
+#define GL_ARB_point_parameters 1
+
+#define GL_POINT_SIZE_MIN_ARB 0x8126
+#define GL_POINT_SIZE_MAX_ARB 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129
+
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, GLfloat* params);
+
+#define glPointParameterfARB GLEW_GET_FUN(__glewPointParameterfARB)
+#define glPointParameterfvARB GLEW_GET_FUN(__glewPointParameterfvARB)
+
+#define GLEW_ARB_point_parameters GLEW_GET_VAR(__GLEW_ARB_point_parameters)
+
+#endif /* GL_ARB_point_parameters */
+
+/* -------------------------- GL_ARB_point_sprite -------------------------- */
+
+#ifndef GL_ARB_point_sprite
+#define GL_ARB_point_sprite 1
+
+#define GL_POINT_SPRITE_ARB 0x8861
+#define GL_COORD_REPLACE_ARB 0x8862
+
+#define GLEW_ARB_point_sprite GLEW_GET_VAR(__GLEW_ARB_point_sprite)
+
+#endif /* GL_ARB_point_sprite */
+
+/* ------------------------- GL_ARB_shader_objects ------------------------- */
+
+#ifndef GL_ARB_shader_objects
+#define GL_ARB_shader_objects 1
+
+#define GL_PROGRAM_OBJECT_ARB 0x8B40
+#define GL_SHADER_OBJECT_ARB 0x8B48
+#define GL_OBJECT_TYPE_ARB 0x8B4E
+#define GL_OBJECT_SUBTYPE_ARB 0x8B4F
+#define GL_FLOAT_VEC2_ARB 0x8B50
+#define GL_FLOAT_VEC3_ARB 0x8B51
+#define GL_FLOAT_VEC4_ARB 0x8B52
+#define GL_INT_VEC2_ARB 0x8B53
+#define GL_INT_VEC3_ARB 0x8B54
+#define GL_INT_VEC4_ARB 0x8B55
+#define GL_BOOL_ARB 0x8B56
+#define GL_BOOL_VEC2_ARB 0x8B57
+#define GL_BOOL_VEC3_ARB 0x8B58
+#define GL_BOOL_VEC4_ARB 0x8B59
+#define GL_FLOAT_MAT2_ARB 0x8B5A
+#define GL_FLOAT_MAT3_ARB 0x8B5B
+#define GL_FLOAT_MAT4_ARB 0x8B5C
+#define GL_SAMPLER_1D_ARB 0x8B5D
+#define GL_SAMPLER_2D_ARB 0x8B5E
+#define GL_SAMPLER_3D_ARB 0x8B5F
+#define GL_SAMPLER_CUBE_ARB 0x8B60
+#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
+#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+
+typedef char GLcharARB;
+typedef int GLhandleARB;
+
+typedef void (GLAPIENTRY * PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
+typedef void (GLAPIENTRY * PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
+typedef GLhandleARB (GLAPIENTRY * PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef GLhandleARB (GLAPIENTRY * PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (GLAPIENTRY * PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
+typedef void (GLAPIENTRY * PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (GLAPIENTRY * PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei* count, GLhandleARB *obj);
+typedef GLhandleARB (GLAPIENTRY * PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (GLAPIENTRY * PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *infoLog);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *source);
+typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint* params);
+typedef void (GLAPIENTRY * PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (GLAPIENTRY * PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint *length);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
+typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+
+#define glAttachObjectARB GLEW_GET_FUN(__glewAttachObjectARB)
+#define glCompileShaderARB GLEW_GET_FUN(__glewCompileShaderARB)
+#define glCreateProgramObjectARB GLEW_GET_FUN(__glewCreateProgramObjectARB)
+#define glCreateShaderObjectARB GLEW_GET_FUN(__glewCreateShaderObjectARB)
+#define glDeleteObjectARB GLEW_GET_FUN(__glewDeleteObjectARB)
+#define glDetachObjectARB GLEW_GET_FUN(__glewDetachObjectARB)
+#define glGetActiveUniformARB GLEW_GET_FUN(__glewGetActiveUniformARB)
+#define glGetAttachedObjectsARB GLEW_GET_FUN(__glewGetAttachedObjectsARB)
+#define glGetHandleARB GLEW_GET_FUN(__glewGetHandleARB)
+#define glGetInfoLogARB GLEW_GET_FUN(__glewGetInfoLogARB)
+#define glGetObjectParameterfvARB GLEW_GET_FUN(__glewGetObjectParameterfvARB)
+#define glGetObjectParameterivARB GLEW_GET_FUN(__glewGetObjectParameterivARB)
+#define glGetShaderSourceARB GLEW_GET_FUN(__glewGetShaderSourceARB)
+#define glGetUniformLocationARB GLEW_GET_FUN(__glewGetUniformLocationARB)
+#define glGetUniformfvARB GLEW_GET_FUN(__glewGetUniformfvARB)
+#define glGetUniformivARB GLEW_GET_FUN(__glewGetUniformivARB)
+#define glLinkProgramARB GLEW_GET_FUN(__glewLinkProgramARB)
+#define glShaderSourceARB GLEW_GET_FUN(__glewShaderSourceARB)
+#define glUniform1fARB GLEW_GET_FUN(__glewUniform1fARB)
+#define glUniform1fvARB GLEW_GET_FUN(__glewUniform1fvARB)
+#define glUniform1iARB GLEW_GET_FUN(__glewUniform1iARB)
+#define glUniform1ivARB GLEW_GET_FUN(__glewUniform1ivARB)
+#define glUniform2fARB GLEW_GET_FUN(__glewUniform2fARB)
+#define glUniform2fvARB GLEW_GET_FUN(__glewUniform2fvARB)
+#define glUniform2iARB GLEW_GET_FUN(__glewUniform2iARB)
+#define glUniform2ivARB GLEW_GET_FUN(__glewUniform2ivARB)
+#define glUniform3fARB GLEW_GET_FUN(__glewUniform3fARB)
+#define glUniform3fvARB GLEW_GET_FUN(__glewUniform3fvARB)
+#define glUniform3iARB GLEW_GET_FUN(__glewUniform3iARB)
+#define glUniform3ivARB GLEW_GET_FUN(__glewUniform3ivARB)
+#define glUniform4fARB GLEW_GET_FUN(__glewUniform4fARB)
+#define glUniform4fvARB GLEW_GET_FUN(__glewUniform4fvARB)
+#define glUniform4iARB GLEW_GET_FUN(__glewUniform4iARB)
+#define glUniform4ivARB GLEW_GET_FUN(__glewUniform4ivARB)
+#define glUniformMatrix2fvARB GLEW_GET_FUN(__glewUniformMatrix2fvARB)
+#define glUniformMatrix3fvARB GLEW_GET_FUN(__glewUniformMatrix3fvARB)
+#define glUniformMatrix4fvARB GLEW_GET_FUN(__glewUniformMatrix4fvARB)
+#define glUseProgramObjectARB GLEW_GET_FUN(__glewUseProgramObjectARB)
+#define glValidateProgramARB GLEW_GET_FUN(__glewValidateProgramARB)
+
+#define GLEW_ARB_shader_objects GLEW_GET_VAR(__GLEW_ARB_shader_objects)
+
+#endif /* GL_ARB_shader_objects */
+
+/* ---------------------- GL_ARB_shading_language_100 ---------------------- */
+
+#ifndef GL_ARB_shading_language_100
+#define GL_ARB_shading_language_100 1
+
+#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
+
+#define GLEW_ARB_shading_language_100 GLEW_GET_VAR(__GLEW_ARB_shading_language_100)
+
+#endif /* GL_ARB_shading_language_100 */
+
+/* ----------------------------- GL_ARB_shadow ----------------------------- */
+
+#ifndef GL_ARB_shadow
+#define GL_ARB_shadow 1
+
+#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
+#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
+
+#define GLEW_ARB_shadow GLEW_GET_VAR(__GLEW_ARB_shadow)
+
+#endif /* GL_ARB_shadow */
+
+/* ------------------------- GL_ARB_shadow_ambient ------------------------- */
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_ARB_shadow_ambient 1
+
+#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
+
+#define GLEW_ARB_shadow_ambient GLEW_GET_VAR(__GLEW_ARB_shadow_ambient)
+
+#endif /* GL_ARB_shadow_ambient */
+
+/* ---------------------- GL_ARB_texture_border_clamp ---------------------- */
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_ARB_texture_border_clamp 1
+
+#define GL_CLAMP_TO_BORDER_ARB 0x812D
+
+#define GLEW_ARB_texture_border_clamp GLEW_GET_VAR(__GLEW_ARB_texture_border_clamp)
+
+#endif /* GL_ARB_texture_border_clamp */
+
+/* ----------------------- GL_ARB_texture_compression ---------------------- */
+
+#ifndef GL_ARB_texture_compression
+#define GL_ARB_texture_compression 1
+
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void* img);
+
+#define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB)
+#define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB)
+#define glCompressedTexImage3DARB GLEW_GET_FUN(__glewCompressedTexImage3DARB)
+#define glCompressedTexSubImage1DARB GLEW_GET_FUN(__glewCompressedTexSubImage1DARB)
+#define glCompressedTexSubImage2DARB GLEW_GET_FUN(__glewCompressedTexSubImage2DARB)
+#define glCompressedTexSubImage3DARB GLEW_GET_FUN(__glewCompressedTexSubImage3DARB)
+#define glGetCompressedTexImageARB GLEW_GET_FUN(__glewGetCompressedTexImageARB)
+
+#define GLEW_ARB_texture_compression GLEW_GET_VAR(__GLEW_ARB_texture_compression)
+
+#endif /* GL_ARB_texture_compression */
+
+/* ------------------------ GL_ARB_texture_cube_map ------------------------ */
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_ARB_texture_cube_map 1
+
+#define GL_NORMAL_MAP_ARB 0x8511
+#define GL_REFLECTION_MAP_ARB 0x8512
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+
+#define GLEW_ARB_texture_cube_map GLEW_GET_VAR(__GLEW_ARB_texture_cube_map)
+
+#endif /* GL_ARB_texture_cube_map */
+
+/* ------------------------- GL_ARB_texture_env_add ------------------------ */
+
+#ifndef GL_ARB_texture_env_add
+#define GL_ARB_texture_env_add 1
+
+#define GLEW_ARB_texture_env_add GLEW_GET_VAR(__GLEW_ARB_texture_env_add)
+
+#endif /* GL_ARB_texture_env_add */
+
+/* ----------------------- GL_ARB_texture_env_combine ---------------------- */
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_ARB_texture_env_combine 1
+
+#define GL_SUBTRACT_ARB 0x84E7
+#define GL_COMBINE_ARB 0x8570
+#define GL_COMBINE_RGB_ARB 0x8571
+#define GL_COMBINE_ALPHA_ARB 0x8572
+#define GL_RGB_SCALE_ARB 0x8573
+#define GL_ADD_SIGNED_ARB 0x8574
+#define GL_INTERPOLATE_ARB 0x8575
+#define GL_CONSTANT_ARB 0x8576
+#define GL_PRIMARY_COLOR_ARB 0x8577
+#define GL_PREVIOUS_ARB 0x8578
+#define GL_SOURCE0_RGB_ARB 0x8580
+#define GL_SOURCE1_RGB_ARB 0x8581
+#define GL_SOURCE2_RGB_ARB 0x8582
+#define GL_SOURCE0_ALPHA_ARB 0x8588
+#define GL_SOURCE1_ALPHA_ARB 0x8589
+#define GL_SOURCE2_ALPHA_ARB 0x858A
+#define GL_OPERAND0_RGB_ARB 0x8590
+#define GL_OPERAND1_RGB_ARB 0x8591
+#define GL_OPERAND2_RGB_ARB 0x8592
+#define GL_OPERAND0_ALPHA_ARB 0x8598
+#define GL_OPERAND1_ALPHA_ARB 0x8599
+#define GL_OPERAND2_ALPHA_ARB 0x859A
+
+#define GLEW_ARB_texture_env_combine GLEW_GET_VAR(__GLEW_ARB_texture_env_combine)
+
+#endif /* GL_ARB_texture_env_combine */
+
+/* ---------------------- GL_ARB_texture_env_crossbar ---------------------- */
+
+#ifndef GL_ARB_texture_env_crossbar
+#define GL_ARB_texture_env_crossbar 1
+
+#define GLEW_ARB_texture_env_crossbar GLEW_GET_VAR(__GLEW_ARB_texture_env_crossbar)
+
+#endif /* GL_ARB_texture_env_crossbar */
+
+/* ------------------------ GL_ARB_texture_env_dot3 ------------------------ */
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_ARB_texture_env_dot3 1
+
+#define GL_DOT3_RGB_ARB 0x86AE
+#define GL_DOT3_RGBA_ARB 0x86AF
+
+#define GLEW_ARB_texture_env_dot3 GLEW_GET_VAR(__GLEW_ARB_texture_env_dot3)
+
+#endif /* GL_ARB_texture_env_dot3 */
+
+/* -------------------------- GL_ARB_texture_float ------------------------- */
+
+#ifndef GL_ARB_texture_float
+#define GL_ARB_texture_float 1
+
+#define GL_RGBA32F_ARB 0x8814
+#define GL_RGB32F_ARB 0x8815
+#define GL_ALPHA32F_ARB 0x8816
+#define GL_INTENSITY32F_ARB 0x8817
+#define GL_LUMINANCE32F_ARB 0x8818
+#define GL_LUMINANCE_ALPHA32F_ARB 0x8819
+#define GL_RGBA16F_ARB 0x881A
+#define GL_RGB16F_ARB 0x881B
+#define GL_ALPHA16F_ARB 0x881C
+#define GL_INTENSITY16F_ARB 0x881D
+#define GL_LUMINANCE16F_ARB 0x881E
+#define GL_LUMINANCE_ALPHA16F_ARB 0x881F
+#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
+#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
+#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
+#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
+#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17
+
+#define GLEW_ARB_texture_float GLEW_GET_VAR(__GLEW_ARB_texture_float)
+
+#endif /* GL_ARB_texture_float */
+
+/* --------------------- GL_ARB_texture_mirrored_repeat -------------------- */
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_ARB_texture_mirrored_repeat 1
+
+#define GL_MIRRORED_REPEAT_ARB 0x8370
+
+#define GLEW_ARB_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_ARB_texture_mirrored_repeat)
+
+#endif /* GL_ARB_texture_mirrored_repeat */
+
+/* -------------------- GL_ARB_texture_non_power_of_two -------------------- */
+
+#ifndef GL_ARB_texture_non_power_of_two
+#define GL_ARB_texture_non_power_of_two 1
+
+#define GLEW_ARB_texture_non_power_of_two GLEW_GET_VAR(__GLEW_ARB_texture_non_power_of_two)
+
+#endif /* GL_ARB_texture_non_power_of_two */
+
+/* ------------------------ GL_ARB_texture_rectangle ----------------------- */
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_ARB_texture_rectangle 1
+
+#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+
+#define GLEW_ARB_texture_rectangle GLEW_GET_VAR(__GLEW_ARB_texture_rectangle)
+
+#endif /* GL_ARB_texture_rectangle */
+
+/* ------------------------ GL_ARB_transpose_matrix ------------------------ */
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_ARB_transpose_matrix 1
+
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
+
+#define GLEW_ARB_transpose_matrix GLEW_GET_VAR(__GLEW_ARB_transpose_matrix)
+
+#endif /* GL_ARB_transpose_matrix */
+
+/* -------------------------- GL_ARB_vertex_blend -------------------------- */
+
+#ifndef GL_ARB_vertex_blend
+#define GL_ARB_vertex_blend 1
+
+#define GL_MODELVIEW0_ARB 0x1700
+#define GL_MODELVIEW1_ARB 0x850A
+#define GL_MAX_VERTEX_UNITS_ARB 0x86A4
+#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5
+#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6
+#define GL_VERTEX_BLEND_ARB 0x86A7
+#define GL_CURRENT_WEIGHT_ARB 0x86A8
+#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC
+#define GL_WEIGHT_ARRAY_ARB 0x86AD
+#define GL_MODELVIEW2_ARB 0x8722
+#define GL_MODELVIEW3_ARB 0x8723
+#define GL_MODELVIEW4_ARB 0x8724
+#define GL_MODELVIEW5_ARB 0x8725
+#define GL_MODELVIEW6_ARB 0x8726
+#define GL_MODELVIEW7_ARB 0x8727
+#define GL_MODELVIEW8_ARB 0x8728
+#define GL_MODELVIEW9_ARB 0x8729
+#define GL_MODELVIEW10_ARB 0x872A
+#define GL_MODELVIEW11_ARB 0x872B
+#define GL_MODELVIEW12_ARB 0x872C
+#define GL_MODELVIEW13_ARB 0x872D
+#define GL_MODELVIEW14_ARB 0x872E
+#define GL_MODELVIEW15_ARB 0x872F
+#define GL_MODELVIEW16_ARB 0x8730
+#define GL_MODELVIEW17_ARB 0x8731
+#define GL_MODELVIEW18_ARB 0x8732
+#define GL_MODELVIEW19_ARB 0x8733
+#define GL_MODELVIEW20_ARB 0x8734
+#define GL_MODELVIEW21_ARB 0x8735
+#define GL_MODELVIEW22_ARB 0x8736
+#define GL_MODELVIEW23_ARB 0x8737
+#define GL_MODELVIEW24_ARB 0x8738
+#define GL_MODELVIEW25_ARB 0x8739
+#define GL_MODELVIEW26_ARB 0x873A
+#define GL_MODELVIEW27_ARB 0x873B
+#define GL_MODELVIEW28_ARB 0x873C
+#define GL_MODELVIEW29_ARB 0x873D
+#define GL_MODELVIEW30_ARB 0x873E
+#define GL_MODELVIEW31_ARB 0x873F
+
+typedef void (GLAPIENTRY * PFNGLVERTEXBLENDARBPROC) (GLint count);
+typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLWEIGHTBVARBPROC) (GLint size, GLbyte *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTDVARBPROC) (GLint size, GLdouble *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTFVARBPROC) (GLint size, GLfloat *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTIVARBPROC) (GLint size, GLint *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTSVARBPROC) (GLint size, GLshort *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTUBVARBPROC) (GLint size, GLubyte *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTUIVARBPROC) (GLint size, GLuint *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTUSVARBPROC) (GLint size, GLushort *weights);
+
+#define glVertexBlendARB GLEW_GET_FUN(__glewVertexBlendARB)
+#define glWeightPointerARB GLEW_GET_FUN(__glewWeightPointerARB)
+#define glWeightbvARB GLEW_GET_FUN(__glewWeightbvARB)
+#define glWeightdvARB GLEW_GET_FUN(__glewWeightdvARB)
+#define glWeightfvARB GLEW_GET_FUN(__glewWeightfvARB)
+#define glWeightivARB GLEW_GET_FUN(__glewWeightivARB)
+#define glWeightsvARB GLEW_GET_FUN(__glewWeightsvARB)
+#define glWeightubvARB GLEW_GET_FUN(__glewWeightubvARB)
+#define glWeightuivARB GLEW_GET_FUN(__glewWeightuivARB)
+#define glWeightusvARB GLEW_GET_FUN(__glewWeightusvARB)
+
+#define GLEW_ARB_vertex_blend GLEW_GET_VAR(__GLEW_ARB_vertex_blend)
+
+#endif /* GL_ARB_vertex_blend */
+
+/* ---------------------- GL_ARB_vertex_buffer_object ---------------------- */
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_ARB_vertex_buffer_object 1
+
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_WRITE_ONLY_ARB 0x88B9
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+
+typedef ptrdiff_t GLsizeiptrARB;
+typedef ptrdiff_t GLintptrARB;
+
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data);
+typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);
+typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target);
+
+#define glBindBufferARB GLEW_GET_FUN(__glewBindBufferARB)
+#define glBufferDataARB GLEW_GET_FUN(__glewBufferDataARB)
+#define glBufferSubDataARB GLEW_GET_FUN(__glewBufferSubDataARB)
+#define glDeleteBuffersARB GLEW_GET_FUN(__glewDeleteBuffersARB)
+#define glGenBuffersARB GLEW_GET_FUN(__glewGenBuffersARB)
+#define glGetBufferParameterivARB GLEW_GET_FUN(__glewGetBufferParameterivARB)
+#define glGetBufferPointervARB GLEW_GET_FUN(__glewGetBufferPointervARB)
+#define glGetBufferSubDataARB GLEW_GET_FUN(__glewGetBufferSubDataARB)
+#define glIsBufferARB GLEW_GET_FUN(__glewIsBufferARB)
+#define glMapBufferARB GLEW_GET_FUN(__glewMapBufferARB)
+#define glUnmapBufferARB GLEW_GET_FUN(__glewUnmapBufferARB)
+
+#define GLEW_ARB_vertex_buffer_object GLEW_GET_VAR(__GLEW_ARB_vertex_buffer_object)
+
+#endif /* GL_ARB_vertex_buffer_object */
+
+/* ------------------------- GL_ARB_vertex_program ------------------------- */
+
+#ifndef GL_ARB_vertex_program
+#define GL_ARB_vertex_program 1
+
+#define GL_COLOR_SUM_ARB 0x8458
+#define GL_VERTEX_PROGRAM_ARB 0x8620
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
+#define GL_PROGRAM_LENGTH_ARB 0x8627
+#define GL_PROGRAM_STRING_ARB 0x8628
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define GL_CURRENT_MATRIX_ARB 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
+#define GL_PROGRAM_BINDING_ARB 0x8677
+#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#define GL_PROGRAM_FORMAT_ARB 0x8876
+#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define GL_PROGRAM_PARAMETERS_ARB 0x88A8
+#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define GL_PROGRAM_ATTRIBS_ARB 0x88AC
+#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
+#define GL_MATRIX0_ARB 0x88C0
+#define GL_MATRIX1_ARB 0x88C1
+#define GL_MATRIX2_ARB 0x88C2
+#define GL_MATRIX3_ARB 0x88C3
+#define GL_MATRIX4_ARB 0x88C4
+#define GL_MATRIX5_ARB 0x88C5
+#define GL_MATRIX6_ARB 0x88C6
+#define GL_MATRIX7_ARB 0x88C7
+#define GL_MATRIX8_ARB 0x88C8
+#define GL_MATRIX9_ARB 0x88C9
+#define GL_MATRIX10_ARB 0x88CA
+#define GL_MATRIX11_ARB 0x88CB
+#define GL_MATRIX12_ARB 0x88CC
+#define GL_MATRIX13_ARB 0x88CD
+#define GL_MATRIX14_ARB 0x88CE
+#define GL_MATRIX15_ARB 0x88CF
+#define GL_MATRIX16_ARB 0x88D0
+#define GL_MATRIX17_ARB 0x88D1
+#define GL_MATRIX18_ARB 0x88D2
+#define GL_MATRIX19_ARB 0x88D3
+#define GL_MATRIX20_ARB 0x88D4
+#define GL_MATRIX21_ARB 0x88D5
+#define GL_MATRIX22_ARB 0x88D6
+#define GL_MATRIX23_ARB 0x88D7
+#define GL_MATRIX24_ARB 0x88D8
+#define GL_MATRIX25_ARB 0x88D9
+#define GL_MATRIX26_ARB 0x88DA
+#define GL_MATRIX27_ARB 0x88DB
+#define GL_MATRIX28_ARB 0x88DC
+#define GL_MATRIX29_ARB 0x88DD
+#define GL_MATRIX30_ARB 0x88DE
+#define GL_MATRIX31_ARB 0x88DF
+
+typedef void (GLAPIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint* programs);
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint* programs);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void* string);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void* string);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
+
+#define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB)
+#define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB)
+#define glDisableVertexAttribArrayARB GLEW_GET_FUN(__glewDisableVertexAttribArrayARB)
+#define glEnableVertexAttribArrayARB GLEW_GET_FUN(__glewEnableVertexAttribArrayARB)
+#define glGenProgramsARB GLEW_GET_FUN(__glewGenProgramsARB)
+#define glGetProgramEnvParameterdvARB GLEW_GET_FUN(__glewGetProgramEnvParameterdvARB)
+#define glGetProgramEnvParameterfvARB GLEW_GET_FUN(__glewGetProgramEnvParameterfvARB)
+#define glGetProgramLocalParameterdvARB GLEW_GET_FUN(__glewGetProgramLocalParameterdvARB)
+#define glGetProgramLocalParameterfvARB GLEW_GET_FUN(__glewGetProgramLocalParameterfvARB)
+#define glGetProgramStringARB GLEW_GET_FUN(__glewGetProgramStringARB)
+#define glGetProgramivARB GLEW_GET_FUN(__glewGetProgramivARB)
+#define glGetVertexAttribPointervARB GLEW_GET_FUN(__glewGetVertexAttribPointervARB)
+#define glGetVertexAttribdvARB GLEW_GET_FUN(__glewGetVertexAttribdvARB)
+#define glGetVertexAttribfvARB GLEW_GET_FUN(__glewGetVertexAttribfvARB)
+#define glGetVertexAttribivARB GLEW_GET_FUN(__glewGetVertexAttribivARB)
+#define glIsProgramARB GLEW_GET_FUN(__glewIsProgramARB)
+#define glProgramEnvParameter4dARB GLEW_GET_FUN(__glewProgramEnvParameter4dARB)
+#define glProgramEnvParameter4dvARB GLEW_GET_FUN(__glewProgramEnvParameter4dvARB)
+#define glProgramEnvParameter4fARB GLEW_GET_FUN(__glewProgramEnvParameter4fARB)
+#define glProgramEnvParameter4fvARB GLEW_GET_FUN(__glewProgramEnvParameter4fvARB)
+#define glProgramLocalParameter4dARB GLEW_GET_FUN(__glewProgramLocalParameter4dARB)
+#define glProgramLocalParameter4dvARB GLEW_GET_FUN(__glewProgramLocalParameter4dvARB)
+#define glProgramLocalParameter4fARB GLEW_GET_FUN(__glewProgramLocalParameter4fARB)
+#define glProgramLocalParameter4fvARB GLEW_GET_FUN(__glewProgramLocalParameter4fvARB)
+#define glProgramStringARB GLEW_GET_FUN(__glewProgramStringARB)
+#define glVertexAttrib1dARB GLEW_GET_FUN(__glewVertexAttrib1dARB)
+#define glVertexAttrib1dvARB GLEW_GET_FUN(__glewVertexAttrib1dvARB)
+#define glVertexAttrib1fARB GLEW_GET_FUN(__glewVertexAttrib1fARB)
+#define glVertexAttrib1fvARB GLEW_GET_FUN(__glewVertexAttrib1fvARB)
+#define glVertexAttrib1sARB GLEW_GET_FUN(__glewVertexAttrib1sARB)
+#define glVertexAttrib1svARB GLEW_GET_FUN(__glewVertexAttrib1svARB)
+#define glVertexAttrib2dARB GLEW_GET_FUN(__glewVertexAttrib2dARB)
+#define glVertexAttrib2dvARB GLEW_GET_FUN(__glewVertexAttrib2dvARB)
+#define glVertexAttrib2fARB GLEW_GET_FUN(__glewVertexAttrib2fARB)
+#define glVertexAttrib2fvARB GLEW_GET_FUN(__glewVertexAttrib2fvARB)
+#define glVertexAttrib2sARB GLEW_GET_FUN(__glewVertexAttrib2sARB)
+#define glVertexAttrib2svARB GLEW_GET_FUN(__glewVertexAttrib2svARB)
+#define glVertexAttrib3dARB GLEW_GET_FUN(__glewVertexAttrib3dARB)
+#define glVertexAttrib3dvARB GLEW_GET_FUN(__glewVertexAttrib3dvARB)
+#define glVertexAttrib3fARB GLEW_GET_FUN(__glewVertexAttrib3fARB)
+#define glVertexAttrib3fvARB GLEW_GET_FUN(__glewVertexAttrib3fvARB)
+#define glVertexAttrib3sARB GLEW_GET_FUN(__glewVertexAttrib3sARB)
+#define glVertexAttrib3svARB GLEW_GET_FUN(__glewVertexAttrib3svARB)
+#define glVertexAttrib4NbvARB GLEW_GET_FUN(__glewVertexAttrib4NbvARB)
+#define glVertexAttrib4NivARB GLEW_GET_FUN(__glewVertexAttrib4NivARB)
+#define glVertexAttrib4NsvARB GLEW_GET_FUN(__glewVertexAttrib4NsvARB)
+#define glVertexAttrib4NubARB GLEW_GET_FUN(__glewVertexAttrib4NubARB)
+#define glVertexAttrib4NubvARB GLEW_GET_FUN(__glewVertexAttrib4NubvARB)
+#define glVertexAttrib4NuivARB GLEW_GET_FUN(__glewVertexAttrib4NuivARB)
+#define glVertexAttrib4NusvARB GLEW_GET_FUN(__glewVertexAttrib4NusvARB)
+#define glVertexAttrib4bvARB GLEW_GET_FUN(__glewVertexAttrib4bvARB)
+#define glVertexAttrib4dARB GLEW_GET_FUN(__glewVertexAttrib4dARB)
+#define glVertexAttrib4dvARB GLEW_GET_FUN(__glewVertexAttrib4dvARB)
+#define glVertexAttrib4fARB GLEW_GET_FUN(__glewVertexAttrib4fARB)
+#define glVertexAttrib4fvARB GLEW_GET_FUN(__glewVertexAttrib4fvARB)
+#define glVertexAttrib4ivARB GLEW_GET_FUN(__glewVertexAttrib4ivARB)
+#define glVertexAttrib4sARB GLEW_GET_FUN(__glewVertexAttrib4sARB)
+#define glVertexAttrib4svARB GLEW_GET_FUN(__glewVertexAttrib4svARB)
+#define glVertexAttrib4ubvARB GLEW_GET_FUN(__glewVertexAttrib4ubvARB)
+#define glVertexAttrib4uivARB GLEW_GET_FUN(__glewVertexAttrib4uivARB)
+#define glVertexAttrib4usvARB GLEW_GET_FUN(__glewVertexAttrib4usvARB)
+#define glVertexAttribPointerARB GLEW_GET_FUN(__glewVertexAttribPointerARB)
+
+#define GLEW_ARB_vertex_program GLEW_GET_VAR(__GLEW_ARB_vertex_program)
+
+#endif /* GL_ARB_vertex_program */
+
+/* -------------------------- GL_ARB_vertex_shader ------------------------- */
+
+#ifndef GL_ARB_vertex_shader
+#define GL_ARB_vertex_shader 1
+
+#define GL_VERTEX_SHADER_ARB 0x8B31
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+
+typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB* name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name);
+
+#define glBindAttribLocationARB GLEW_GET_FUN(__glewBindAttribLocationARB)
+#define glGetActiveAttribARB GLEW_GET_FUN(__glewGetActiveAttribARB)
+#define glGetAttribLocationARB GLEW_GET_FUN(__glewGetAttribLocationARB)
+
+#define GLEW_ARB_vertex_shader GLEW_GET_VAR(__GLEW_ARB_vertex_shader)
+
+#endif /* GL_ARB_vertex_shader */
+
+/* --------------------------- GL_ARB_window_pos --------------------------- */
+
+#ifndef GL_ARB_window_pos
+#define GL_ARB_window_pos 1
+
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVARBPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVARBPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVARBPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVARBPROC) (const GLshort* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVARBPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVARBPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVARBPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVARBPROC) (const GLshort* p);
+
+#define glWindowPos2dARB GLEW_GET_FUN(__glewWindowPos2dARB)
+#define glWindowPos2dvARB GLEW_GET_FUN(__glewWindowPos2dvARB)
+#define glWindowPos2fARB GLEW_GET_FUN(__glewWindowPos2fARB)
+#define glWindowPos2fvARB GLEW_GET_FUN(__glewWindowPos2fvARB)
+#define glWindowPos2iARB GLEW_GET_FUN(__glewWindowPos2iARB)
+#define glWindowPos2ivARB GLEW_GET_FUN(__glewWindowPos2ivARB)
+#define glWindowPos2sARB GLEW_GET_FUN(__glewWindowPos2sARB)
+#define glWindowPos2svARB GLEW_GET_FUN(__glewWindowPos2svARB)
+#define glWindowPos3dARB GLEW_GET_FUN(__glewWindowPos3dARB)
+#define glWindowPos3dvARB GLEW_GET_FUN(__glewWindowPos3dvARB)
+#define glWindowPos3fARB GLEW_GET_FUN(__glewWindowPos3fARB)
+#define glWindowPos3fvARB GLEW_GET_FUN(__glewWindowPos3fvARB)
+#define glWindowPos3iARB GLEW_GET_FUN(__glewWindowPos3iARB)
+#define glWindowPos3ivARB GLEW_GET_FUN(__glewWindowPos3ivARB)
+#define glWindowPos3sARB GLEW_GET_FUN(__glewWindowPos3sARB)
+#define glWindowPos3svARB GLEW_GET_FUN(__glewWindowPos3svARB)
+
+#define GLEW_ARB_window_pos GLEW_GET_VAR(__GLEW_ARB_window_pos)
+
+#endif /* GL_ARB_window_pos */
+
+/* ------------------------- GL_ATIX_point_sprites ------------------------- */
+
+#ifndef GL_ATIX_point_sprites
+#define GL_ATIX_point_sprites 1
+
+#define GLEW_ATIX_point_sprites GLEW_GET_VAR(__GLEW_ATIX_point_sprites)
+
+#endif /* GL_ATIX_point_sprites */
+
+/* ---------------------- GL_ATIX_texture_env_combine3 --------------------- */
+
+#ifndef GL_ATIX_texture_env_combine3
+#define GL_ATIX_texture_env_combine3 1
+
+#define GL_MODULATE_ADD_ATIX 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATIX 0x8745
+#define GL_MODULATE_SUBTRACT_ATIX 0x8746
+
+#define GLEW_ATIX_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATIX_texture_env_combine3)
+
+#endif /* GL_ATIX_texture_env_combine3 */
+
+/* ----------------------- GL_ATIX_texture_env_route ----------------------- */
+
+#ifndef GL_ATIX_texture_env_route
+#define GL_ATIX_texture_env_route 1
+
+#define GL_SECONDARY_COLOR_ATIX 0x8747
+#define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748
+#define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749
+
+#define GLEW_ATIX_texture_env_route GLEW_GET_VAR(__GLEW_ATIX_texture_env_route)
+
+#endif /* GL_ATIX_texture_env_route */
+
+/* ---------------- GL_ATIX_vertex_shader_output_point_size ---------------- */
+
+#ifndef GL_ATIX_vertex_shader_output_point_size
+#define GL_ATIX_vertex_shader_output_point_size 1
+
+#define GL_OUTPUT_POINT_SIZE_ATIX 0x610E
+
+#define GLEW_ATIX_vertex_shader_output_point_size GLEW_GET_VAR(__GLEW_ATIX_vertex_shader_output_point_size)
+
+#endif /* GL_ATIX_vertex_shader_output_point_size */
+
+/* -------------------------- GL_ATI_draw_buffers -------------------------- */
+
+#ifndef GL_ATI_draw_buffers
+#define GL_ATI_draw_buffers 1
+
+#define GL_MAX_DRAW_BUFFERS_ATI 0x8824
+#define GL_DRAW_BUFFER0_ATI 0x8825
+#define GL_DRAW_BUFFER1_ATI 0x8826
+#define GL_DRAW_BUFFER2_ATI 0x8827
+#define GL_DRAW_BUFFER3_ATI 0x8828
+#define GL_DRAW_BUFFER4_ATI 0x8829
+#define GL_DRAW_BUFFER5_ATI 0x882A
+#define GL_DRAW_BUFFER6_ATI 0x882B
+#define GL_DRAW_BUFFER7_ATI 0x882C
+#define GL_DRAW_BUFFER8_ATI 0x882D
+#define GL_DRAW_BUFFER9_ATI 0x882E
+#define GL_DRAW_BUFFER10_ATI 0x882F
+#define GL_DRAW_BUFFER11_ATI 0x8830
+#define GL_DRAW_BUFFER12_ATI 0x8831
+#define GL_DRAW_BUFFER13_ATI 0x8832
+#define GL_DRAW_BUFFER14_ATI 0x8833
+#define GL_DRAW_BUFFER15_ATI 0x8834
+
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bufs);
+
+#define glDrawBuffersATI GLEW_GET_FUN(__glewDrawBuffersATI)
+
+#define GLEW_ATI_draw_buffers GLEW_GET_VAR(__GLEW_ATI_draw_buffers)
+
+#endif /* GL_ATI_draw_buffers */
+
+/* -------------------------- GL_ATI_element_array ------------------------- */
+
+#ifndef GL_ATI_element_array
+#define GL_ATI_element_array 1
+
+#define GL_ELEMENT_ARRAY_ATI 0x8768
+#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769
+#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A
+
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void* pointer);
+
+#define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI)
+#define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI)
+#define glElementPointerATI GLEW_GET_FUN(__glewElementPointerATI)
+
+#define GLEW_ATI_element_array GLEW_GET_VAR(__GLEW_ATI_element_array)
+
+#endif /* GL_ATI_element_array */
+
+/* ------------------------- GL_ATI_envmap_bumpmap ------------------------- */
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_ATI_envmap_bumpmap 1
+
+#define GL_BUMP_ROT_MATRIX_ATI 0x8775
+#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776
+#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777
+#define GL_BUMP_TEX_UNITS_ATI 0x8778
+#define GL_DUDV_ATI 0x8779
+#define GL_DU8DV8_ATI 0x877A
+#define GL_BUMP_ENVMAP_ATI 0x877B
+#define GL_BUMP_TARGET_ATI 0x877C
+
+typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+
+#define glGetTexBumpParameterfvATI GLEW_GET_FUN(__glewGetTexBumpParameterfvATI)
+#define glGetTexBumpParameterivATI GLEW_GET_FUN(__glewGetTexBumpParameterivATI)
+#define glTexBumpParameterfvATI GLEW_GET_FUN(__glewTexBumpParameterfvATI)
+#define glTexBumpParameterivATI GLEW_GET_FUN(__glewTexBumpParameterivATI)
+
+#define GLEW_ATI_envmap_bumpmap GLEW_GET_VAR(__GLEW_ATI_envmap_bumpmap)
+
+#endif /* GL_ATI_envmap_bumpmap */
+
+/* ------------------------- GL_ATI_fragment_shader ------------------------ */
+
+#ifndef GL_ATI_fragment_shader
+#define GL_ATI_fragment_shader 1
+
+#define GL_RED_BIT_ATI 0x00000001
+#define GL_2X_BIT_ATI 0x00000001
+#define GL_4X_BIT_ATI 0x00000002
+#define GL_GREEN_BIT_ATI 0x00000002
+#define GL_COMP_BIT_ATI 0x00000002
+#define GL_BLUE_BIT_ATI 0x00000004
+#define GL_8X_BIT_ATI 0x00000004
+#define GL_NEGATE_BIT_ATI 0x00000004
+#define GL_BIAS_BIT_ATI 0x00000008
+#define GL_HALF_BIT_ATI 0x00000008
+#define GL_QUARTER_BIT_ATI 0x00000010
+#define GL_EIGHTH_BIT_ATI 0x00000020
+#define GL_SATURATE_BIT_ATI 0x00000040
+#define GL_FRAGMENT_SHADER_ATI 0x8920
+#define GL_REG_0_ATI 0x8921
+#define GL_REG_1_ATI 0x8922
+#define GL_REG_2_ATI 0x8923
+#define GL_REG_3_ATI 0x8924
+#define GL_REG_4_ATI 0x8925
+#define GL_REG_5_ATI 0x8926
+#define GL_CON_0_ATI 0x8941
+#define GL_CON_1_ATI 0x8942
+#define GL_CON_2_ATI 0x8943
+#define GL_CON_3_ATI 0x8944
+#define GL_CON_4_ATI 0x8945
+#define GL_CON_5_ATI 0x8946
+#define GL_CON_6_ATI 0x8947
+#define GL_CON_7_ATI 0x8948
+#define GL_MOV_ATI 0x8961
+#define GL_ADD_ATI 0x8963
+#define GL_MUL_ATI 0x8964
+#define GL_SUB_ATI 0x8965
+#define GL_DOT3_ATI 0x8966
+#define GL_DOT4_ATI 0x8967
+#define GL_MAD_ATI 0x8968
+#define GL_LERP_ATI 0x8969
+#define GL_CND_ATI 0x896A
+#define GL_CND0_ATI 0x896B
+#define GL_DOT2_ADD_ATI 0x896C
+#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D
+#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
+#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F
+#define GL_NUM_PASSES_ATI 0x8970
+#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971
+#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972
+#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973
+#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974
+#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975
+#define GL_SWIZZLE_STR_ATI 0x8976
+#define GL_SWIZZLE_STQ_ATI 0x8977
+#define GL_SWIZZLE_STR_DR_ATI 0x8978
+#define GL_SWIZZLE_STQ_DQ_ATI 0x8979
+
+typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (GLAPIENTRY * PFNGLBEGINFRAGMENTSHADERATIPROC) (void);
+typedef void (GLAPIENTRY * PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (GLAPIENTRY * PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENDFRAGMENTSHADERATIPROC) (void);
+typedef GLuint (GLAPIENTRY * PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);
+typedef void (GLAPIENTRY * PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);
+typedef void (GLAPIENTRY * PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);
+typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat* value);
+
+#define glAlphaFragmentOp1ATI GLEW_GET_FUN(__glewAlphaFragmentOp1ATI)
+#define glAlphaFragmentOp2ATI GLEW_GET_FUN(__glewAlphaFragmentOp2ATI)
+#define glAlphaFragmentOp3ATI GLEW_GET_FUN(__glewAlphaFragmentOp3ATI)
+#define glBeginFragmentShaderATI GLEW_GET_FUN(__glewBeginFragmentShaderATI)
+#define glBindFragmentShaderATI GLEW_GET_FUN(__glewBindFragmentShaderATI)
+#define glColorFragmentOp1ATI GLEW_GET_FUN(__glewColorFragmentOp1ATI)
+#define glColorFragmentOp2ATI GLEW_GET_FUN(__glewColorFragmentOp2ATI)
+#define glColorFragmentOp3ATI GLEW_GET_FUN(__glewColorFragmentOp3ATI)
+#define glDeleteFragmentShaderATI GLEW_GET_FUN(__glewDeleteFragmentShaderATI)
+#define glEndFragmentShaderATI GLEW_GET_FUN(__glewEndFragmentShaderATI)
+#define glGenFragmentShadersATI GLEW_GET_FUN(__glewGenFragmentShadersATI)
+#define glPassTexCoordATI GLEW_GET_FUN(__glewPassTexCoordATI)
+#define glSampleMapATI GLEW_GET_FUN(__glewSampleMapATI)
+#define glSetFragmentShaderConstantATI GLEW_GET_FUN(__glewSetFragmentShaderConstantATI)
+
+#define GLEW_ATI_fragment_shader GLEW_GET_VAR(__GLEW_ATI_fragment_shader)
+
+#endif /* GL_ATI_fragment_shader */
+
+/* ------------------------ GL_ATI_map_object_buffer ----------------------- */
+
+#ifndef GL_ATI_map_object_buffer
+#define GL_ATI_map_object_buffer 1
+
+typedef void* (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+
+#define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI)
+#define glUnmapObjectBufferATI GLEW_GET_FUN(__glewUnmapObjectBufferATI)
+
+#define GLEW_ATI_map_object_buffer GLEW_GET_VAR(__GLEW_ATI_map_object_buffer)
+
+#endif /* GL_ATI_map_object_buffer */
+
+/* -------------------------- GL_ATI_pn_triangles -------------------------- */
+
+#ifndef GL_ATI_pn_triangles
+#define GL_ATI_pn_triangles 1
+
+#define GL_PN_TRIANGLES_ATI 0x87F0
+#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
+#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
+#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
+#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
+#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
+#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
+#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
+#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
+
+typedef void (GLAPIENTRY * PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);
+
+#define glPNTrianglesfATI GLEW_GET_FUN(__glPNTrianglewesfATI)
+#define glPNTrianglesiATI GLEW_GET_FUN(__glPNTrianglewesiATI)
+
+#define GLEW_ATI_pn_triangles GLEW_GET_VAR(__GLEW_ATI_pn_triangles)
+
+#endif /* GL_ATI_pn_triangles */
+
+/* ------------------------ GL_ATI_separate_stencil ------------------------ */
+
+#ifndef GL_ATI_separate_stencil
+#define GL_ATI_separate_stencil 1
+
+#define GL_STENCIL_BACK_FUNC_ATI 0x8800
+#define GL_STENCIL_BACK_FAIL_ATI 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803
+
+typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+
+#define glStencilFuncSeparateATI GLEW_GET_FUN(__glewStencilFuncSeparateATI)
+#define glStencilOpSeparateATI GLEW_GET_FUN(__glewStencilOpSeparateATI)
+
+#define GLEW_ATI_separate_stencil GLEW_GET_VAR(__GLEW_ATI_separate_stencil)
+
+#endif /* GL_ATI_separate_stencil */
+
+/* ---------------------- GL_ATI_text_fragment_shader ---------------------- */
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_ATI_text_fragment_shader 1
+
+#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200
+
+#define GLEW_ATI_text_fragment_shader GLEW_GET_VAR(__GLEW_ATI_text_fragment_shader)
+
+#endif /* GL_ATI_text_fragment_shader */
+
+/* --------------------- GL_ATI_texture_compression_3dc -------------------- */
+
+#ifndef GL_ATI_texture_compression_3dc
+#define GL_ATI_texture_compression_3dc 1
+
+#define GL_COMPRESSED_RGB_3DC_ATI 0x8837
+
+#define GLEW_ATI_texture_compression_3dc GLEW_GET_VAR(__GLEW_ATI_texture_compression_3dc)
+
+#endif /* GL_ATI_texture_compression_3dc */
+
+/* ---------------------- GL_ATI_texture_env_combine3 ---------------------- */
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_ATI_texture_env_combine3 1
+
+#define GL_MODULATE_ADD_ATI 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
+#define GL_MODULATE_SUBTRACT_ATI 0x8746
+
+#define GLEW_ATI_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATI_texture_env_combine3)
+
+#endif /* GL_ATI_texture_env_combine3 */
+
+/* -------------------------- GL_ATI_texture_float ------------------------- */
+
+#ifndef GL_ATI_texture_float
+#define GL_ATI_texture_float 1
+
+#define GL_RGBA_FLOAT32_ATI 0x8814
+#define GL_RGB_FLOAT32_ATI 0x8815
+#define GL_ALPHA_FLOAT32_ATI 0x8816
+#define GL_INTENSITY_FLOAT32_ATI 0x8817
+#define GL_LUMINANCE_FLOAT32_ATI 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819
+#define GL_RGBA_FLOAT16_ATI 0x881A
+#define GL_RGB_FLOAT16_ATI 0x881B
+#define GL_ALPHA_FLOAT16_ATI 0x881C
+#define GL_INTENSITY_FLOAT16_ATI 0x881D
+#define GL_LUMINANCE_FLOAT16_ATI 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F
+
+#define GLEW_ATI_texture_float GLEW_GET_VAR(__GLEW_ATI_texture_float)
+
+#endif /* GL_ATI_texture_float */
+
+/* ----------------------- GL_ATI_texture_mirror_once ---------------------- */
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_ATI_texture_mirror_once 1
+
+#define GL_MIRROR_CLAMP_ATI 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743
+
+#define GLEW_ATI_texture_mirror_once GLEW_GET_VAR(__GLEW_ATI_texture_mirror_once)
+
+#endif /* GL_ATI_texture_mirror_once */
+
+/* ----------------------- GL_ATI_vertex_array_object ---------------------- */
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_ATI_vertex_array_object 1
+
+#define GL_STATIC_ATI 0x8760
+#define GL_DYNAMIC_ATI 0x8761
+#define GL_PRESERVE_ATI 0x8762
+#define GL_DISCARD_ATI 0x8763
+#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764
+#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765
+#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766
+#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767
+
+typedef void (GLAPIENTRY * PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (GLAPIENTRY * PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void* pointer, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void* pointer, GLenum preserve);
+typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+
+#define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI)
+#define glFreeObjectBufferATI GLEW_GET_FUN(__glewFreeObjectBufferATI)
+#define glGetArrayObjectfvATI GLEW_GET_FUN(__glewGetArrayObjectfvATI)
+#define glGetArrayObjectivATI GLEW_GET_FUN(__glewGetArrayObjectivATI)
+#define glGetObjectBufferfvATI GLEW_GET_FUN(__glewGetObjectBufferfvATI)
+#define glGetObjectBufferivATI GLEW_GET_FUN(__glewGetObjectBufferivATI)
+#define glGetVariantArrayObjectfvATI GLEW_GET_FUN(__glewGetVariantArrayObjectfvATI)
+#define glGetVariantArrayObjectivATI GLEW_GET_FUN(__glewGetVariantArrayObjectivATI)
+#define glIsObjectBufferATI GLEW_GET_FUN(__glewIsObjectBufferATI)
+#define glNewObjectBufferATI GLEW_GET_FUN(__glewNewObjectBufferATI)
+#define glUpdateObjectBufferATI GLEW_GET_FUN(__glewUpdateObjectBufferATI)
+#define glVariantArrayObjectATI GLEW_GET_FUN(__glewVariantArrayObjectATI)
+
+#define GLEW_ATI_vertex_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_array_object)
+
+#endif /* GL_ATI_vertex_array_object */
+
+/* ------------------- GL_ATI_vertex_attrib_array_object ------------------- */
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#define GL_ATI_vertex_attrib_array_object 1
+
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+
+#define glGetVertexAttribArrayObjectfvATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectfvATI)
+#define glGetVertexAttribArrayObjectivATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectivATI)
+#define glVertexAttribArrayObjectATI GLEW_GET_FUN(__glewVertexAttribArrayObjectATI)
+
+#define GLEW_ATI_vertex_attrib_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_attrib_array_object)
+
+#endif /* GL_ATI_vertex_attrib_array_object */
+
+/* ------------------------- GL_ATI_vertex_streams ------------------------- */
+
+#ifndef GL_ATI_vertex_streams
+#define GL_ATI_vertex_streams 1
+
+#define GL_MAX_VERTEX_STREAMS_ATI 0x876B
+#define GL_VERTEX_SOURCE_ATI 0x876C
+#define GL_VERTEX_STREAM0_ATI 0x876D
+#define GL_VERTEX_STREAM1_ATI 0x876E
+#define GL_VERTEX_STREAM2_ATI 0x876F
+#define GL_VERTEX_STREAM3_ATI 0x8770
+#define GL_VERTEX_STREAM4_ATI 0x8771
+#define GL_VERTEX_STREAM5_ATI 0x8772
+#define GL_VERTEX_STREAM6_ATI 0x8773
+#define GL_VERTEX_STREAM7_ATI 0x8774
+
+typedef void (GLAPIENTRY * PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte x, GLbyte y, GLbyte z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *v);
+
+#define glClientActiveVertexStreamATI GLEW_GET_FUN(__glewClientActiveVertexStreamATI)
+#define glNormalStream3bATI GLEW_GET_FUN(__glewNormalStream3bATI)
+#define glNormalStream3bvATI GLEW_GET_FUN(__glewNormalStream3bvATI)
+#define glNormalStream3dATI GLEW_GET_FUN(__glewNormalStream3dATI)
+#define glNormalStream3dvATI GLEW_GET_FUN(__glewNormalStream3dvATI)
+#define glNormalStream3fATI GLEW_GET_FUN(__glewNormalStream3fATI)
+#define glNormalStream3fvATI GLEW_GET_FUN(__glewNormalStream3fvATI)
+#define glNormalStream3iATI GLEW_GET_FUN(__glewNormalStream3iATI)
+#define glNormalStream3ivATI GLEW_GET_FUN(__glewNormalStream3ivATI)
+#define glNormalStream3sATI GLEW_GET_FUN(__glewNormalStream3sATI)
+#define glNormalStream3svATI GLEW_GET_FUN(__glewNormalStream3svATI)
+#define glVertexBlendEnvfATI GLEW_GET_FUN(__glewVertexBlendEnvfATI)
+#define glVertexBlendEnviATI GLEW_GET_FUN(__glewVertexBlendEnviATI)
+#define glVertexStream2dATI GLEW_GET_FUN(__glewVertexStream2dATI)
+#define glVertexStream2dvATI GLEW_GET_FUN(__glewVertexStream2dvATI)
+#define glVertexStream2fATI GLEW_GET_FUN(__glewVertexStream2fATI)
+#define glVertexStream2fvATI GLEW_GET_FUN(__glewVertexStream2fvATI)
+#define glVertexStream2iATI GLEW_GET_FUN(__glewVertexStream2iATI)
+#define glVertexStream2ivATI GLEW_GET_FUN(__glewVertexStream2ivATI)
+#define glVertexStream2sATI GLEW_GET_FUN(__glewVertexStream2sATI)
+#define glVertexStream2svATI GLEW_GET_FUN(__glewVertexStream2svATI)
+#define glVertexStream3dATI GLEW_GET_FUN(__glewVertexStream3dATI)
+#define glVertexStream3dvATI GLEW_GET_FUN(__glewVertexStream3dvATI)
+#define glVertexStream3fATI GLEW_GET_FUN(__glewVertexStream3fATI)
+#define glVertexStream3fvATI GLEW_GET_FUN(__glewVertexStream3fvATI)
+#define glVertexStream3iATI GLEW_GET_FUN(__glewVertexStream3iATI)
+#define glVertexStream3ivATI GLEW_GET_FUN(__glewVertexStream3ivATI)
+#define glVertexStream3sATI GLEW_GET_FUN(__glewVertexStream3sATI)
+#define glVertexStream3svATI GLEW_GET_FUN(__glewVertexStream3svATI)
+#define glVertexStream4dATI GLEW_GET_FUN(__glewVertexStream4dATI)
+#define glVertexStream4dvATI GLEW_GET_FUN(__glewVertexStream4dvATI)
+#define glVertexStream4fATI GLEW_GET_FUN(__glewVertexStream4fATI)
+#define glVertexStream4fvATI GLEW_GET_FUN(__glewVertexStream4fvATI)
+#define glVertexStream4iATI GLEW_GET_FUN(__glewVertexStream4iATI)
+#define glVertexStream4ivATI GLEW_GET_FUN(__glewVertexStream4ivATI)
+#define glVertexStream4sATI GLEW_GET_FUN(__glewVertexStream4sATI)
+#define glVertexStream4svATI GLEW_GET_FUN(__glewVertexStream4svATI)
+
+#define GLEW_ATI_vertex_streams GLEW_GET_VAR(__GLEW_ATI_vertex_streams)
+
+#endif /* GL_ATI_vertex_streams */
+
+/* --------------------------- GL_EXT_422_pixels --------------------------- */
+
+#ifndef GL_EXT_422_pixels
+#define GL_EXT_422_pixels 1
+
+#define GL_422_EXT 0x80CC
+#define GL_422_REV_EXT 0x80CD
+#define GL_422_AVERAGE_EXT 0x80CE
+#define GL_422_REV_AVERAGE_EXT 0x80CF
+
+#define GLEW_EXT_422_pixels GLEW_GET_VAR(__GLEW_EXT_422_pixels)
+
+#endif /* GL_EXT_422_pixels */
+
+/* ---------------------------- GL_EXT_Cg_shader --------------------------- */
+
+#ifndef GL_EXT_Cg_shader
+#define GL_EXT_Cg_shader 1
+
+#define GL_CG_VERTEX_SHADER_EXT 0x890E
+#define GL_CG_FRAGMENT_SHADER_EXT 0x890F
+
+#define GLEW_EXT_Cg_shader GLEW_GET_VAR(__GLEW_EXT_Cg_shader)
+
+#endif /* GL_EXT_Cg_shader */
+
+/* ------------------------------ GL_EXT_abgr ------------------------------ */
+
+#ifndef GL_EXT_abgr
+#define GL_EXT_abgr 1
+
+#define GL_ABGR_EXT 0x8000
+
+#define GLEW_EXT_abgr GLEW_GET_VAR(__GLEW_EXT_abgr)
+
+#endif /* GL_EXT_abgr */
+
+/* ------------------------------ GL_EXT_bgra ------------------------------ */
+
+#ifndef GL_EXT_bgra
+#define GL_EXT_bgra 1
+
+#define GL_BGR_EXT 0x80E0
+#define GL_BGRA_EXT 0x80E1
+
+#define GLEW_EXT_bgra GLEW_GET_VAR(__GLEW_EXT_bgra)
+
+#endif /* GL_EXT_bgra */
+
+/* --------------------------- GL_EXT_blend_color -------------------------- */
+
+#ifndef GL_EXT_blend_color
+#define GL_EXT_blend_color 1
+
+#define GL_CONSTANT_COLOR_EXT 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002
+#define GL_CONSTANT_ALPHA_EXT 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004
+#define GL_BLEND_COLOR_EXT 0x8005
+
+typedef void (GLAPIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+
+#define glBlendColorEXT GLEW_GET_FUN(__glewBlendColorEXT)
+
+#define GLEW_EXT_blend_color GLEW_GET_VAR(__GLEW_EXT_blend_color)
+
+#endif /* GL_EXT_blend_color */
+
+/* --------------------- GL_EXT_blend_equation_separate -------------------- */
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_EXT_blend_equation_separate 1
+
+#define GL_BLEND_EQUATION_RGB_EXT 0x8009
+#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);
+
+#define glBlendEquationSeparateEXT GLEW_GET_FUN(__glewBlendEquationSeparateEXT)
+
+#define GLEW_EXT_blend_equation_separate GLEW_GET_VAR(__GLEW_EXT_blend_equation_separate)
+
+#endif /* GL_EXT_blend_equation_separate */
+
+/* ----------------------- GL_EXT_blend_func_separate ---------------------- */
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_EXT_blend_func_separate 1
+
+#define GL_BLEND_DST_RGB_EXT 0x80C8
+#define GL_BLEND_SRC_RGB_EXT 0x80C9
+#define GL_BLEND_DST_ALPHA_EXT 0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT 0x80CB
+
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+
+#define glBlendFuncSeparateEXT GLEW_GET_FUN(__glewBlendFuncSeparateEXT)
+
+#define GLEW_EXT_blend_func_separate GLEW_GET_VAR(__GLEW_EXT_blend_func_separate)
+
+#endif /* GL_EXT_blend_func_separate */
+
+/* ------------------------- GL_EXT_blend_logic_op ------------------------- */
+
+#ifndef GL_EXT_blend_logic_op
+#define GL_EXT_blend_logic_op 1
+
+#define GLEW_EXT_blend_logic_op GLEW_GET_VAR(__GLEW_EXT_blend_logic_op)
+
+#endif /* GL_EXT_blend_logic_op */
+
+/* -------------------------- GL_EXT_blend_minmax -------------------------- */
+
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+
+#define GL_FUNC_ADD_EXT 0x8006
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#define GL_BLEND_EQUATION_EXT 0x8009
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+
+#define glBlendEquationEXT GLEW_GET_FUN(__glewBlendEquationEXT)
+
+#define GLEW_EXT_blend_minmax GLEW_GET_VAR(__GLEW_EXT_blend_minmax)
+
+#endif /* GL_EXT_blend_minmax */
+
+/* ------------------------- GL_EXT_blend_subtract ------------------------- */
+
+#ifndef GL_EXT_blend_subtract
+#define GL_EXT_blend_subtract 1
+
+#define GL_FUNC_SUBTRACT_EXT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B
+
+#define GLEW_EXT_blend_subtract GLEW_GET_VAR(__GLEW_EXT_blend_subtract)
+
+#endif /* GL_EXT_blend_subtract */
+
+/* ------------------------ GL_EXT_clip_volume_hint ------------------------ */
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_EXT_clip_volume_hint 1
+
+#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0
+
+#define GLEW_EXT_clip_volume_hint GLEW_GET_VAR(__GLEW_EXT_clip_volume_hint)
+
+#endif /* GL_EXT_clip_volume_hint */
+
+/* ------------------------------ GL_EXT_cmyka ----------------------------- */
+
+#ifndef GL_EXT_cmyka
+#define GL_EXT_cmyka 1
+
+#define GL_CMYK_EXT 0x800C
+#define GL_CMYKA_EXT 0x800D
+#define GL_PACK_CMYK_HINT_EXT 0x800E
+#define GL_UNPACK_CMYK_HINT_EXT 0x800F
+
+#define GLEW_EXT_cmyka GLEW_GET_VAR(__GLEW_EXT_cmyka)
+
+#endif /* GL_EXT_cmyka */
+
+/* ------------------------- GL_EXT_color_subtable ------------------------- */
+
+#ifndef GL_EXT_color_subtable
+#define GL_EXT_color_subtable 1
+
+typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+
+#define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT)
+#define glCopyColorSubTableEXT GLEW_GET_FUN(__glewCopyColorSubTableEXT)
+
+#define GLEW_EXT_color_subtable GLEW_GET_VAR(__GLEW_EXT_color_subtable)
+
+#endif /* GL_EXT_color_subtable */
+
+/* ---------------------- GL_EXT_compiled_vertex_array --------------------- */
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_EXT_compiled_vertex_array 1
+
+typedef void (GLAPIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
+
+#define glLockArraysEXT GLEW_GET_FUN(__glewLockArraysEXT)
+#define glUnlockArraysEXT GLEW_GET_FUN(__glewUnlockArraysEXT)
+
+#define GLEW_EXT_compiled_vertex_array GLEW_GET_VAR(__GLEW_EXT_compiled_vertex_array)
+
+#endif /* GL_EXT_compiled_vertex_array */
+
+/* --------------------------- GL_EXT_convolution -------------------------- */
+
+#ifndef GL_EXT_convolution
+#define GL_EXT_convolution 1
+
+#define GL_CONVOLUTION_1D_EXT 0x8010
+#define GL_CONVOLUTION_2D_EXT 0x8011
+#define GL_SEPARABLE_2D_EXT 0x8012
+#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015
+#define GL_REDUCE_EXT 0x8016
+#define GL_CONVOLUTION_FORMAT_EXT 0x8017
+#define GL_CONVOLUTION_WIDTH_EXT 0x8018
+#define GL_CONVOLUTION_HEIGHT_EXT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* image);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* row, void* column, void* span);
+typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* row, const void* column);
+
+#define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT)
+#define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT)
+#define glConvolutionParameterfEXT GLEW_GET_FUN(__glewConvolutionParameterfEXT)
+#define glConvolutionParameterfvEXT GLEW_GET_FUN(__glewConvolutionParameterfvEXT)
+#define glConvolutionParameteriEXT GLEW_GET_FUN(__glewConvolutionParameteriEXT)
+#define glConvolutionParameterivEXT GLEW_GET_FUN(__glewConvolutionParameterivEXT)
+#define glCopyConvolutionFilter1DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter1DEXT)
+#define glCopyConvolutionFilter2DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter2DEXT)
+#define glGetConvolutionFilterEXT GLEW_GET_FUN(__glewGetConvolutionFilterEXT)
+#define glGetConvolutionParameterfvEXT GLEW_GET_FUN(__glewGetConvolutionParameterfvEXT)
+#define glGetConvolutionParameterivEXT GLEW_GET_FUN(__glewGetConvolutionParameterivEXT)
+#define glGetSeparableFilterEXT GLEW_GET_FUN(__glewGetSeparableFilterEXT)
+#define glSeparableFilter2DEXT GLEW_GET_FUN(__glewSeparableFilter2DEXT)
+
+#define GLEW_EXT_convolution GLEW_GET_VAR(__GLEW_EXT_convolution)
+
+#endif /* GL_EXT_convolution */
+
+/* ------------------------ GL_EXT_coordinate_frame ------------------------ */
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_EXT_coordinate_frame 1
+
+#define GL_TANGENT_ARRAY_EXT 0x8439
+#define GL_BINORMAL_ARRAY_EXT 0x843A
+#define GL_CURRENT_TANGENT_EXT 0x843B
+#define GL_CURRENT_BINORMAL_EXT 0x843C
+#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E
+#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F
+#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440
+#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441
+#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442
+#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443
+#define GL_MAP1_TANGENT_EXT 0x8444
+#define GL_MAP2_TANGENT_EXT 0x8445
+#define GL_MAP1_BINORMAL_EXT 0x8446
+#define GL_MAP2_BINORMAL_EXT 0x8447
+
+typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer);
+typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer);
+
+#define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT)
+#define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT)
+
+#define GLEW_EXT_coordinate_frame GLEW_GET_VAR(__GLEW_EXT_coordinate_frame)
+
+#endif /* GL_EXT_coordinate_frame */
+
+/* -------------------------- GL_EXT_copy_texture -------------------------- */
+
+#ifndef GL_EXT_copy_texture
+#define GL_EXT_copy_texture 1
+
+typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define glCopyTexImage1DEXT GLEW_GET_FUN(__glewCopyTexImage1DEXT)
+#define glCopyTexImage2DEXT GLEW_GET_FUN(__glewCopyTexImage2DEXT)
+#define glCopyTexSubImage1DEXT GLEW_GET_FUN(__glewCopyTexSubImage1DEXT)
+#define glCopyTexSubImage2DEXT GLEW_GET_FUN(__glewCopyTexSubImage2DEXT)
+#define glCopyTexSubImage3DEXT GLEW_GET_FUN(__glewCopyTexSubImage3DEXT)
+
+#define GLEW_EXT_copy_texture GLEW_GET_VAR(__GLEW_EXT_copy_texture)
+
+#endif /* GL_EXT_copy_texture */
+
+/* --------------------------- GL_EXT_cull_vertex -------------------------- */
+
+#ifndef GL_EXT_cull_vertex
+#define GL_EXT_cull_vertex 1
+
+typedef void (GLAPIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat* params);
+
+#define glCullParameterdvEXT GLEW_GET_FUN(__glewCullParameterdvEXT)
+#define glCullParameterfvEXT GLEW_GET_FUN(__glewCullParameterfvEXT)
+
+#define GLEW_EXT_cull_vertex GLEW_GET_VAR(__GLEW_EXT_cull_vertex)
+
+#endif /* GL_EXT_cull_vertex */
+
+/* ------------------------ GL_EXT_depth_bounds_test ----------------------- */
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_EXT_depth_bounds_test 1
+
+#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890
+#define GL_DEPTH_BOUNDS_EXT 0x8891
+
+typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);
+
+#define glDepthBoundsEXT GLEW_GET_FUN(__glewDepthBoundsEXT)
+
+#define GLEW_EXT_depth_bounds_test GLEW_GET_VAR(__GLEW_EXT_depth_bounds_test)
+
+#endif /* GL_EXT_depth_bounds_test */
+
+/* ----------------------- GL_EXT_draw_range_elements ---------------------- */
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_EXT_draw_range_elements 1
+
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+
+#define glDrawRangeElementsEXT GLEW_GET_FUN(__glewDrawRangeElementsEXT)
+
+#define GLEW_EXT_draw_range_elements GLEW_GET_VAR(__GLEW_EXT_draw_range_elements)
+
+#endif /* GL_EXT_draw_range_elements */
+
+/* ---------------------------- GL_EXT_fog_coord --------------------------- */
+
+#ifndef GL_EXT_fog_coord
+#define GL_EXT_fog_coord 1
+
+#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
+#define GL_FOG_COORDINATE_EXT 0x8451
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457
+
+typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
+
+#define glFogCoordPointerEXT GLEW_GET_FUN(__glewFogCoordPointerEXT)
+#define glFogCoorddEXT GLEW_GET_FUN(__glewFogCoorddEXT)
+#define glFogCoorddvEXT GLEW_GET_FUN(__glewFogCoorddvEXT)
+#define glFogCoordfEXT GLEW_GET_FUN(__glewFogCoordfEXT)
+#define glFogCoordfvEXT GLEW_GET_FUN(__glewFogCoordfvEXT)
+
+#define GLEW_EXT_fog_coord GLEW_GET_VAR(__GLEW_EXT_fog_coord)
+
+#endif /* GL_EXT_fog_coord */
+
+/* ------------------------ GL_EXT_fragment_lighting ----------------------- */
+
+#ifndef GL_EXT_fragment_lighting
+#define GL_EXT_fragment_lighting 1
+
+#define GL_FRAGMENT_LIGHTING_EXT 0x8400
+#define GL_FRAGMENT_COLOR_MATERIAL_EXT 0x8401
+#define GL_FRAGMENT_COLOR_MATERIAL_FACE_EXT 0x8402
+#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_EXT 0x8403
+#define GL_MAX_FRAGMENT_LIGHTS_EXT 0x8404
+#define GL_MAX_ACTIVE_LIGHTS_EXT 0x8405
+#define GL_CURRENT_RASTER_NORMAL_EXT 0x8406
+#define GL_LIGHT_ENV_MODE_EXT 0x8407
+#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_EXT 0x8408
+#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_EXT 0x8409
+#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_EXT 0x840A
+#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_EXT 0x840B
+#define GL_FRAGMENT_LIGHT0_EXT 0x840C
+#define GL_FRAGMENT_LIGHT7_EXT 0x8413
+
+typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALEXTPROC) (GLenum face, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVEXTPROC) (GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIEXTPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVEXTPROC) (GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFEXTPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIEXTPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFEXTPROC) (GLenum face, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIEXTPROC) (GLenum face, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLLIGHTENVIEXTPROC) (GLenum pname, GLint param);
+
+#define glFragmentColorMaterialEXT GLEW_GET_FUN(__glewFragmentColorMaterialEXT)
+#define glFragmentLightModelfEXT GLEW_GET_FUN(__glewFragmentLightModelfEXT)
+#define glFragmentLightModelfvEXT GLEW_GET_FUN(__glewFragmentLightModelfvEXT)
+#define glFragmentLightModeliEXT GLEW_GET_FUN(__glewFragmentLightModeliEXT)
+#define glFragmentLightModelivEXT GLEW_GET_FUN(__glewFragmentLightModelivEXT)
+#define glFragmentLightfEXT GLEW_GET_FUN(__glewFragmentLightfEXT)
+#define glFragmentLightfvEXT GLEW_GET_FUN(__glewFragmentLightfvEXT)
+#define glFragmentLightiEXT GLEW_GET_FUN(__glewFragmentLightiEXT)
+#define glFragmentLightivEXT GLEW_GET_FUN(__glewFragmentLightivEXT)
+#define glFragmentMaterialfEXT GLEW_GET_FUN(__glewFragmentMaterialfEXT)
+#define glFragmentMaterialfvEXT GLEW_GET_FUN(__glewFragmentMaterialfvEXT)
+#define glFragmentMaterialiEXT GLEW_GET_FUN(__glewFragmentMaterialiEXT)
+#define glFragmentMaterialivEXT GLEW_GET_FUN(__glewFragmentMaterialivEXT)
+#define glGetFragmentLightfvEXT GLEW_GET_FUN(__glewGetFragmentLightfvEXT)
+#define glGetFragmentLightivEXT GLEW_GET_FUN(__glewGetFragmentLightivEXT)
+#define glGetFragmentMaterialfvEXT GLEW_GET_FUN(__glewGetFragmentMaterialfvEXT)
+#define glGetFragmentMaterialivEXT GLEW_GET_FUN(__glewGetFragmentMaterialivEXT)
+#define glLightEnviEXT GLEW_GET_FUN(__glewLightEnviEXT)
+
+#define GLEW_EXT_fragment_lighting GLEW_GET_VAR(__GLEW_EXT_fragment_lighting)
+
+#endif /* GL_EXT_fragment_lighting */
+
+/* ---------------------------- GL_EXT_histogram --------------------------- */
+
+#ifndef GL_EXT_histogram
+#define GL_EXT_histogram 1
+
+#define GL_HISTOGRAM_EXT 0x8024
+#define GL_PROXY_HISTOGRAM_EXT 0x8025
+#define GL_HISTOGRAM_WIDTH_EXT 0x8026
+#define GL_HISTOGRAM_FORMAT_EXT 0x8027
+#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C
+#define GL_HISTOGRAM_SINK_EXT 0x802D
+#define GL_MINMAX_EXT 0x802E
+#define GL_MINMAX_FORMAT_EXT 0x802F
+#define GL_MINMAX_SINK_EXT 0x8030
+
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target);
+
+#define glGetHistogramEXT GLEW_GET_FUN(__glewGetHistogramEXT)
+#define glGetHistogramParameterfvEXT GLEW_GET_FUN(__glewGetHistogramParameterfvEXT)
+#define glGetHistogramParameterivEXT GLEW_GET_FUN(__glewGetHistogramParameterivEXT)
+#define glGetMinmaxEXT GLEW_GET_FUN(__glewGetMinmaxEXT)
+#define glGetMinmaxParameterfvEXT GLEW_GET_FUN(__glewGetMinmaxParameterfvEXT)
+#define glGetMinmaxParameterivEXT GLEW_GET_FUN(__glewGetMinmaxParameterivEXT)
+#define glHistogramEXT GLEW_GET_FUN(__glewHistogramEXT)
+#define glMinmaxEXT GLEW_GET_FUN(__glewMinmaxEXT)
+#define glResetHistogramEXT GLEW_GET_FUN(__glewResetHistogramEXT)
+#define glResetMinmaxEXT GLEW_GET_FUN(__glewResetMinmaxEXT)
+
+#define GLEW_EXT_histogram GLEW_GET_VAR(__GLEW_EXT_histogram)
+
+#endif /* GL_EXT_histogram */
+
+/* ----------------------- GL_EXT_index_array_formats ---------------------- */
+
+#ifndef GL_EXT_index_array_formats
+#define GL_EXT_index_array_formats 1
+
+#define GLEW_EXT_index_array_formats GLEW_GET_VAR(__GLEW_EXT_index_array_formats)
+
+#endif /* GL_EXT_index_array_formats */
+
+/* --------------------------- GL_EXT_index_func --------------------------- */
+
+#ifndef GL_EXT_index_func
+#define GL_EXT_index_func 1
+
+typedef void (GLAPIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLfloat ref);
+
+#define glIndexFuncEXT GLEW_GET_FUN(__glewIndexFuncEXT)
+
+#define GLEW_EXT_index_func GLEW_GET_VAR(__GLEW_EXT_index_func)
+
+#endif /* GL_EXT_index_func */
+
+/* ------------------------- GL_EXT_index_material ------------------------- */
+
+#ifndef GL_EXT_index_material
+#define GL_EXT_index_material 1
+
+typedef void (GLAPIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);
+
+#define glIndexMaterialEXT GLEW_GET_FUN(__glewIndexMaterialEXT)
+
+#define GLEW_EXT_index_material GLEW_GET_VAR(__GLEW_EXT_index_material)
+
+#endif /* GL_EXT_index_material */
+
+/* -------------------------- GL_EXT_index_texture ------------------------- */
+
+#ifndef GL_EXT_index_texture
+#define GL_EXT_index_texture 1
+
+#define GLEW_EXT_index_texture GLEW_GET_VAR(__GLEW_EXT_index_texture)
+
+#endif /* GL_EXT_index_texture */
+
+/* -------------------------- GL_EXT_light_texture ------------------------- */
+
+#ifndef GL_EXT_light_texture
+#define GL_EXT_light_texture 1
+
+#define GL_FRAGMENT_MATERIAL_EXT 0x8349
+#define GL_FRAGMENT_NORMAL_EXT 0x834A
+#define GL_FRAGMENT_COLOR_EXT 0x834C
+#define GL_ATTENUATION_EXT 0x834D
+#define GL_SHADOW_ATTENUATION_EXT 0x834E
+#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F
+#define GL_TEXTURE_LIGHT_EXT 0x8350
+#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351
+#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+
+typedef void (GLAPIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);
+typedef void (GLAPIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);
+typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);
+
+#define glApplyTextureEXT GLEW_GET_FUN(__glewApplyTextureEXT)
+#define glTextureLightEXT GLEW_GET_FUN(__glewTextureLightEXT)
+#define glTextureMaterialEXT GLEW_GET_FUN(__glewTextureMaterialEXT)
+
+#define GLEW_EXT_light_texture GLEW_GET_VAR(__GLEW_EXT_light_texture)
+
+#endif /* GL_EXT_light_texture */
+
+/* ------------------------- GL_EXT_misc_attribute ------------------------- */
+
+#ifndef GL_EXT_misc_attribute
+#define GL_EXT_misc_attribute 1
+
+#define GLEW_EXT_misc_attribute GLEW_GET_VAR(__GLEW_EXT_misc_attribute)
+
+#endif /* GL_EXT_misc_attribute */
+
+/* ------------------------ GL_EXT_multi_draw_arrays ----------------------- */
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint* first, GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount);
+
+#define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT)
+#define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT)
+
+#define GLEW_EXT_multi_draw_arrays GLEW_GET_VAR(__GLEW_EXT_multi_draw_arrays)
+
+#endif /* GL_EXT_multi_draw_arrays */
+
+/* --------------------------- GL_EXT_multisample -------------------------- */
+
+#ifndef GL_EXT_multisample
+#define GL_EXT_multisample 1
+
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define GL_SAMPLE_MASK_EXT 0x80A0
+#define GL_1PASS_EXT 0x80A1
+#define GL_2PASS_0_EXT 0x80A2
+#define GL_2PASS_1_EXT 0x80A3
+#define GL_4PASS_0_EXT 0x80A4
+#define GL_4PASS_1_EXT 0x80A5
+#define GL_4PASS_2_EXT 0x80A6
+#define GL_4PASS_3_EXT 0x80A7
+#define GL_SAMPLE_BUFFERS_EXT 0x80A8
+#define GL_SAMPLES_EXT 0x80A9
+#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA
+#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB
+#define GL_SAMPLE_PATTERN_EXT 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);
+typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
+
+#define glSampleMaskEXT GLEW_GET_FUN(__glewSampleMaskEXT)
+#define glSamplePatternEXT GLEW_GET_FUN(__glewSamplePatternEXT)
+
+#define GLEW_EXT_multisample GLEW_GET_VAR(__GLEW_EXT_multisample)
+
+#endif /* GL_EXT_multisample */
+
+/* -------------------------- GL_EXT_packed_pixels ------------------------- */
+
+#ifndef GL_EXT_packed_pixels
+#define GL_EXT_packed_pixels 1
+
+#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036
+
+#define GLEW_EXT_packed_pixels GLEW_GET_VAR(__GLEW_EXT_packed_pixels)
+
+#endif /* GL_EXT_packed_pixels */
+
+/* ------------------------ GL_EXT_paletted_texture ------------------------ */
+
+#ifndef GL_EXT_paletted_texture
+#define GL_EXT_paletted_texture 1
+
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8
+#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void* data);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void* data);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+
+#define glColorTableEXT GLEW_GET_FUN(__glewColorTableEXT)
+#define glGetColorTableEXT GLEW_GET_FUN(__glewGetColorTableEXT)
+#define glGetColorTableParameterfvEXT GLEW_GET_FUN(__glewGetColorTableParameterfvEXT)
+#define glGetColorTableParameterivEXT GLEW_GET_FUN(__glewGetColorTableParameterivEXT)
+
+#define GLEW_EXT_paletted_texture GLEW_GET_VAR(__GLEW_EXT_paletted_texture)
+
+#endif /* GL_EXT_paletted_texture */
+
+/* ----------------------- GL_EXT_pixel_buffer_object ---------------------- */
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_EXT_pixel_buffer_object 1
+
+#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
+
+#define GLEW_EXT_pixel_buffer_object GLEW_GET_VAR(__GLEW_EXT_pixel_buffer_object)
+
+#endif /* GL_EXT_pixel_buffer_object */
+
+/* ------------------------- GL_EXT_pixel_transform ------------------------ */
+
+#ifndef GL_EXT_pixel_transform
+#define GL_EXT_pixel_transform 1
+
+#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330
+#define GL_PIXEL_MAG_FILTER_EXT 0x8331
+#define GL_PIXEL_MIN_FILTER_EXT 0x8332
+#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333
+#define GL_CUBIC_EXT 0x8334
+#define GL_AVERAGE_EXT 0x8335
+#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338
+
+typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params);
+
+#define glGetPixelTransformParameterfvEXT GLEW_GET_FUN(__glewGetPixelTransformParameterfvEXT)
+#define glGetPixelTransformParameterivEXT GLEW_GET_FUN(__glewGetPixelTransformParameterivEXT)
+#define glPixelTransformParameterfEXT GLEW_GET_FUN(__glewPixelTransformParameterfEXT)
+#define glPixelTransformParameterfvEXT GLEW_GET_FUN(__glewPixelTransformParameterfvEXT)
+#define glPixelTransformParameteriEXT GLEW_GET_FUN(__glewPixelTransformParameteriEXT)
+#define glPixelTransformParameterivEXT GLEW_GET_FUN(__glewPixelTransformParameterivEXT)
+
+#define GLEW_EXT_pixel_transform GLEW_GET_VAR(__GLEW_EXT_pixel_transform)
+
+#endif /* GL_EXT_pixel_transform */
+
+/* ------------------- GL_EXT_pixel_transform_color_table ------------------ */
+
+#ifndef GL_EXT_pixel_transform_color_table
+#define GL_EXT_pixel_transform_color_table 1
+
+#define GLEW_EXT_pixel_transform_color_table GLEW_GET_VAR(__GLEW_EXT_pixel_transform_color_table)
+
+#endif /* GL_EXT_pixel_transform_color_table */
+
+/* ------------------------ GL_EXT_point_parameters ------------------------ */
+
+#ifndef GL_EXT_point_parameters
+#define GL_EXT_point_parameters 1
+
+#define GL_POINT_SIZE_MIN_EXT 0x8126
+#define GL_POINT_SIZE_MAX_EXT 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
+#define GL_DISTANCE_ATTENUATION_EXT 0x8129
+
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, GLfloat* params);
+
+#define glPointParameterfEXT GLEW_GET_FUN(__glewPointParameterfEXT)
+#define glPointParameterfvEXT GLEW_GET_FUN(__glewPointParameterfvEXT)
+
+#define GLEW_EXT_point_parameters GLEW_GET_VAR(__GLEW_EXT_point_parameters)
+
+#endif /* GL_EXT_point_parameters */
+
+/* ------------------------- GL_EXT_polygon_offset ------------------------- */
+
+#ifndef GL_EXT_polygon_offset
+#define GL_EXT_polygon_offset 1
+
+#define GL_POLYGON_OFFSET_EXT 0x8037
+#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038
+#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039
+
+typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);
+
+#define glPolygonOffsetEXT GLEW_GET_FUN(__glewPolygonOffsetEXT)
+
+#define GLEW_EXT_polygon_offset GLEW_GET_VAR(__GLEW_EXT_polygon_offset)
+
+#endif /* GL_EXT_polygon_offset */
+
+/* ------------------------- GL_EXT_rescale_normal ------------------------- */
+
+#ifndef GL_EXT_rescale_normal
+#define GL_EXT_rescale_normal 1
+
+#define GLEW_EXT_rescale_normal GLEW_GET_VAR(__GLEW_EXT_rescale_normal)
+
+#endif /* GL_EXT_rescale_normal */
+
+/* -------------------------- GL_EXT_scene_marker -------------------------- */
+
+#ifndef GL_EXT_scene_marker
+#define GL_EXT_scene_marker 1
+
+typedef void (GLAPIENTRY * PFNGLBEGINSCENEEXTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLENDSCENEEXTPROC) (void);
+
+#define glBeginSceneEXT GLEW_GET_FUN(__glewBeginSceneEXT)
+#define glEndSceneEXT GLEW_GET_FUN(__glewEndSceneEXT)
+
+#define GLEW_EXT_scene_marker GLEW_GET_VAR(__GLEW_EXT_scene_marker)
+
+#endif /* GL_EXT_scene_marker */
+
+/* ------------------------- GL_EXT_secondary_color ------------------------ */
+
+#ifndef GL_EXT_secondary_color
+#define GL_EXT_secondary_color 1
+
+#define GL_COLOR_SUM_EXT 0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E
+
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer);
+
+#define glSecondaryColor3bEXT GLEW_GET_FUN(__glewSecondaryColor3bEXT)
+#define glSecondaryColor3bvEXT GLEW_GET_FUN(__glewSecondaryColor3bvEXT)
+#define glSecondaryColor3dEXT GLEW_GET_FUN(__glewSecondaryColor3dEXT)
+#define glSecondaryColor3dvEXT GLEW_GET_FUN(__glewSecondaryColor3dvEXT)
+#define glSecondaryColor3fEXT GLEW_GET_FUN(__glewSecondaryColor3fEXT)
+#define glSecondaryColor3fvEXT GLEW_GET_FUN(__glewSecondaryColor3fvEXT)
+#define glSecondaryColor3iEXT GLEW_GET_FUN(__glewSecondaryColor3iEXT)
+#define glSecondaryColor3ivEXT GLEW_GET_FUN(__glewSecondaryColor3ivEXT)
+#define glSecondaryColor3sEXT GLEW_GET_FUN(__glewSecondaryColor3sEXT)
+#define glSecondaryColor3svEXT GLEW_GET_FUN(__glewSecondaryColor3svEXT)
+#define glSecondaryColor3ubEXT GLEW_GET_FUN(__glewSecondaryColor3ubEXT)
+#define glSecondaryColor3ubvEXT GLEW_GET_FUN(__glewSecondaryColor3ubvEXT)
+#define glSecondaryColor3uiEXT GLEW_GET_FUN(__glewSecondaryColor3uiEXT)
+#define glSecondaryColor3uivEXT GLEW_GET_FUN(__glewSecondaryColor3uivEXT)
+#define glSecondaryColor3usEXT GLEW_GET_FUN(__glewSecondaryColor3usEXT)
+#define glSecondaryColor3usvEXT GLEW_GET_FUN(__glewSecondaryColor3usvEXT)
+#define glSecondaryColorPointerEXT GLEW_GET_FUN(__glewSecondaryColorPointerEXT)
+
+#define GLEW_EXT_secondary_color GLEW_GET_VAR(__GLEW_EXT_secondary_color)
+
+#endif /* GL_EXT_secondary_color */
+
+/* --------------------- GL_EXT_separate_specular_color -------------------- */
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_EXT_separate_specular_color 1
+
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define GL_SINGLE_COLOR_EXT 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+
+#define GLEW_EXT_separate_specular_color GLEW_GET_VAR(__GLEW_EXT_separate_specular_color)
+
+#endif /* GL_EXT_separate_specular_color */
+
+/* -------------------------- GL_EXT_shadow_funcs -------------------------- */
+
+#ifndef GL_EXT_shadow_funcs
+#define GL_EXT_shadow_funcs 1
+
+#define GLEW_EXT_shadow_funcs GLEW_GET_VAR(__GLEW_EXT_shadow_funcs)
+
+#endif /* GL_EXT_shadow_funcs */
+
+/* --------------------- GL_EXT_shared_texture_palette --------------------- */
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_EXT_shared_texture_palette 1
+
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+
+#define GLEW_EXT_shared_texture_palette GLEW_GET_VAR(__GLEW_EXT_shared_texture_palette)
+
+#endif /* GL_EXT_shared_texture_palette */
+
+/* ------------------------ GL_EXT_stencil_two_side ------------------------ */
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_EXT_stencil_two_side 1
+
+#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
+#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
+
+typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
+
+#define glActiveStencilFaceEXT GLEW_GET_FUN(__glewActiveStencilFaceEXT)
+
+#define GLEW_EXT_stencil_two_side GLEW_GET_VAR(__GLEW_EXT_stencil_two_side)
+
+#endif /* GL_EXT_stencil_two_side */
+
+/* -------------------------- GL_EXT_stencil_wrap -------------------------- */
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_EXT_stencil_wrap 1
+
+#define GL_INCR_WRAP_EXT 0x8507
+#define GL_DECR_WRAP_EXT 0x8508
+
+#define GLEW_EXT_stencil_wrap GLEW_GET_VAR(__GLEW_EXT_stencil_wrap)
+
+#endif /* GL_EXT_stencil_wrap */
+
+/* --------------------------- GL_EXT_subtexture --------------------------- */
+
+#ifndef GL_EXT_subtexture
+#define GL_EXT_subtexture 1
+
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+
+#define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT)
+#define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT)
+#define glTexSubImage3DEXT GLEW_GET_FUN(__glewTexSubImage3DEXT)
+
+#define GLEW_EXT_subtexture GLEW_GET_VAR(__GLEW_EXT_subtexture)
+
+#endif /* GL_EXT_subtexture */
+
+/* ----------------------------- GL_EXT_texture ---------------------------- */
+
+#ifndef GL_EXT_texture
+#define GL_EXT_texture 1
+
+#define GL_ALPHA4_EXT 0x803B
+#define GL_ALPHA8_EXT 0x803C
+#define GL_ALPHA12_EXT 0x803D
+#define GL_ALPHA16_EXT 0x803E
+#define GL_LUMINANCE4_EXT 0x803F
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE12_EXT 0x8041
+#define GL_LUMINANCE16_EXT 0x8042
+#define GL_LUMINANCE4_ALPHA4_EXT 0x8043
+#define GL_LUMINANCE6_ALPHA2_EXT 0x8044
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_LUMINANCE12_ALPHA4_EXT 0x8046
+#define GL_LUMINANCE12_ALPHA12_EXT 0x8047
+#define GL_LUMINANCE16_ALPHA16_EXT 0x8048
+#define GL_INTENSITY_EXT 0x8049
+#define GL_INTENSITY4_EXT 0x804A
+#define GL_INTENSITY8_EXT 0x804B
+#define GL_INTENSITY12_EXT 0x804C
+#define GL_INTENSITY16_EXT 0x804D
+#define GL_RGB2_EXT 0x804E
+#define GL_RGB4_EXT 0x804F
+#define GL_RGB5_EXT 0x8050
+#define GL_RGB8_EXT 0x8051
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB12_EXT 0x8053
+#define GL_RGB16_EXT 0x8054
+#define GL_RGBA2_EXT 0x8055
+#define GL_RGBA4_EXT 0x8056
+#define GL_RGB5_A1_EXT 0x8057
+#define GL_RGBA8_EXT 0x8058
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGBA12_EXT 0x805A
+#define GL_RGBA16_EXT 0x805B
+#define GL_TEXTURE_RED_SIZE_EXT 0x805C
+#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D
+#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E
+#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061
+#define GL_REPLACE_EXT 0x8062
+#define GL_PROXY_TEXTURE_1D_EXT 0x8063
+#define GL_PROXY_TEXTURE_2D_EXT 0x8064
+
+#define GLEW_EXT_texture GLEW_GET_VAR(__GLEW_EXT_texture)
+
+#endif /* GL_EXT_texture */
+
+/* ---------------------------- GL_EXT_texture3D --------------------------- */
+
+#ifndef GL_EXT_texture3D
+#define GL_EXT_texture3D 1
+
+#define GL_PACK_SKIP_IMAGES_EXT 0x806B
+#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C
+#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_TEXTURE_DEPTH_EXT 0x8071
+#define GL_TEXTURE_WRAP_R_EXT 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
+
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+
+#define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT)
+
+#define GLEW_EXT_texture3D GLEW_GET_VAR(__GLEW_EXT_texture3D)
+
+#endif /* GL_EXT_texture3D */
+
+/* -------------------- GL_EXT_texture_compression_dxt1 -------------------- */
+
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+
+#define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1)
+
+#endif /* GL_EXT_texture_compression_dxt1 */
+
+/* -------------------- GL_EXT_texture_compression_s3tc -------------------- */
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_EXT_texture_compression_s3tc 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+
+#define GLEW_EXT_texture_compression_s3tc GLEW_GET_VAR(__GLEW_EXT_texture_compression_s3tc)
+
+#endif /* GL_EXT_texture_compression_s3tc */
+
+/* ------------------------ GL_EXT_texture_cube_map ------------------------ */
+
+#ifndef GL_EXT_texture_cube_map
+#define GL_EXT_texture_cube_map 1
+
+#define GL_NORMAL_MAP_EXT 0x8511
+#define GL_REFLECTION_MAP_EXT 0x8512
+#define GL_TEXTURE_CUBE_MAP_EXT 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
+
+#define GLEW_EXT_texture_cube_map GLEW_GET_VAR(__GLEW_EXT_texture_cube_map)
+
+#endif /* GL_EXT_texture_cube_map */
+
+/* ----------------------- GL_EXT_texture_edge_clamp ----------------------- */
+
+#ifndef GL_EXT_texture_edge_clamp
+#define GL_EXT_texture_edge_clamp 1
+
+#define GL_CLAMP_TO_EDGE_EXT 0x812F
+
+#define GLEW_EXT_texture_edge_clamp GLEW_GET_VAR(__GLEW_EXT_texture_edge_clamp)
+
+#endif /* GL_EXT_texture_edge_clamp */
+
+/* --------------------------- GL_EXT_texture_env -------------------------- */
+
+#ifndef GL_EXT_texture_env
+#define GL_EXT_texture_env 1
+
+#define GL_TEXTURE_ENV0_EXT 0
+#define GL_ENV_BLEND_EXT 0
+#define GL_TEXTURE_ENV_SHIFT_EXT 0
+#define GL_ENV_REPLACE_EXT 0
+#define GL_ENV_ADD_EXT 0
+#define GL_ENV_SUBTRACT_EXT 0
+#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0
+#define GL_ENV_REVERSE_SUBTRACT_EXT 0
+#define GL_ENV_REVERSE_BLEND_EXT 0
+#define GL_ENV_COPY_EXT 0
+#define GL_ENV_MODULATE_EXT 0
+
+#define GLEW_EXT_texture_env GLEW_GET_VAR(__GLEW_EXT_texture_env)
+
+#endif /* GL_EXT_texture_env */
+
+/* ------------------------- GL_EXT_texture_env_add ------------------------ */
+
+#ifndef GL_EXT_texture_env_add
+#define GL_EXT_texture_env_add 1
+
+#define GLEW_EXT_texture_env_add GLEW_GET_VAR(__GLEW_EXT_texture_env_add)
+
+#endif /* GL_EXT_texture_env_add */
+
+/* ----------------------- GL_EXT_texture_env_combine ---------------------- */
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_EXT_texture_env_combine 1
+
+#define GL_COMBINE_EXT 0x8570
+#define GL_COMBINE_RGB_EXT 0x8571
+#define GL_COMBINE_ALPHA_EXT 0x8572
+#define GL_RGB_SCALE_EXT 0x8573
+#define GL_ADD_SIGNED_EXT 0x8574
+#define GL_INTERPOLATE_EXT 0x8575
+#define GL_CONSTANT_EXT 0x8576
+#define GL_PRIMARY_COLOR_EXT 0x8577
+#define GL_PREVIOUS_EXT 0x8578
+#define GL_SOURCE0_RGB_EXT 0x8580
+#define GL_SOURCE1_RGB_EXT 0x8581
+#define GL_SOURCE2_RGB_EXT 0x8582
+#define GL_SOURCE0_ALPHA_EXT 0x8588
+#define GL_SOURCE1_ALPHA_EXT 0x8589
+#define GL_SOURCE2_ALPHA_EXT 0x858A
+#define GL_OPERAND0_RGB_EXT 0x8590
+#define GL_OPERAND1_RGB_EXT 0x8591
+#define GL_OPERAND2_RGB_EXT 0x8592
+#define GL_OPERAND0_ALPHA_EXT 0x8598
+#define GL_OPERAND1_ALPHA_EXT 0x8599
+#define GL_OPERAND2_ALPHA_EXT 0x859A
+
+#define GLEW_EXT_texture_env_combine GLEW_GET_VAR(__GLEW_EXT_texture_env_combine)
+
+#endif /* GL_EXT_texture_env_combine */
+
+/* ------------------------ GL_EXT_texture_env_dot3 ------------------------ */
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_EXT_texture_env_dot3 1
+
+#define GL_DOT3_RGB_EXT 0x8740
+#define GL_DOT3_RGBA_EXT 0x8741
+
+#define GLEW_EXT_texture_env_dot3 GLEW_GET_VAR(__GLEW_EXT_texture_env_dot3)
+
+#endif /* GL_EXT_texture_env_dot3 */
+
+/* ------------------- GL_EXT_texture_filter_anisotropic ------------------- */
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+
+#define GLEW_EXT_texture_filter_anisotropic GLEW_GET_VAR(__GLEW_EXT_texture_filter_anisotropic)
+
+#endif /* GL_EXT_texture_filter_anisotropic */
+
+/* ------------------------ GL_EXT_texture_lod_bias ------------------------ */
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_EXT_texture_lod_bias 1
+
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
+
+#define GLEW_EXT_texture_lod_bias GLEW_GET_VAR(__GLEW_EXT_texture_lod_bias)
+
+#endif /* GL_EXT_texture_lod_bias */
+
+/* ---------------------- GL_EXT_texture_mirror_clamp ---------------------- */
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_EXT_texture_mirror_clamp 1
+
+#define GL_MIRROR_CLAMP_EXT 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
+
+#define GLEW_EXT_texture_mirror_clamp GLEW_GET_VAR(__GLEW_EXT_texture_mirror_clamp)
+
+#endif /* GL_EXT_texture_mirror_clamp */
+
+/* ------------------------- GL_EXT_texture_object ------------------------- */
+
+#ifndef GL_EXT_texture_object
+#define GL_EXT_texture_object 1
+
+#define GL_TEXTURE_PRIORITY_EXT 0x8066
+#define GL_TEXTURE_RESIDENT_EXT 0x8067
+#define GL_TEXTURE_1D_BINDING_EXT 0x8068
+#define GL_TEXTURE_2D_BINDING_EXT 0x8069
+#define GL_TEXTURE_3D_BINDING_EXT 0x806A
+
+typedef GLboolean (GLAPIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint* textures, GLboolean* residences);
+typedef void (GLAPIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);
+typedef void (GLAPIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint* textures);
+typedef void (GLAPIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint* textures);
+typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture);
+typedef void (GLAPIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint* textures, const GLclampf* priorities);
+
+#define glAreTexturesResidentEXT GLEW_GET_FUN(__glewAreTexturesResidentEXT)
+#define glBindTextureEXT GLEW_GET_FUN(__glewBindTextureEXT)
+#define glDeleteTexturesEXT GLEW_GET_FUN(__glewDeleteTexturesEXT)
+#define glGenTexturesEXT GLEW_GET_FUN(__glewGenTexturesEXT)
+#define glIsTextureEXT GLEW_GET_FUN(__glewIsTextureEXT)
+#define glPrioritizeTexturesEXT GLEW_GET_FUN(__glewPrioritizeTexturesEXT)
+
+#define GLEW_EXT_texture_object GLEW_GET_VAR(__GLEW_EXT_texture_object)
+
+#endif /* GL_EXT_texture_object */
+
+/* --------------------- GL_EXT_texture_perturb_normal --------------------- */
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_EXT_texture_perturb_normal 1
+
+#define GL_PERTURB_EXT 0x85AE
+#define GL_TEXTURE_NORMAL_EXT 0x85AF
+
+typedef void (GLAPIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode);
+
+#define glTextureNormalEXT GLEW_GET_FUN(__glewTextureNormalEXT)
+
+#define GLEW_EXT_texture_perturb_normal GLEW_GET_VAR(__GLEW_EXT_texture_perturb_normal)
+
+#endif /* GL_EXT_texture_perturb_normal */
+
+/* ------------------------ GL_EXT_texture_rectangle ----------------------- */
+
+#ifndef GL_EXT_texture_rectangle
+#define GL_EXT_texture_rectangle 1
+
+#define GL_TEXTURE_RECTANGLE_EXT 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_EXT 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_EXT 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT 0x84F8
+
+#define GLEW_EXT_texture_rectangle GLEW_GET_VAR(__GLEW_EXT_texture_rectangle)
+
+#endif /* GL_EXT_texture_rectangle */
+
+/* -------------------------- GL_EXT_vertex_array -------------------------- */
+
+#ifndef GL_EXT_vertex_array
+#define GL_EXT_vertex_array 1
+
+#define GL_DOUBLE_EXT 0x140A
+#define GL_VERTEX_ARRAY_EXT 0x8074
+#define GL_NORMAL_ARRAY_EXT 0x8075
+#define GL_COLOR_ARRAY_EXT 0x8076
+#define GL_INDEX_ARRAY_EXT 0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT 0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT 0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT 0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT 0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT 0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT 0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT 0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
+
+typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer);
+typedef void (GLAPIENTRY * PFNGLGETPOINTERVEXTPROC) (GLenum pname, void** params);
+typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+
+#define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT)
+#define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT)
+#define glDrawArraysEXT GLEW_GET_FUN(__glewDrawArraysEXT)
+#define glEdgeFlagPointerEXT GLEW_GET_FUN(__glewEdgeFlagPointerEXT)
+#define glGetPointervEXT GLEW_GET_FUN(__glewGetPointervEXT)
+#define glIndexPointerEXT GLEW_GET_FUN(__glewIndexPointerEXT)
+#define glNormalPointerEXT GLEW_GET_FUN(__glewNormalPointerEXT)
+#define glTexCoordPointerEXT GLEW_GET_FUN(__glewTexCoordPointerEXT)
+#define glVertexPointerEXT GLEW_GET_FUN(__glewVertexPointerEXT)
+
+#define GLEW_EXT_vertex_array GLEW_GET_VAR(__GLEW_EXT_vertex_array)
+
+#endif /* GL_EXT_vertex_array */
+
+/* -------------------------- GL_EXT_vertex_shader ------------------------- */
+
+#ifndef GL_EXT_vertex_shader
+#define GL_EXT_vertex_shader 1
+
+#define GL_VERTEX_SHADER_EXT 0x8780
+#define GL_VERTEX_SHADER_BINDING_EXT 0x8781
+#define GL_OP_INDEX_EXT 0x8782
+#define GL_OP_NEGATE_EXT 0x8783
+#define GL_OP_DOT3_EXT 0x8784
+#define GL_OP_DOT4_EXT 0x8785
+#define GL_OP_MUL_EXT 0x8786
+#define GL_OP_ADD_EXT 0x8787
+#define GL_OP_MADD_EXT 0x8788
+#define GL_OP_FRAC_EXT 0x8789
+#define GL_OP_MAX_EXT 0x878A
+#define GL_OP_MIN_EXT 0x878B
+#define GL_OP_SET_GE_EXT 0x878C
+#define GL_OP_SET_LT_EXT 0x878D
+#define GL_OP_CLAMP_EXT 0x878E
+#define GL_OP_FLOOR_EXT 0x878F
+#define GL_OP_ROUND_EXT 0x8790
+#define GL_OP_EXP_BASE_2_EXT 0x8791
+#define GL_OP_LOG_BASE_2_EXT 0x8792
+#define GL_OP_POWER_EXT 0x8793
+#define GL_OP_RECIP_EXT 0x8794
+#define GL_OP_RECIP_SQRT_EXT 0x8795
+#define GL_OP_SUB_EXT 0x8796
+#define GL_OP_CROSS_PRODUCT_EXT 0x8797
+#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798
+#define GL_OP_MOV_EXT 0x8799
+#define GL_OUTPUT_VERTEX_EXT 0x879A
+#define GL_OUTPUT_COLOR0_EXT 0x879B
+#define GL_OUTPUT_COLOR1_EXT 0x879C
+#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D
+#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E
+#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F
+#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0
+#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1
+#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2
+#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3
+#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4
+#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5
+#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6
+#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7
+#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8
+#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9
+#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA
+#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB
+#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC
+#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD
+#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE
+#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF
+#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0
+#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1
+#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2
+#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3
+#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4
+#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5
+#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6
+#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7
+#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8
+#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9
+#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA
+#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB
+#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC
+#define GL_OUTPUT_FOG_EXT 0x87BD
+#define GL_SCALAR_EXT 0x87BE
+#define GL_VECTOR_EXT 0x87BF
+#define GL_MATRIX_EXT 0x87C0
+#define GL_VARIANT_EXT 0x87C1
+#define GL_INVARIANT_EXT 0x87C2
+#define GL_LOCAL_CONSTANT_EXT 0x87C3
+#define GL_LOCAL_EXT 0x87C4
+#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
+#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
+#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
+#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
+#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CC
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CD
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
+#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF
+#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0
+#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1
+#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2
+#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3
+#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4
+#define GL_X_EXT 0x87D5
+#define GL_Y_EXT 0x87D6
+#define GL_Z_EXT 0x87D7
+#define GL_W_EXT 0x87D8
+#define GL_NEGATIVE_X_EXT 0x87D9
+#define GL_NEGATIVE_Y_EXT 0x87DA
+#define GL_NEGATIVE_Z_EXT 0x87DB
+#define GL_NEGATIVE_W_EXT 0x87DC
+#define GL_ZERO_EXT 0x87DD
+#define GL_ONE_EXT 0x87DE
+#define GL_NEGATIVE_ONE_EXT 0x87DF
+#define GL_NORMALIZED_RANGE_EXT 0x87E0
+#define GL_FULL_RANGE_EXT 0x87E1
+#define GL_CURRENT_VERTEX_EXT 0x87E2
+#define GL_MVP_MATRIX_EXT 0x87E3
+#define GL_VARIANT_VALUE_EXT 0x87E4
+#define GL_VARIANT_DATATYPE_EXT 0x87E5
+#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6
+#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7
+#define GL_VARIANT_ARRAY_EXT 0x87E8
+#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9
+#define GL_INVARIANT_VALUE_EXT 0x87EA
+#define GL_INVARIANT_DATATYPE_EXT 0x87EB
+#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC
+#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED
+
+typedef void (GLAPIENTRY * PFNGLBEGINVERTEXSHADEREXTPROC) (void);
+typedef GLuint (GLAPIENTRY * PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDPARAMETEREXTPROC) (GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENDVERTEXSHADEREXTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLuint (GLAPIENTRY * PFNGLGENSYMBOLSEXTPROC) (GLenum dataType, GLenum storageType, GLenum range, GLuint components);
+typedef GLuint (GLAPIENTRY * PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);
+typedef void (GLAPIENTRY * PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (GLAPIENTRY * PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (GLAPIENTRY * PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid **data);
+typedef void (GLAPIENTRY * PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLboolean (GLAPIENTRY * PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);
+typedef void (GLAPIENTRY * PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr);
+typedef void (GLAPIENTRY * PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr);
+typedef void (GLAPIENTRY * PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);
+typedef void (GLAPIENTRY * PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+typedef void (GLAPIENTRY * PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+typedef void (GLAPIENTRY * PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (GLAPIENTRY * PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, GLvoid *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTBVEXTPROC) (GLuint id, GLbyte *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTDVEXTPROC) (GLuint id, GLdouble *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTFVEXTPROC) (GLuint id, GLfloat *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTIVEXTPROC) (GLuint id, GLint *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTSVEXTPROC) (GLuint id, GLshort *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTUBVEXTPROC) (GLuint id, GLubyte *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTUIVEXTPROC) (GLuint id, GLuint *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTUSVEXTPROC) (GLuint id, GLushort *addr);
+typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+
+#define glBeginVertexShaderEXT GLEW_GET_FUN(__glewBeginVertexShaderEXT)
+#define glBindLightParameterEXT GLEW_GET_FUN(__glewBindLightParameterEXT)
+#define glBindMaterialParameterEXT GLEW_GET_FUN(__glewBindMaterialParameterEXT)
+#define glBindParameterEXT GLEW_GET_FUN(__glewBindParameterEXT)
+#define glBindTexGenParameterEXT GLEW_GET_FUN(__glewBindTexGenParameterEXT)
+#define glBindTextureUnitParameterEXT GLEW_GET_FUN(__glewBindTextureUnitParameterEXT)
+#define glBindVertexShaderEXT GLEW_GET_FUN(__glewBindVertexShaderEXT)
+#define glDeleteVertexShaderEXT GLEW_GET_FUN(__glewDeleteVertexShaderEXT)
+#define glDisableVariantClientStateEXT GLEW_GET_FUN(__glewDisableVariantClientStateEXT)
+#define glEnableVariantClientStateEXT GLEW_GET_FUN(__glewEnableVariantClientStateEXT)
+#define glEndVertexShaderEXT GLEW_GET_FUN(__glewEndVertexShaderEXT)
+#define glExtractComponentEXT GLEW_GET_FUN(__glewExtractComponentEXT)
+#define glGenSymbolsEXT GLEW_GET_FUN(__glewGenSymbolsEXT)
+#define glGenVertexShadersEXT GLEW_GET_FUN(__glewGenVertexShadersEXT)
+#define glGetInvariantBooleanvEXT GLEW_GET_FUN(__glewGetInvariantBooleanvEXT)
+#define glGetInvariantFloatvEXT GLEW_GET_FUN(__glewGetInvariantFloatvEXT)
+#define glGetInvariantIntegervEXT GLEW_GET_FUN(__glewGetInvariantIntegervEXT)
+#define glGetLocalConstantBooleanvEXT GLEW_GET_FUN(__glewGetLocalConstantBooleanvEXT)
+#define glGetLocalConstantFloatvEXT GLEW_GET_FUN(__glewGetLocalConstantFloatvEXT)
+#define glGetLocalConstantIntegervEXT GLEW_GET_FUN(__glewGetLocalConstantIntegervEXT)
+#define glGetVariantBooleanvEXT GLEW_GET_FUN(__glewGetVariantBooleanvEXT)
+#define glGetVariantFloatvEXT GLEW_GET_FUN(__glewGetVariantFloatvEXT)
+#define glGetVariantIntegervEXT GLEW_GET_FUN(__glewGetVariantIntegervEXT)
+#define glGetVariantPointervEXT GLEW_GET_FUN(__glewGetVariantPointervEXT)
+#define glInsertComponentEXT GLEW_GET_FUN(__glewInsertComponentEXT)
+#define glIsVariantEnabledEXT GLEW_GET_FUN(__glewIsVariantEnabledEXT)
+#define glSetInvariantEXT GLEW_GET_FUN(__glewSetInvariantEXT)
+#define glSetLocalConstantEXT GLEW_GET_FUN(__glewSetLocalConstantEXT)
+#define glShaderOp1EXT GLEW_GET_FUN(__glewShaderOp1EXT)
+#define glShaderOp2EXT GLEW_GET_FUN(__glewShaderOp2EXT)
+#define glShaderOp3EXT GLEW_GET_FUN(__glewShaderOp3EXT)
+#define glSwizzleEXT GLEW_GET_FUN(__glewSwizzleEXT)
+#define glVariantPointerEXT GLEW_GET_FUN(__glewVariantPointerEXT)
+#define glVariantbvEXT GLEW_GET_FUN(__glewVariantbvEXT)
+#define glVariantdvEXT GLEW_GET_FUN(__glewVariantdvEXT)
+#define glVariantfvEXT GLEW_GET_FUN(__glewVariantfvEXT)
+#define glVariantivEXT GLEW_GET_FUN(__glewVariantivEXT)
+#define glVariantsvEXT GLEW_GET_FUN(__glewVariantsvEXT)
+#define glVariantubvEXT GLEW_GET_FUN(__glewVariantubvEXT)
+#define glVariantuivEXT GLEW_GET_FUN(__glewVariantuivEXT)
+#define glVariantusvEXT GLEW_GET_FUN(__glewVariantusvEXT)
+#define glWriteMaskEXT GLEW_GET_FUN(__glewWriteMaskEXT)
+
+#define GLEW_EXT_vertex_shader GLEW_GET_VAR(__GLEW_EXT_vertex_shader)
+
+#endif /* GL_EXT_vertex_shader */
+
+/* ------------------------ GL_EXT_vertex_weighting ------------------------ */
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_EXT_vertex_weighting 1
+
+#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3
+#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6
+#define GL_MODELVIEW0_EXT 0x1700
+#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502
+#define GL_MODELVIEW1_MATRIX_EXT 0x8506
+#define GL_VERTEX_WEIGHTING_EXT 0x8509
+#define GL_MODELVIEW1_EXT 0x850A
+#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B
+#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C
+#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D
+#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E
+#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight);
+
+#define glVertexWeightPointerEXT GLEW_GET_FUN(__glewVertexWeightPointerEXT)
+#define glVertexWeightfEXT GLEW_GET_FUN(__glewVertexWeightfEXT)
+#define glVertexWeightfvEXT GLEW_GET_FUN(__glewVertexWeightfvEXT)
+
+#define GLEW_EXT_vertex_weighting GLEW_GET_VAR(__GLEW_EXT_vertex_weighting)
+
+#endif /* GL_EXT_vertex_weighting */
+
+/* --------------------- GL_HP_convolution_border_modes -------------------- */
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_HP_convolution_border_modes 1
+
+#define GLEW_HP_convolution_border_modes GLEW_GET_VAR(__GLEW_HP_convolution_border_modes)
+
+#endif /* GL_HP_convolution_border_modes */
+
+/* ------------------------- GL_HP_image_transform ------------------------- */
+
+#ifndef GL_HP_image_transform
+#define GL_HP_image_transform 1
+
+typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params);
+
+#define glGetImageTransformParameterfvHP GLEW_GET_FUN(__glewGetImageTransformParameterfvHP)
+#define glGetImageTransformParameterivHP GLEW_GET_FUN(__glewGetImageTransformParameterivHP)
+#define glImageTransformParameterfHP GLEW_GET_FUN(__glewImageTransformParameterfHP)
+#define glImageTransformParameterfvHP GLEW_GET_FUN(__glewImageTransformParameterfvHP)
+#define glImageTransformParameteriHP GLEW_GET_FUN(__glewImageTransformParameteriHP)
+#define glImageTransformParameterivHP GLEW_GET_FUN(__glewImageTransformParameterivHP)
+
+#define GLEW_HP_image_transform GLEW_GET_VAR(__GLEW_HP_image_transform)
+
+#endif /* GL_HP_image_transform */
+
+/* -------------------------- GL_HP_occlusion_test ------------------------- */
+
+#ifndef GL_HP_occlusion_test
+#define GL_HP_occlusion_test 1
+
+#define GL_OCCLUSION_TEST_HP 0x8165
+#define GL_OCCLUSION_TEST_RESULT_HP 0x8166
+
+#define GLEW_HP_occlusion_test GLEW_GET_VAR(__GLEW_HP_occlusion_test)
+
+#endif /* GL_HP_occlusion_test */
+
+/* ------------------------- GL_HP_texture_lighting ------------------------ */
+
+#ifndef GL_HP_texture_lighting
+#define GL_HP_texture_lighting 1
+
+#define GLEW_HP_texture_lighting GLEW_GET_VAR(__GLEW_HP_texture_lighting)
+
+#endif /* GL_HP_texture_lighting */
+
+/* --------------------------- GL_IBM_cull_vertex -------------------------- */
+
+#ifndef GL_IBM_cull_vertex
+#define GL_IBM_cull_vertex 1
+
+#define GL_CULL_VERTEX_IBM 103050
+
+#define GLEW_IBM_cull_vertex GLEW_GET_VAR(__GLEW_IBM_cull_vertex)
+
+#endif /* GL_IBM_cull_vertex */
+
+/* ---------------------- GL_IBM_multimode_draw_arrays --------------------- */
+
+#ifndef GL_IBM_multimode_draw_arrays
+#define GL_IBM_multimode_draw_arrays 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum* mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, GLint modestride);
+
+#define glMultiModeDrawArraysIBM GLEW_GET_FUN(__glewMultiModeDrawArraysIBM)
+#define glMultiModeDrawElementsIBM GLEW_GET_FUN(__glewMultiModeDrawElementsIBM)
+
+#define GLEW_IBM_multimode_draw_arrays GLEW_GET_VAR(__GLEW_IBM_multimode_draw_arrays)
+
+#endif /* GL_IBM_multimode_draw_arrays */
+
+/* ------------------------- GL_IBM_rasterpos_clip ------------------------- */
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_IBM_rasterpos_clip 1
+
+#define GL_RASTER_POSITION_UNCLIPPED_IBM 103010
+
+#define GLEW_IBM_rasterpos_clip GLEW_GET_VAR(__GLEW_IBM_rasterpos_clip)
+
+#endif /* GL_IBM_rasterpos_clip */
+
+/* --------------------------- GL_IBM_static_data -------------------------- */
+
+#ifndef GL_IBM_static_data
+#define GL_IBM_static_data 1
+
+#define GL_ALL_STATIC_DATA_IBM 103060
+#define GL_STATIC_VERTEX_ARRAY_IBM 103061
+
+#define GLEW_IBM_static_data GLEW_GET_VAR(__GLEW_IBM_static_data)
+
+#endif /* GL_IBM_static_data */
+
+/* --------------------- GL_IBM_texture_mirrored_repeat -------------------- */
+
+#ifndef GL_IBM_texture_mirrored_repeat
+#define GL_IBM_texture_mirrored_repeat 1
+
+#define GL_MIRRORED_REPEAT_IBM 0x8370
+
+#define GLEW_IBM_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_IBM_texture_mirrored_repeat)
+
+#endif /* GL_IBM_texture_mirrored_repeat */
+
+/* ----------------------- GL_IBM_vertex_array_lists ----------------------- */
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_IBM_vertex_array_lists 1
+
+#define GL_VERTEX_ARRAY_LIST_IBM 103070
+#define GL_NORMAL_ARRAY_LIST_IBM 103071
+#define GL_COLOR_ARRAY_LIST_IBM 103072
+#define GL_INDEX_ARRAY_LIST_IBM 103073
+#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074
+#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075
+#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076
+#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080
+#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081
+#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082
+#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083
+#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+
+typedef void (GLAPIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+
+#define glColorPointerListIBM GLEW_GET_FUN(__glewColorPointerListIBM)
+#define glEdgeFlagPointerListIBM GLEW_GET_FUN(__glewEdgeFlagPointerListIBM)
+#define glFogCoordPointerListIBM GLEW_GET_FUN(__glewFogCoordPointerListIBM)
+#define glIndexPointerListIBM GLEW_GET_FUN(__glewIndexPointerListIBM)
+#define glNormalPointerListIBM GLEW_GET_FUN(__glewNormalPointerListIBM)
+#define glSecondaryColorPointerListIBM GLEW_GET_FUN(__glewSecondaryColorPointerListIBM)
+#define glTexCoordPointerListIBM GLEW_GET_FUN(__glewTexCoordPointerListIBM)
+#define glVertexPointerListIBM GLEW_GET_FUN(__glewVertexPointerListIBM)
+
+#define GLEW_IBM_vertex_array_lists GLEW_GET_VAR(__GLEW_IBM_vertex_array_lists)
+
+#endif /* GL_IBM_vertex_array_lists */
+
+/* -------------------------- GL_INGR_color_clamp -------------------------- */
+
+#ifndef GL_INGR_color_clamp
+#define GL_INGR_color_clamp 1
+
+#define GL_RED_MIN_CLAMP_INGR 0x8560
+#define GL_GREEN_MIN_CLAMP_INGR 0x8561
+#define GL_BLUE_MIN_CLAMP_INGR 0x8562
+#define GL_ALPHA_MIN_CLAMP_INGR 0x8563
+#define GL_RED_MAX_CLAMP_INGR 0x8564
+#define GL_GREEN_MAX_CLAMP_INGR 0x8565
+#define GL_BLUE_MAX_CLAMP_INGR 0x8566
+#define GL_ALPHA_MAX_CLAMP_INGR 0x8567
+
+#define GLEW_INGR_color_clamp GLEW_GET_VAR(__GLEW_INGR_color_clamp)
+
+#endif /* GL_INGR_color_clamp */
+
+/* ------------------------- GL_INGR_interlace_read ------------------------ */
+
+#ifndef GL_INGR_interlace_read
+#define GL_INGR_interlace_read 1
+
+#define GL_INTERLACE_READ_INGR 0x8568
+
+#define GLEW_INGR_interlace_read GLEW_GET_VAR(__GLEW_INGR_interlace_read)
+
+#endif /* GL_INGR_interlace_read */
+
+/* ------------------------ GL_INTEL_parallel_arrays ----------------------- */
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_INTEL_parallel_arrays 1
+
+#define GL_PARALLEL_ARRAYS_INTEL 0x83F4
+#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+
+typedef void (GLAPIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer);
+typedef void (GLAPIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void** pointer);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer);
+
+#define glColorPointervINTEL GLEW_GET_FUN(__glewColorPointervINTEL)
+#define glNormalPointervINTEL GLEW_GET_FUN(__glewNormalPointervINTEL)
+#define glTexCoordPointervINTEL GLEW_GET_FUN(__glewTexCoordPointervINTEL)
+#define glVertexPointervINTEL GLEW_GET_FUN(__glewVertexPointervINTEL)
+
+#define GLEW_INTEL_parallel_arrays GLEW_GET_VAR(__GLEW_INTEL_parallel_arrays)
+
+#endif /* GL_INTEL_parallel_arrays */
+
+/* ------------------------ GL_INTEL_texture_scissor ----------------------- */
+
+#ifndef GL_INTEL_texture_scissor
+#define GL_INTEL_texture_scissor 1
+
+typedef void (GLAPIENTRY * PFNGLTEXSCISSORFUNCINTELPROC) (GLenum target, GLenum lfunc, GLenum hfunc);
+typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tlow, GLclampf thigh);
+
+#define glTexScissorFuncINTEL GLEW_GET_FUN(__glewTexScissorFuncINTEL)
+#define glTexScissorINTEL GLEW_GET_FUN(__glewTexScissorINTEL)
+
+#define GLEW_INTEL_texture_scissor GLEW_GET_VAR(__GLEW_INTEL_texture_scissor)
+
+#endif /* GL_INTEL_texture_scissor */
+
+/* -------------------------- GL_KTX_buffer_region ------------------------- */
+
+#ifndef GL_KTX_buffer_region
+#define GL_KTX_buffer_region 1
+
+#define GL_KTX_FRONT_REGION 0x0
+#define GL_KTX_BACK_REGION 0x1
+#define GL_KTX_Z_REGION 0x2
+#define GL_KTX_STENCIL_REGION 0x3
+
+typedef GLuint (GLAPIENTRY * PFNGLBUFFERREGIONENABLEDEXTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERREGIONEXTPROC) (GLenum region);
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height, GLint xDest, GLint yDest);
+typedef GLuint (GLAPIENTRY * PFNGLNEWBUFFERREGIONEXTPROC) (GLenum region);
+typedef void (GLAPIENTRY * PFNGLREADBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define glBufferRegionEnabledEXT GLEW_GET_FUN(__glewBufferRegionEnabledEXT)
+#define glDeleteBufferRegionEXT GLEW_GET_FUN(__glewDeleteBufferRegionEXT)
+#define glDrawBufferRegionEXT GLEW_GET_FUN(__glewDrawBufferRegionEXT)
+#define glNewBufferRegionEXT GLEW_GET_FUN(__glewNewBufferRegionEXT)
+#define glReadBufferRegionEXT GLEW_GET_FUN(__glewReadBufferRegionEXT)
+
+#define GLEW_KTX_buffer_region GLEW_GET_VAR(__GLEW_KTX_buffer_region)
+
+#endif /* GL_KTX_buffer_region */
+
+/* -------------------------- GL_MESA_pack_invert -------------------------- */
+
+#ifndef GL_MESA_pack_invert
+#define GL_MESA_pack_invert 1
+
+#define GL_PACK_INVERT_MESA 0x8758
+
+#define GLEW_MESA_pack_invert GLEW_GET_VAR(__GLEW_MESA_pack_invert)
+
+#endif /* GL_MESA_pack_invert */
+
+/* ------------------------- GL_MESA_resize_buffers ------------------------ */
+
+#ifndef GL_MESA_resize_buffers
+#define GL_MESA_resize_buffers 1
+
+typedef void (GLAPIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void);
+
+#define glResizeBuffersMESA GLEW_GET_FUN(__glewResizeBuffersMESA)
+
+#define GLEW_MESA_resize_buffers GLEW_GET_VAR(__GLEW_MESA_resize_buffers)
+
+#endif /* GL_MESA_resize_buffers */
+
+/* --------------------------- GL_MESA_window_pos -------------------------- */
+
+#ifndef GL_MESA_window_pos
+#define GL_MESA_window_pos 1
+
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p);
+
+#define glWindowPos2dMESA GLEW_GET_FUN(__glewWindowPos2dMESA)
+#define glWindowPos2dvMESA GLEW_GET_FUN(__glewWindowPos2dvMESA)
+#define glWindowPos2fMESA GLEW_GET_FUN(__glewWindowPos2fMESA)
+#define glWindowPos2fvMESA GLEW_GET_FUN(__glewWindowPos2fvMESA)
+#define glWindowPos2iMESA GLEW_GET_FUN(__glewWindowPos2iMESA)
+#define glWindowPos2ivMESA GLEW_GET_FUN(__glewWindowPos2ivMESA)
+#define glWindowPos2sMESA GLEW_GET_FUN(__glewWindowPos2sMESA)
+#define glWindowPos2svMESA GLEW_GET_FUN(__glewWindowPos2svMESA)
+#define glWindowPos3dMESA GLEW_GET_FUN(__glewWindowPos3dMESA)
+#define glWindowPos3dvMESA GLEW_GET_FUN(__glewWindowPos3dvMESA)
+#define glWindowPos3fMESA GLEW_GET_FUN(__glewWindowPos3fMESA)
+#define glWindowPos3fvMESA GLEW_GET_FUN(__glewWindowPos3fvMESA)
+#define glWindowPos3iMESA GLEW_GET_FUN(__glewWindowPos3iMESA)
+#define glWindowPos3ivMESA GLEW_GET_FUN(__glewWindowPos3ivMESA)
+#define glWindowPos3sMESA GLEW_GET_FUN(__glewWindowPos3sMESA)
+#define glWindowPos3svMESA GLEW_GET_FUN(__glewWindowPos3svMESA)
+#define glWindowPos4dMESA GLEW_GET_FUN(__glewWindowPos4dMESA)
+#define glWindowPos4dvMESA GLEW_GET_FUN(__glewWindowPos4dvMESA)
+#define glWindowPos4fMESA GLEW_GET_FUN(__glewWindowPos4fMESA)
+#define glWindowPos4fvMESA GLEW_GET_FUN(__glewWindowPos4fvMESA)
+#define glWindowPos4iMESA GLEW_GET_FUN(__glewWindowPos4iMESA)
+#define glWindowPos4ivMESA GLEW_GET_FUN(__glewWindowPos4ivMESA)
+#define glWindowPos4sMESA GLEW_GET_FUN(__glewWindowPos4sMESA)
+#define glWindowPos4svMESA GLEW_GET_FUN(__glewWindowPos4svMESA)
+
+#define GLEW_MESA_window_pos GLEW_GET_VAR(__GLEW_MESA_window_pos)
+
+#endif /* GL_MESA_window_pos */
+
+/* ------------------------- GL_MESA_ycbcr_texture ------------------------- */
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_MESA_ycbcr_texture 1
+
+#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB
+#define GL_YCBCR_MESA 0x8757
+
+#define GLEW_MESA_ycbcr_texture GLEW_GET_VAR(__GLEW_MESA_ycbcr_texture)
+
+#endif /* GL_MESA_ycbcr_texture */
+
+/* --------------------------- GL_NV_blend_square -------------------------- */
+
+#ifndef GL_NV_blend_square
+#define GL_NV_blend_square 1
+
+#define GLEW_NV_blend_square GLEW_GET_VAR(__GLEW_NV_blend_square)
+
+#endif /* GL_NV_blend_square */
+
+/* ----------------------- GL_NV_copy_depth_to_color ----------------------- */
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_NV_copy_depth_to_color 1
+
+#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
+#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F
+
+#define GLEW_NV_copy_depth_to_color GLEW_GET_VAR(__GLEW_NV_copy_depth_to_color)
+
+#endif /* GL_NV_copy_depth_to_color */
+
+/* --------------------------- GL_NV_depth_clamp --------------------------- */
+
+#ifndef GL_NV_depth_clamp
+#define GL_NV_depth_clamp 1
+
+#define GL_DEPTH_CLAMP_NV 0x864F
+
+#define GLEW_NV_depth_clamp GLEW_GET_VAR(__GLEW_NV_depth_clamp)
+
+#endif /* GL_NV_depth_clamp */
+
+/* ---------------------------- GL_NV_evaluators --------------------------- */
+
+#ifndef GL_NV_evaluators
+#define GL_NV_evaluators 1
+
+#define GL_EVAL_2D_NV 0x86C0
+#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1
+#define GL_MAP_TESSELLATION_NV 0x86C2
+#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3
+#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4
+#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5
+#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6
+#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7
+#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8
+#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9
+#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA
+#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB
+#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC
+#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD
+#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE
+#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF
+#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0
+#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1
+#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2
+#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3
+#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4
+#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5
+#define GL_MAX_MAP_TESSELLATION_NV 0x86D6
+#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7
+
+typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void* points);
+typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void* points);
+typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params);
+
+#define glEvalMapsNV GLEW_GET_FUN(__glewEvalMapsNV)
+#define glGetMapAttribParameterfvNV GLEW_GET_FUN(__glewGetMapAttribParameterfvNV)
+#define glGetMapAttribParameterivNV GLEW_GET_FUN(__glewGetMapAttribParameterivNV)
+#define glGetMapControlPointsNV GLEW_GET_FUN(__glewGetMapControlPointsNV)
+#define glGetMapParameterfvNV GLEW_GET_FUN(__glewGetMapParameterfvNV)
+#define glGetMapParameterivNV GLEW_GET_FUN(__glewGetMapParameterivNV)
+#define glMapControlPointsNV GLEW_GET_FUN(__glewMapControlPointsNV)
+#define glMapParameterfvNV GLEW_GET_FUN(__glewMapParameterfvNV)
+#define glMapParameterivNV GLEW_GET_FUN(__glewMapParameterivNV)
+
+#define GLEW_NV_evaluators GLEW_GET_VAR(__GLEW_NV_evaluators)
+
+#endif /* GL_NV_evaluators */
+
+/* ------------------------------ GL_NV_fence ------------------------------ */
+
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+
+typedef void (GLAPIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFENCENVPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence);
+
+#define glDeleteFencesNV GLEW_GET_FUN(__glewDeleteFencesNV)
+#define glFinishFenceNV GLEW_GET_FUN(__glewFinishFenceNV)
+#define glGenFencesNV GLEW_GET_FUN(__glewGenFencesNV)
+#define glGetFenceivNV GLEW_GET_FUN(__glewGetFenceivNV)
+#define glIsFenceNV GLEW_GET_FUN(__glewIsFenceNV)
+#define glSetFenceNV GLEW_GET_FUN(__glewSetFenceNV)
+#define glTestFenceNV GLEW_GET_FUN(__glewTestFenceNV)
+
+#define GLEW_NV_fence GLEW_GET_VAR(__GLEW_NV_fence)
+
+#endif /* GL_NV_fence */
+
+/* --------------------------- GL_NV_float_buffer -------------------------- */
+
+#ifndef GL_NV_float_buffer
+#define GL_NV_float_buffer 1
+
+#define GL_FLOAT_R_NV 0x8880
+#define GL_FLOAT_RG_NV 0x8881
+#define GL_FLOAT_RGB_NV 0x8882
+#define GL_FLOAT_RGBA_NV 0x8883
+#define GL_FLOAT_R16_NV 0x8884
+#define GL_FLOAT_R32_NV 0x8885
+#define GL_FLOAT_RG16_NV 0x8886
+#define GL_FLOAT_RG32_NV 0x8887
+#define GL_FLOAT_RGB16_NV 0x8888
+#define GL_FLOAT_RGB32_NV 0x8889
+#define GL_FLOAT_RGBA16_NV 0x888A
+#define GL_FLOAT_RGBA32_NV 0x888B
+#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C
+#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D
+#define GL_FLOAT_RGBA_MODE_NV 0x888E
+
+#define GLEW_NV_float_buffer GLEW_GET_VAR(__GLEW_NV_float_buffer)
+
+#endif /* GL_NV_float_buffer */
+
+/* --------------------------- GL_NV_fog_distance -------------------------- */
+
+#ifndef GL_NV_fog_distance
+#define GL_NV_fog_distance 1
+
+#define GL_FOG_DISTANCE_MODE_NV 0x855A
+#define GL_EYE_RADIAL_NV 0x855B
+#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C
+
+#define GLEW_NV_fog_distance GLEW_GET_VAR(__GLEW_NV_fog_distance)
+
+#endif /* GL_NV_fog_distance */
+
+/* ------------------------- GL_NV_fragment_program ------------------------ */
+
+#ifndef GL_NV_fragment_program
+#define GL_NV_fragment_program 1
+
+#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#define GL_FRAGMENT_PROGRAM_NV 0x8870
+#define GL_MAX_TEXTURE_COORDS_NV 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872
+#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873
+#define GL_PROGRAM_ERROR_STRING_NV 0x8874
+
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble *params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLdouble v[]);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLfloat v[]);
+
+#define glGetProgramNamedParameterdvNV GLEW_GET_FUN(__glewGetProgramNamedParameterdvNV)
+#define glGetProgramNamedParameterfvNV GLEW_GET_FUN(__glewGetProgramNamedParameterfvNV)
+#define glProgramNamedParameter4dNV GLEW_GET_FUN(__glewProgramNamedParameter4dNV)
+#define glProgramNamedParameter4dvNV GLEW_GET_FUN(__glewProgramNamedParameter4dvNV)
+#define glProgramNamedParameter4fNV GLEW_GET_FUN(__glewProgramNamedParameter4fNV)
+#define glProgramNamedParameter4fvNV GLEW_GET_FUN(__glewProgramNamedParameter4fvNV)
+
+#define GLEW_NV_fragment_program GLEW_GET_VAR(__GLEW_NV_fragment_program)
+
+#endif /* GL_NV_fragment_program */
+
+/* ------------------------ GL_NV_fragment_program2 ------------------------ */
+
+#ifndef GL_NV_fragment_program2
+#define GL_NV_fragment_program2 1
+
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6
+#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7
+#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8
+
+#define GLEW_NV_fragment_program2 GLEW_GET_VAR(__GLEW_NV_fragment_program2)
+
+#endif /* GL_NV_fragment_program2 */
+
+/* --------------------- GL_NV_fragment_program_option --------------------- */
+
+#ifndef GL_NV_fragment_program_option
+#define GL_NV_fragment_program_option 1
+
+#define GLEW_NV_fragment_program_option GLEW_GET_VAR(__GLEW_NV_fragment_program_option)
+
+#endif /* GL_NV_fragment_program_option */
+
+/* ---------------------------- GL_NV_half_float --------------------------- */
+
+#ifndef GL_NV_half_float
+#define GL_NV_half_float 1
+
+#define GL_HALF_FLOAT_NV 0x140B
+
+typedef unsigned short GLhalf;
+
+typedef void (GLAPIENTRY * PFNGLCOLOR3HNVPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4HNVPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+typedef void (GLAPIENTRY * PFNGLCOLOR4HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDHNVPROC) (GLuint fog);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDHVNVPROC) (const GLuint* fog);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLuint s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLuint s, GLuint t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLuint s, GLuint t, GLuint r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLuint s, GLuint t, GLuint r, GLuint q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLNORMAL3HNVPROC) (GLuint nx, GLuint ny, GLuint nz);
+typedef void (GLAPIENTRY * PFNGLNORMAL3HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HNVPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1HNVPROC) (GLuint s);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2HNVPROC) (GLuint s, GLuint t);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3HNVPROC) (GLuint s, GLuint t, GLuint r);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4HNVPROC) (GLuint s, GLuint t, GLuint r, GLuint q);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEX2HNVPROC) (GLuint x, GLuint y);
+typedef void (GLAPIENTRY * PFNGLVERTEX2HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEX3HNVPROC) (GLuint x, GLuint y, GLuint z);
+typedef void (GLAPIENTRY * PFNGLVERTEX3HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEX4HNVPROC) (GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLVERTEX4HVNVPROC) (const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLuint x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHNVPROC) (GLuint weight);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLuint* weight);
+
+#define glColor3hNV GLEW_GET_FUN(__glewColor3hNV)
+#define glColor3hvNV GLEW_GET_FUN(__glewColor3hvNV)
+#define glColor4hNV GLEW_GET_FUN(__glewColor4hNV)
+#define glColor4hvNV GLEW_GET_FUN(__glewColor4hvNV)
+#define glFogCoordhNV GLEW_GET_FUN(__glewFogCoordhNV)
+#define glFogCoordhvNV GLEW_GET_FUN(__glewFogCoordhvNV)
+#define glMultiTexCoord1hNV GLEW_GET_FUN(__glewMultiTexCoord1hNV)
+#define glMultiTexCoord1hvNV GLEW_GET_FUN(__glewMultiTexCoord1hvNV)
+#define glMultiTexCoord2hNV GLEW_GET_FUN(__glewMultiTexCoord2hNV)
+#define glMultiTexCoord2hvNV GLEW_GET_FUN(__glewMultiTexCoord2hvNV)
+#define glMultiTexCoord3hNV GLEW_GET_FUN(__glewMultiTexCoord3hNV)
+#define glMultiTexCoord3hvNV GLEW_GET_FUN(__glewMultiTexCoord3hvNV)
+#define glMultiTexCoord4hNV GLEW_GET_FUN(__glewMultiTexCoord4hNV)
+#define glMultiTexCoord4hvNV GLEW_GET_FUN(__glewMultiTexCoord4hvNV)
+#define glNormal3hNV GLEW_GET_FUN(__glewNormal3hNV)
+#define glNormal3hvNV GLEW_GET_FUN(__glewNormal3hvNV)
+#define glSecondaryColor3hNV GLEW_GET_FUN(__glewSecondaryColor3hNV)
+#define glSecondaryColor3hvNV GLEW_GET_FUN(__glewSecondaryColor3hvNV)
+#define glTexCoord1hNV GLEW_GET_FUN(__glewTexCoord1hNV)
+#define glTexCoord1hvNV GLEW_GET_FUN(__glewTexCoord1hvNV)
+#define glTexCoord2hNV GLEW_GET_FUN(__glewTexCoord2hNV)
+#define glTexCoord2hvNV GLEW_GET_FUN(__glewTexCoord2hvNV)
+#define glTexCoord3hNV GLEW_GET_FUN(__glewTexCoord3hNV)
+#define glTexCoord3hvNV GLEW_GET_FUN(__glewTexCoord3hvNV)
+#define glTexCoord4hNV GLEW_GET_FUN(__glewTexCoord4hNV)
+#define glTexCoord4hvNV GLEW_GET_FUN(__glewTexCoord4hvNV)
+#define glVertex2hNV GLEW_GET_FUN(__glewVertex2hNV)
+#define glVertex2hvNV GLEW_GET_FUN(__glewVertex2hvNV)
+#define glVertex3hNV GLEW_GET_FUN(__glewVertex3hNV)
+#define glVertex3hvNV GLEW_GET_FUN(__glewVertex3hvNV)
+#define glVertex4hNV GLEW_GET_FUN(__glewVertex4hNV)
+#define glVertex4hvNV GLEW_GET_FUN(__glewVertex4hvNV)
+#define glVertexAttrib1hNV GLEW_GET_FUN(__glewVertexAttrib1hNV)
+#define glVertexAttrib1hvNV GLEW_GET_FUN(__glewVertexAttrib1hvNV)
+#define glVertexAttrib2hNV GLEW_GET_FUN(__glewVertexAttrib2hNV)
+#define glVertexAttrib2hvNV GLEW_GET_FUN(__glewVertexAttrib2hvNV)
+#define glVertexAttrib3hNV GLEW_GET_FUN(__glewVertexAttrib3hNV)
+#define glVertexAttrib3hvNV GLEW_GET_FUN(__glewVertexAttrib3hvNV)
+#define glVertexAttrib4hNV GLEW_GET_FUN(__glewVertexAttrib4hNV)
+#define glVertexAttrib4hvNV GLEW_GET_FUN(__glewVertexAttrib4hvNV)
+#define glVertexAttribs1hvNV GLEW_GET_FUN(__glewVertexAttribs1hvNV)
+#define glVertexAttribs2hvNV GLEW_GET_FUN(__glewVertexAttribs2hvNV)
+#define glVertexAttribs3hvNV GLEW_GET_FUN(__glewVertexAttribs3hvNV)
+#define glVertexAttribs4hvNV GLEW_GET_FUN(__glewVertexAttribs4hvNV)
+#define glVertexWeighthNV GLEW_GET_FUN(__glewVertexWeighthNV)
+#define glVertexWeighthvNV GLEW_GET_FUN(__glewVertexWeighthvNV)
+
+#define GLEW_NV_half_float GLEW_GET_VAR(__GLEW_NV_half_float)
+
+#endif /* GL_NV_half_float */
+
+/* ------------------------ GL_NV_light_max_exponent ----------------------- */
+
+#ifndef GL_NV_light_max_exponent
+#define GL_NV_light_max_exponent 1
+
+#define GL_MAX_SHININESS_NV 0x8504
+#define GL_MAX_SPOT_EXPONENT_NV 0x8505
+
+#define GLEW_NV_light_max_exponent GLEW_GET_VAR(__GLEW_NV_light_max_exponent)
+
+#endif /* GL_NV_light_max_exponent */
+
+/* --------------------- GL_NV_multisample_filter_hint --------------------- */
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_NV_multisample_filter_hint 1
+
+#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534
+
+#define GLEW_NV_multisample_filter_hint GLEW_GET_VAR(__GLEW_NV_multisample_filter_hint)
+
+#endif /* GL_NV_multisample_filter_hint */
+
+/* ------------------------- GL_NV_occlusion_query ------------------------- */
+
+#ifndef GL_NV_occlusion_query
+#define GL_NV_occlusion_query 1
+
+#define GL_PIXEL_COUNTER_BITS_NV 0x8864
+#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865
+#define GL_PIXEL_COUNT_NV 0x8866
+#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867
+
+typedef void (GLAPIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);
+
+#define glBeginOcclusionQueryNV GLEW_GET_FUN(__glewBeginOcclusionQueryNV)
+#define glDeleteOcclusionQueriesNV GLEW_GET_FUN(__glewDeleteOcclusionQueriesNV)
+#define glEndOcclusionQueryNV GLEW_GET_FUN(__glewEndOcclusionQueryNV)
+#define glGenOcclusionQueriesNV GLEW_GET_FUN(__glewGenOcclusionQueriesNV)
+#define glGetOcclusionQueryivNV GLEW_GET_FUN(__glewGetOcclusionQueryivNV)
+#define glGetOcclusionQueryuivNV GLEW_GET_FUN(__glewGetOcclusionQueryuivNV)
+#define glIsOcclusionQueryNV GLEW_GET_FUN(__glewIsOcclusionQueryNV)
+
+#define GLEW_NV_occlusion_query GLEW_GET_VAR(__GLEW_NV_occlusion_query)
+
+#endif /* GL_NV_occlusion_query */
+
+/* ----------------------- GL_NV_packed_depth_stencil ---------------------- */
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_NV_packed_depth_stencil 1
+
+#define GL_DEPTH_STENCIL_NV 0x84F9
+#define GL_UNSIGNED_INT_24_8_NV 0x84FA
+
+#define GLEW_NV_packed_depth_stencil GLEW_GET_VAR(__GLEW_NV_packed_depth_stencil)
+
+#endif /* GL_NV_packed_depth_stencil */
+
+/* ------------------------- GL_NV_pixel_data_range ------------------------ */
+
+#ifndef GL_NV_pixel_data_range
+#define GL_NV_pixel_data_range 1
+
+#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
+#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879
+#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+
+typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void* pointer);
+
+#define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV)
+#define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV)
+
+#define GLEW_NV_pixel_data_range GLEW_GET_VAR(__GLEW_NV_pixel_data_range)
+
+#endif /* GL_NV_pixel_data_range */
+
+/* --------------------------- GL_NV_point_sprite -------------------------- */
+
+#ifndef GL_NV_point_sprite
+#define GL_NV_point_sprite 1
+
+#define GL_POINT_SPRITE_NV 0x8861
+#define GL_COORD_REPLACE_NV 0x8862
+#define GL_POINT_SPRITE_R_MODE_NV 0x8863
+
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint* params);
+
+#define glPointParameteriNV GLEW_GET_FUN(__glewPointParameteriNV)
+#define glPointParameterivNV GLEW_GET_FUN(__glewPointParameterivNV)
+
+#define GLEW_NV_point_sprite GLEW_GET_VAR(__GLEW_NV_point_sprite)
+
+#endif /* GL_NV_point_sprite */
+
+/* ------------------------ GL_NV_primitive_restart ------------------------ */
+
+#ifndef GL_NV_primitive_restart
+#define GL_NV_primitive_restart 1
+
+#define GL_PRIMITIVE_RESTART_NV 0x8558
+#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559
+
+typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTNVPROC) (void);
+
+#define glPrimitiveRestartIndexNV GLEW_GET_FUN(__glewPrimitiveRestartIndexNV)
+#define glPrimitiveRestartNV GLEW_GET_FUN(__glewPrimitiveRestartNV)
+
+#define GLEW_NV_primitive_restart GLEW_GET_VAR(__GLEW_NV_primitive_restart)
+
+#endif /* GL_NV_primitive_restart */
+
+/* ------------------------ GL_NV_register_combiners ----------------------- */
+
+#ifndef GL_NV_register_combiners
+#define GL_NV_register_combiners 1
+
+#define GL_REGISTER_COMBINERS_NV 0x8522
+#define GL_VARIABLE_A_NV 0x8523
+#define GL_VARIABLE_B_NV 0x8524
+#define GL_VARIABLE_C_NV 0x8525
+#define GL_VARIABLE_D_NV 0x8526
+#define GL_VARIABLE_E_NV 0x8527
+#define GL_VARIABLE_F_NV 0x8528
+#define GL_VARIABLE_G_NV 0x8529
+#define GL_CONSTANT_COLOR0_NV 0x852A
+#define GL_CONSTANT_COLOR1_NV 0x852B
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_SPARE0_NV 0x852E
+#define GL_SPARE1_NV 0x852F
+#define GL_DISCARD_NV 0x8530
+#define GL_E_TIMES_F_NV 0x8531
+#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define GL_UNSIGNED_IDENTITY_NV 0x8536
+#define GL_UNSIGNED_INVERT_NV 0x8537
+#define GL_EXPAND_NORMAL_NV 0x8538
+#define GL_EXPAND_NEGATE_NV 0x8539
+#define GL_HALF_BIAS_NORMAL_NV 0x853A
+#define GL_HALF_BIAS_NEGATE_NV 0x853B
+#define GL_SIGNED_IDENTITY_NV 0x853C
+#define GL_SIGNED_NEGATE_NV 0x853D
+#define GL_SCALE_BY_TWO_NV 0x853E
+#define GL_SCALE_BY_FOUR_NV 0x853F
+#define GL_SCALE_BY_ONE_HALF_NV 0x8540
+#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541
+#define GL_COMBINER_INPUT_NV 0x8542
+#define GL_COMBINER_MAPPING_NV 0x8543
+#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544
+#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545
+#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546
+#define GL_COMBINER_MUX_SUM_NV 0x8547
+#define GL_COMBINER_SCALE_NV 0x8548
+#define GL_COMBINER_BIAS_NV 0x8549
+#define GL_COMBINER_AB_OUTPUT_NV 0x854A
+#define GL_COMBINER_CD_OUTPUT_NV 0x854B
+#define GL_COMBINER_SUM_OUTPUT_NV 0x854C
+#define GL_MAX_GENERAL_COMBINERS_NV 0x854D
+#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
+#define GL_COLOR_SUM_CLAMP_NV 0x854F
+#define GL_COMBINER0_NV 0x8550
+#define GL_COMBINER1_NV 0x8551
+#define GL_COMBINER2_NV 0x8552
+#define GL_COMBINER3_NV 0x8553
+#define GL_COMBINER4_NV 0x8554
+#define GL_COMBINER5_NV 0x8555
+#define GL_COMBINER6_NV 0x8556
+#define GL_COMBINER7_NV 0x8557
+
+typedef void (GLAPIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (GLAPIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint* params);
+
+#define glCombinerInputNV GLEW_GET_FUN(__glewCombinerInputNV)
+#define glCombinerOutputNV GLEW_GET_FUN(__glewCombinerOutputNV)
+#define glCombinerParameterfNV GLEW_GET_FUN(__glewCombinerParameterfNV)
+#define glCombinerParameterfvNV GLEW_GET_FUN(__glewCombinerParameterfvNV)
+#define glCombinerParameteriNV GLEW_GET_FUN(__glewCombinerParameteriNV)
+#define glCombinerParameterivNV GLEW_GET_FUN(__glewCombinerParameterivNV)
+#define glFinalCombinerInputNV GLEW_GET_FUN(__glewFinalCombinerInputNV)
+#define glGetCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetCombinerInputParameterfvNV)
+#define glGetCombinerInputParameterivNV GLEW_GET_FUN(__glewGetCombinerInputParameterivNV)
+#define glGetCombinerOutputParameterfvNV GLEW_GET_FUN(__glewGetCombinerOutputParameterfvNV)
+#define glGetCombinerOutputParameterivNV GLEW_GET_FUN(__glewGetCombinerOutputParameterivNV)
+#define glGetFinalCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterfvNV)
+#define glGetFinalCombinerInputParameterivNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterivNV)
+
+#define GLEW_NV_register_combiners GLEW_GET_VAR(__GLEW_NV_register_combiners)
+
+#endif /* GL_NV_register_combiners */
+
+/* ----------------------- GL_NV_register_combiners2 ----------------------- */
+
+#ifndef GL_NV_register_combiners2
+#define GL_NV_register_combiners2 1
+
+#define GL_PER_STAGE_CONSTANTS_NV 0x8535
+
+typedef void (GLAPIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat* params);
+
+#define glCombinerStageParameterfvNV GLEW_GET_FUN(__glewCombinerStageParameterfvNV)
+#define glGetCombinerStageParameterfvNV GLEW_GET_FUN(__glewGetCombinerStageParameterfvNV)
+
+#define GLEW_NV_register_combiners2 GLEW_GET_VAR(__GLEW_NV_register_combiners2)
+
+#endif /* GL_NV_register_combiners2 */
+
+/* -------------------------- GL_NV_texgen_emboss -------------------------- */
+
+#ifndef GL_NV_texgen_emboss
+#define GL_NV_texgen_emboss 1
+
+#define GL_EMBOSS_LIGHT_NV 0x855D
+#define GL_EMBOSS_CONSTANT_NV 0x855E
+#define GL_EMBOSS_MAP_NV 0x855F
+
+#define GLEW_NV_texgen_emboss GLEW_GET_VAR(__GLEW_NV_texgen_emboss)
+
+#endif /* GL_NV_texgen_emboss */
+
+/* ------------------------ GL_NV_texgen_reflection ------------------------ */
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NV_texgen_reflection 1
+
+#define GL_NORMAL_MAP_NV 0x8511
+#define GL_REFLECTION_MAP_NV 0x8512
+
+#define GLEW_NV_texgen_reflection GLEW_GET_VAR(__GLEW_NV_texgen_reflection)
+
+#endif /* GL_NV_texgen_reflection */
+
+/* --------------------- GL_NV_texture_compression_vtc --------------------- */
+
+#ifndef GL_NV_texture_compression_vtc
+#define GL_NV_texture_compression_vtc 1
+
+#define GLEW_NV_texture_compression_vtc GLEW_GET_VAR(__GLEW_NV_texture_compression_vtc)
+
+#endif /* GL_NV_texture_compression_vtc */
+
+/* ----------------------- GL_NV_texture_env_combine4 ---------------------- */
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_NV_texture_env_combine4 1
+
+#define GL_COMBINE4_NV 0x8503
+#define GL_SOURCE3_RGB_NV 0x8583
+#define GL_SOURCE3_ALPHA_NV 0x858B
+#define GL_OPERAND3_RGB_NV 0x8593
+#define GL_OPERAND3_ALPHA_NV 0x859B
+
+#define GLEW_NV_texture_env_combine4 GLEW_GET_VAR(__GLEW_NV_texture_env_combine4)
+
+#endif /* GL_NV_texture_env_combine4 */
+
+/* ---------------------- GL_NV_texture_expand_normal ---------------------- */
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_NV_texture_expand_normal 1
+
+#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F
+
+#define GLEW_NV_texture_expand_normal GLEW_GET_VAR(__GLEW_NV_texture_expand_normal)
+
+#endif /* GL_NV_texture_expand_normal */
+
+/* ------------------------ GL_NV_texture_rectangle ------------------------ */
+
+#ifndef GL_NV_texture_rectangle
+#define GL_NV_texture_rectangle 1
+
+#define GL_TEXTURE_RECTANGLE_NV 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8
+
+#define GLEW_NV_texture_rectangle GLEW_GET_VAR(__GLEW_NV_texture_rectangle)
+
+#endif /* GL_NV_texture_rectangle */
+
+/* -------------------------- GL_NV_texture_shader ------------------------- */
+
+#ifndef GL_NV_texture_shader
+#define GL_NV_texture_shader 1
+
+#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C
+#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_SHADER_CONSISTENT_NV 0x86DD
+#define GL_TEXTURE_SHADER_NV 0x86DE
+#define GL_SHADER_OPERATION_NV 0x86DF
+#define GL_CULL_MODES_NV 0x86E0
+#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3
+#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4
+#define GL_CONST_EYE_NV 0x86E5
+#define GL_PASS_THROUGH_NV 0x86E6
+#define GL_CULL_FRAGMENT_NV 0x86E7
+#define GL_OFFSET_TEXTURE_2D_NV 0x86E8
+#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9
+#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA
+#define GL_DOT_PRODUCT_NV 0x86EC
+#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED
+#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE
+#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define GL_HI_SCALE_NV 0x870E
+#define GL_LO_SCALE_NV 0x870F
+#define GL_DS_SCALE_NV 0x8710
+#define GL_DT_SCALE_NV 0x8711
+#define GL_MAGNITUDE_SCALE_NV 0x8712
+#define GL_VIBRANCE_SCALE_NV 0x8713
+#define GL_HI_BIAS_NV 0x8714
+#define GL_LO_BIAS_NV 0x8715
+#define GL_DS_BIAS_NV 0x8716
+#define GL_DT_BIAS_NV 0x8717
+#define GL_MAGNITUDE_BIAS_NV 0x8718
+#define GL_VIBRANCE_BIAS_NV 0x8719
+#define GL_TEXTURE_BORDER_VALUES_NV 0x871A
+#define GL_TEXTURE_HI_SIZE_NV 0x871B
+#define GL_TEXTURE_LO_SIZE_NV 0x871C
+#define GL_TEXTURE_DS_SIZE_NV 0x871D
+#define GL_TEXTURE_DT_SIZE_NV 0x871E
+#define GL_TEXTURE_MAG_SIZE_NV 0x871F
+
+#define GLEW_NV_texture_shader GLEW_GET_VAR(__GLEW_NV_texture_shader)
+
+#endif /* GL_NV_texture_shader */
+
+/* ------------------------- GL_NV_texture_shader2 ------------------------- */
+
+#ifndef GL_NV_texture_shader2
+#define GL_NV_texture_shader2 1
+
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+
+#define GLEW_NV_texture_shader2 GLEW_GET_VAR(__GLEW_NV_texture_shader2)
+
+#endif /* GL_NV_texture_shader2 */
+
+/* ------------------------- GL_NV_texture_shader3 ------------------------- */
+
+#ifndef GL_NV_texture_shader3
+#define GL_NV_texture_shader3 1
+
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854
+#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858
+#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859
+#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B
+#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C
+#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define GL_HILO8_NV 0x885E
+#define GL_SIGNED_HILO8_NV 0x885F
+#define GL_FORCE_BLUE_TO_ONE_NV 0x8860
+
+#define GLEW_NV_texture_shader3 GLEW_GET_VAR(__GLEW_NV_texture_shader3)
+
+#endif /* GL_NV_texture_shader3 */
+
+/* ------------------------ GL_NV_vertex_array_range ----------------------- */
+
+#ifndef GL_NV_vertex_array_range
+#define GL_NV_vertex_array_range 1
+
+#define GL_VERTEX_ARRAY_RANGE_NV 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E
+#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521
+
+typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void* pointer);
+
+#define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV)
+#define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV)
+
+#define GLEW_NV_vertex_array_range GLEW_GET_VAR(__GLEW_NV_vertex_array_range)
+
+#endif /* GL_NV_vertex_array_range */
+
+/* ----------------------- GL_NV_vertex_array_range2 ----------------------- */
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_NV_vertex_array_range2 1
+
+#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+
+#define GLEW_NV_vertex_array_range2 GLEW_GET_VAR(__GLEW_NV_vertex_array_range2)
+
+#endif /* GL_NV_vertex_array_range2 */
+
+/* -------------------------- GL_NV_vertex_program ------------------------- */
+
+#ifndef GL_NV_vertex_program
+#define GL_NV_vertex_program 1
+
+#define GL_VERTEX_PROGRAM_NV 0x8620
+#define GL_VERTEX_STATE_PROGRAM_NV 0x8621
+#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623
+#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624
+#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625
+#define GL_CURRENT_ATTRIB_NV 0x8626
+#define GL_PROGRAM_LENGTH_NV 0x8627
+#define GL_PROGRAM_STRING_NV 0x8628
+#define GL_MODELVIEW_PROJECTION_NV 0x8629
+#define GL_IDENTITY_NV 0x862A
+#define GL_INVERSE_NV 0x862B
+#define GL_TRANSPOSE_NV 0x862C
+#define GL_INVERSE_TRANSPOSE_NV 0x862D
+#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define GL_MAX_TRACK_MATRICES_NV 0x862F
+#define GL_MATRIX0_NV 0x8630
+#define GL_MATRIX1_NV 0x8631
+#define GL_MATRIX2_NV 0x8632
+#define GL_MATRIX3_NV 0x8633
+#define GL_MATRIX4_NV 0x8634
+#define GL_MATRIX5_NV 0x8635
+#define GL_MATRIX6_NV 0x8636
+#define GL_MATRIX7_NV 0x8637
+#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640
+#define GL_CURRENT_MATRIX_NV 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643
+#define GL_PROGRAM_PARAMETER_NV 0x8644
+#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645
+#define GL_PROGRAM_TARGET_NV 0x8646
+#define GL_PROGRAM_RESIDENT_NV 0x8647
+#define GL_TRACK_MATRIX_NV 0x8648
+#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649
+#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A
+#define GL_PROGRAM_ERROR_POSITION_NV 0x864B
+#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650
+#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651
+#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652
+#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653
+#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654
+#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655
+#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656
+#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657
+#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658
+#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659
+#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A
+#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B
+#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C
+#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D
+#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E
+#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F
+#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660
+#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661
+#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662
+#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663
+#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664
+#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665
+#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666
+#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667
+#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668
+#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669
+#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A
+#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B
+#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C
+#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D
+#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E
+#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F
+#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670
+#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671
+#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672
+#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673
+#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674
+#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675
+#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676
+#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677
+#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678
+#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679
+#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A
+#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B
+#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C
+#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D
+#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E
+#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F
+
+typedef GLboolean (GLAPIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint* ids, GLboolean *residences);
+typedef void (GLAPIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte* program);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid** pointer);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte* program);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint num, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint num, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei n, const GLubyte* v);
+
+#define glAreProgramsResidentNV GLEW_GET_FUN(__glewAreProgramsResidentNV)
+#define glBindProgramNV GLEW_GET_FUN(__glewBindProgramNV)
+#define glDeleteProgramsNV GLEW_GET_FUN(__glewDeleteProgramsNV)
+#define glExecuteProgramNV GLEW_GET_FUN(__glewExecuteProgramNV)
+#define glGenProgramsNV GLEW_GET_FUN(__glewGenProgramsNV)
+#define glGetProgramParameterdvNV GLEW_GET_FUN(__glewGetProgramParameterdvNV)
+#define glGetProgramParameterfvNV GLEW_GET_FUN(__glewGetProgramParameterfvNV)
+#define glGetProgramStringNV GLEW_GET_FUN(__glewGetProgramStringNV)
+#define glGetProgramivNV GLEW_GET_FUN(__glewGetProgramivNV)
+#define glGetTrackMatrixivNV GLEW_GET_FUN(__glewGetTrackMatrixivNV)
+#define glGetVertexAttribPointervNV GLEW_GET_FUN(__glewGetVertexAttribPointervNV)
+#define glGetVertexAttribdvNV GLEW_GET_FUN(__glewGetVertexAttribdvNV)
+#define glGetVertexAttribfvNV GLEW_GET_FUN(__glewGetVertexAttribfvNV)
+#define glGetVertexAttribivNV GLEW_GET_FUN(__glewGetVertexAttribivNV)
+#define glIsProgramNV GLEW_GET_FUN(__glewIsProgramNV)
+#define glLoadProgramNV GLEW_GET_FUN(__glewLoadProgramNV)
+#define glProgramParameter4dNV GLEW_GET_FUN(__glewProgramParameter4dNV)
+#define glProgramParameter4dvNV GLEW_GET_FUN(__glewProgramParameter4dvNV)
+#define glProgramParameter4fNV GLEW_GET_FUN(__glewProgramParameter4fNV)
+#define glProgramParameter4fvNV GLEW_GET_FUN(__glewProgramParameter4fvNV)
+#define glProgramParameters4dvNV GLEW_GET_FUN(__glewProgramParameters4dvNV)
+#define glProgramParameters4fvNV GLEW_GET_FUN(__glewProgramParameters4fvNV)
+#define glRequestResidentProgramsNV GLEW_GET_FUN(__glewRequestResidentProgramsNV)
+#define glTrackMatrixNV GLEW_GET_FUN(__glewTrackMatrixNV)
+#define glVertexAttrib1dNV GLEW_GET_FUN(__glewVertexAttrib1dNV)
+#define glVertexAttrib1dvNV GLEW_GET_FUN(__glewVertexAttrib1dvNV)
+#define glVertexAttrib1fNV GLEW_GET_FUN(__glewVertexAttrib1fNV)
+#define glVertexAttrib1fvNV GLEW_GET_FUN(__glewVertexAttrib1fvNV)
+#define glVertexAttrib1sNV GLEW_GET_FUN(__glewVertexAttrib1sNV)
+#define glVertexAttrib1svNV GLEW_GET_FUN(__glewVertexAttrib1svNV)
+#define glVertexAttrib2dNV GLEW_GET_FUN(__glewVertexAttrib2dNV)
+#define glVertexAttrib2dvNV GLEW_GET_FUN(__glewVertexAttrib2dvNV)
+#define glVertexAttrib2fNV GLEW_GET_FUN(__glewVertexAttrib2fNV)
+#define glVertexAttrib2fvNV GLEW_GET_FUN(__glewVertexAttrib2fvNV)
+#define glVertexAttrib2sNV GLEW_GET_FUN(__glewVertexAttrib2sNV)
+#define glVertexAttrib2svNV GLEW_GET_FUN(__glewVertexAttrib2svNV)
+#define glVertexAttrib3dNV GLEW_GET_FUN(__glewVertexAttrib3dNV)
+#define glVertexAttrib3dvNV GLEW_GET_FUN(__glewVertexAttrib3dvNV)
+#define glVertexAttrib3fNV GLEW_GET_FUN(__glewVertexAttrib3fNV)
+#define glVertexAttrib3fvNV GLEW_GET_FUN(__glewVertexAttrib3fvNV)
+#define glVertexAttrib3sNV GLEW_GET_FUN(__glewVertexAttrib3sNV)
+#define glVertexAttrib3svNV GLEW_GET_FUN(__glewVertexAttrib3svNV)
+#define glVertexAttrib4dNV GLEW_GET_FUN(__glewVertexAttrib4dNV)
+#define glVertexAttrib4dvNV GLEW_GET_FUN(__glewVertexAttrib4dvNV)
+#define glVertexAttrib4fNV GLEW_GET_FUN(__glewVertexAttrib4fNV)
+#define glVertexAttrib4fvNV GLEW_GET_FUN(__glewVertexAttrib4fvNV)
+#define glVertexAttrib4sNV GLEW_GET_FUN(__glewVertexAttrib4sNV)
+#define glVertexAttrib4svNV GLEW_GET_FUN(__glewVertexAttrib4svNV)
+#define glVertexAttrib4ubNV GLEW_GET_FUN(__glewVertexAttrib4ubNV)
+#define glVertexAttrib4ubvNV GLEW_GET_FUN(__glewVertexAttrib4ubvNV)
+#define glVertexAttribPointerNV GLEW_GET_FUN(__glewVertexAttribPointerNV)
+#define glVertexAttribs1dvNV GLEW_GET_FUN(__glewVertexAttribs1dvNV)
+#define glVertexAttribs1fvNV GLEW_GET_FUN(__glewVertexAttribs1fvNV)
+#define glVertexAttribs1svNV GLEW_GET_FUN(__glewVertexAttribs1svNV)
+#define glVertexAttribs2dvNV GLEW_GET_FUN(__glewVertexAttribs2dvNV)
+#define glVertexAttribs2fvNV GLEW_GET_FUN(__glewVertexAttribs2fvNV)
+#define glVertexAttribs2svNV GLEW_GET_FUN(__glewVertexAttribs2svNV)
+#define glVertexAttribs3dvNV GLEW_GET_FUN(__glewVertexAttribs3dvNV)
+#define glVertexAttribs3fvNV GLEW_GET_FUN(__glewVertexAttribs3fvNV)
+#define glVertexAttribs3svNV GLEW_GET_FUN(__glewVertexAttribs3svNV)
+#define glVertexAttribs4dvNV GLEW_GET_FUN(__glewVertexAttribs4dvNV)
+#define glVertexAttribs4fvNV GLEW_GET_FUN(__glewVertexAttribs4fvNV)
+#define glVertexAttribs4svNV GLEW_GET_FUN(__glewVertexAttribs4svNV)
+#define glVertexAttribs4ubvNV GLEW_GET_FUN(__glewVertexAttribs4ubvNV)
+
+#define GLEW_NV_vertex_program GLEW_GET_VAR(__GLEW_NV_vertex_program)
+
+#endif /* GL_NV_vertex_program */
+
+/* ------------------------ GL_NV_vertex_program1_1 ------------------------ */
+
+#ifndef GL_NV_vertex_program1_1
+#define GL_NV_vertex_program1_1 1
+
+#define GLEW_NV_vertex_program1_1 GLEW_GET_VAR(__GLEW_NV_vertex_program1_1)
+
+#endif /* GL_NV_vertex_program1_1 */
+
+/* ------------------------- GL_NV_vertex_program2 ------------------------- */
+
+#ifndef GL_NV_vertex_program2
+#define GL_NV_vertex_program2 1
+
+#define GLEW_NV_vertex_program2 GLEW_GET_VAR(__GLEW_NV_vertex_program2)
+
+#endif /* GL_NV_vertex_program2 */
+
+/* ---------------------- GL_NV_vertex_program2_option --------------------- */
+
+#ifndef GL_NV_vertex_program2_option
+#define GL_NV_vertex_program2_option 1
+
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+
+#define GLEW_NV_vertex_program2_option GLEW_GET_VAR(__GLEW_NV_vertex_program2_option)
+
+#endif /* GL_NV_vertex_program2_option */
+
+/* ------------------------- GL_NV_vertex_program3 ------------------------- */
+
+#ifndef GL_NV_vertex_program3
+#define GL_NV_vertex_program3 1
+
+#define MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+
+#define GLEW_NV_vertex_program3 GLEW_GET_VAR(__GLEW_NV_vertex_program3)
+
+#endif /* GL_NV_vertex_program3 */
+
+/* ---------------------------- GL_OML_interlace --------------------------- */
+
+#ifndef GL_OML_interlace
+#define GL_OML_interlace 1
+
+#define GL_INTERLACE_OML 0x8980
+#define GL_INTERLACE_READ_OML 0x8981
+
+#define GLEW_OML_interlace GLEW_GET_VAR(__GLEW_OML_interlace)
+
+#endif /* GL_OML_interlace */
+
+/* ---------------------------- GL_OML_resample ---------------------------- */
+
+#ifndef GL_OML_resample
+#define GL_OML_resample 1
+
+#define GL_PACK_RESAMPLE_OML 0x8984
+#define GL_UNPACK_RESAMPLE_OML 0x8985
+#define GL_RESAMPLE_REPLICATE_OML 0x8986
+#define GL_RESAMPLE_ZERO_FILL_OML 0x8987
+#define GL_RESAMPLE_AVERAGE_OML 0x8988
+#define GL_RESAMPLE_DECIMATE_OML 0x8989
+
+#define GLEW_OML_resample GLEW_GET_VAR(__GLEW_OML_resample)
+
+#endif /* GL_OML_resample */
+
+/* ---------------------------- GL_OML_subsample --------------------------- */
+
+#ifndef GL_OML_subsample
+#define GL_OML_subsample 1
+
+#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982
+#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
+
+#define GLEW_OML_subsample GLEW_GET_VAR(__GLEW_OML_subsample)
+
+#endif /* GL_OML_subsample */
+
+/* --------------------------- GL_PGI_misc_hints --------------------------- */
+
+#ifndef GL_PGI_misc_hints
+#define GL_PGI_misc_hints 1
+
+#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 107000
+#define GL_CONSERVE_MEMORY_HINT_PGI 107005
+#define GL_RECLAIM_MEMORY_HINT_PGI 107006
+#define GL_NATIVE_GRAPHICS_HANDLE_PGI 107010
+#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 107011
+#define GL_NATIVE_GRAPHICS_END_HINT_PGI 107012
+#define GL_ALWAYS_FAST_HINT_PGI 107020
+#define GL_ALWAYS_SOFT_HINT_PGI 107021
+#define GL_ALLOW_DRAW_OBJ_HINT_PGI 107022
+#define GL_ALLOW_DRAW_WIN_HINT_PGI 107023
+#define GL_ALLOW_DRAW_FRG_HINT_PGI 107024
+#define GL_ALLOW_DRAW_MEM_HINT_PGI 107025
+#define GL_STRICT_DEPTHFUNC_HINT_PGI 107030
+#define GL_STRICT_LIGHTING_HINT_PGI 107031
+#define GL_STRICT_SCISSOR_HINT_PGI 107032
+#define GL_FULL_STIPPLE_HINT_PGI 107033
+#define GL_CLIP_NEAR_HINT_PGI 107040
+#define GL_CLIP_FAR_HINT_PGI 107041
+#define GL_WIDE_LINE_HINT_PGI 107042
+#define GL_BACK_NORMALS_HINT_PGI 107043
+
+#define GLEW_PGI_misc_hints GLEW_GET_VAR(__GLEW_PGI_misc_hints)
+
+#endif /* GL_PGI_misc_hints */
+
+/* -------------------------- GL_PGI_vertex_hints -------------------------- */
+
+#ifndef GL_PGI_vertex_hints
+#define GL_PGI_vertex_hints 1
+
+#define GL_VERTEX23_BIT_PGI 0x00000004
+#define GL_VERTEX4_BIT_PGI 0x00000008
+#define GL_COLOR3_BIT_PGI 0x00010000
+#define GL_COLOR4_BIT_PGI 0x00020000
+#define GL_EDGEFLAG_BIT_PGI 0x00040000
+#define GL_INDEX_BIT_PGI 0x00080000
+#define GL_MAT_AMBIENT_BIT_PGI 0x00100000
+#define GL_VERTEX_DATA_HINT_PGI 107050
+#define GL_VERTEX_CONSISTENT_HINT_PGI 107051
+#define GL_MATERIAL_SIDE_HINT_PGI 107052
+#define GL_MAX_VERTEX_HINT_PGI 107053
+#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000
+#define GL_MAT_EMISSION_BIT_PGI 0x00800000
+#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000
+#define GL_MAT_SHININESS_BIT_PGI 0x02000000
+#define GL_MAT_SPECULAR_BIT_PGI 0x04000000
+#define GL_NORMAL_BIT_PGI 0x08000000
+#define GL_TEXCOORD1_BIT_PGI 0x10000000
+#define GL_TEXCOORD2_BIT_PGI 0x20000000
+#define GL_TEXCOORD3_BIT_PGI 0x40000000
+#define GL_TEXCOORD4_BIT_PGI 0x80000000
+
+#define GLEW_PGI_vertex_hints GLEW_GET_VAR(__GLEW_PGI_vertex_hints)
+
+#endif /* GL_PGI_vertex_hints */
+
+/* ----------------------- GL_REND_screen_coordinates ---------------------- */
+
+#ifndef GL_REND_screen_coordinates
+#define GL_REND_screen_coordinates 1
+
+#define GL_SCREEN_COORDINATES_REND 0x8490
+#define GL_INVERTED_SCREEN_W_REND 0x8491
+
+#define GLEW_REND_screen_coordinates GLEW_GET_VAR(__GLEW_REND_screen_coordinates)
+
+#endif /* GL_REND_screen_coordinates */
+
+/* ------------------------------- GL_S3_s3tc ------------------------------ */
+
+#ifndef GL_S3_s3tc
+#define GL_S3_s3tc 1
+
+#define GL_RGB_S3TC 0x83A0
+#define GL_RGB4_S3TC 0x83A1
+#define GL_RGBA_S3TC 0x83A2
+#define GL_RGBA4_S3TC 0x83A3
+#define GL_RGBA_DXT5_S3TC 0x83A4
+#define GL_RGBA4_DXT5_S3TC 0x83A5
+
+#define GLEW_S3_s3tc GLEW_GET_VAR(__GLEW_S3_s3tc)
+
+#endif /* GL_S3_s3tc */
+
+/* -------------------------- GL_SGIS_color_range -------------------------- */
+
+#ifndef GL_SGIS_color_range
+#define GL_SGIS_color_range 1
+
+#define GL_EXTENDED_RANGE_SGIS 0x85A5
+#define GL_MIN_RED_SGIS 0x85A6
+#define GL_MAX_RED_SGIS 0x85A7
+#define GL_MIN_GREEN_SGIS 0x85A8
+#define GL_MAX_GREEN_SGIS 0x85A9
+#define GL_MIN_BLUE_SGIS 0x85AA
+#define GL_MAX_BLUE_SGIS 0x85AB
+#define GL_MIN_ALPHA_SGIS 0x85AC
+#define GL_MAX_ALPHA_SGIS 0x85AD
+
+#define GLEW_SGIS_color_range GLEW_GET_VAR(__GLEW_SGIS_color_range)
+
+#endif /* GL_SGIS_color_range */
+
+/* ------------------------- GL_SGIS_detail_texture ------------------------ */
+
+#ifndef GL_SGIS_detail_texture
+#define GL_SGIS_detail_texture 1
+
+typedef void (GLAPIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat* points);
+
+#define glDetailTexFuncSGIS GLEW_GET_FUN(__glewDetailTexFuncSGIS)
+#define glGetDetailTexFuncSGIS GLEW_GET_FUN(__glewGetDetailTexFuncSGIS)
+
+#define GLEW_SGIS_detail_texture GLEW_GET_VAR(__GLEW_SGIS_detail_texture)
+
+#endif /* GL_SGIS_detail_texture */
+
+/* -------------------------- GL_SGIS_fog_function ------------------------- */
+
+#ifndef GL_SGIS_fog_function
+#define GL_SGIS_fog_function 1
+
+typedef void (GLAPIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLGETFOGFUNCSGISPROC) (GLfloat* points);
+
+#define glFogFuncSGIS GLEW_GET_FUN(__glewFogFuncSGIS)
+#define glGetFogFuncSGIS GLEW_GET_FUN(__glewGetFogFuncSGIS)
+
+#define GLEW_SGIS_fog_function GLEW_GET_VAR(__GLEW_SGIS_fog_function)
+
+#endif /* GL_SGIS_fog_function */
+
+/* ------------------------ GL_SGIS_generate_mipmap ------------------------ */
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_SGIS_generate_mipmap 1
+
+#define GL_GENERATE_MIPMAP_SGIS 0x8191
+#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
+
+#define GLEW_SGIS_generate_mipmap GLEW_GET_VAR(__GLEW_SGIS_generate_mipmap)
+
+#endif /* GL_SGIS_generate_mipmap */
+
+/* -------------------------- GL_SGIS_multisample -------------------------- */
+
+#ifndef GL_SGIS_multisample
+#define GL_SGIS_multisample 1
+
+#define GL_MULTISAMPLE_SGIS 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F
+#define GL_SAMPLE_MASK_SGIS 0x80A0
+#define GL_1PASS_SGIS 0x80A1
+#define GL_2PASS_0_SGIS 0x80A2
+#define GL_2PASS_1_SGIS 0x80A3
+#define GL_4PASS_0_SGIS 0x80A4
+#define GL_4PASS_1_SGIS 0x80A5
+#define GL_4PASS_2_SGIS 0x80A6
+#define GL_4PASS_3_SGIS 0x80A7
+#define GL_SAMPLE_BUFFERS_SGIS 0x80A8
+#define GL_SAMPLES_SGIS 0x80A9
+#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA
+#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB
+#define GL_SAMPLE_PATTERN_SGIS 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);
+typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);
+
+#define glSampleMaskSGIS GLEW_GET_FUN(__glewSampleMaskSGIS)
+#define glSamplePatternSGIS GLEW_GET_FUN(__glewSamplePatternSGIS)
+
+#define GLEW_SGIS_multisample GLEW_GET_VAR(__GLEW_SGIS_multisample)
+
+#endif /* GL_SGIS_multisample */
+
+/* ------------------------- GL_SGIS_pixel_texture ------------------------- */
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_SGIS_pixel_texture 1
+
+#define GLEW_SGIS_pixel_texture GLEW_GET_VAR(__GLEW_SGIS_pixel_texture)
+
+#endif /* GL_SGIS_pixel_texture */
+
+/* ------------------------ GL_SGIS_sharpen_texture ------------------------ */
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_SGIS_sharpen_texture 1
+
+typedef void (GLAPIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points);
+
+#define glGetSharpenTexFuncSGIS GLEW_GET_FUN(__glewGetSharpenTexFuncSGIS)
+#define glSharpenTexFuncSGIS GLEW_GET_FUN(__glewSharpenTexFuncSGIS)
+
+#define GLEW_SGIS_sharpen_texture GLEW_GET_VAR(__GLEW_SGIS_sharpen_texture)
+
+#endif /* GL_SGIS_sharpen_texture */
+
+/* --------------------------- GL_SGIS_texture4D --------------------------- */
+
+#ifndef GL_SGIS_texture4D
+#define GL_SGIS_texture4D 1
+
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void* pixels);
+
+#define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS)
+#define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS)
+
+#define GLEW_SGIS_texture4D GLEW_GET_VAR(__GLEW_SGIS_texture4D)
+
+#endif /* GL_SGIS_texture4D */
+
+/* ---------------------- GL_SGIS_texture_border_clamp --------------------- */
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_SGIS_texture_border_clamp 1
+
+#define GL_CLAMP_TO_BORDER_SGIS 0x812D
+
+#define GLEW_SGIS_texture_border_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_border_clamp)
+
+#endif /* GL_SGIS_texture_border_clamp */
+
+/* ----------------------- GL_SGIS_texture_edge_clamp ---------------------- */
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_SGIS_texture_edge_clamp 1
+
+#define GL_CLAMP_TO_EDGE_SGIS 0x812F
+
+#define GLEW_SGIS_texture_edge_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_edge_clamp)
+
+#endif /* GL_SGIS_texture_edge_clamp */
+
+/* ------------------------ GL_SGIS_texture_filter4 ------------------------ */
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_SGIS_texture_filter4 1
+
+typedef void (GLAPIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat* weights);
+typedef void (GLAPIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat* weights);
+
+#define glGetTexFilterFuncSGIS GLEW_GET_FUN(__glewGetTexFilterFuncSGIS)
+#define glTexFilterFuncSGIS GLEW_GET_FUN(__glewTexFilterFuncSGIS)
+
+#define GLEW_SGIS_texture_filter4 GLEW_GET_VAR(__GLEW_SGIS_texture_filter4)
+
+#endif /* GL_SGIS_texture_filter4 */
+
+/* -------------------------- GL_SGIS_texture_lod -------------------------- */
+
+#ifndef GL_SGIS_texture_lod
+#define GL_SGIS_texture_lod 1
+
+#define GL_TEXTURE_MIN_LOD_SGIS 0x813A
+#define GL_TEXTURE_MAX_LOD_SGIS 0x813B
+#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C
+#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D
+
+#define GLEW_SGIS_texture_lod GLEW_GET_VAR(__GLEW_SGIS_texture_lod)
+
+#endif /* GL_SGIS_texture_lod */
+
+/* ------------------------- GL_SGIS_texture_select ------------------------ */
+
+#ifndef GL_SGIS_texture_select
+#define GL_SGIS_texture_select 1
+
+#define GLEW_SGIS_texture_select GLEW_GET_VAR(__GLEW_SGIS_texture_select)
+
+#endif /* GL_SGIS_texture_select */
+
+/* ----------------------------- GL_SGIX_async ----------------------------- */
+
+#ifndef GL_SGIX_async
+#define GL_SGIX_async 1
+
+#define GL_ASYNC_MARKER_SGIX 0x8329
+
+typedef void (GLAPIENTRY * PFNGLASYNCMARKERSGIXPROC) (GLuint marker);
+typedef void (GLAPIENTRY * PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);
+typedef GLint (GLAPIENTRY * PFNGLFINISHASYNCSGIXPROC) (GLuint* markerp);
+typedef GLuint (GLAPIENTRY * PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);
+typedef GLboolean (GLAPIENTRY * PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);
+typedef GLint (GLAPIENTRY * PFNGLPOLLASYNCSGIXPROC) (GLuint* markerp);
+
+#define glAsyncMarkerSGIX GLEW_GET_FUN(__glewAsyncMarkerSGIX)
+#define glDeleteAsyncMarkersSGIX GLEW_GET_FUN(__glewDeleteAsyncMarkersSGIX)
+#define glFinishAsyncSGIX GLEW_GET_FUN(__glewFinishAsyncSGIX)
+#define glGenAsyncMarkersSGIX GLEW_GET_FUN(__glewGenAsyncMarkersSGIX)
+#define glIsAsyncMarkerSGIX GLEW_GET_FUN(__glewIsAsyncMarkerSGIX)
+#define glPollAsyncSGIX GLEW_GET_FUN(__glewPollAsyncSGIX)
+
+#define GLEW_SGIX_async GLEW_GET_VAR(__GLEW_SGIX_async)
+
+#endif /* GL_SGIX_async */
+
+/* ------------------------ GL_SGIX_async_histogram ------------------------ */
+
+#ifndef GL_SGIX_async_histogram
+#define GL_SGIX_async_histogram 1
+
+#define GL_ASYNC_HISTOGRAM_SGIX 0x832C
+#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D
+
+#define GLEW_SGIX_async_histogram GLEW_GET_VAR(__GLEW_SGIX_async_histogram)
+
+#endif /* GL_SGIX_async_histogram */
+
+/* -------------------------- GL_SGIX_async_pixel -------------------------- */
+
+#ifndef GL_SGIX_async_pixel
+#define GL_SGIX_async_pixel 1
+
+#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C
+#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D
+#define GL_ASYNC_READ_PIXELS_SGIX 0x835E
+#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F
+#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360
+#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361
+
+#define GLEW_SGIX_async_pixel GLEW_GET_VAR(__GLEW_SGIX_async_pixel)
+
+#endif /* GL_SGIX_async_pixel */
+
+/* ----------------------- GL_SGIX_blend_alpha_minmax ---------------------- */
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_SGIX_blend_alpha_minmax 1
+
+#define GL_ALPHA_MIN_SGIX 0x8320
+#define GL_ALPHA_MAX_SGIX 0x8321
+
+#define GLEW_SGIX_blend_alpha_minmax GLEW_GET_VAR(__GLEW_SGIX_blend_alpha_minmax)
+
+#endif /* GL_SGIX_blend_alpha_minmax */
+
+/* ---------------------------- GL_SGIX_clipmap ---------------------------- */
+
+#ifndef GL_SGIX_clipmap
+#define GL_SGIX_clipmap 1
+
+#define GLEW_SGIX_clipmap GLEW_GET_VAR(__GLEW_SGIX_clipmap)
+
+#endif /* GL_SGIX_clipmap */
+
+/* ------------------------- GL_SGIX_depth_texture ------------------------- */
+
+#ifndef GL_SGIX_depth_texture
+#define GL_SGIX_depth_texture 1
+
+#define GL_DEPTH_COMPONENT16_SGIX 0x81A5
+#define GL_DEPTH_COMPONENT24_SGIX 0x81A6
+#define GL_DEPTH_COMPONENT32_SGIX 0x81A7
+
+#define GLEW_SGIX_depth_texture GLEW_GET_VAR(__GLEW_SGIX_depth_texture)
+
+#endif /* GL_SGIX_depth_texture */
+
+/* -------------------------- GL_SGIX_flush_raster ------------------------- */
+
+#ifndef GL_SGIX_flush_raster
+#define GL_SGIX_flush_raster 1
+
+typedef void (GLAPIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void);
+
+#define glFlushRasterSGIX GLEW_GET_FUN(__glewFlushRasterSGIX)
+
+#define GLEW_SGIX_flush_raster GLEW_GET_VAR(__GLEW_SGIX_flush_raster)
+
+#endif /* GL_SGIX_flush_raster */
+
+/* --------------------------- GL_SGIX_fog_offset -------------------------- */
+
+#ifndef GL_SGIX_fog_offset
+#define GL_SGIX_fog_offset 1
+
+#define GL_FOG_OFFSET_SGIX 0x8198
+#define GL_FOG_OFFSET_VALUE_SGIX 0x8199
+
+#define GLEW_SGIX_fog_offset GLEW_GET_VAR(__GLEW_SGIX_fog_offset)
+
+#endif /* GL_SGIX_fog_offset */
+
+/* -------------------------- GL_SGIX_fog_texture -------------------------- */
+
+#ifndef GL_SGIX_fog_texture
+#define GL_SGIX_fog_texture 1
+
+#define GL_TEXTURE_FOG_SGIX 0
+#define GL_FOG_PATCHY_FACTOR_SGIX 0
+#define GL_FRAGMENT_FOG_SGIX 0
+
+typedef void (GLAPIENTRY * PFNGLTEXTUREFOGSGIXPROC) (GLenum pname);
+
+#define glTextureFogSGIX GLEW_GET_FUN(__glewTextureFogSGIX)
+
+#define GLEW_SGIX_fog_texture GLEW_GET_VAR(__GLEW_SGIX_fog_texture)
+
+#endif /* GL_SGIX_fog_texture */
+
+/* ------------------- GL_SGIX_fragment_specular_lighting ------------------ */
+
+#ifndef GL_SGIX_fragment_specular_lighting
+#define GL_SGIX_fragment_specular_lighting 1
+
+typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum value, GLfloat* data);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum value, GLint* data);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* data);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* data);
+
+#define glFragmentColorMaterialSGIX GLEW_GET_FUN(__glewFragmentColorMaterialSGIX)
+#define glFragmentLightModelfSGIX GLEW_GET_FUN(__glewFragmentLightModelfSGIX)
+#define glFragmentLightModelfvSGIX GLEW_GET_FUN(__glewFragmentLightModelfvSGIX)
+#define glFragmentLightModeliSGIX GLEW_GET_FUN(__glewFragmentLightModeliSGIX)
+#define glFragmentLightModelivSGIX GLEW_GET_FUN(__glewFragmentLightModelivSGIX)
+#define glFragmentLightfSGIX GLEW_GET_FUN(__glewFragmentLightfSGIX)
+#define glFragmentLightfvSGIX GLEW_GET_FUN(__glewFragmentLightfvSGIX)
+#define glFragmentLightiSGIX GLEW_GET_FUN(__glewFragmentLightiSGIX)
+#define glFragmentLightivSGIX GLEW_GET_FUN(__glewFragmentLightivSGIX)
+#define glFragmentMaterialfSGIX GLEW_GET_FUN(__glewFragmentMaterialfSGIX)
+#define glFragmentMaterialfvSGIX GLEW_GET_FUN(__glewFragmentMaterialfvSGIX)
+#define glFragmentMaterialiSGIX GLEW_GET_FUN(__glewFragmentMaterialiSGIX)
+#define glFragmentMaterialivSGIX GLEW_GET_FUN(__glewFragmentMaterialivSGIX)
+#define glGetFragmentLightfvSGIX GLEW_GET_FUN(__glewGetFragmentLightfvSGIX)
+#define glGetFragmentLightivSGIX GLEW_GET_FUN(__glewGetFragmentLightivSGIX)
+#define glGetFragmentMaterialfvSGIX GLEW_GET_FUN(__glewGetFragmentMaterialfvSGIX)
+#define glGetFragmentMaterialivSGIX GLEW_GET_FUN(__glewGetFragmentMaterialivSGIX)
+
+#define GLEW_SGIX_fragment_specular_lighting GLEW_GET_VAR(__GLEW_SGIX_fragment_specular_lighting)
+
+#endif /* GL_SGIX_fragment_specular_lighting */
+
+/* --------------------------- GL_SGIX_framezoom --------------------------- */
+
+#ifndef GL_SGIX_framezoom
+#define GL_SGIX_framezoom 1
+
+typedef void (GLAPIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor);
+
+#define glFrameZoomSGIX GLEW_GET_FUN(__glewFrameZoomSGIX)
+
+#define GLEW_SGIX_framezoom GLEW_GET_VAR(__GLEW_SGIX_framezoom)
+
+#endif /* GL_SGIX_framezoom */
+
+/* --------------------------- GL_SGIX_interlace --------------------------- */
+
+#ifndef GL_SGIX_interlace
+#define GL_SGIX_interlace 1
+
+#define GL_INTERLACE_SGIX 0x8094
+
+#define GLEW_SGIX_interlace GLEW_GET_VAR(__GLEW_SGIX_interlace)
+
+#endif /* GL_SGIX_interlace */
+
+/* ------------------------- GL_SGIX_ir_instrument1 ------------------------ */
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_SGIX_ir_instrument1 1
+
+#define GLEW_SGIX_ir_instrument1 GLEW_GET_VAR(__GLEW_SGIX_ir_instrument1)
+
+#endif /* GL_SGIX_ir_instrument1 */
+
+/* ------------------------- GL_SGIX_list_priority ------------------------- */
+
+#ifndef GL_SGIX_list_priority
+#define GL_SGIX_list_priority 1
+
+#define GLEW_SGIX_list_priority GLEW_GET_VAR(__GLEW_SGIX_list_priority)
+
+#endif /* GL_SGIX_list_priority */
+
+/* ------------------------- GL_SGIX_pixel_texture ------------------------- */
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_SGIX_pixel_texture 1
+
+typedef void (GLAPIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);
+
+#define glPixelTexGenSGIX GLEW_GET_FUN(__glewPixelTexGenSGIX)
+
+#define GLEW_SGIX_pixel_texture GLEW_GET_VAR(__GLEW_SGIX_pixel_texture)
+
+#endif /* GL_SGIX_pixel_texture */
+
+/* ----------------------- GL_SGIX_pixel_texture_bits ---------------------- */
+
+#ifndef GL_SGIX_pixel_texture_bits
+#define GL_SGIX_pixel_texture_bits 1
+
+#define GLEW_SGIX_pixel_texture_bits GLEW_GET_VAR(__GLEW_SGIX_pixel_texture_bits)
+
+#endif /* GL_SGIX_pixel_texture_bits */
+
+/* ------------------------ GL_SGIX_reference_plane ------------------------ */
+
+#ifndef GL_SGIX_reference_plane
+#define GL_SGIX_reference_plane 1
+
+typedef void (GLAPIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble* equation);
+
+#define glReferencePlaneSGIX GLEW_GET_FUN(__glewReferencePlaneSGIX)
+
+#define GLEW_SGIX_reference_plane GLEW_GET_VAR(__GLEW_SGIX_reference_plane)
+
+#endif /* GL_SGIX_reference_plane */
+
+/* ---------------------------- GL_SGIX_resample --------------------------- */
+
+#ifndef GL_SGIX_resample
+#define GL_SGIX_resample 1
+
+#define GL_PACK_RESAMPLE_SGIX 0x842E
+#define GL_UNPACK_RESAMPLE_SGIX 0x842F
+#define GL_RESAMPLE_DECIMATE_SGIX 0x8430
+#define GL_RESAMPLE_REPLICATE_SGIX 0x8433
+#define GL_RESAMPLE_ZERO_FILL_SGIX 0x8434
+
+#define GLEW_SGIX_resample GLEW_GET_VAR(__GLEW_SGIX_resample)
+
+#endif /* GL_SGIX_resample */
+
+/* ----------------------------- GL_SGIX_shadow ---------------------------- */
+
+#ifndef GL_SGIX_shadow
+#define GL_SGIX_shadow 1
+
+#define GLEW_SGIX_shadow GLEW_GET_VAR(__GLEW_SGIX_shadow)
+
+#endif /* GL_SGIX_shadow */
+
+/* ------------------------- GL_SGIX_shadow_ambient ------------------------ */
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SGIX_shadow_ambient 1
+
+#define GL_SHADOW_AMBIENT_SGIX 0x80BF
+
+#define GLEW_SGIX_shadow_ambient GLEW_GET_VAR(__GLEW_SGIX_shadow_ambient)
+
+#endif /* GL_SGIX_shadow_ambient */
+
+/* ----------------------------- GL_SGIX_sprite ---------------------------- */
+
+#ifndef GL_SGIX_sprite
+#define GL_SGIX_sprite 1
+
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, GLint* params);
+
+#define glSpriteParameterfSGIX GLEW_GET_FUN(__glewSpriteParameterfSGIX)
+#define glSpriteParameterfvSGIX GLEW_GET_FUN(__glewSpriteParameterfvSGIX)
+#define glSpriteParameteriSGIX GLEW_GET_FUN(__glewSpriteParameteriSGIX)
+#define glSpriteParameterivSGIX GLEW_GET_FUN(__glewSpriteParameterivSGIX)
+
+#define GLEW_SGIX_sprite GLEW_GET_VAR(__GLEW_SGIX_sprite)
+
+#endif /* GL_SGIX_sprite */
+
+/* ----------------------- GL_SGIX_tag_sample_buffer ----------------------- */
+
+#ifndef GL_SGIX_tag_sample_buffer
+#define GL_SGIX_tag_sample_buffer 1
+
+typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);
+
+#define glTagSampleBufferSGIX GLEW_GET_FUN(__glewTagSampleBufferSGIX)
+
+#define GLEW_SGIX_tag_sample_buffer GLEW_GET_VAR(__GLEW_SGIX_tag_sample_buffer)
+
+#endif /* GL_SGIX_tag_sample_buffer */
+
+/* ------------------------ GL_SGIX_texture_add_env ------------------------ */
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_SGIX_texture_add_env 1
+
+#define GLEW_SGIX_texture_add_env GLEW_GET_VAR(__GLEW_SGIX_texture_add_env)
+
+#endif /* GL_SGIX_texture_add_env */
+
+/* -------------------- GL_SGIX_texture_coordinate_clamp ------------------- */
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_SGIX_texture_coordinate_clamp 1
+
+#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369
+#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A
+#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B
+
+#define GLEW_SGIX_texture_coordinate_clamp GLEW_GET_VAR(__GLEW_SGIX_texture_coordinate_clamp)
+
+#endif /* GL_SGIX_texture_coordinate_clamp */
+
+/* ------------------------ GL_SGIX_texture_lod_bias ----------------------- */
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_SGIX_texture_lod_bias 1
+
+#define GLEW_SGIX_texture_lod_bias GLEW_GET_VAR(__GLEW_SGIX_texture_lod_bias)
+
+#endif /* GL_SGIX_texture_lod_bias */
+
+/* ---------------------- GL_SGIX_texture_multi_buffer --------------------- */
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_SGIX_texture_multi_buffer 1
+
+#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+
+#define GLEW_SGIX_texture_multi_buffer GLEW_GET_VAR(__GLEW_SGIX_texture_multi_buffer)
+
+#endif /* GL_SGIX_texture_multi_buffer */
+
+/* ------------------------- GL_SGIX_texture_range ------------------------- */
+
+#ifndef GL_SGIX_texture_range
+#define GL_SGIX_texture_range 1
+
+#define GL_RGB_SIGNED_SGIX 0x85E0
+#define GL_RGBA_SIGNED_SGIX 0x85E1
+#define GL_ALPHA_SIGNED_SGIX 0x85E2
+#define GL_LUMINANCE_SIGNED_SGIX 0x85E3
+#define GL_INTENSITY_SIGNED_SGIX 0x85E4
+#define GL_LUMINANCE_ALPHA_SIGNED_SGIX 0x85E5
+#define GL_RGB16_SIGNED_SGIX 0x85E6
+#define GL_RGBA16_SIGNED_SGIX 0x85E7
+#define GL_ALPHA16_SIGNED_SGIX 0x85E8
+#define GL_LUMINANCE16_SIGNED_SGIX 0x85E9
+#define GL_INTENSITY16_SIGNED_SGIX 0x85EA
+#define GL_LUMINANCE16_ALPHA16_SIGNED_SGIX 0x85EB
+#define GL_RGB_EXTENDED_RANGE_SGIX 0x85EC
+#define GL_RGBA_EXTENDED_RANGE_SGIX 0x85ED
+#define GL_ALPHA_EXTENDED_RANGE_SGIX 0x85EE
+#define GL_LUMINANCE_EXTENDED_RANGE_SGIX 0x85EF
+#define GL_INTENSITY_EXTENDED_RANGE_SGIX 0x85F0
+#define GL_LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX 0x85F1
+#define GL_RGB16_EXTENDED_RANGE_SGIX 0x85F2
+#define GL_RGBA16_EXTENDED_RANGE_SGIX 0x85F3
+#define GL_ALPHA16_EXTENDED_RANGE_SGIX 0x85F4
+#define GL_LUMINANCE16_EXTENDED_RANGE_SGIX 0x85F5
+#define GL_INTENSITY16_EXTENDED_RANGE_SGIX 0x85F6
+#define GL_LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX 0x85F7
+#define GL_MIN_LUMINANCE_SGIS 0x85F8
+#define GL_MAX_LUMINANCE_SGIS 0x85F9
+#define GL_MIN_INTENSITY_SGIS 0x85FA
+#define GL_MAX_INTENSITY_SGIS 0x85FB
+
+#define GLEW_SGIX_texture_range GLEW_GET_VAR(__GLEW_SGIX_texture_range)
+
+#endif /* GL_SGIX_texture_range */
+
+/* ----------------------- GL_SGIX_texture_scale_bias ---------------------- */
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_SGIX_texture_scale_bias 1
+
+#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179
+#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+
+#define GLEW_SGIX_texture_scale_bias GLEW_GET_VAR(__GLEW_SGIX_texture_scale_bias)
+
+#endif /* GL_SGIX_texture_scale_bias */
+
+/* ------------------------- GL_SGIX_vertex_preclip ------------------------ */
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_SGIX_vertex_preclip 1
+
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+
+#define GLEW_SGIX_vertex_preclip GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip)
+
+#endif /* GL_SGIX_vertex_preclip */
+
+/* ---------------------- GL_SGIX_vertex_preclip_hint ---------------------- */
+
+#ifndef GL_SGIX_vertex_preclip_hint
+#define GL_SGIX_vertex_preclip_hint 1
+
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+
+#define GLEW_SGIX_vertex_preclip_hint GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip_hint)
+
+#endif /* GL_SGIX_vertex_preclip_hint */
+
+/* ----------------------------- GL_SGIX_ycrcb ----------------------------- */
+
+#ifndef GL_SGIX_ycrcb
+#define GL_SGIX_ycrcb 1
+
+#define GLEW_SGIX_ycrcb GLEW_GET_VAR(__GLEW_SGIX_ycrcb)
+
+#endif /* GL_SGIX_ycrcb */
+
+/* -------------------------- GL_SGI_color_matrix -------------------------- */
+
+#ifndef GL_SGI_color_matrix
+#define GL_SGI_color_matrix 1
+
+#define GL_COLOR_MATRIX_SGI 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+
+#define GLEW_SGI_color_matrix GLEW_GET_VAR(__GLEW_SGI_color_matrix)
+
+#endif /* GL_SGI_color_matrix */
+
+/* --------------------------- GL_SGI_color_table -------------------------- */
+
+#ifndef GL_SGI_color_table
+#define GL_SGI_color_table 1
+
+#define GL_COLOR_TABLE_SGI 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define GL_PROXY_COLOR_TABLE_SGI 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define GL_COLOR_TABLE_SCALE_SGI 0x80D6
+#define GL_COLOR_TABLE_BIAS_SGI 0x80D7
+#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8
+#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* table);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void* table);
+
+#define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI)
+#define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI)
+#define glColorTableSGI GLEW_GET_FUN(__glewColorTableSGI)
+#define glCopyColorTableSGI GLEW_GET_FUN(__glewCopyColorTableSGI)
+#define glGetColorTableParameterfvSGI GLEW_GET_FUN(__glewGetColorTableParameterfvSGI)
+#define glGetColorTableParameterivSGI GLEW_GET_FUN(__glewGetColorTableParameterivSGI)
+#define glGetColorTableSGI GLEW_GET_FUN(__glewGetColorTableSGI)
+
+#define GLEW_SGI_color_table GLEW_GET_VAR(__GLEW_SGI_color_table)
+
+#endif /* GL_SGI_color_table */
+
+/* ----------------------- GL_SGI_texture_color_table ---------------------- */
+
+#ifndef GL_SGI_texture_color_table
+#define GL_SGI_texture_color_table 1
+
+#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC
+#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD
+
+#define GLEW_SGI_texture_color_table GLEW_GET_VAR(__GLEW_SGI_texture_color_table)
+
+#endif /* GL_SGI_texture_color_table */
+
+/* ------------------------- GL_SUNX_constant_data ------------------------- */
+
+#ifndef GL_SUNX_constant_data
+#define GL_SUNX_constant_data 1
+
+#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5
+#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6
+
+typedef void (GLAPIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void);
+
+#define glFinishTextureSUNX GLEW_GET_FUN(__glewFinishTextureSUNX)
+
+#define GLEW_SUNX_constant_data GLEW_GET_VAR(__GLEW_SUNX_constant_data)
+
+#endif /* GL_SUNX_constant_data */
+
+/* -------------------- GL_SUN_convolution_border_modes -------------------- */
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_SUN_convolution_border_modes 1
+
+#define GL_WRAP_BORDER_SUN 0x81D4
+
+#define GLEW_SUN_convolution_border_modes GLEW_GET_VAR(__GLEW_SUN_convolution_border_modes)
+
+#endif /* GL_SUN_convolution_border_modes */
+
+/* -------------------------- GL_SUN_global_alpha -------------------------- */
+
+#ifndef GL_SUN_global_alpha
+#define GL_SUN_global_alpha 1
+
+#define GL_GLOBAL_ALPHA_SUN 0x81D9
+#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA
+
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);
+
+#define glGlobalAlphaFactorbSUN GLEW_GET_FUN(__glewGlobalAlphaFactorbSUN)
+#define glGlobalAlphaFactordSUN GLEW_GET_FUN(__glewGlobalAlphaFactordSUN)
+#define glGlobalAlphaFactorfSUN GLEW_GET_FUN(__glewGlobalAlphaFactorfSUN)
+#define glGlobalAlphaFactoriSUN GLEW_GET_FUN(__glewGlobalAlphaFactoriSUN)
+#define glGlobalAlphaFactorsSUN GLEW_GET_FUN(__glewGlobalAlphaFactorsSUN)
+#define glGlobalAlphaFactorubSUN GLEW_GET_FUN(__glewGlobalAlphaFactorubSUN)
+#define glGlobalAlphaFactoruiSUN GLEW_GET_FUN(__glewGlobalAlphaFactoruiSUN)
+#define glGlobalAlphaFactorusSUN GLEW_GET_FUN(__glewGlobalAlphaFactorusSUN)
+
+#define GLEW_SUN_global_alpha GLEW_GET_VAR(__GLEW_SUN_global_alpha)
+
+#endif /* GL_SUN_global_alpha */
+
+/* --------------------------- GL_SUN_mesh_array --------------------------- */
+
+#ifndef GL_SUN_mesh_array
+#define GL_SUN_mesh_array 1
+
+#define GL_QUAD_MESH_SUN 0x8614
+#define GL_TRIANGLE_MESH_SUN 0x8615
+
+#define GLEW_SUN_mesh_array GLEW_GET_VAR(__GLEW_SUN_mesh_array)
+
+#endif /* GL_SUN_mesh_array */
+
+/* ------------------------ GL_SUN_read_video_pixels ----------------------- */
+
+#ifndef GL_SUN_read_video_pixels
+#define GL_SUN_read_video_pixels 1
+
+typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+
+#define glReadVideoPixelsSUN GLEW_GET_FUN(__glewReadVideoPixelsSUN)
+
+#define GLEW_SUN_read_video_pixels GLEW_GET_VAR(__GLEW_SUN_read_video_pixels)
+
+#endif /* GL_SUN_read_video_pixels */
+
+/* --------------------------- GL_SUN_slice_accum -------------------------- */
+
+#ifndef GL_SUN_slice_accum
+#define GL_SUN_slice_accum 1
+
+#define GL_SLICE_ACCUM_SUN 0x85CC
+
+#define GLEW_SUN_slice_accum GLEW_GET_VAR(__GLEW_SUN_slice_accum)
+
+#endif /* GL_SUN_slice_accum */
+
+/* -------------------------- GL_SUN_triangle_list ------------------------- */
+
+#ifndef GL_SUN_triangle_list
+#define GL_SUN_triangle_list 1
+
+#define GL_RESTART_SUN 0x01
+#define GL_REPLACE_MIDDLE_SUN 0x02
+#define GL_REPLACE_OLDEST_SUN 0x03
+#define GL_TRIANGLE_LIST_SUN 0x81D7
+#define GL_REPLACEMENT_CODE_SUN 0x81D8
+#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0
+#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define GL_R1UI_V3F_SUN 0x85C4
+#define GL_R1UI_C4UB_V3F_SUN 0x85C5
+#define GL_R1UI_C3F_V3F_SUN 0x85C6
+#define GL_R1UI_N3F_V3F_SUN 0x85C7
+#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8
+#define GL_R1UI_T2F_V3F_SUN 0x85C9
+#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA
+#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB
+
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint* code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort* code);
+
+#define glReplacementCodePointerSUN GLEW_GET_FUN(__glewReplacementCodePointerSUN)
+#define glReplacementCodeubSUN GLEW_GET_FUN(__glewReplacementCodeubSUN)
+#define glReplacementCodeubvSUN GLEW_GET_FUN(__glewReplacementCodeubvSUN)
+#define glReplacementCodeuiSUN GLEW_GET_FUN(__glewReplacementCodeuiSUN)
+#define glReplacementCodeuivSUN GLEW_GET_FUN(__glewReplacementCodeuivSUN)
+#define glReplacementCodeusSUN GLEW_GET_FUN(__glewReplacementCodeusSUN)
+#define glReplacementCodeusvSUN GLEW_GET_FUN(__glewReplacementCodeusvSUN)
+
+#define GLEW_SUN_triangle_list GLEW_GET_VAR(__GLEW_SUN_triangle_list)
+
+#endif /* GL_SUN_triangle_list */
+
+/* ----------------------------- GL_SUN_vertex ----------------------------- */
+
+#ifndef GL_SUN_vertex
+#define GL_SUN_vertex 1
+
+typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte* c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte* c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint* rc, const GLubyte *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat* tc, const GLubyte *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *v);
+
+#define glColor3fVertex3fSUN GLEW_GET_FUN(__glewColor3fVertex3fSUN)
+#define glColor3fVertex3fvSUN GLEW_GET_FUN(__glewColor3fVertex3fvSUN)
+#define glColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fSUN)
+#define glColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fvSUN)
+#define glColor4ubVertex2fSUN GLEW_GET_FUN(__glewColor4ubVertex2fSUN)
+#define glColor4ubVertex2fvSUN GLEW_GET_FUN(__glewColor4ubVertex2fvSUN)
+#define glColor4ubVertex3fSUN GLEW_GET_FUN(__glewColor4ubVertex3fSUN)
+#define glColor4ubVertex3fvSUN GLEW_GET_FUN(__glewColor4ubVertex3fvSUN)
+#define glNormal3fVertex3fSUN GLEW_GET_FUN(__glewNormal3fVertex3fSUN)
+#define glNormal3fVertex3fvSUN GLEW_GET_FUN(__glewNormal3fVertex3fvSUN)
+#define glReplacementCodeuiColor3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fSUN)
+#define glReplacementCodeuiColor3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fvSUN)
+#define glReplacementCodeuiColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fSUN)
+#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fvSUN)
+#define glReplacementCodeuiColor4ubVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fSUN)
+#define glReplacementCodeuiColor4ubVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fvSUN)
+#define glReplacementCodeuiNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fSUN)
+#define glReplacementCodeuiNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fvSUN)
+#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN)
+#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN)
+#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN)
+#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN)
+#define glReplacementCodeuiTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fSUN)
+#define glReplacementCodeuiTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fvSUN)
+#define glReplacementCodeuiVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fSUN)
+#define glReplacementCodeuiVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fvSUN)
+#define glTexCoord2fColor3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fSUN)
+#define glTexCoord2fColor3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fvSUN)
+#define glTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fSUN)
+#define glTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fvSUN)
+#define glTexCoord2fColor4ubVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fSUN)
+#define glTexCoord2fColor4ubVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fvSUN)
+#define glTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fSUN)
+#define glTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fvSUN)
+#define glTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fSUN)
+#define glTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fvSUN)
+#define glTexCoord4fColor4fNormal3fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fSUN)
+#define glTexCoord4fColor4fNormal3fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fvSUN)
+#define glTexCoord4fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fSUN)
+#define glTexCoord4fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fvSUN)
+
+#define GLEW_SUN_vertex GLEW_GET_VAR(__GLEW_SUN_vertex)
+
+#endif /* GL_SUN_vertex */
+
+/* -------------------------- GL_WIN_phong_shading ------------------------- */
+
+#ifndef GL_WIN_phong_shading
+#define GL_WIN_phong_shading 1
+
+#define GL_PHONG_WIN 0x80EA
+#define GL_PHONG_HINT_WIN 0x80EB
+
+#define GLEW_WIN_phong_shading GLEW_GET_VAR(__GLEW_WIN_phong_shading)
+
+#endif /* GL_WIN_phong_shading */
+
+/* -------------------------- GL_WIN_specular_fog -------------------------- */
+
+#ifndef GL_WIN_specular_fog
+#define GL_WIN_specular_fog 1
+
+#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
+
+#define GLEW_WIN_specular_fog GLEW_GET_VAR(__GLEW_WIN_specular_fog)
+
+#endif /* GL_WIN_specular_fog */
+
+/* ---------------------------- GL_WIN_swap_hint --------------------------- */
+
+#ifndef GL_WIN_swap_hint
+#define GL_WIN_swap_hint 1
+
+typedef void (GLAPIENTRY * PFNGLADDSWAPHINTRECTWINPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define glAddSwapHintRectWIN GLEW_GET_FUN(__glewAddSwapHintRectWIN)
+
+#define GLEW_WIN_swap_hint GLEW_GET_VAR(__GLEW_WIN_swap_hint)
+
+#endif /* GL_WIN_swap_hint */
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(GLEW_MX) && defined(_WIN32)
+#define GLEW_FUN_EXPORT
+#else
+#define GLEW_FUN_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#if defined(GLEW_MX)
+#define GLEW_VAR_EXPORT
+#else
+#define GLEW_VAR_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#if defined(GLEW_MX) && defined(_WIN32)
+struct GLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DPROC __glewTexImage3D;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D;
+
+GLEW_FUN_EXPORT PFNGLACTIVETEXTUREPROC __glewActiveTexture;
+GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D;
+GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage;
+GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd;
+GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf;
+GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd;
+GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv;
+GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage;
+
+GLEW_FUN_EXPORT PFNGLBLENDCOLORPROC __glewBlendColor;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONPROC __glewBlendEquation;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate;
+GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDPROC __glewFogCoordd;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDVPROC __glewFogCoorddv;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFPROC __glewFogCoordf;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFVPROC __glewFogCoordfv;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFPROC __glewPointParameterf;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DPROC __glewWindowPos2d;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FPROC __glewWindowPos2f;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IPROC __glewWindowPos2i;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SPROC __glewWindowPos2s;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DPROC __glewWindowPos3d;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FPROC __glewWindowPos3f;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IPROC __glewWindowPos3i;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SPROC __glewWindowPos3s;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYPROC __glewBeginQuery;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer;
+GLEW_FUN_EXPORT PFNGLBUFFERDATAPROC __glewBufferData;
+GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAPROC __glewBufferSubData;
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERSPROC __glewDeleteBuffers;
+GLEW_FUN_EXPORT PFNGLDELETEQUERIESPROC __glewDeleteQueries;
+GLEW_FUN_EXPORT PFNGLENDQUERYPROC __glewEndQuery;
+GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers;
+GLEW_FUN_EXPORT PFNGLGENQUERIESPROC __glewGenQueries;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv;
+GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv;
+GLEW_FUN_EXPORT PFNGLGETQUERYIVPROC __glewGetQueryiv;
+GLEW_FUN_EXPORT PFNGLISBUFFERPROC __glewIsBuffer;
+GLEW_FUN_EXPORT PFNGLISQUERYPROC __glewIsQuery;
+GLEW_FUN_EXPORT PFNGLMAPBUFFERPROC __glewMapBuffer;
+GLEW_FUN_EXPORT PFNGLUNMAPBUFFERPROC __glewUnmapBuffer;
+
+GLEW_FUN_EXPORT PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX;
+
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE;
+
+GLEW_FUN_EXPORT PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE;
+GLEW_FUN_EXPORT PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE;
+GLEW_FUN_EXPORT PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE;
+GLEW_FUN_EXPORT PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE;
+
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE;
+GLEW_FUN_EXPORT PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE;
+
+GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE;
+GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE;
+GLEW_FUN_EXPORT PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE;
+
+GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE;
+
+GLEW_FUN_EXPORT PFNGLCLAMPCOLORARBPROC __glewClampColorARB;
+
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB;
+
+GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEPROC __glewColorSubTable;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPROC __glewColorTable;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPROC __glewGetColorTable;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPROC __glewGetHistogram;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPROC __glewGetMinmax;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv;
+GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter;
+GLEW_FUN_EXPORT PFNGLHISTOGRAMPROC __glewHistogram;
+GLEW_FUN_EXPORT PFNGLMINMAXPROC __glewMinmax;
+GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMPROC __glewResetHistogram;
+GLEW_FUN_EXPORT PFNGLRESETMINMAXPROC __glewResetMinmax;
+GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D;
+
+GLEW_FUN_EXPORT PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB;
+
+GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB;
+
+GLEW_FUN_EXPORT PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB;
+GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYARBPROC __glewBeginQueryARB;
+GLEW_FUN_EXPORT PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB;
+GLEW_FUN_EXPORT PFNGLENDQUERYARBPROC __glewEndQueryARB;
+GLEW_FUN_EXPORT PFNGLGENQUERIESARBPROC __glewGenQueriesARB;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB;
+GLEW_FUN_EXPORT PFNGLGETQUERYIVARBPROC __glewGetQueryivARB;
+GLEW_FUN_EXPORT PFNGLISQUERYARBPROC __glewIsQueryARB;
+
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB;
+
+GLEW_FUN_EXPORT PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB;
+GLEW_FUN_EXPORT PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB;
+GLEW_FUN_EXPORT PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB;
+GLEW_FUN_EXPORT PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB;
+GLEW_FUN_EXPORT PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB;
+GLEW_FUN_EXPORT PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB;
+GLEW_FUN_EXPORT PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB;
+GLEW_FUN_EXPORT PFNGLGETHANDLEARBPROC __glewGetHandleARB;
+GLEW_FUN_EXPORT PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB;
+GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB;
+GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB;
+GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB;
+GLEW_FUN_EXPORT PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB;
+GLEW_FUN_EXPORT PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FARBPROC __glewUniform1fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IARBPROC __glewUniform1iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FARBPROC __glewUniform2fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IARBPROC __glewUniform2iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FARBPROC __glewUniform3fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IARBPROC __glewUniform3iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FARBPROC __glewUniform4fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IARBPROC __glewUniform4iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB;
+GLEW_FUN_EXPORT PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB;
+GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB;
+
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB;
+GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB;
+
+GLEW_FUN_EXPORT PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTBVARBPROC __glewWeightbvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTDVARBPROC __glewWeightdvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTFVARBPROC __glewWeightfvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTIVARBPROC __glewWeightivARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTSVARBPROC __glewWeightsvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTUBVARBPROC __glewWeightubvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTUIVARBPROC __glewWeightuivARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTUSVARBPROC __glewWeightusvARB;
+
+GLEW_FUN_EXPORT PFNGLBINDBUFFERARBPROC __glewBindBufferARB;
+GLEW_FUN_EXPORT PFNGLBUFFERDATAARBPROC __glewBufferDataARB;
+GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB;
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB;
+GLEW_FUN_EXPORT PFNGLGENBUFFERSARBPROC __glewGenBuffersARB;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB;
+GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB;
+GLEW_FUN_EXPORT PFNGLISBUFFERARBPROC __glewIsBufferARB;
+GLEW_FUN_EXPORT PFNGLMAPBUFFERARBPROC __glewMapBufferARB;
+GLEW_FUN_EXPORT PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB;
+
+GLEW_FUN_EXPORT PFNGLBINDPROGRAMARBPROC __glewBindProgramARB;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB;
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB;
+GLEW_FUN_EXPORT PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB;
+GLEW_FUN_EXPORT PFNGLISPROGRAMARBPROC __glewIsProgramARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB;
+
+GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB;
+GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB;
+GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB;
+
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB;
+
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI;
+
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI;
+GLEW_FUN_EXPORT PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI;
+
+GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI;
+GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI;
+GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI;
+GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI;
+
+GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI;
+GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI;
+GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI;
+GLEW_FUN_EXPORT PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI;
+GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI;
+GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI;
+GLEW_FUN_EXPORT PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI;
+GLEW_FUN_EXPORT PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI;
+GLEW_FUN_EXPORT PFNGLSAMPLEMAPATIPROC __glewSampleMapATI;
+GLEW_FUN_EXPORT PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI;
+
+GLEW_FUN_EXPORT PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI;
+
+GLEW_FUN_EXPORT PFNGLPNTRIANGLESFATIPROC __glPNTrianglewesfATI;
+GLEW_FUN_EXPORT PFNGLPNTRIANGLESIATIPROC __glPNTrianglewesiATI;
+
+GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI;
+GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI;
+
+GLEW_FUN_EXPORT PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI;
+GLEW_FUN_EXPORT PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI;
+GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI;
+GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI;
+GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI;
+GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI;
+GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI;
+GLEW_FUN_EXPORT PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI;
+
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI;
+
+GLEW_FUN_EXPORT PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI;
+GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI;
+GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI;
+
+GLEW_FUN_EXPORT PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT;
+
+GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT;
+
+GLEW_FUN_EXPORT PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT;
+GLEW_FUN_EXPORT PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT;
+
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT;
+GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT;
+
+GLEW_FUN_EXPORT PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT;
+GLEW_FUN_EXPORT PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT;
+GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT;
+
+GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT;
+
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT;
+
+GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT;
+GLEW_FUN_EXPORT PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT;
+
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT;
+GLEW_FUN_EXPORT PFNGLHISTOGRAMEXTPROC __glewHistogramEXT;
+GLEW_FUN_EXPORT PFNGLMINMAXEXTPROC __glewMinmaxEXT;
+GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT;
+GLEW_FUN_EXPORT PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT;
+
+GLEW_FUN_EXPORT PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT;
+
+GLEW_FUN_EXPORT PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT;
+
+GLEW_FUN_EXPORT PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT;
+
+GLEW_FUN_EXPORT PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT;
+GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT;
+
+GLEW_FUN_EXPORT PFNGLCOLORTABLEEXTPROC __glewColorTableEXT;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT;
+
+GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT;
+
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT;
+
+GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT;
+
+GLEW_FUN_EXPORT PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT;
+GLEW_FUN_EXPORT PFNGLENDSCENEEXTPROC __glewEndSceneEXT;
+
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT;
+GLEW_FUN_EXPORT PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT;
+GLEW_FUN_EXPORT PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT;
+GLEW_FUN_EXPORT PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT;
+GLEW_FUN_EXPORT PFNGLISTEXTUREEXTPROC __glewIsTextureEXT;
+GLEW_FUN_EXPORT PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT;
+
+GLEW_FUN_EXPORT PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT;
+GLEW_FUN_EXPORT PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT;
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT;
+GLEW_FUN_EXPORT PFNGLGETPOINTERVEXTPROC __glewGetPointervEXT;
+GLEW_FUN_EXPORT PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT;
+GLEW_FUN_EXPORT PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT;
+GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT;
+GLEW_FUN_EXPORT PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT;
+GLEW_FUN_EXPORT PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT;
+GLEW_FUN_EXPORT PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT;
+GLEW_FUN_EXPORT PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT;
+GLEW_FUN_EXPORT PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT;
+GLEW_FUN_EXPORT PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT;
+GLEW_FUN_EXPORT PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT;
+GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT;
+GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT;
+GLEW_FUN_EXPORT PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT;
+GLEW_FUN_EXPORT PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT;
+GLEW_FUN_EXPORT PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT;
+GLEW_FUN_EXPORT PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT;
+GLEW_FUN_EXPORT PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT;
+GLEW_FUN_EXPORT PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT;
+GLEW_FUN_EXPORT PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT;
+GLEW_FUN_EXPORT PFNGLSWIZZLEEXTPROC __glewSwizzleEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTBVEXTPROC __glewVariantbvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTDVEXTPROC __glewVariantdvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTFVEXTPROC __glewVariantfvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTIVEXTPROC __glewVariantivEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTSVEXTPROC __glewVariantsvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT;
+GLEW_FUN_EXPORT PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT;
+
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT;
+
+GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP;
+GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP;
+
+GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM;
+GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM;
+
+GLEW_FUN_EXPORT PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM;
+GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM;
+GLEW_FUN_EXPORT PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM;
+GLEW_FUN_EXPORT PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM;
+GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM;
+GLEW_FUN_EXPORT PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM;
+
+GLEW_FUN_EXPORT PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL;
+GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL;
+GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL;
+GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL;
+
+GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL;
+GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL;
+
+GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT;
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT;
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT;
+GLEW_FUN_EXPORT PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT;
+GLEW_FUN_EXPORT PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT;
+
+GLEW_FUN_EXPORT PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA;
+
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA;
+
+GLEW_FUN_EXPORT PFNGLEVALMAPSNVPROC __glewEvalMapsNV;
+GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV;
+GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV;
+GLEW_FUN_EXPORT PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV;
+GLEW_FUN_EXPORT PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV;
+GLEW_FUN_EXPORT PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV;
+GLEW_FUN_EXPORT PFNGLFINISHFENCENVPROC __glewFinishFenceNV;
+GLEW_FUN_EXPORT PFNGLGENFENCESNVPROC __glewGenFencesNV;
+GLEW_FUN_EXPORT PFNGLGETFENCEIVNVPROC __glewGetFenceivNV;
+GLEW_FUN_EXPORT PFNGLISFENCENVPROC __glewIsFenceNV;
+GLEW_FUN_EXPORT PFNGLSETFENCENVPROC __glewSetFenceNV;
+GLEW_FUN_EXPORT PFNGLTESTFENCENVPROC __glewTestFenceNV;
+
+GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV;
+
+GLEW_FUN_EXPORT PFNGLCOLOR3HNVPROC __glewColor3hNV;
+GLEW_FUN_EXPORT PFNGLCOLOR3HVNVPROC __glewColor3hvNV;
+GLEW_FUN_EXPORT PFNGLCOLOR4HNVPROC __glewColor4hNV;
+GLEW_FUN_EXPORT PFNGLCOLOR4HVNVPROC __glewColor4hvNV;
+GLEW_FUN_EXPORT PFNGLFOGCOORDHNVPROC __glewFogCoordhNV;
+GLEW_FUN_EXPORT PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV;
+GLEW_FUN_EXPORT PFNGLNORMAL3HNVPROC __glewNormal3hNV;
+GLEW_FUN_EXPORT PFNGLNORMAL3HVNVPROC __glewNormal3hvNV;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEX2HNVPROC __glewVertex2hNV;
+GLEW_FUN_EXPORT PFNGLVERTEX2HVNVPROC __glewVertex2hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEX3HNVPROC __glewVertex3hNV;
+GLEW_FUN_EXPORT PFNGLVERTEX3HVNVPROC __glewVertex3hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEX4HNVPROC __glewVertex4hNV;
+GLEW_FUN_EXPORT PFNGLVERTEX4HVNVPROC __glewVertex4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV;
+
+GLEW_FUN_EXPORT PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV;
+GLEW_FUN_EXPORT PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV;
+GLEW_FUN_EXPORT PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV;
+GLEW_FUN_EXPORT PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV;
+GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV;
+GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV;
+GLEW_FUN_EXPORT PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV;
+
+GLEW_FUN_EXPORT PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV;
+GLEW_FUN_EXPORT PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV;
+
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV;
+GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV;
+
+GLEW_FUN_EXPORT PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV;
+GLEW_FUN_EXPORT PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV;
+GLEW_FUN_EXPORT PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV;
+
+GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV;
+
+GLEW_FUN_EXPORT PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV;
+GLEW_FUN_EXPORT PFNGLBINDPROGRAMNVPROC __glewBindProgramNV;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV;
+GLEW_FUN_EXPORT PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV;
+GLEW_FUN_EXPORT PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV;
+GLEW_FUN_EXPORT PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV;
+GLEW_FUN_EXPORT PFNGLISPROGRAMNVPROC __glewIsProgramNV;
+GLEW_FUN_EXPORT PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV;
+GLEW_FUN_EXPORT PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV;
+GLEW_FUN_EXPORT PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV;
+
+GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS;
+GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS;
+GLEW_FUN_EXPORT PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS;
+GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS;
+
+GLEW_FUN_EXPORT PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS;
+GLEW_FUN_EXPORT PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS;
+
+GLEW_FUN_EXPORT PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS;
+GLEW_FUN_EXPORT PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX;
+GLEW_FUN_EXPORT PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX;
+GLEW_FUN_EXPORT PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX;
+GLEW_FUN_EXPORT PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX;
+GLEW_FUN_EXPORT PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX;
+GLEW_FUN_EXPORT PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX;
+
+GLEW_FUN_EXPORT PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX;
+
+GLEW_FUN_EXPORT PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX;
+
+GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX;
+
+GLEW_FUN_EXPORT PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX;
+
+GLEW_FUN_EXPORT PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX;
+
+GLEW_FUN_EXPORT PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX;
+
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX;
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX;
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX;
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX;
+
+GLEW_FUN_EXPORT PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX;
+
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI;
+GLEW_FUN_EXPORT PFNGLCOLORTABLESGIPROC __glewColorTableSGI;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI;
+
+GLEW_FUN_EXPORT PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX;
+
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN;
+
+GLEW_FUN_EXPORT PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN;
+
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN;
+
+GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN;
+
+GLEW_FUN_EXPORT PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN;
+
+#if defined(GLEW_MX) && !defined(_WIN32)
+struct GLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_3;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_4;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_5;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_tbuffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_texture_compression_FXT1;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_client_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_element_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_fence;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_float_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_specular_vector;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_transform_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_ycbcr_422;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_color_buffer_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program_shadow;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_pixel;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_imaging;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_matrix_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multitexture;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_parameters;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_objects;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_100;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow_ambient;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_border_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_add;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_combine;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_crossbar;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_dot3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirrored_repeat;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_non_power_of_two;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rectangle;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transpose_matrix;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_blend;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_window_pos;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_point_sprites;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_combine3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_route;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_vertex_shader_output_point_size;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_draw_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_element_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_envmap_bumpmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_fragment_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_map_object_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_pn_triangles;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_separate_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_text_fragment_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_compression_3dc;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_env_combine3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_mirror_once;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_attrib_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_streams;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_422_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_Cg_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_abgr;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bgra;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_equation_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_func_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_logic_op;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_minmax;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_subtract;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_clip_volume_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cmyka;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_color_subtable;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_compiled_vertex_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_range_elements;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fog_coord;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fragment_lighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_histogram;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_array_formats;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_func;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_material;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_light_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_misc_attribute;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multi_draw_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_paletted_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform_color_table;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_point_parameters;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_polygon_offset;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_rescale_normal;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_scene_marker;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_secondary_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_specular_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_funcs;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shared_texture_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_two_side;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_wrap;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_subtexture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture3D;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_dxt1;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_s3tc;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_edge_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_add;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_combine;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_dot3;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_filter_anisotropic;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_lod_bias;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_mirror_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_perturb_normal;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_rectangle;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_weighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_convolution_border_modes;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_image_transform;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_occlusion_test;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_texture_lighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_cull_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_multimode_draw_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_rasterpos_clip;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_static_data;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists;
+GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read;
+GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor;
+GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_pack_invert;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_resize_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_window_pos;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_ycbcr_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_square;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_depth_to_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_evaluators;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_float_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fog_distance;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program_option;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_half_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_light_max_exponent;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_filter_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_occlusion_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_data_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_point_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_primitive_restart;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_vtc;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_env_combine4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_expand_normal;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_rectangle;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader3;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program1_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2_option;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program3;
+GLEW_VAR_EXPORT GLboolean __GLEW_OML_interlace;
+GLEW_VAR_EXPORT GLboolean __GLEW_OML_resample;
+GLEW_VAR_EXPORT GLboolean __GLEW_OML_subsample;
+GLEW_VAR_EXPORT GLboolean __GLEW_PGI_misc_hints;
+GLEW_VAR_EXPORT GLboolean __GLEW_PGI_vertex_hints;
+GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates;
+GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_detail_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_fog_function;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_generate_mipmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_pixel_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_sharpen_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture4D;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_border_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_edge_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_filter4;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_select;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_histogram;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_pixel;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_blend_alpha_minmax;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_clipmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_depth_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_flush_raster;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_offset;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fragment_specular_lighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_framezoom;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_interlace;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ir_instrument1;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_list_priority;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture_bits;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_reference_plane;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_resample;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow_ambient;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_tag_sample_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_add_env;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_coordinate_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_lod_bias;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_multi_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_scale_bias;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ycrcb;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_matrix;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_table;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGI_texture_color_table;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUNX_constant_data;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_convolution_border_modes;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_global_alpha;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_mesh_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_read_video_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_slice_accum;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_triangle_list;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_WIN_phong_shading;
+GLEW_VAR_EXPORT GLboolean __GLEW_WIN_specular_fog;
+GLEW_VAR_EXPORT GLboolean __GLEW_WIN_swap_hint;
+
+#ifdef GLEW_MX
+}; /* GLEWContextStruct */
+#endif /* GLEW_MX */
+
+/* ------------------------------------------------------------------------- */
+
+/* error codes */
+#define GLEW_OK 0
+#define GLEW_NO_ERROR 0
+#define GLEW_ERROR_NO_GL_VERSION 1  /* missing GL version */
+#define GLEW_ERROR_GL_VERSION_10_ONLY 2  /* GL 1.1 and up are not supported */
+#define GLEW_ERROR_GLX_VERSION_11_ONLY 3  /* GLX 1.2 and up are not supported */
+
+/* string codes */
+#define GLEW_VERSION 1
+
+/* API */
+#ifdef GLEW_MX
+
+typedef struct GLEWContextStruct GLEWContext;
+GLEWAPI GLenum glewContextInit (GLEWContext* ctx);
+
+#ifdef _WIN32
+#  define GLEW_GET_VAR(x) glewGetContext()->x
+#  define GLEW_GET_FUN(x) glewGetContext()->x
+#else
+#  define GLEW_GET_VAR(x) glewGetContext()->x
+#  define GLEW_GET_FUN(x) x
+#endif
+
+#else /* GLEW_MX */
+
+GLEWAPI GLenum glewInit ();
+
+#define GLEW_GET_VAR(x) x
+#define GLEW_GET_FUN(x) x
+
+#endif /* GLEW_MX */
+
+GLEWAPI GLboolean glewExperimental;
+GLEWAPI GLboolean glewGetExtension (const char* name);
+GLEWAPI const GLubyte* glewGetErrorString (GLenum error);
+GLEWAPI const GLubyte* glewGetString (GLenum name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef GLEW_APIENTRY_DEFINED
+#undef GLEW_APIENTRY_DEFINED
+#undef APIENTRY
+#undef GLAPIENTRY
+#endif
+
+#ifdef GLEW_CALLBACK_DEFINED
+#undef GLEW_CALLBACK_DEFINED
+#undef CALLBACK
+#endif
+
+#ifdef GLEW_WINGDIAPI_DEFINED
+#undef GLEW_WINGDIAPI_DEFINED
+#undef WINGDIAPI
+#endif
+
+#undef GLAPI
+/* #undef GLEWAPI */
+
+#endif /* __glew_h__ */
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GL/glext.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GL/glext.h	(revision 493)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GL/glext.h	(revision 493)
@@ -0,0 +1,3081 @@
+#ifndef __glext_h_
+#define __glext_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright 1998, 1999, 2000, 2001, NVIDIA Corporation.
+** All rights Reserved.
+** 
+** THE INFORMATION CONTAINED HEREIN IS PROPRIETARY AND CONFIDENTIAL TO
+** NVIDIA, CORPORATION.  USE, REPRODUCTION OR DISCLOSURE TO ANY THIRD PARTY
+** IS SUBJECT TO WRITTEN PRE-APPROVAL BY NVIDIA, CORPORATION.
+*/
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+** 
+** http://oss.sgi.com/projects/FreeB
+** 
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+** 
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+** 
+** Additional Notice Provisions: This software was created using the
+** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has
+** not been independently verified as being compliant with the OpenGL(R)
+** version 1.2.1 Specification.
+*/
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__)
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+
+/*************************************************************/
+
+/* Header file version number, required by OpenGL ABI for Linux */
+#define GL_GLEXT_VERSION 6
+
+#ifndef GL_VERSION_1_2
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+#define GL_FUNC_ADD                       0x8006
+#define GL_MIN                            0x8007
+#define GL_MAX                            0x8008
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+#define GL_CONVOLUTION_1D                 0x8010
+#define GL_CONVOLUTION_2D                 0x8011
+#define GL_SEPARABLE_2D                   0x8012
+#define GL_CONVOLUTION_BORDER_MODE        0x8013
+#define GL_CONVOLUTION_FILTER_SCALE       0x8014
+#define GL_CONVOLUTION_FILTER_BIAS        0x8015
+#define GL_REDUCE                         0x8016
+#define GL_CONVOLUTION_FORMAT             0x8017
+#define GL_CONVOLUTION_WIDTH              0x8018
+#define GL_CONVOLUTION_HEIGHT             0x8019
+#define GL_MAX_CONVOLUTION_WIDTH          0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT         0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE     0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE   0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE    0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE   0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS      0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS    0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS     0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS    0x8023
+#define GL_HISTOGRAM                      0x8024
+#define GL_PROXY_HISTOGRAM                0x8025
+#define GL_HISTOGRAM_WIDTH                0x8026
+#define GL_HISTOGRAM_FORMAT               0x8027
+#define GL_HISTOGRAM_RED_SIZE             0x8028
+#define GL_HISTOGRAM_GREEN_SIZE           0x8029
+#define GL_HISTOGRAM_BLUE_SIZE            0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE           0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE       0x802C
+#define GL_HISTOGRAM_SINK                 0x802D
+#define GL_MINMAX                         0x802E
+#define GL_MINMAX_FORMAT                  0x802F
+#define GL_MINMAX_SINK                    0x8030
+#define GL_TABLE_TOO_LARGE                0x8031
+#define GL_UNSIGNED_BYTE_3_3_2            0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_INT_8_8_8_8           0x8035
+#define GL_UNSIGNED_INT_10_10_10_2        0x8036
+#define GL_RESCALE_NORMAL                 0x803A
+#define GL_UNSIGNED_BYTE_2_3_3_REV        0x8362
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV       0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV     0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV     0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV       0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV    0x8368
+#define GL_COLOR_MATRIX                   0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH       0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH   0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE    0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE  0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE   0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE  0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS     0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS   0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS    0x80BA
+#define GL_COLOR_TABLE                    0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE   0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE  0x80D2
+#define GL_PROXY_COLOR_TABLE              0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE              0x80D6
+#define GL_COLOR_TABLE_BIAS               0x80D7
+#define GL_COLOR_TABLE_FORMAT             0x80D8
+#define GL_COLOR_TABLE_WIDTH              0x80D9
+#define GL_COLOR_TABLE_RED_SIZE           0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE         0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE          0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE         0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE     0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE     0x80DF
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_TEXTURE_MIN_LOD                0x813A
+#define GL_TEXTURE_MAX_LOD                0x813B
+#define GL_TEXTURE_BASE_LEVEL             0x813C
+#define GL_TEXTURE_MAX_LEVEL              0x813D
+#define GL_LIGHT_MODEL_COLOR_CONTROL      0x81F8
+#define GL_SINGLE_COLOR                   0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR        0x81FA
+
+#define GL_COMBINE                    0x8570
+#define GL_COMBINE_RGB                0x8571
+#define GL_COMBINE_ALPHA              0x8572
+#define GL_RGB_SCALE                  0x8573
+#define GL_ADD_SIGNED                 0x8574
+#define GL_INTERPOLATE                0x8575
+#define GL_CONSTANT                   0x8576
+#define GL_PRIMARY_COLOR              0x8577
+#define GL_PREVIOUS                   0x8578
+#define GL_SOURCE0_RGB                0x8580
+#define GL_SOURCE1_RGB                0x8581
+#define GL_SOURCE2_RGB                0x8582
+#define GL_SOURCE3_RGB                0x8583
+#define GL_SOURCE4_RGB                0x8584
+#define GL_SOURCE5_RGB                0x8585
+#define GL_SOURCE6_RGB                0x8586
+#define GL_SOURCE7_RGB                0x8587
+#define GL_SOURCE0_ALPHA              0x8588
+#define GL_SOURCE1_ALPHA              0x8589
+#define GL_SOURCE2_ALPHA              0x858A
+#define GL_SOURCE3_ALPHA              0x858B
+#define GL_SOURCE4_ALPHA              0x858C
+#define GL_SOURCE5_ALPHA              0x858D
+#define GL_SOURCE6_ALPHA              0x858E
+#define GL_SOURCE7_ALPHA              0x858F
+#define GL_OPERAND0_RGB               0x8590
+#define GL_OPERAND1_RGB               0x8591
+#define GL_OPERAND2_RGB               0x8592
+#define GL_OPERAND3_RGB               0x8593
+#define GL_OPERAND4_RGB               0x8594
+#define GL_OPERAND5_RGB               0x8595
+#define GL_OPERAND6_RGB               0x8596
+#define GL_OPERAND7_RGB               0x8597
+#define GL_OPERAND0_ALPHA             0x8598
+#define GL_OPERAND1_ALPHA             0x8599
+#define GL_OPERAND2_ALPHA             0x859A
+#define GL_OPERAND3_ALPHA             0x859B
+#define GL_OPERAND4_ALPHA             0x859C
+#define GL_OPERAND5_ALPHA             0x859D
+#define GL_OPERAND6_ALPHA             0x859E
+#define GL_OPERAND7_ALPHA             0x859F
+#define GL_SUBTRACT                   0x84E7
+#define GL_DOT3_RGB                   0x86AE
+#define GL_DOT3_RGBA                  0x86AF
+
+#define GL_TEXTURE0                   0x84C0
+#define GL_TEXTURE1                   0x84C1
+#define GL_TEXTURE2                   0x84C2
+#define GL_TEXTURE3                   0x84C3
+#define GL_TEXTURE4                   0x84C4
+#define GL_TEXTURE5                   0x84C5
+#define GL_TEXTURE6                   0x84C6
+#define GL_TEXTURE7                   0x84C7
+#define GL_TEXTURE8                   0x84C8
+#define GL_TEXTURE9                   0x84C9
+#define GL_TEXTURE10                  0x84CA
+#define GL_TEXTURE11                  0x84CB
+#define GL_TEXTURE12                  0x84CC
+#define GL_TEXTURE13                  0x84CD
+#define GL_TEXTURE14                  0x84CE
+#define GL_TEXTURE15                  0x84CF
+#define GL_TEXTURE16                  0x84D0
+#define GL_TEXTURE17                  0x84D1
+#define GL_TEXTURE18                  0x84D2
+#define GL_TEXTURE19                  0x84D3
+#define GL_TEXTURE20                  0x84D4
+#define GL_TEXTURE21                  0x84D5
+#define GL_TEXTURE22                  0x84D6
+#define GL_TEXTURE23                  0x84D7
+#define GL_TEXTURE24                  0x84D8
+#define GL_TEXTURE25                  0x84D9
+#define GL_TEXTURE26                  0x84DA
+#define GL_TEXTURE27                  0x84DB
+#define GL_TEXTURE28                  0x84DC
+#define GL_TEXTURE29                  0x84DD
+#define GL_TEXTURE30                  0x84DE
+#define GL_TEXTURE31                  0x84DF
+#define GL_ACTIVE_TEXTURE             0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE      0x84E1
+#define GL_MAX_TEXTURE_UNITS          0x84E2
+#define GL_CLAMP_TO_BORDER            0x812D
+#endif
+
+#ifndef GL_APPLE_specular_vector
+#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+#endif
+
+#ifndef GL_APPLE_transform_hint
+#define GL_TRANSFORM_HINT_APPLE           0x85B1
+#endif
+
+#ifndef GL_ARB_depth_texture
+#define GL_DEPTH_COMPONENT16_ARB          0x81A5
+#define GL_DEPTH_COMPONENT24_ARB          0x81A6
+#define GL_DEPTH_COMPONENT32_ARB          0x81A7
+#define GL_TEXTURE_DEPTH_SIZE_ARB         0x884A
+#define GL_DEPTH_TEXTURE_MODE_ARB         0x884B
+#endif
+
+#ifndef GL_ARB_fragment_program
+#define GL_FRAGMENT_PROGRAM_ARB                     0x8804
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB             0x8805
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB             0x8806
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB             0x8807
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB      0x8808
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB      0x8809
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB      0x880A
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB         0x880B
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB         0x880C
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB         0x880D
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB  0x880E
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB  0x880F
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB  0x8810
+#define GL_MAX_TEXTURE_COORDS_ARB                   0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB              0x8872
+#endif
+
+#ifndef GL_ARB_multisample
+#define GL_MULTISAMPLE_ARB                0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB   0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB        0x809F
+#define GL_SAMPLE_COVERAGE_ARB            0x80A0
+#define GL_SAMPLE_BUFFERS_ARB             0x80A8
+#define GL_SAMPLES_ARB                    0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB      0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB     0x80AB
+#define GL_MULTISAMPLE_BIT_ARB            0x20000000
+#endif
+
+#ifndef GL_ARB_multitexture
+#define GL_TEXTURE0_ARB                   0x84C0
+#define GL_TEXTURE1_ARB                   0x84C1
+#define GL_TEXTURE2_ARB                   0x84C2
+#define GL_TEXTURE3_ARB                   0x84C3
+#define GL_TEXTURE4_ARB                   0x84C4
+#define GL_TEXTURE5_ARB                   0x84C5
+#define GL_TEXTURE6_ARB                   0x84C6
+#define GL_TEXTURE7_ARB                   0x84C7
+#define GL_TEXTURE8_ARB                   0x84C8
+#define GL_TEXTURE9_ARB                   0x84C9
+#define GL_TEXTURE10_ARB                  0x84CA
+#define GL_TEXTURE11_ARB                  0x84CB
+#define GL_TEXTURE12_ARB                  0x84CC
+#define GL_TEXTURE13_ARB                  0x84CD
+#define GL_TEXTURE14_ARB                  0x84CE
+#define GL_TEXTURE15_ARB                  0x84CF
+#define GL_TEXTURE16_ARB                  0x84D0
+#define GL_TEXTURE17_ARB                  0x84D1
+#define GL_TEXTURE18_ARB                  0x84D2
+#define GL_TEXTURE19_ARB                  0x84D3
+#define GL_TEXTURE20_ARB                  0x84D4
+#define GL_TEXTURE21_ARB                  0x84D5
+#define GL_TEXTURE22_ARB                  0x84D6
+#define GL_TEXTURE23_ARB                  0x84D7
+#define GL_TEXTURE24_ARB                  0x84D8
+#define GL_TEXTURE25_ARB                  0x84D9
+#define GL_TEXTURE26_ARB                  0x84DA
+#define GL_TEXTURE27_ARB                  0x84DB
+#define GL_TEXTURE28_ARB                  0x84DC
+#define GL_TEXTURE29_ARB                  0x84DD
+#define GL_TEXTURE30_ARB                  0x84DE
+#define GL_TEXTURE31_ARB                  0x84DF
+#define GL_ACTIVE_TEXTURE_ARB             0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB      0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB          0x84E2
+#endif
+
+#ifndef GL_ARB_point_parameters
+#define GL_POINT_SIZE_MIN_ARB                0x8126
+#define GL_POINT_SIZE_MAX_ARB                0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_ARB     0x8128
+#define GL_POINT_DISTANCE_ATTENUATION_ARB    0x8129
+#endif
+
+#ifndef GL_EXT_point_parameters
+#define GL_POINT_SIZE_MIN_EXT                0x8126
+#define GL_POINT_SIZE_MAX_EXT                0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT     0x8128
+#define GL_DISTANCE_ATTENUATION_EXT          0x8129
+#endif
+
+#ifndef GL_ARB_shadow
+#define GL_TEXTURE_COMPARE_MODE_ARB       0x884C
+#define GL_TEXTURE_COMPARE_FUNC_ARB       0x884D
+#define GL_COMPARE_R_TO_TEXTURE_ARB       0x884E
+#endif
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_CLAMP_TO_BORDER_ARB            0x812D
+#endif
+
+#ifndef GL_ARB_texture_compression
+#define GL_COMPRESSED_ALPHA_ARB           0x84E9
+#define GL_COMPRESSED_LUMINANCE_ARB       0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_INTENSITY_ARB       0x84EC
+#define GL_COMPRESSED_RGB_ARB             0x84ED
+#define GL_COMPRESSED_RGBA_ARB            0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT_ARB   0x84EF
+#define GL_TEXTURE_IMAGE_SIZE_ARB         0x86A0
+#define GL_TEXTURE_COMPRESSED_ARB         0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+#endif
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_NORMAL_MAP_ARB                 0x8511
+#define GL_REFLECTION_MAP_ARB             0x8512
+#define GL_TEXTURE_CUBE_MAP_ARB           0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB   0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB     0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB  0x851C
+#endif
+
+#ifndef GL_ARB_texture_env_add
+#endif
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_COMBINE_ARB                    0x8570
+#define GL_COMBINE_RGB_ARB                0x8571
+#define GL_COMBINE_ALPHA_ARB              0x8572
+#define GL_RGB_SCALE_ARB                  0x8573
+#define GL_ADD_SIGNED_ARB                 0x8574
+#define GL_INTERPOLATE_ARB                0x8575
+#define GL_CONSTANT_ARB                   0x8576
+#define GL_PRIMARY_COLOR_ARB              0x8577
+#define GL_PREVIOUS_ARB                   0x8578
+#define GL_SOURCE0_RGB_ARB                0x8580
+#define GL_SOURCE1_RGB_ARB                0x8581
+#define GL_SOURCE2_RGB_ARB                0x8582
+#define GL_SOURCE0_ALPHA_ARB              0x8588
+#define GL_SOURCE1_ALPHA_ARB              0x8589
+#define GL_SOURCE2_ALPHA_ARB              0x858A
+#define GL_OPERAND0_RGB_ARB               0x8590
+#define GL_OPERAND1_RGB_ARB               0x8591
+#define GL_OPERAND2_RGB_ARB               0x8592
+#define GL_OPERAND0_ALPHA_ARB             0x8598
+#define GL_OPERAND1_ALPHA_ARB             0x8599
+#define GL_OPERAND2_ALPHA_ARB             0x859A
+#define GL_SUBTRACT_ARB                   0x84E7
+#endif
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_DOT3_RGB_ARB                   0x86AE
+#define GL_DOT3_RGBA_ARB                  0x86AF
+#endif
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_MIRRORED_REPEAT_ARB            0x8370
+#endif
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB   0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB     0x84E6
+#endif
+
+#ifndef GL_ARB_vertex_program
+#define GL_VERTEX_PROGRAM_ARB                       0x8620
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB            0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB              0x8643
+#define GL_COLOR_SUM_ARB                            0x8458
+#define GL_PROGRAM_FORMAT_ASCII_ARB                 0x8875
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB          0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB             0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB           0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB             0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB       0x886A
+#define GL_CURRENT_VERTEX_ATTRIB_ARB                0x8626
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB          0x8645
+#define GL_PROGRAM_LENGTH_ARB                       0x8627
+#define GL_PROGRAM_FORMAT_ARB                       0x8876
+#define GL_PROGRAM_BINDING_ARB                      0x8677
+#define GL_PROGRAM_INSTRUCTIONS_ARB                 0x88A0
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB             0x88A1
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB          0x88A2
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB      0x88A3
+#define GL_PROGRAM_TEMPORARIES_ARB                  0x88A4
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB              0x88A5
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB           0x88A6
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB       0x88A7
+#define GL_PROGRAM_PARAMETERS_ARB                   0x88A8
+#define GL_MAX_PROGRAM_PARAMETERS_ARB               0x88A9
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB            0x88AA
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB        0x88AB
+#define GL_PROGRAM_ATTRIBS_ARB                      0x88AC
+#define GL_MAX_PROGRAM_ATTRIBS_ARB                  0x88AD
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB               0x88AE
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB           0x88AF
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB            0x88B0
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB        0x88B1
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB     0x88B2
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB         0x88B4
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB           0x88B5
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB          0x88B6
+#define GL_PROGRAM_STRING_ARB                       0x8628
+#define GL_PROGRAM_ERROR_POSITION_ARB               0x864B
+#define GL_CURRENT_MATRIX_ARB                       0x8641
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB             0x88B7
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB           0x8640
+#define GL_MAX_VERTEX_ATTRIBS_ARB                   0x8869
+#define GL_MAX_PROGRAM_MATRICES_ARB                 0x862F
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB       0x862E
+#define GL_PROGRAM_ERROR_STRING_ARB                 0x8874
+#define GL_MATRIX0_ARB                              0x88C0
+#define GL_MATRIX1_ARB                              0x88C1
+#define GL_MATRIX2_ARB                              0x88C2
+#define GL_MATRIX3_ARB                              0x88C3
+#define GL_MATRIX4_ARB                              0x88C4
+#define GL_MATRIX5_ARB                              0x88C5
+#define GL_MATRIX6_ARB                              0x88C6
+#define GL_MATRIX7_ARB                              0x88C7
+#define GL_MATRIX8_ARB                              0x88C8
+#define GL_MATRIX9_ARB                              0x88C9
+#define GL_MATRIX10_ARB                             0x88CA
+#define GL_MATRIX11_ARB                             0x88CB
+#define GL_MATRIX12_ARB                             0x88CC
+#define GL_MATRIX13_ARB                             0x88CD
+#define GL_MATRIX14_ARB                             0x88CE
+#define GL_MATRIX15_ARB                             0x88CF
+#define GL_MATRIX16_ARB                             0x88D0
+#define GL_MATRIX17_ARB                             0x88D1
+#define GL_MATRIX18_ARB                             0x88D2
+#define GL_MATRIX19_ARB                             0x88D3
+#define GL_MATRIX20_ARB                             0x88D4
+#define GL_MATRIX21_ARB                             0x88D5
+#define GL_MATRIX22_ARB                             0x88D6
+#define GL_MATRIX23_ARB                             0x88D7
+#define GL_MATRIX24_ARB                             0x88D8
+#define GL_MATRIX25_ARB                             0x88D9
+#define GL_MATRIX26_ARB                             0x88DA
+#define GL_MATRIX27_ARB                             0x88DB
+#define GL_MATRIX28_ARB                             0x88DC
+#define GL_MATRIX29_ARB                             0x88DD
+#define GL_MATRIX30_ARB                             0x88DE
+#define GL_MATRIX31_ARB                             0x88DF
+#endif
+
+#ifndef GL_ARB_window_pos
+#endif
+
+#ifndef GL_EXT_422_pixels
+#define GL_422_EXT                        0x80CC
+#define GL_422_REV_EXT                    0x80CD
+#define GL_422_AVERAGE_EXT                0x80CE
+#define GL_422_REV_AVERAGE_EXT            0x80CF
+#endif
+
+#ifndef GL_EXT_abgr
+#define GL_ABGR_EXT                       0x8000
+#endif
+
+#ifndef GL_EXT_bgra
+#define GL_BGR_EXT                        0x80E0
+#define GL_BGRA_EXT                       0x80E1
+#endif
+
+#ifndef GL_EXT_blend_color
+#define GL_CONSTANT_COLOR_EXT             0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR_EXT   0x8002
+#define GL_CONSTANT_ALPHA_EXT             0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT   0x8004
+#define GL_BLEND_COLOR_EXT                0x8005
+#endif
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_BLEND_DST_RGB_EXT              0x80C8
+#define GL_BLEND_SRC_RGB_EXT              0x80C9
+#define GL_BLEND_DST_ALPHA_EXT            0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT            0x80CB
+#endif
+
+#ifndef GL_EXT_blend_logic_op
+#endif
+
+#ifndef GL_EXT_blend_minmax
+#define GL_FUNC_ADD_EXT                   0x8006
+#define GL_MIN_EXT                        0x8007
+#define GL_MAX_EXT                        0x8008
+#define GL_BLEND_EQUATION_EXT             0x8009
+#endif
+
+#ifndef GL_EXT_blend_subtract
+#define GL_FUNC_SUBTRACT_EXT              0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_EXT      0x800B
+#endif
+
+#ifndef GL_EXT_polygon_offset
+#define GL_POLYGON_OFFSET_EXT             0x8037
+#define GL_POLYGON_OFFSET_FACTOR_EXT      0x8038
+#define GL_POLYGON_OFFSET_BIAS_EXT        0x8039
+#endif
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT  0x80F0
+#endif
+
+#ifndef GL_EXT_cmyka
+#define GL_CMYK_EXT                       0x800C
+#define GL_CMYKA_EXT                      0x800D
+#define GL_PACK_CMYK_HINT_EXT             0x800E
+#define GL_UNPACK_CMYK_HINT_EXT           0x800F
+#endif
+
+#ifndef GL_EXT_color_subtable
+#endif
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT   0x81A8
+#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT   0x81A9
+#endif
+
+#ifndef GL_EXT_convolution
+#define GL_CONVOLUTION_1D_EXT             0x8010
+#define GL_CONVOLUTION_2D_EXT             0x8011
+#define GL_SEPARABLE_2D_EXT               0x8012
+#define GL_CONVOLUTION_BORDER_MODE_EXT    0x8013
+#define GL_CONVOLUTION_FILTER_SCALE_EXT   0x8014
+#define GL_CONVOLUTION_FILTER_BIAS_EXT    0x8015
+#define GL_REDUCE_EXT                     0x8016
+#define GL_CONVOLUTION_FORMAT_EXT         0x8017
+#define GL_CONVOLUTION_WIDTH_EXT          0x8018
+#define GL_CONVOLUTION_HEIGHT_EXT         0x8019
+#define GL_MAX_CONVOLUTION_WIDTH_EXT      0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT_EXT     0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS_EXT  0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+#endif
+
+#ifndef GL_EXT_copy_texture
+#endif
+
+#ifndef GL_EXT_cull_vertex
+#define GL_CULL_VERTEX_EXT                0x81AA
+#define GL_CULL_VERTEX_EYE_POSITION_EXT   0x81AB
+#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC
+#endif
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_MAX_ELEMENTS_VERTICES_EXT      0x80E8
+#define GL_MAX_ELEMENTS_INDICES_EXT       0x80E9
+#endif
+
+#ifndef GL_EXT_fog_coord
+#define GL_FOG_COORDINATE_SOURCE_EXT      0x8450
+#define GL_FOG_COORDINATE_EXT             0x8451
+#define GL_FRAGMENT_DEPTH_EXT             0x8452
+#define GL_CURRENT_FOG_COORDINATE_EXT     0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT  0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_EXT       0x8457
+#endif
+
+#ifndef GL_EXT_histogram
+#define GL_HISTOGRAM_EXT                  0x8024
+#define GL_PROXY_HISTOGRAM_EXT            0x8025
+#define GL_HISTOGRAM_WIDTH_EXT            0x8026
+#define GL_HISTOGRAM_FORMAT_EXT           0x8027
+#define GL_HISTOGRAM_RED_SIZE_EXT         0x8028
+#define GL_HISTOGRAM_GREEN_SIZE_EXT       0x8029
+#define GL_HISTOGRAM_BLUE_SIZE_EXT        0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE_EXT       0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT   0x802C
+#define GL_HISTOGRAM_SINK_EXT             0x802D
+#define GL_MINMAX_EXT                     0x802E
+#define GL_MINMAX_FORMAT_EXT              0x802F
+#define GL_MINMAX_SINK_EXT                0x8030
+#define GL_TABLE_TOO_LARGE_EXT            0x8031
+#endif
+
+#ifndef GL_EXT_misc_attribute
+#endif
+
+#ifndef GL_EXT_index_array_formats
+#define GL_IUI_V2F_EXT                    0x81AD
+#define GL_IUI_V3F_EXT                    0x81AE
+#define GL_IUI_N3F_V2F_EXT                0x81AF
+#define GL_IUI_N3F_V3F_EXT                0x81B0
+#define GL_T2F_IUI_V2F_EXT                0x81B1
+#define GL_T2F_IUI_V3F_EXT                0x81B2
+#define GL_T2F_IUI_N3F_V2F_EXT            0x81B3
+#define GL_T2F_IUI_N3F_V3F_EXT            0x81B4
+#endif
+
+#ifndef GL_EXT_index_func
+#define GL_INDEX_TEST_EXT                 0x81B5
+#define GL_INDEX_TEST_FUNC_EXT            0x81B6
+#define GL_INDEX_TEST_REF_EXT             0x81B7
+#endif
+
+#ifndef GL_EXT_index_material
+#define GL_INDEX_MATERIAL_EXT             0x81B8
+#define GL_INDEX_MATERIAL_PARAMETER_EXT   0x81B9
+#define GL_INDEX_MATERIAL_FACE_EXT        0x81BA
+#endif
+
+#ifndef GL_EXT_index_texture
+#endif
+
+#ifndef GL_EXT_light_texture
+#define GL_FRAGMENT_MATERIAL_EXT          0x8349
+#define GL_FRAGMENT_NORMAL_EXT            0x834A
+#define GL_FRAGMENT_COLOR_EXT             0x834C
+#define GL_ATTENUATION_EXT                0x834D
+#define GL_SHADOW_ATTENUATION_EXT         0x834E
+#define GL_TEXTURE_APPLICATION_MODE_EXT   0x834F
+#define GL_TEXTURE_LIGHT_EXT              0x8350
+#define GL_TEXTURE_MATERIAL_FACE_EXT      0x8351
+#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+/* reuse GL_FRAGMENT_DEPTH_EXT */
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#endif
+
+#ifndef GL_EXT_packed_pixels
+#define GL_UNSIGNED_BYTE_3_3_2_EXT        0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4_EXT     0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1_EXT     0x8034
+#define GL_UNSIGNED_INT_8_8_8_8_EXT       0x8035
+#define GL_UNSIGNED_INT_10_10_10_2_EXT    0x8036
+#endif
+
+#ifndef GL_EXT_paletted_texture
+#define GL_COLOR_INDEX1_EXT               0x80E2
+#define GL_COLOR_INDEX2_EXT               0x80E3
+#define GL_COLOR_INDEX4_EXT               0x80E4
+#define GL_COLOR_INDEX8_EXT               0x80E5
+#define GL_COLOR_INDEX12_EXT              0x80E6
+#define GL_COLOR_INDEX16_EXT              0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT         0x80ED
+#endif
+
+#ifndef GL_EXT_pixel_transform
+#define GL_PIXEL_TRANSFORM_2D_EXT         0x8330
+#define GL_PIXEL_MAG_FILTER_EXT           0x8331
+#define GL_PIXEL_MIN_FILTER_EXT           0x8332
+#define GL_PIXEL_CUBIC_WEIGHT_EXT         0x8333
+#define GL_CUBIC_EXT                      0x8334
+#define GL_AVERAGE_EXT                    0x8335
+#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT  0x8338
+#endif
+
+#ifndef GL_EXT_pixel_transform_color_table
+#endif
+
+#ifndef GL_EXT_point_parameters
+#endif
+
+#ifndef GL_EXT_rescale_normal
+#define GL_RESCALE_NORMAL_EXT             0x803A
+#endif
+
+#ifndef GL_EXT_secondary_color
+#define GL_COLOR_SUM_EXT                  0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT    0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT      0x845E
+#endif
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT  0x81F8
+#define GL_SINGLE_COLOR_EXT               0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT    0x81FA
+#endif
+
+#ifndef GL_EXT_shadow_funcs
+#endif
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_SHARED_TEXTURE_PALETTE_EXT     0x81FB
+#endif
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_STENCIL_TEST_TWO_SIDE_EXT      0x8910
+#define GL_ACTIVE_STENCIL_FACE_EXT        0x8911
+#endif
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_INCR_WRAP_EXT                  0x8507
+#define GL_DECR_WRAP_EXT                  0x8508
+#endif
+
+#ifndef GL_EXT_subtexture
+#endif
+
+#ifndef GL_EXT_texture
+#define GL_ALPHA4_EXT                     0x803B
+#define GL_ALPHA8_EXT                     0x803C
+#define GL_ALPHA12_EXT                    0x803D
+#define GL_ALPHA16_EXT                    0x803E
+#define GL_LUMINANCE4_EXT                 0x803F
+#define GL_LUMINANCE8_EXT                 0x8040
+#define GL_LUMINANCE12_EXT                0x8041
+#define GL_LUMINANCE16_EXT                0x8042
+#define GL_LUMINANCE4_ALPHA4_EXT          0x8043
+#define GL_LUMINANCE6_ALPHA2_EXT          0x8044
+#define GL_LUMINANCE8_ALPHA8_EXT          0x8045
+#define GL_LUMINANCE12_ALPHA4_EXT         0x8046
+#define GL_LUMINANCE12_ALPHA12_EXT        0x8047
+#define GL_LUMINANCE16_ALPHA16_EXT        0x8048
+#define GL_INTENSITY_EXT                  0x8049
+#define GL_INTENSITY4_EXT                 0x804A
+#define GL_INTENSITY8_EXT                 0x804B
+#define GL_INTENSITY12_EXT                0x804C
+#define GL_INTENSITY16_EXT                0x804D
+#define GL_RGB2_EXT                       0x804E
+#define GL_RGB4_EXT                       0x804F
+#define GL_RGB5_EXT                       0x8050
+#define GL_RGB8_EXT                       0x8051
+#define GL_RGB10_EXT                      0x8052
+#define GL_RGB12_EXT                      0x8053
+#define GL_RGB16_EXT                      0x8054
+#define GL_RGBA2_EXT                      0x8055
+#define GL_RGBA4_EXT                      0x8056
+#define GL_RGB5_A1_EXT                    0x8057
+#define GL_RGBA8_EXT                      0x8058
+#define GL_RGB10_A2_EXT                   0x8059
+#define GL_RGBA12_EXT                     0x805A
+#define GL_RGBA16_EXT                     0x805B
+#define GL_TEXTURE_RED_SIZE_EXT           0x805C
+#define GL_TEXTURE_GREEN_SIZE_EXT         0x805D
+#define GL_TEXTURE_BLUE_SIZE_EXT          0x805E
+#define GL_TEXTURE_ALPHA_SIZE_EXT         0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE_EXT     0x8060
+#define GL_TEXTURE_INTENSITY_SIZE_EXT     0x8061
+#define GL_REPLACE_EXT                    0x8062
+#define GL_PROXY_TEXTURE_1D_EXT           0x8063
+#define GL_PROXY_TEXTURE_2D_EXT           0x8064
+#define GL_TEXTURE_TOO_LARGE_EXT          0x8065
+#endif
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3
+#endif
+
+#ifndef GL_EXT_texture_cube_map
+#define GL_NORMAL_MAP_EXT                 0x8511
+#define GL_REFLECTION_MAP_EXT             0x8512
+#define GL_TEXTURE_CUBE_MAP_EXT           0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_EXT   0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_EXT     0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT  0x851C
+#endif
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_TANGENT_ARRAY_EXT              0x8439
+#define GL_BINORMAL_ARRAY_EXT             0x843A
+#define GL_CURRENT_TANGENT_EXT            0x843B
+#define GL_CURRENT_BINORMAL_EXT           0x843C
+#define GL_TANGENT_ARRAY_TYPE_EXT         0x843E
+#define GL_TANGENT_ARRAY_STRIDE_EXT       0x843F
+#define GL_BINORMAL_ARRAY_TYPE_EXT        0x8440
+#define GL_BINORMAL_ARRAY_STRIDE_EXT      0x8441
+#define GL_TANGENT_ARRAY_POINTER_EXT      0x8442
+#define GL_BINORMAL_ARRAY_POINTER_EXT     0x8443
+#define GL_MAP1_TANGENT_EXT               0x8444
+#define GL_MAP2_TANGENT_EXT               0x8445
+#define GL_MAP1_BINORMAL_EXT              0x8446
+#define GL_MAP2_BINORMAL_EXT              0x8447
+#endif
+
+#ifndef GL_EXT_texture_edge_clamp
+#define CLAMP_TO_EDGE_EXT                 0x812F
+#endif
+
+#ifndef GL_EXT_texture_env_add
+#endif
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_COMBINE_EXT                    0x8570
+#define GL_COMBINE_RGB_EXT                0x8571
+#define GL_COMBINE_ALPHA_EXT              0x8572
+#define GL_RGB_SCALE_EXT                  0x8573
+#define GL_ADD_SIGNED_EXT                 0x8574
+#define GL_INTERPOLATE_EXT                0x8575
+#define GL_CONSTANT_EXT                   0x8576
+#define GL_PRIMARY_COLOR_EXT              0x8577
+#define GL_PREVIOUS_EXT                   0x8578
+#define GL_SOURCE0_RGB_EXT                0x8580
+#define GL_SOURCE1_RGB_EXT                0x8581
+#define GL_SOURCE2_RGB_EXT                0x8582
+#define GL_SOURCE3_RGB_EXT                0x8583
+#define GL_SOURCE4_RGB_EXT                0x8584
+#define GL_SOURCE5_RGB_EXT                0x8585
+#define GL_SOURCE6_RGB_EXT                0x8586
+#define GL_SOURCE7_RGB_EXT                0x8587
+#define GL_SOURCE0_ALPHA_EXT              0x8588
+#define GL_SOURCE1_ALPHA_EXT              0x8589
+#define GL_SOURCE2_ALPHA_EXT              0x858A
+#define GL_SOURCE3_ALPHA_EXT              0x858B
+#define GL_SOURCE4_ALPHA_EXT              0x858C
+#define GL_SOURCE5_ALPHA_EXT              0x858D
+#define GL_SOURCE6_ALPHA_EXT              0x858E
+#define GL_SOURCE7_ALPHA_EXT              0x858F
+#define GL_OPERAND0_RGB_EXT               0x8590
+#define GL_OPERAND1_RGB_EXT               0x8591
+#define GL_OPERAND2_RGB_EXT               0x8592
+#define GL_OPERAND3_RGB_EXT               0x8593
+#define GL_OPERAND4_RGB_EXT               0x8594
+#define GL_OPERAND5_RGB_EXT               0x8595
+#define GL_OPERAND6_RGB_EXT               0x8596
+#define GL_OPERAND7_RGB_EXT               0x8597
+#define GL_OPERAND0_ALPHA_EXT             0x8598
+#define GL_OPERAND1_ALPHA_EXT             0x8599
+#define GL_OPERAND2_ALPHA_EXT             0x859A
+#define GL_OPERAND3_ALPHA_EXT             0x859B
+#define GL_OPERAND4_ALPHA_EXT             0x859C
+#define GL_OPERAND5_ALPHA_EXT             0x859D
+#define GL_OPERAND6_ALPHA_EXT             0x859E
+#define GL_OPERAND7_ALPHA_EXT             0x859F
+#endif
+
+#ifndef GL_EXT_texture_env_dot3 
+#define GL_DOT3_RGB_EXT                   0x8740
+#define GL_DOT3_RGBA_EXT                  0x8741
+#endif 
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT     0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT       0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT     0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT           0x8501
+#endif
+
+#ifndef GL_EXT_texture_object
+#define GL_TEXTURE_PRIORITY_EXT           0x8066
+#define GL_TEXTURE_RESIDENT_EXT           0x8067
+#define GL_TEXTURE_1D_BINDING_EXT         0x8068
+#define GL_TEXTURE_2D_BINDING_EXT         0x8069
+#define GL_TEXTURE_3D_BINDING_EXT         0x806A
+#endif
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_PERTURB_EXT                    0x85AE
+#define GL_TEXTURE_NORMAL_EXT             0x85AF
+#endif
+
+#ifndef GL_EXT_texture3D
+#define GL_PACK_SKIP_IMAGES               0x806B
+#define GL_PACK_SKIP_IMAGES_EXT           0x806B
+#define GL_PACK_IMAGE_HEIGHT              0x806C
+#define GL_PACK_IMAGE_HEIGHT_EXT          0x806C
+#define GL_UNPACK_SKIP_IMAGES             0x806D
+#define GL_UNPACK_SKIP_IMAGES_EXT         0x806D
+#define GL_UNPACK_IMAGE_HEIGHT            0x806E
+#define GL_UNPACK_IMAGE_HEIGHT_EXT        0x806E
+#define GL_TEXTURE_3D                     0x806F
+#define GL_TEXTURE_3D_EXT                 0x806F
+#define GL_PROXY_TEXTURE_3D               0x8070
+#define GL_PROXY_TEXTURE_3D_EXT           0x8070
+#define GL_TEXTURE_DEPTH                  0x8071
+#define GL_TEXTURE_DEPTH_EXT              0x8071
+#define GL_TEXTURE_WRAP_R                 0x8072
+#define GL_TEXTURE_WRAP_R_EXT             0x8072
+#define GL_MAX_3D_TEXTURE_SIZE            0x8073
+#define GL_MAX_3D_TEXTURE_SIZE_EXT        0x8073
+#endif
+
+#ifndef GL_EXT_vertex_array
+#define GL_VERTEX_ARRAY_EXT               0x8074
+#define GL_NORMAL_ARRAY_EXT               0x8075
+#define GL_COLOR_ARRAY_EXT                0x8076
+#define GL_INDEX_ARRAY_EXT                0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT        0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT            0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT          0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT          0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT        0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT         0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT          0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT        0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT         0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT           0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT           0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT         0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT          0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT           0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT         0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT          0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT   0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT   0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT  0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT     0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT      0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT       0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT       0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT        0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT        0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT    0x8093
+#endif
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_MODELVIEW0_STACK_DEPTH_EXT     GL_MODELVIEW_STACK_DEPTH
+#define GL_MODELVIEW1_STACK_DEPTH_EXT     0x8502
+#define GL_MODELVIEW0_MATRIX_EXT          GL_MODELVIEW_MATRIX
+#define GL_MODELVIEW_MATRIX1_EXT          0x8506
+#define GL_VERTEX_WEIGHTING_EXT           0x8509
+#define GL_MODELVIEW0_EXT                 GL_MODELVIEW
+#define GL_MODELVIEW1_EXT                 0x850A
+#define GL_CURRENT_VERTEX_WEIGHT_EXT      0x850B
+#define GL_VERTEX_WEIGHT_ARRAY_EXT        0x850C
+#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT   0x850D
+#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT   0x850E
+#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+#endif
+
+#ifndef GL_HP_occlusion_test
+#define GL_OCCLUSION_TEST_HP              0x8165
+#define GL_OCCLUSION_TEST_RESULT_HP       0x8166
+#endif
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_IGNORE_BORDER_HP               0x8150
+#define GL_CONSTANT_BORDER_HP             0x8151
+#define GL_REPLICATE_BORDER_HP            0x8153
+#define GL_CONVOLUTION_BORDER_COLOR_HP    0x8154
+#endif
+
+#ifndef GL_HP_image_transform
+#define GL_IMAGE_SCALE_X_HP               0x8155
+#define GL_IMAGE_SCALE_Y_HP               0x8156
+#define GL_IMAGE_TRANSLATE_X_HP           0x8157
+#define GL_IMAGE_TRANSLATE_Y_HP           0x8158
+#define GL_IMAGE_ROTATE_ANGLE_HP          0x8159
+#define GL_IMAGE_ROTATE_ORIGIN_X_HP       0x815A
+#define GL_IMAGE_ROTATE_ORIGIN_Y_HP       0x815B
+#define GL_IMAGE_MAG_FILTER_HP            0x815C
+#define GL_IMAGE_MIN_FILTER_HP            0x815D
+#define GL_IMAGE_CUBIC_WEIGHT_HP          0x815E
+#define GL_CUBIC_HP                       0x815F
+#define GL_AVERAGE_HP                     0x8160
+#define GL_IMAGE_TRANSFORM_2D_HP          0x8161
+#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162
+#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163
+#endif
+
+#ifndef GL_HP_texture_lighting
+#define GL_TEXTURE_LIGHTING_MODE_HP       0x8167
+#define GL_TEXTURE_POST_SPECULAR_HP       0x8168
+#define GL_TEXTURE_PRE_SPECULAR_HP        0x8169
+#endif
+
+#ifndef GL_IBM_cull_vertex
+#define GL_CULL_VERTEX_IBM                103050
+#endif
+
+#ifndef GL_IBM_multimode_draw_arrays
+#endif
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_RASTER_POSITION_UNCLIPPED_IBM  0x19262
+#endif
+
+#ifndef GL_IBM_texture_mirrored_repeat
+#define GL_MIRRORED_REPEAT_IBM            0x8370
+#endif
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_VERTEX_ARRAY_LIST_IBM          103070
+#define GL_NORMAL_ARRAY_LIST_IBM          103071
+#define GL_COLOR_ARRAY_LIST_IBM           103072
+#define GL_INDEX_ARRAY_LIST_IBM           103073
+#define GL_TEXTURE_COORD_ARRAY_LIST_IBM   103074
+#define GL_EDGE_FLAG_ARRAY_LIST_IBM       103075
+#define GL_FOG_COORDINATE_ARRAY_LIST_IBM  103076
+#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM   103080
+#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM   103081
+#define GL_COLOR_ARRAY_LIST_STRIDE_IBM    103082
+#define GL_INDEX_ARRAY_LIST_STRIDE_IBM    103083
+#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+#endif
+
+#ifndef GL_INGR_color_clamp
+#define GL_RED_MIN_CLAMP_INGR             0x8560
+#define GL_GREEN_MIN_CLAMP_INGR           0x8561
+#define GL_BLUE_MIN_CLAMP_INGR            0x8562
+#define GL_ALPHA_MIN_CLAMP_INGR           0x8563
+#define GL_RED_MAX_CLAMP_INGR             0x8564
+#define GL_GREEN_MAX_CLAMP_INGR           0x8565
+#define GL_BLUE_MAX_CLAMP_INGR            0x8566
+#define GL_ALPHA_MAX_CLAMP_INGR           0x8567
+#endif
+
+#ifndef GL_INGR_interlace_read
+#define GL_INTERLACE_READ_INGR            0x8568
+#endif
+
+#ifndef GL_INGR_palette_buffer
+#endif
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_PARALLEL_ARRAYS_INTEL          0x83F4
+#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+#endif
+
+#ifndef GL_INTEL_texture_scissor
+#endif
+
+#ifndef GL_MESA_resize_buffers
+#endif
+
+#ifndef GL_MESA_window_pos
+#endif
+
+#ifndef GL_NV_blend_square
+#endif
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_DEPTH_STENCIL_TO_RGBA_NV       0x886E
+#define GL_DEPTH_STENCIL_TO_BGRA_NV       0x886F
+#endif
+
+#ifndef GL_NV_depth_clamp
+#define GL_DEPTH_CLAMP_NV                 0x864F
+#endif
+
+#ifndef GL_NV_element_array
+#define GL_ELEMENT_ARRAY_TYPE_NV          0x8769
+#define GL_ELEMENT_ARRAY_POINTER_NV       0x876A
+#endif
+
+#ifndef GL_NV_fence 
+#define GL_ALL_COMPLETED_NV               0x84F2
+#define GL_FENCE_STATUS_NV                0x84F3
+#define GL_FENCE_CONDITION_NV             0x84F4
+#endif
+
+#ifndef GL_NV_float_buffer
+#define GL_FLOAT_R_NV                     0x8880
+#define GL_FLOAT_RG_NV                    0x8881
+#define GL_FLOAT_RGB_NV                   0x8882
+#define GL_FLOAT_RGBA_NV                  0x8883
+#define GL_FLOAT_R16_NV                   0x8884
+#define GL_FLOAT_R32_NV                   0x8885
+#define GL_FLOAT_RG16_NV                  0x8886
+#define GL_FLOAT_RG32_NV                  0x8887
+#define GL_FLOAT_RGB16_NV                 0x8888
+#define GL_FLOAT_RGB32_NV                 0x8889
+#define GL_FLOAT_RGBA16_NV                0x888A
+#define GL_FLOAT_RGBA32_NV                0x888B
+#define GL_TEXTURE_FLOAT_COMPONENTS_NV    0x888C
+#define GL_FLOAT_CLEAR_COLOR_VALUE_NV     0x888D
+#define GL_FLOAT_RGBA_MODE_NV             0x888E
+#endif
+
+#ifndef GL_NV_fog_distance
+#define GL_FOG_DISTANCE_MODE_NV           0x855A
+#define GL_EYE_RADIAL_NV                  0x855B
+#define GL_EYE_PLANE_ABSOLUTE_NV          0x855C
+/* reuse GL_EYE_PLANE */
+#endif
+
+#ifndef GL_NV_fragment_program
+#define GL_FRAGMENT_PROGRAM_NV            0x8870
+#define GL_MAX_TEXTURE_COORDS_NV          0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_NV     0x8872
+#define GL_FRAGMENT_PROGRAM_BINDING_NV    0x8873
+#define GL_PROGRAM_ERROR_STRING_NV        0x8874
+#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#endif
+
+#ifndef GL_NV_half_float
+#define GL_HALF_FLOAT_NV                  0x140B
+#endif
+
+#ifndef GL_NV_light_max_exponent
+#define GL_MAX_SHININESS_NV               0x8504
+#define GL_MAX_SPOT_EXPONENT_NV           0x8505
+#endif
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_MULTISAMPLE_FILTER_HINT_NV     0x8534
+#endif
+
+#ifndef GL_NV_occlusion_query
+#define GL_PIXEL_COUNTER_BITS_NV          0x8864
+#define GL_CURRENT_OCCLUSION_QUERY_ID_NV  0x8865
+#define GL_PIXEL_COUNT_NV                 0x8866
+#define GL_PIXEL_COUNT_AVAILABLE_NV       0x8867
+#endif
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_DEPTH_STENCIL_NV               0x84F9
+#define GL_UNSIGNED_INT_24_8_NV           0x84FA
+#endif
+
+#ifndef GL_NV_pixel_data_range
+#define GL_WRITE_PIXEL_DATA_RANGE_NV      0x8878
+#define GL_READ_PIXEL_DATA_RANGE_NV       0x8879
+#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+#endif
+
+#ifndef GL_NV_point_sprite
+#define GL_POINT_SPRITE_NV                0x8861
+#define GL_COORD_REPLACE_NV               0x8862
+#define GL_POINT_SPRITE_R_MODE_NV         0x8863
+#endif
+
+#ifndef GL_NV_primitive_restart
+#define GL_PRIMITIVE_RESTART_NV           0x8558
+#define GL_PRIMITIVE_RESTART_INDEX_NV     0x8559
+#endif
+
+#ifndef GL_NV_register_combiners
+#define GL_REGISTER_COMBINERS_NV          0x8522
+#define GL_VARIABLE_A_NV                  0x8523
+#define GL_VARIABLE_B_NV                  0x8524
+#define GL_VARIABLE_C_NV                  0x8525
+#define GL_VARIABLE_D_NV                  0x8526
+#define GL_VARIABLE_E_NV                  0x8527
+#define GL_VARIABLE_F_NV                  0x8528
+#define GL_VARIABLE_G_NV                  0x8529
+#define GL_CONSTANT_COLOR0_NV             0x852A
+#define GL_CONSTANT_COLOR1_NV             0x852B
+#define GL_PRIMARY_COLOR_NV               0x852C
+#define GL_SECONDARY_COLOR_NV             0x852D
+#define GL_SPARE0_NV                      0x852E
+#define GL_SPARE1_NV                      0x852F
+#define GL_DISCARD_NV                     0x8530
+#define GL_E_TIMES_F_NV                   0x8531
+#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define GL_UNSIGNED_IDENTITY_NV           0x8536
+#define GL_UNSIGNED_INVERT_NV             0x8537
+#define GL_EXPAND_NORMAL_NV               0x8538
+#define GL_EXPAND_NEGATE_NV               0x8539
+#define GL_HALF_BIAS_NORMAL_NV            0x853A
+#define GL_HALF_BIAS_NEGATE_NV            0x853B
+#define GL_SIGNED_IDENTITY_NV             0x853C
+#define GL_SIGNED_NEGATE_NV               0x853D
+#define GL_SCALE_BY_TWO_NV                0x853E
+#define GL_SCALE_BY_FOUR_NV               0x853F
+#define GL_SCALE_BY_ONE_HALF_NV           0x8540
+#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV   0x8541
+#define GL_COMBINER_INPUT_NV              0x8542
+#define GL_COMBINER_MAPPING_NV            0x8543
+#define GL_COMBINER_COMPONENT_USAGE_NV    0x8544
+#define GL_COMBINER_AB_DOT_PRODUCT_NV     0x8545
+#define GL_COMBINER_CD_DOT_PRODUCT_NV     0x8546
+#define GL_COMBINER_MUX_SUM_NV            0x8547
+#define GL_COMBINER_SCALE_NV              0x8548
+#define GL_COMBINER_BIAS_NV               0x8549
+#define GL_COMBINER_AB_OUTPUT_NV          0x854A
+#define GL_COMBINER_CD_OUTPUT_NV          0x854B
+#define GL_COMBINER_SUM_OUTPUT_NV         0x854C
+#define GL_MAX_GENERAL_COMBINERS_NV       0x854D
+#define GL_NUM_GENERAL_COMBINERS_NV       0x854E
+#define GL_COLOR_SUM_CLAMP_NV             0x854F
+#define GL_COMBINER0_NV                   0x8550
+#define GL_COMBINER1_NV                   0x8551
+#define GL_COMBINER2_NV                   0x8552
+#define GL_COMBINER3_NV                   0x8553
+#define GL_COMBINER4_NV                   0x8554
+#define GL_COMBINER5_NV                   0x8555
+#define GL_COMBINER6_NV                   0x8556
+#define GL_COMBINER7_NV                   0x8557
+/* reuse GL_TEXTURE0_ARB */
+/* reuse GL_TEXTURE1_ARB */
+/* reuse GL_ZERO */
+/* reuse GL_NONE */
+/* reuse GL_FOG */
+#endif
+
+#ifndef GL_NV_register_combiners2
+#define GL_PER_STAGE_CONSTANTS_NV         0x8535
+#endif
+
+#ifndef GL_NV_stencil_two_side
+#define GL_STENCIL_TEST_TWO_SIDE_NV       0x8910
+#define GL_ACTIVE_STENCIL_FACE_NV         0x8911
+#endif
+
+#ifndef GL_NV_texgen_emboss
+#define GL_EMBOSS_LIGHT_NV                0x855D
+#define GL_EMBOSS_CONSTANT_NV             0x855E
+#define GL_EMBOSS_MAP_NV                  0x855F
+#endif
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NORMAL_MAP_NV                  0x8511
+#define GL_REFLECTION_MAP_NV              0x8512
+#endif
+
+#ifndef GL_NV_texture_compression_vtc
+#endif
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_COMBINE4_NV                    0x8503
+#define GL_SOURCE3_RGB_NV                 0x8583
+#define GL_SOURCE3_ALPHA_NV               0x858B
+#define GL_OPERAND3_RGB_NV                0x8593
+#define GL_OPERAND3_ALPHA_NV              0x859B
+#endif
+
+#ifndef GL_NV_texture_rectangle
+#define GL_TEXTURE_RECTANGLE_NV           0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_NV   0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_NV     0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV  0x84F8
+#endif
+
+#ifndef GL_NV_texture_shader
+#define GL_OFFSET_TEXTURE_RECTANGLE_NV    0x864C
+#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV      0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV  0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV          0x86DC
+#define GL_SHADER_CONSISTENT_NV           0x86DD
+#define GL_TEXTURE_SHADER_NV              0x86DE
+#define GL_SHADER_OPERATION_NV            0x86DF
+#define GL_CULL_MODES_NV                  0x86E0
+#define GL_OFFSET_TEXTURE_MATRIX_NV       0x86E1
+#define GL_OFFSET_TEXTURE_SCALE_NV        0x86E2
+#define GL_OFFSET_TEXTURE_BIAS_NV         0x86E3
+#define GL_OFFSET_TEXTURE_2D_MATRIX_NV    GL_OFFSET_TEXTURE_MATRIX_NV
+#define GL_OFFSET_TEXTURE_2D_SCALE_NV     GL_OFFSET_TEXTURE_SCALE_NV
+#define GL_OFFSET_TEXTURE_2D_BIAS_NV      GL_OFFSET_TEXTURE_BIAS_NV
+#define GL_PREVIOUS_TEXTURE_INPUT_NV      0x86E4
+#define GL_CONST_EYE_NV                   0x86E5
+#define GL_PASS_THROUGH_NV                0x86E6
+#define GL_CULL_FRAGMENT_NV               0x86E7
+#define GL_OFFSET_TEXTURE_2D_NV           0x86E8
+#define GL_DEPENDENT_AR_TEXTURE_2D_NV     0x86E9
+#define GL_DEPENDENT_GB_TEXTURE_2D_NV     0x86EA
+#define GL_DOT_PRODUCT_NV                 0x86EC
+#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV   0x86ED
+#define GL_DOT_PRODUCT_TEXTURE_2D_NV      0x86EE
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV      0x86EF
+#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define GL_HILO_NV                        0x86F4
+#define GL_DSDT_NV                        0x86F5
+#define GL_DSDT_MAG_NV                    0x86F6
+#define GL_DSDT_MAG_VIB_NV                0x86F7
+#define GL_HILO16_NV                      0x86F8
+#define GL_SIGNED_HILO_NV                 0x86F9
+#define GL_SIGNED_HILO16_NV               0x86FA
+#define GL_SIGNED_RGBA_NV                 0x86FB
+#define GL_SIGNED_RGBA8_NV                0x86FC
+#define GL_SIGNED_RGB_NV                  0x86FE
+#define GL_SIGNED_RGB8_NV                 0x86FF
+#define GL_SIGNED_LUMINANCE_NV            0x8701
+#define GL_SIGNED_LUMINANCE8_NV           0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV      0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV    0x8704
+#define GL_SIGNED_ALPHA_NV                0x8705
+#define GL_SIGNED_ALPHA8_NV               0x8706
+#define GL_SIGNED_INTENSITY_NV            0x8707
+#define GL_SIGNED_INTENSITY8_NV           0x8708
+#define GL_DSDT8_NV                       0x8709
+#define GL_DSDT8_MAG8_NV                  0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV       0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV   0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define GL_HI_SCALE_NV                    0x870E
+#define GL_LO_SCALE_NV                    0x870F
+#define GL_DS_SCALE_NV                    0x8710
+#define GL_DT_SCALE_NV                    0x8711
+#define GL_MAGNITUDE_SCALE_NV             0x8712
+#define GL_VIBRANCE_SCALE_NV              0x8713
+#define GL_HI_BIAS_NV                     0x8714
+#define GL_LO_BIAS_NV                     0x8715
+#define GL_DS_BIAS_NV                     0x8716
+#define GL_DT_BIAS_NV                     0x8717
+#define GL_MAGNITUDE_BIAS_NV              0x8718
+#define GL_VIBRANCE_BIAS_NV               0x8719
+#define GL_TEXTURE_BORDER_VALUES_NV       0x871A
+#define GL_TEXTURE_HI_SIZE_NV             0x871B
+#define GL_TEXTURE_LO_SIZE_NV             0x871C
+#define GL_TEXTURE_DS_SIZE_NV             0x871D
+#define GL_TEXTURE_DT_SIZE_NV             0x871E
+#define GL_TEXTURE_MAG_SIZE_NV            0x871F
+#endif
+
+#ifndef GL_NV_texture_shader2
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV      0x86EF
+#endif
+
+#ifndef GL_NV_texture_shader3
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define GL_OFFSET_HILO_TEXTURE_2D_NV      0x8854
+#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define GL_DEPENDENT_HILO_TEXTURE_2D_NV   0x8858
+#define GL_DEPENDENT_RGB_TEXTURE_3D_NV    0x8859
+#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define GL_DOT_PRODUCT_PASS_THROUGH_NV    0x885B
+#define GL_DOT_PRODUCT_TEXTURE_1D_NV      0x885C
+#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define GL_HILO8_NV                       0x885E
+#define GL_SIGNED_HILO8_NV                0x885F
+#define GL_FORCE_BLUE_TO_ONE_NV           0x8860
+#endif
+
+#ifndef GL_NV_vertex_array_range
+#define GL_VERTEX_ARRAY_RANGE_NV          0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV   0x851E
+#define GL_VERTEX_ARRAY_RANGE_VALID_NV    0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_NV  0x8521
+#endif
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+#endif
+
+#ifndef GL_NV_vertex_program
+#define GL_VERTEX_PROGRAM_NV              0x8620
+#define GL_VERTEX_STATE_PROGRAM_NV        0x8621
+#define GL_ATTRIB_ARRAY_SIZE_NV           0x8623
+#define GL_ATTRIB_ARRAY_STRIDE_NV         0x8624
+#define GL_ATTRIB_ARRAY_TYPE_NV           0x8625
+#define GL_CURRENT_ATTRIB_NV              0x8626
+#define GL_PROGRAM_LENGTH_NV              0x8627
+#define GL_PROGRAM_STRING_NV              0x8628
+#define GL_MODELVIEW_PROJECTION_NV        0x8629
+#define GL_IDENTITY_NV                    0x862A
+#define GL_INVERSE_NV                     0x862B
+#define GL_TRANSPOSE_NV                   0x862C
+#define GL_INVERSE_TRANSPOSE_NV           0x862D
+#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define GL_MAX_TRACK_MATRICES_NV          0x862F
+#define GL_MATRIX0_NV                     0x8630
+#define GL_MATRIX1_NV                     0x8631
+#define GL_MATRIX2_NV                     0x8632
+#define GL_MATRIX3_NV                     0x8633
+#define GL_MATRIX4_NV                     0x8634
+#define GL_MATRIX5_NV                     0x8635
+#define GL_MATRIX6_NV                     0x8636
+#define GL_MATRIX7_NV                     0x8637
+#define GL_CURRENT_MATRIX_STACK_DEPTH_NV  0x8640
+#define GL_CURRENT_MATRIX_NV              0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_NV   0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_NV     0x8643
+#define GL_PROGRAM_PARAMETER_NV           0x8644
+#define GL_ATTRIB_ARRAY_POINTER_NV        0x8645
+#define GL_PROGRAM_TARGET_NV              0x8646
+#define GL_PROGRAM_RESIDENT_NV            0x8647
+#define GL_TRACK_MATRIX_NV                0x8648
+#define GL_TRACK_MATRIX_TRANSFORM_NV      0x8649
+#define GL_VERTEX_PROGRAM_BINDING_NV      0x864A
+#define GL_PROGRAM_ERROR_POSITION_NV      0x864B
+#define GL_VERTEX_ATTRIB_ARRAY0_NV        0x8650
+#define GL_VERTEX_ATTRIB_ARRAY1_NV        0x8651
+#define GL_VERTEX_ATTRIB_ARRAY2_NV        0x8652
+#define GL_VERTEX_ATTRIB_ARRAY3_NV        0x8653
+#define GL_VERTEX_ATTRIB_ARRAY4_NV        0x8654
+#define GL_VERTEX_ATTRIB_ARRAY5_NV        0x8655
+#define GL_VERTEX_ATTRIB_ARRAY6_NV        0x8656
+#define GL_VERTEX_ATTRIB_ARRAY7_NV        0x8657
+#define GL_VERTEX_ATTRIB_ARRAY8_NV        0x8658
+#define GL_VERTEX_ATTRIB_ARRAY9_NV        0x8659
+#define GL_VERTEX_ATTRIB_ARRAY10_NV       0x865A
+#define GL_VERTEX_ATTRIB_ARRAY11_NV       0x865B
+#define GL_VERTEX_ATTRIB_ARRAY12_NV       0x865C
+#define GL_VERTEX_ATTRIB_ARRAY13_NV       0x865D
+#define GL_VERTEX_ATTRIB_ARRAY14_NV       0x865E
+#define GL_VERTEX_ATTRIB_ARRAY15_NV       0x865F
+#define GL_MAP1_VERTEX_ATTRIB0_4_NV       0x8660
+#define GL_MAP1_VERTEX_ATTRIB1_4_NV       0x8661
+#define GL_MAP1_VERTEX_ATTRIB2_4_NV       0x8662
+#define GL_MAP1_VERTEX_ATTRIB3_4_NV       0x8663
+#define GL_MAP1_VERTEX_ATTRIB4_4_NV       0x8664
+#define GL_MAP1_VERTEX_ATTRIB5_4_NV       0x8665
+#define GL_MAP1_VERTEX_ATTRIB6_4_NV       0x8666
+#define GL_MAP1_VERTEX_ATTRIB7_4_NV       0x8667
+#define GL_MAP1_VERTEX_ATTRIB8_4_NV       0x8668
+#define GL_MAP1_VERTEX_ATTRIB9_4_NV       0x8669
+#define GL_MAP1_VERTEX_ATTRIB10_4_NV      0x866A
+#define GL_MAP1_VERTEX_ATTRIB11_4_NV      0x866B
+#define GL_MAP1_VERTEX_ATTRIB12_4_NV      0x866C
+#define GL_MAP1_VERTEX_ATTRIB13_4_NV      0x866D
+#define GL_MAP1_VERTEX_ATTRIB14_4_NV      0x866E
+#define GL_MAP1_VERTEX_ATTRIB15_4_NV      0x866F
+#define GL_MAP2_VERTEX_ATTRIB0_4_NV       0x8670
+#define GL_MAP2_VERTEX_ATTRIB1_4_NV       0x8671
+#define GL_MAP2_VERTEX_ATTRIB2_4_NV       0x8672
+#define GL_MAP2_VERTEX_ATTRIB3_4_NV       0x8673
+#define GL_MAP2_VERTEX_ATTRIB4_4_NV       0x8674
+#define GL_MAP2_VERTEX_ATTRIB5_4_NV       0x8675
+#define GL_MAP2_VERTEX_ATTRIB6_4_NV       0x8676
+#define GL_MAP2_VERTEX_ATTRIB7_4_NV       0x8677
+#define GL_MAP2_VERTEX_ATTRIB8_4_NV       0x8678
+#define GL_MAP2_VERTEX_ATTRIB9_4_NV       0x8679
+#define GL_MAP2_VERTEX_ATTRIB10_4_NV      0x867A
+#define GL_MAP2_VERTEX_ATTRIB11_4_NV      0x867B
+#define GL_MAP2_VERTEX_ATTRIB12_4_NV      0x867C
+#define GL_MAP2_VERTEX_ATTRIB13_4_NV      0x867D
+#define GL_MAP2_VERTEX_ATTRIB14_4_NV      0x867E
+#define GL_MAP2_VERTEX_ATTRIB15_4_NV      0x867F
+#endif
+
+#ifndef GL_NV_vertex_program1_1
+#endif
+
+#ifndef GL_NV_vertex_program2
+#endif
+
+#ifndef GL_PGI_misc_hints
+#define GL_PREFER_DOUBLEBUFFER_HINT_PGI   0x1A1F8
+#define GL_CONSERVE_MEMORY_HINT_PGI       0x1A1FD
+#define GL_RECLAIM_MEMORY_HINT_PGI        0x1A1FE
+#define GL_NATIVE_GRAPHICS_HANDLE_PGI     0x1A202
+#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203
+#define GL_NATIVE_GRAPHICS_END_HINT_PGI   0x1A204
+#define GL_ALWAYS_FAST_HINT_PGI           0x1A20C
+#define GL_ALWAYS_SOFT_HINT_PGI           0x1A20D
+#define GL_ALLOW_DRAW_OBJ_HINT_PGI        0x1A20E
+#define GL_ALLOW_DRAW_WIN_HINT_PGI        0x1A20F
+#define GL_ALLOW_DRAW_FRG_HINT_PGI        0x1A210
+#define GL_ALLOW_DRAW_MEM_HINT_PGI        0x1A211
+#define GL_STRICT_DEPTHFUNC_HINT_PGI      0x1A216
+#define GL_STRICT_LIGHTING_HINT_PGI       0x1A217
+#define GL_STRICT_SCISSOR_HINT_PGI        0x1A218
+#define GL_FULL_STIPPLE_HINT_PGI          0x1A219
+#define GL_CLIP_NEAR_HINT_PGI             0x1A220
+#define GL_CLIP_FAR_HINT_PGI              0x1A221
+#define GL_WIDE_LINE_HINT_PGI             0x1A222
+#define GL_BACK_NORMALS_HINT_PGI          0x1A223
+#endif
+
+#ifndef GL_PGI_vertex_hints
+#define GL_VERTEX_DATA_HINT_PGI           0x1A22A
+#define GL_VERTEX_CONSISTENT_HINT_PGI     0x1A22B
+#define GL_MATERIAL_SIDE_HINT_PGI         0x1A22C
+#define GL_MAX_VERTEX_HINT_PGI            0x1A22D
+#define GL_COLOR3_BIT_PGI                 0x00010000
+#define GL_COLOR4_BIT_PGI                 0x00020000
+#define GL_EDGEFLAG_BIT_PGI               0x00040000
+#define GL_INDEX_BIT_PGI                  0x00080000
+#define GL_MAT_AMBIENT_BIT_PGI            0x00100000
+#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define GL_MAT_DIFFUSE_BIT_PGI            0x00400000
+#define GL_MAT_EMISSION_BIT_PGI           0x00800000
+#define GL_MAT_COLOR_INDEXES_BIT_PGI      0x01000000
+#define GL_MAT_SHININESS_BIT_PGI          0x02000000
+#define GL_MAT_SPECULAR_BIT_PGI           0x04000000
+#define GL_NORMAL_BIT_PGI                 0x08000000
+#define GL_TEXCOORD1_BIT_PGI              0x10000000
+#define GL_TEXCOORD2_BIT_PGI              0x20000000
+#define GL_TEXCOORD3_BIT_PGI              0x40000000
+#define GL_TEXCOORD4_BIT_PGI              0x80000000
+#define GL_VERTEX23_BIT_PGI               0x00000004
+#define GL_VERTEX4_BIT_PGI                0x00000008
+#endif
+
+#ifndef GL_REND_screen_coordinates
+#define GL_SCREEN_COORDINATES_REND        0x8490
+#define GL_INVERTED_SCREEN_W_REND         0x8491
+#endif
+
+#ifndef GL_SGI_color_matrix
+#define GL_COLOR_MATRIX_SGI               0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH_SGI   0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+#endif
+
+#ifndef GL_SGI_color_table
+#define GL_COLOR_TABLE_SGI                0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define GL_PROXY_COLOR_TABLE_SGI          0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define GL_COLOR_TABLE_SCALE_SGI          0x80D6
+#define GL_COLOR_TABLE_BIAS_SGI           0x80D7
+#define GL_COLOR_TABLE_FORMAT_SGI         0x80D8
+#define GL_COLOR_TABLE_WIDTH_SGI          0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_SGI       0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_SGI     0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_SGI      0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_SGI     0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+#endif
+
+#ifndef GL_SGI_texture_color_table
+#define GL_TEXTURE_COLOR_TABLE_SGI        0x80BC
+#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI  0x80BD
+#endif
+
+#ifndef GL_SGIS_detail_texture
+#define GL_DETAIL_TEXTURE_2D_SGIS         0x8095
+#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096
+#define GL_LINEAR_DETAIL_SGIS             0x8097
+#define GL_LINEAR_DETAIL_ALPHA_SGIS       0x8098
+#define GL_LINEAR_DETAIL_COLOR_SGIS       0x8099
+#define GL_DETAIL_TEXTURE_LEVEL_SGIS      0x809A
+#define GL_DETAIL_TEXTURE_MODE_SGIS       0x809B
+#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C
+#endif
+
+#ifndef GL_SGIS_fog_function
+#define GL_FOG_FUNC_SGIS                  0x812A
+#define GL_FOG_FUNC_POINTS_SGIS           0x812B
+#define GL_MAX_FOG_FUNC_POINTS_SGIS       0x812C
+#endif
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_GENERATE_MIPMAP_SGIS           0x8191
+#define GL_GENERATE_MIPMAP_HINT_SGIS      0x8192
+#endif
+
+#ifndef GL_SGIS_multisample
+#define GL_MULTISAMPLE_SGIS               0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_SGIS      0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_SGIS       0x809F
+#define GL_SAMPLE_MASK_SGIS               0x80A0
+#define GL_1PASS_SGIS                     0x80A1
+#define GL_2PASS_0_SGIS                   0x80A2
+#define GL_2PASS_1_SGIS                   0x80A3
+#define GL_4PASS_0_SGIS                   0x80A4
+#define GL_4PASS_1_SGIS                   0x80A5
+#define GL_4PASS_2_SGIS                   0x80A6
+#define GL_4PASS_3_SGIS                   0x80A7
+#define GL_SAMPLE_BUFFERS_SGIS            0x80A8
+#define GL_SAMPLES_SGIS                   0x80A9
+#define GL_SAMPLE_MASK_VALUE_SGIS         0x80AA
+#define GL_SAMPLE_MASK_INVERT_SGIS        0x80AB
+#define GL_SAMPLE_PATTERN_SGIS            0x80AC
+#endif
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_PIXEL_TEXTURE_SGIS             0x8353
+#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354
+#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355
+#define GL_PIXEL_GROUP_COLOR_SGIS         0x8356
+#endif
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_LINEAR_SHARPEN_SGIS            0x80AD
+#define GL_LINEAR_SHARPEN_ALPHA_SGIS      0x80AE
+#define GL_LINEAR_SHARPEN_COLOR_SGIS      0x80AF
+#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0
+#endif
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_CLAMP_TO_BORDER_SGIS           0x812D
+#endif
+
+#ifndef GL_SGIS_texture_color_mask
+#define GL_TEXTURE_COLOR_WRITEMASK_SGIS   0x81EF
+#endif
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_CLAMP_TO_EDGE_SGIS             0x812F
+#endif
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_FILTER4_SGIS                   0x8146
+#define GL_TEXTURE_FILTER4_SIZE_SGIS      0x8147
+#endif
+
+#ifndef GL_SGIS_texture_lod
+#define GL_TEXTURE_MIN_LOD_SGIS           0x813A
+#define GL_TEXTURE_MAX_LOD_SGIS           0x813B
+#define GL_TEXTURE_BASE_LEVEL_SGIS        0x813C
+#define GL_TEXTURE_MAX_LEVEL_SGIS         0x813D
+#endif
+
+#ifndef GL_SGIS_texture_select
+#define GL_DUAL_ALPHA4_SGIS               0x8110
+#define GL_DUAL_ALPHA8_SGIS               0x8111
+#define GL_DUAL_ALPHA12_SGIS              0x8112
+#define GL_DUAL_ALPHA16_SGIS              0x8113
+#define GL_DUAL_LUMINANCE4_SGIS           0x8114
+#define GL_DUAL_LUMINANCE8_SGIS           0x8115
+#define GL_DUAL_LUMINANCE12_SGIS          0x8116
+#define GL_DUAL_LUMINANCE16_SGIS          0x8117
+#define GL_DUAL_INTENSITY4_SGIS           0x8118
+#define GL_DUAL_INTENSITY8_SGIS           0x8119
+#define GL_DUAL_INTENSITY12_SGIS          0x811A
+#define GL_DUAL_INTENSITY16_SGIS          0x811B
+#define GL_DUAL_LUMINANCE_ALPHA4_SGIS     0x811C
+#define GL_DUAL_LUMINANCE_ALPHA8_SGIS     0x811D
+#define GL_QUAD_ALPHA4_SGIS               0x811E
+#define GL_QUAD_ALPHA8_SGIS               0x811F
+#define GL_QUAD_LUMINANCE4_SGIS           0x8120
+#define GL_QUAD_LUMINANCE8_SGIS           0x8121
+#define GL_QUAD_INTENSITY4_SGIS           0x8122
+#define GL_QUAD_INTENSITY8_SGIS           0x8123
+#define GL_DUAL_TEXTURE_SELECT_SGIS       0x8124
+#define GL_QUAD_TEXTURE_SELECT_SGIS       0x8125
+#endif
+
+#ifndef GL_SGIS_texture4D
+#define GL_PACK_SKIP_VOLUMES_SGIS         0x8130
+#define GL_PACK_IMAGE_DEPTH_SGIS          0x8131
+#define GL_UNPACK_SKIP_VOLUMES_SGIS       0x8132
+#define GL_UNPACK_IMAGE_DEPTH_SGIS        0x8133
+#define GL_TEXTURE_4D_SGIS                0x8134
+#define GL_PROXY_TEXTURE_4D_SGIS          0x8135
+#define GL_TEXTURE_4DSIZE_SGIS            0x8136
+#define GL_TEXTURE_WRAP_Q_SGIS            0x8137
+#define GL_MAX_4D_TEXTURE_SIZE_SGIS       0x8138
+#define GL_TEXTURE_4D_BINDING_SGIS        0x814F
+#endif
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_ALPHA_MIN_SGIX                 0x8320
+#define GL_ALPHA_MAX_SGIX                 0x8321
+#endif
+
+#ifndef GL_SGIX_clipmap
+#define GL_LINEAR_CLIPMAP_LINEAR_SGIX     0x8170
+#define GL_TEXTURE_CLIPMAP_CENTER_SGIX    0x8171
+#define GL_TEXTURE_CLIPMAP_FRAME_SGIX     0x8172
+#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX    0x8173
+#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174
+#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175
+#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX     0x8176
+#define GL_MAX_CLIPMAP_DEPTH_SGIX         0x8177
+#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178
+#define GL_NEAREST_CLIPMAP_NEAREST_SGIX   0x844D
+#define GL_NEAREST_CLIPMAP_LINEAR_SGIX    0x844E
+#define GL_LINEAR_CLIPMAP_NEAREST_SGIX    0x844F
+#endif
+
+#ifndef GL_SGIX_depth_texture
+#define GL_DEPTH_COMPONENT16_SGIX         0x81A5
+#define GL_DEPTH_COMPONENT24_SGIX         0x81A6
+#define GL_DEPTH_COMPONENT32_SGIX         0x81A7
+#endif
+
+#ifndef GL_SGIX_flush_raster
+#endif
+
+#ifndef GL_SGIX_fog_offset
+#define GL_FOG_OFFSET_SGIX                0x8198
+#define GL_FOG_OFFSET_VALUE_SGIX          0x8199
+#endif
+
+#ifndef GL_SGIX_framezoom
+#define GL_FRAMEZOOM_SGIX                 0x818B
+#define GL_FRAMEZOOM_FACTOR_SGIX          0x818C
+#define GL_MAX_FRAMEZOOM_FACTOR_SGIX      0x818D
+#endif
+
+#ifndef GL_SGIX_instruments
+#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180
+#define GL_INSTRUMENT_MEASUREMENTS_SGIX   0x8181
+#endif
+
+#ifndef GL_SGIX_interlace
+#define GL_INTERLACE_SGIX                 0x8094
+#endif
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_IR_INSTRUMENT1_SGIX            0x817F
+#endif
+
+#ifndef GL_SGIX_list_priority
+#define GL_LIST_PRIORITY_SGIX             0x8182
+#endif
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_PIXEL_TEX_GEN_SGIX             0x8139
+#define GL_PIXEL_TEX_GEN_MODE_SGIX        0x832B
+#endif
+
+#ifndef GL_SGIX_reference_plane
+#define GL_REFERENCE_PLANE_SGIX           0x817D
+#define GL_REFERENCE_PLANE_EQUATION_SGIX  0x817E
+#endif
+
+#ifndef GL_SGIX_resample
+#define GL_PACK_RESAMPLE_SGIX             0x842C
+#define GL_UNPACK_RESAMPLE_SGIX           0x842D
+#define GL_RESAMPLE_REPLICATE_SGIX        0x842E
+#define GL_RESAMPLE_ZERO_FILL_SGIX        0x842F
+#define GL_RESAMPLE_DECIMATE_SGIX         0x8430
+#endif
+
+#ifndef GL_SGIX_shadow
+#define GL_TEXTURE_COMPARE_SGIX           0x819A
+#define GL_TEXTURE_COMPARE_OPERATOR_SGIX  0x819B
+#define GL_TEXTURE_LEQUAL_R_SGIX          0x819C
+#define GL_TEXTURE_GEQUAL_R_SGIX          0x819D
+#endif
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SHADOW_AMBIENT_SGIX            0x80BF
+#endif
+
+#ifndef GL_SGIX_sprite
+#define GL_SPRITE_SGIX                    0x8148
+#define GL_SPRITE_MODE_SGIX               0x8149
+#define GL_SPRITE_AXIS_SGIX               0x814A
+#define GL_SPRITE_TRANSLATION_SGIX        0x814B
+#define GL_SPRITE_AXIAL_SGIX              0x814C
+#define GL_SPRITE_OBJECT_ALIGNED_SGIX     0x814D
+#define GL_SPRITE_EYE_ALIGNED_SGIX        0x814E
+#endif
+
+#ifndef GL_SGIX_tag_sample_buffer
+#endif
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_TEXTURE_ENV_BIAS_SGIX          0x80BE
+#endif
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_TEXTURE_LOD_BIAS_S_SGIX        0x818E
+#define GL_TEXTURE_LOD_BIAS_T_SGIX        0x818F
+#define GL_TEXTURE_LOD_BIAS_R_SGIX        0x8190
+#endif
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+#endif
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_POST_TEXTURE_FILTER_BIAS_SGIX  0x8179
+#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+#endif
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_VERTEX_PRECLIP_SGIX            0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX       0x83EF
+#endif
+
+#ifndef GL_SGIX_ycrcb
+#define GL_YCRCB_422_SGIX                 0x81BB
+#define GL_YCRCB_444_SGIX                 0x81BC
+#endif
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_WRAP_BORDER_SUN                0x81D4
+#endif
+
+#ifndef GL_SUN_global_alpha
+#define GL_GLOBAL_ALPHA_SUN               0x81D9
+#define GL_GLOBAL_ALPHA_FACTOR_SUN        0x81DA
+#endif
+
+#ifndef GL_SUN_triangle_list
+#define GL_RESTART_SUN                    0x01
+#define GL_REPLACE_MIDDLE_SUN             0x02
+#define GL_REPLACE_OLDEST_SUN             0x03
+#define GL_TRIANGLE_LIST_SUN              0x81D7
+#define GL_REPLACEMENT_CODE_SUN           0x81D8
+#define GL_REPLACEMENT_CODE_ARRAY_SUN     0x85C0
+#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define GL_R1UI_V3F_SUN                   0x85C4
+#define GL_R1UI_C4UB_V3F_SUN              0x85C5
+#define GL_R1UI_C3F_V3F_SUN               0x85C6
+#define GL_R1UI_N3F_V3F_SUN               0x85C7
+#define GL_R1UI_C4F_N3F_V3F_SUN           0x85C8
+#define GL_R1UI_T2F_V3F_SUN               0x85C9
+#define GL_R1UI_T2F_N3F_V3F_SUN           0x85CA
+#define GL_R1UI_T2F_C4F_N3F_V3F_SUN       0x85CB
+#endif
+
+#ifndef GL_SUN_vertex
+#endif
+
+#ifndef GL_SUNX_constant_data
+#define GL_UNPACK_CONSTANT_DATA_SUNX      0x81D5
+#define GL_TEXTURE_CONSTANT_DATA_SUNX     0x81D6
+#endif
+
+#ifndef GL_WIN_phong_shading
+#define GL_PHONG_WIN                      0x80EA
+#define GL_PHONG_HINT_WIN                 0x80EB
+#endif
+
+#ifndef GL_WIN_specular_fog
+#define GL_FOG_SPECULAR_TEXTURE_WIN       0x80EC
+#endif
+
+/*************************************************************/
+
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf);
+extern void APIENTRY glBlendEquation (GLenum);
+extern void APIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);
+extern void APIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+extern void APIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *);
+extern void APIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *);
+extern void APIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei);
+extern void APIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *);
+extern void APIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *);
+extern void APIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *);
+extern void APIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+extern void APIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei);
+extern void APIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+extern void APIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+extern void APIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat);
+extern void APIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *);
+extern void APIENTRY glConvolutionParameteri (GLenum, GLenum, GLint);
+extern void APIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *);
+extern void APIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei);
+extern void APIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei);
+extern void APIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *);
+extern void APIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *);
+extern void APIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *);
+extern void APIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *);
+extern void APIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *);
+extern void APIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *);
+extern void APIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *);
+extern void APIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *);
+extern void APIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *);
+extern void APIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *);
+extern void APIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *);
+extern void APIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean);
+extern void APIENTRY glMinmax (GLenum, GLenum, GLboolean);
+extern void APIENTRY glResetHistogram (GLenum);
+extern void APIENTRY glResetMinmax (GLenum);
+extern void APIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+extern void APIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+extern void APIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (APIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (APIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
+typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (APIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
+typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (APIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+typedef void (APIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target);
+typedef void (APIENTRY * PFNGLRESETMINMAXPROC) (GLenum target);
+typedef void (APIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_ARB_depth_texture
+#define GL_ARB_depth_texture 1
+#endif
+
+#ifndef GL_ARB_fragment_program
+#define GL_ARB_fragment_program 1
+#endif
+
+
+#ifndef GL_ARB_multisample
+#define GL_ARB_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glSampleCoverageARB (GLclampf, GLboolean);
+extern void APIENTRY glSamplePassARB (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRY * PFNGLSAMPLEPASSARBPROC) (GLenum pass);
+#endif
+
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glActiveTextureARB (GLenum);
+extern void APIENTRY glClientActiveTextureARB (GLenum);
+extern void APIENTRY glMultiTexCoord1dARB (GLenum, GLdouble);
+extern void APIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *);
+extern void APIENTRY glMultiTexCoord1fARB (GLenum, GLfloat);
+extern void APIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *);
+extern void APIENTRY glMultiTexCoord1iARB (GLenum, GLint);
+extern void APIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *);
+extern void APIENTRY glMultiTexCoord1sARB (GLenum, GLshort);
+extern void APIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *);
+extern void APIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble);
+extern void APIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *);
+extern void APIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat);
+extern void APIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *);
+extern void APIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint);
+extern void APIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *);
+extern void APIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort);
+extern void APIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *);
+extern void APIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble);
+extern void APIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *);
+extern void APIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat);
+extern void APIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *);
+extern void APIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint);
+extern void APIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *);
+extern void APIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort);
+extern void APIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *);
+extern void APIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);
+extern void APIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *);
+extern void APIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
+extern void APIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *);
+extern void APIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint);
+extern void APIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *);
+extern void APIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort);
+extern void APIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+#endif
+
+#ifndef GL_ARB_point_parameters
+#define GL_ARB_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glPointParameterfARB(GLenum pname, GLfloat param);
+extern void APIENTRY glPointParameterfvARB(GLenum pname, GLfloat *params);
+#endif
+typedef void (APIENTRY * PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_ARB_shadow
+#define GL_ARB_shadow 1
+#endif
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_ARB_texture_border_clamp 1 
+#endif
+
+#ifndef GL_ARB_texture_compression
+#define GL_ARB_texture_compression 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+extern void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+extern void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);
+extern void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+extern void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+extern void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);
+extern void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, void *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, void *img);
+#endif
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_ARB_texture_cube_map 1
+#endif
+
+#ifndef GL_ARB_texture_env_add
+#define GL_ARB_texture_env_add 1
+#endif
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_ARB_texture_env_combine 1
+#endif
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_ARB_texture_env_dot3 1
+#endif
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_ARB_texture_mirrored_repeat 1
+#endif
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_ARB_transpose_matrix 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *);
+extern void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *);
+extern void APIENTRY glMultTransposeMatrixfARB (const GLfloat *);
+extern void APIENTRY glMultTransposeMatrixdARB (const GLdouble *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+typedef void (APIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+#endif
+
+#ifndef GL_ARB_vertex_program
+#define GL_ARB_vertex_program 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glVertexAttrib1sARB(GLuint index, GLshort x);
+extern void APIENTRY glVertexAttrib1fARB(GLuint index, GLfloat x);
+extern void APIENTRY glVertexAttrib1dARB(GLuint index, GLdouble x);
+extern void APIENTRY glVertexAttrib2sARB(GLuint index, GLshort x, GLshort y);
+extern void APIENTRY glVertexAttrib2fARB(GLuint index, GLfloat x, GLfloat y);
+extern void APIENTRY glVertexAttrib2dARB(GLuint index, GLdouble x, GLdouble y);
+extern void APIENTRY glVertexAttrib3sARB(GLuint index, GLshort x, GLshort y, GLshort z);
+extern void APIENTRY glVertexAttrib3fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+extern void APIENTRY glVertexAttrib3dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+extern void APIENTRY glVertexAttrib4sARB(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+extern void APIENTRY glVertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern void APIENTRY glVertexAttrib4dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+extern void APIENTRY glVertexAttrib4NubARB(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+extern void APIENTRY glVertexAttrib1svARB(GLuint index, const GLshort *v);
+extern void APIENTRY glVertexAttrib1fvARB(GLuint index, const GLfloat *v);
+extern void APIENTRY glVertexAttrib1dvARB(GLuint index, const GLdouble *v);
+extern void APIENTRY glVertexAttrib2svARB(GLuint index, const GLshort *v);
+extern void APIENTRY glVertexAttrib2fvARB(GLuint index, const GLfloat *v);
+extern void APIENTRY glVertexAttrib2dvARB(GLuint index, const GLdouble *v);
+extern void APIENTRY glVertexAttrib3svARB(GLuint index, const GLshort *v);
+extern void APIENTRY glVertexAttrib3fvARB(GLuint index, const GLfloat *v);
+extern void APIENTRY glVertexAttrib3dvARB(GLuint index, const GLdouble *v);
+extern void APIENTRY glVertexAttrib4bvARB(GLuint index, const GLbyte *v);
+extern void APIENTRY glVertexAttrib4svARB(GLuint index, const GLshort *v);
+extern void APIENTRY glVertexAttrib4ivARB(GLuint index, const GLint *v);
+extern void APIENTRY glVertexAttrib4ubvARB(GLuint index, const GLubyte *v);
+extern void APIENTRY glVertexAttrib4usvARB(GLuint index, const GLushort *v);
+extern void APIENTRY glVertexAttrib4uivARB(GLuint index, const GLuint *v);
+extern void APIENTRY glVertexAttrib4fvARB(GLuint index, const GLfloat *v);
+extern void APIENTRY glVertexAttrib4dvARB(GLuint index, const GLdouble *v);
+extern void APIENTRY glVertexAttrib4NbvARB(GLuint index, const GLbyte *v);
+extern void APIENTRY glVertexAttrib4NsvARB(GLuint index, const GLshort *v);
+extern void APIENTRY glVertexAttrib4NivARB(GLuint index, const GLint *v);
+extern void APIENTRY glVertexAttrib4NubvARB(GLuint index, const GLubyte *v);
+extern void APIENTRY glVertexAttrib4NusvARB(GLuint index, const GLushort *v);
+extern void APIENTRY glVertexAttrib4NuivARB(GLuint index, const GLuint *v);
+extern void APIENTRY glVertexAttribPointerARB(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+extern void APIENTRY glEnableVertexAttribArrayARB(GLuint index);
+extern void APIENTRY glDisableVertexAttribArrayARB(GLuint index);
+extern void APIENTRY glProgramStringARB(GLenum target, GLenum format, GLsizei len, const void *string); 
+extern void APIENTRY glBindProgramARB(GLenum target, GLuint program);
+extern void APIENTRY glDeleteProgramsARB(GLsizei n, const GLuint *programs);
+extern void APIENTRY glGenProgramsARB(GLsizei n, GLuint *programs);
+extern void APIENTRY glProgramEnvParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+extern void APIENTRY glProgramEnvParameter4dvARB(GLenum target, GLuint index, const GLdouble *params);
+extern void APIENTRY glProgramEnvParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern void APIENTRY glProgramEnvParameter4fvARB(GLenum target, GLuint index, const GLfloat *params);
+extern void APIENTRY glProgramLocalParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+extern void APIENTRY glProgramLocalParameter4dvARB(GLenum target, GLuint index, const GLdouble *params);
+extern void APIENTRY glProgramLocalParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern void APIENTRY glProgramLocalParameter4fvARB(GLenum target, GLuint index, const GLfloat *params);
+extern void APIENTRY glGetProgramEnvParameterdvARB(GLenum target, GLuint index, GLdouble *params);
+extern void APIENTRY glGetProgramEnvParameterfvARB(GLenum target, GLuint index, GLfloat *params);
+extern void APIENTRY glGetProgramLocalParameterdvARB(GLenum target, GLuint index, GLdouble *params);
+extern void APIENTRY glGetProgramLocalParameterfvARB(GLenum target, GLuint index, GLfloat *params);
+extern void APIENTRY glGetProgramivARB(GLenum target, GLenum pname, GLint *params);
+extern void APIENTRY glGetProgramStringARB(GLenum target, GLenum pname, void *string);
+extern void APIENTRY glGetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params);
+extern void APIENTRY glGetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params);
+extern void APIENTRY glGetVertexAttribivARB(GLuint index, GLenum pname, GLint *params);
+extern void APIENTRY glGetVertexAttribPointervARB(GLuint index, GLenum pname, void **pointer);
+extern GLboolean APIENTRY glIsProgramARB(GLuint program);
+#endif
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (APIENTRY * PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void *string); 
+typedef void (APIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
+typedef void (APIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void *string);
+typedef void (APIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, void **pointer);
+typedef GLboolean (APIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program);
+#endif
+
+#ifndef GL_ARB_window_pos
+#define GL_ARB_window_pos 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glWindowPos2dARB(GLdouble x, GLdouble y);
+extern void APIENTRY glWindowPos2fARB(GLfloat x, GLfloat y);
+extern void APIENTRY glWindowPos2iARB(GLint x, GLint y);
+extern void APIENTRY glWindowPos2sARB(GLshort x, GLshort y);
+extern void APIENTRY glWindowPos2dvARB(const GLdouble *p);
+extern void APIENTRY glWindowPos2fvARB(const GLfloat *p);
+extern void APIENTRY glWindowPos2ivARB(const GLint *p);
+extern void APIENTRY glWindowPos2svARB(const GLshort *p);
+extern void APIENTRY glWindowPos3dARB(GLdouble x, GLdouble y, GLdouble z);
+extern void APIENTRY glWindowPos3fARB(GLfloat x, GLfloat y, GLfloat z);
+extern void APIENTRY glWindowPos3iARB(GLint x, GLint y, GLint z);
+extern void APIENTRY glWindowPos3sARB(GLshort x, GLshort y, GLshort z);
+extern void APIENTRY glWindowPos3dvARB(const GLdouble *p);
+extern void APIENTRY glWindowPos3fvARB(const GLfloat *p);
+extern void APIENTRY glWindowPos3ivARB(const GLint *p);
+extern void APIENTRY glWindowPos3svARB(const GLshort *p);
+#endif
+typedef void (APIENTRY * PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRY * PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRY * PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);
+typedef void (APIENTRY * PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);
+typedef void (APIENTRY * PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *p);
+typedef void (APIENTRY * PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *p);
+typedef void (APIENTRY * PFNGLWINDOWPOS2IVARBPROC) (const GLint *p);
+typedef void (APIENTRY * PFNGLWINDOWPOS2SVARBPROC) (const GLshort *p);
+typedef void (APIENTRY * PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY * PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY * PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRY * PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRY * PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *p);
+typedef void (APIENTRY * PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *p);
+typedef void (APIENTRY * PFNGLWINDOWPOS3IVARBPROC) (const GLint *p);
+typedef void (APIENTRY * PFNGLWINDOWPOS3SVARBPROC) (const GLshort *p);
+#endif
+
+#ifndef GL_EXT_abgr
+#define GL_EXT_abgr 1
+#endif
+
+#ifndef GL_EXT_bgra
+#define GL_EXT_bgra 1
+#endif
+
+#ifndef GL_EXT_blend_color
+#define GL_EXT_blend_color 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+#endif
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_EXT_blend_func_separate 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glBlendEquationEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+#endif
+
+#ifndef GL_EXT_blend_subtract
+#define GL_EXT_blend_subtract 1
+#endif
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_EXT_compiled_vertex_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glLockArraysEXT (GLint, GLsizei);
+extern void APIENTRY glUnlockArraysEXT (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
+#endif
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_EXT_draw_range_elements 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+#endif
+
+#ifndef GL_EXT_fog_coord
+#define GL_EXT_fog_coord 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glFogCoordfEXT (GLfloat);
+extern void APIENTRY glFogCoordfvEXT (const GLfloat *);
+extern void APIENTRY glFogCoorddEXT (GLdouble);
+extern void APIENTRY glFogCoorddvEXT (const GLdouble *);
+extern void APIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord);
+typedef void (APIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
+typedef void (APIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord);
+typedef void (APIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
+typedef void (APIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei);
+extern void APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (APIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+
+#ifndef GL_EXT_packed_pixels
+#define GL_EXT_packed_pixels 1
+#endif
+
+#ifndef GL_EXT_paletted_texture
+#define GL_EXT_paletted_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+extern void APIENTRY glColorSubTableEXT (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+extern void APIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *);
+extern void APIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *);
+extern void APIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (APIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data);
+typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_EXT_point_parameters
+#define GL_EXT_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glPointParameterfEXT (GLenum, GLfloat);
+extern void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *);
+extern void APIENTRY glPointParameterfSGIS (GLenum, GLfloat);
+extern void APIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRY * PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRY * PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_EXT_rescale_normal
+#define GL_EXT_rescale_normal 1
+#endif
+
+#ifndef GL_EXT_secondary_color
+#define GL_EXT_secondary_color 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte);
+extern void APIENTRY glSecondaryColor3bvEXT (const GLbyte *);
+extern void APIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble);
+extern void APIENTRY glSecondaryColor3dvEXT (const GLdouble *);
+extern void APIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat);
+extern void APIENTRY glSecondaryColor3fvEXT (const GLfloat *);
+extern void APIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint);
+extern void APIENTRY glSecondaryColor3ivEXT (const GLint *);
+extern void APIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort);
+extern void APIENTRY glSecondaryColor3svEXT (const GLshort *);
+extern void APIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte);
+extern void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *);
+extern void APIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint);
+extern void APIENTRY glSecondaryColor3uivEXT (const GLuint *);
+extern void APIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort);
+extern void APIENTRY glSecondaryColor3usvEXT (const GLushort *);
+extern void APIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);
+typedef void (APIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_EXT_separate_specular_color 1
+#endif
+
+#ifndef GL_EXT_shadow_funcs
+#define GL_EXT_shadow_funcs 1
+#endif
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_EXT_shared_texture_palette 1
+#endif
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_EXT_stencil_two_side 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void glActiveStencilFaceEXT(GLenum face);
+#endif
+typedef void (APIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
+#endif
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_EXT_stencil_wrap 1
+#endif
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_EXT_texture_compression_s3tc 1
+#endif
+
+#ifndef GL_EXT_texture_env_add
+#define GL_EXT_texture_env_add 1
+#endif
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_EXT_texture_env_combine 1
+#endif
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_EXT_texture_env_dot3 1
+#endif
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_EXT_texture_lod_bias 1
+#endif
+
+#ifndef GL_EXT_texture_object
+#define GL_EXT_texture_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *);
+extern void APIENTRY glBindTextureEXT (GLenum, GLuint);
+extern void APIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *);
+extern void APIENTRY glGenTexturesEXT (GLsizei, GLuint *);
+extern GLboolean APIENTRY glIsTextureEXT (GLuint);
+extern void APIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLboolean (APIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences);
+typedef void (APIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);
+typedef void (APIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures);
+typedef void (APIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures);
+typedef GLboolean (APIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture);
+typedef void (APIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#endif
+
+#ifndef GL_EXT_texture3D
+#define GL_EXT_texture3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+extern void APIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+
+#ifndef GL_EXT_vertex_array
+#define GL_EXT_vertex_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glArrayElementEXT (GLint);
+extern void APIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);
+extern void APIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei);
+extern void APIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *);
+extern void APIENTRY glGetPointervEXT (GLenum, GLvoid* *);
+extern void APIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *);
+extern void APIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *);
+extern void APIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);
+extern void APIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (APIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer);
+typedef void (APIENTRY * PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params);
+typedef void (APIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_EXT_vertex_weighting 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glVertexWeightfEXT (GLfloat);
+extern void APIENTRY glVertexWeightfvEXT (const GLfloat *);
+extern void APIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
+typedef void (APIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight);
+typedef void (APIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_HP_occlusion_test
+#define GL_HP_occlusion_test 1
+#endif
+
+#ifndef GL_IBM_texture_mirrored_repeat
+#define GL_IBM_texture_mirrored_repeat 1
+#endif
+
+#ifndef GL_NV_blend_square
+#define GL_NV_blend_square 1
+#endif
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_NV_copy_depth_to_color 1
+#endif
+
+#ifndef GL_NV_depth_clamp
+#define GL_NV_depth_clamp 1
+#endif
+
+#ifndef GL_NV_element_array
+#define GL_NV_element_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glElementPointerNV(GLenum type, const GLvoid *pointer);
+extern void APIENTRY glDrawElementArrayNV(GLenum mode, GLint first, GLsizei count);
+extern void APIENTRY glDrawRangeElementArrayNV(GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+extern void APIENTRY glMultiDrawElementArrayNV(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+extern void APIENTRY glMultiDrawRangeElementArrayNV(GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#endif
+typedef void (APIENTRY * PFNGLELEMENTPOINTERNVPROC) (GLenum type, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLDRAWELEMENTARRAYNVPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTARRAYNVPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+typedef void (APIENTRY * PFNGLMULTIDRAWELEMENTARRAYNVPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYNVPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#endif
+
+#ifndef GL_NV_fence
+#define GL_NV_fence 1 
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glDeleteFencesNV(GLsizei n, const GLuint *fences);
+extern void APIENTRY glGenFencesNV(GLsizei n, GLuint *fences);
+extern GLboolean APIENTRY glIsFenceNV(GLuint fence);
+extern GLboolean APIENTRY glTestFenceNV(GLuint fence);
+extern void APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params);
+extern void APIENTRY glFinishFenceNV(GLuint fence);
+extern void APIENTRY glSetFenceNV(GLuint fence, GLenum condition);
+#endif
+typedef void (APIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (APIENTRY * PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (APIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (APIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (APIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+#ifndef GL_NV_float_buffer
+#define GL_NV_float_buffer 1
+#endif
+
+#ifndef GL_NV_fog_distance
+#define GL_NV_fog_distance 1
+#endif
+
+#ifndef GL_NV_fragment_program
+#define GL_NV_fragment_program 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern void APIENTRY glProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+extern void APIENTRY glProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, const GLfloat v[]);
+extern void APIENTRY glProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, const GLdouble v[]);
+extern void APIENTRY glGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+extern void APIENTRY glGetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#endif
+typedef void (APIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat v[]);
+typedef void (APIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble v[]);
+typedef void (APIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#endif
+
+#ifndef GL_NV_half_float
+#define GL_NV_half_float 1
+#ifndef GLhalf
+typedef unsigned short GLhalf;
+#endif
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glVertex2hNV(GLhalf x, GLhalf y);
+extern void APIENTRY glVertex2hvNV(const GLhalf *v);
+extern void APIENTRY glVertex3hNV(GLhalf x, GLhalf y, GLhalf z);
+extern void APIENTRY glVertex3hvNV(const GLhalf *v);
+extern void APIENTRY glVertex4hNV(GLhalf x, GLhalf y, GLhalf z, GLhalf w);
+extern void APIENTRY glVertex4hvNV(const GLhalf *v);
+extern void APIENTRY glNormal3hNV(GLhalf nx, GLhalf ny, GLhalf nz);
+extern void APIENTRY glNormal3hvNV(const GLhalf *v);
+extern void APIENTRY glColor3hNV(GLhalf red, GLhalf green, GLhalf blue);
+extern void APIENTRY glColor3hvNV(const GLhalf *v);
+extern void APIENTRY glColor4hNV(GLhalf red, GLhalf green, GLhalf blue, GLhalf alpha);
+extern void APIENTRY glColor4hvNV(const GLhalf *v);
+extern void APIENTRY glTexCoord1hNV(GLhalf s);
+extern void APIENTRY glTexCoord1hvNV(const GLhalf *v);
+extern void APIENTRY glTexCoord2hNV(GLhalf s, GLhalf t);
+extern void APIENTRY glTexCoord2hvNV(const GLhalf *v);
+extern void APIENTRY glTexCoord3hNV(GLhalf s, GLhalf t, GLhalf r);
+extern void APIENTRY glTexCoord3hvNV(const GLhalf *v);
+extern void APIENTRY glTexCoord4hNV(GLhalf s, GLhalf t, GLhalf r, GLhalf q);
+extern void APIENTRY glTexCoord4hvNV(const GLhalf *v);
+extern void APIENTRY glMultiTexCoord1hNV(GLenum target, GLhalf s);
+extern void APIENTRY glMultiTexCoord1hvNV(GLenum target, const GLhalf *v);
+extern void APIENTRY glMultiTexCoord2hNV(GLenum target, GLhalf s, GLhalf t);
+extern void APIENTRY glMultiTexCoord2hvNV(GLenum target, const GLhalf *v);
+extern void APIENTRY glMultiTexCoord3hNV(GLenum target, GLhalf s, GLhalf t, GLhalf r);
+extern void APIENTRY glMultiTexCoord3hvNV(GLenum target, const GLhalf *v);
+extern void APIENTRY glMultiTexCoord4hNV(GLenum target, GLhalf s, GLhalf t, GLhalf r, GLhalf q);
+extern void APIENTRY glMultiTexCoord4hvNV(GLenum target, const GLhalf *v);
+extern void APIENTRY glFogCoordhNV(GLhalf fog);
+extern void APIENTRY glFogCoordhvNV(const GLhalf *fog);
+extern void APIENTRY glSecondaryColor3hNV(GLhalf red, GLhalf green, GLhalf blue);
+extern void APIENTRY glSecondaryColor3hvNV(const GLhalf *v);
+extern void APIENTRY glVertexWeighthNV(GLhalf weight);
+extern void APIENTRY glVertexWeighthvNV(const GLhalf *weight);
+extern void APIENTRY glVertexAttrib1hNV(GLuint index, GLhalf x);
+extern void APIENTRY glVertexAttrib1hvNV(GLuint index, const GLhalf *v);
+extern void APIENTRY glVertexAttrib2hNV(GLuint index, GLhalf x, GLhalf y);
+extern void APIENTRY glVertexAttrib2hvNV(GLuint index, const GLhalf *v);
+extern void APIENTRY glVertexAttrib3hNV(GLuint index, GLhalf x, GLhalf y, GLhalf z);
+extern void APIENTRY glVertexAttrib3hvNV(GLuint index, const GLhalf *v);
+extern void APIENTRY glVertexAttrib4hNV(GLuint index, GLhalf x, GLhalf y, GLhalf z, GLhalf w);
+extern void APIENTRY glVertexAttrib4hvNV(GLuint index, const GLhalf *v);
+extern void APIENTRY glVertexAttribs1hvNV(GLuint index, GLsizei n, const GLhalf *v);
+extern void APIENTRY glVertexAttribs2hvNV(GLuint index, GLsizei n, const GLhalf *v);
+extern void APIENTRY glVertexAttribs3hvNV(GLuint index, GLsizei n, const GLhalf *v);
+extern void APIENTRY glVertexAttribs4hvNV(GLuint index, GLsizei n, const GLhalf *v);
+#endif
+typedef void (APIENTRY * PFNGLVERTEX2HNVPROC) (GLhalf x, GLhalf y);
+typedef void (APIENTRY * PFNGLVERTEX2HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLVERTEX3HNVPROC) (GLhalf x, GLhalf y, GLhalf z);
+typedef void (APIENTRY * PFNGLVERTEX3HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLVERTEX4HNVPROC) (GLhalf x, GLhalf y, GLhalf z, GLhalf w);
+typedef void (APIENTRY * PFNGLVERTEX4HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLNORMAL3HNVPROC) (GLhalf nx, GLhalf ny, GLhalf nz);
+typedef void (APIENTRY * PFNGLNORMAL3HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue);
+typedef void (APIENTRY * PFNGLCOLOR3HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLCOLOR4HNVPROC) (GLhalf red, GLhalf green, GLhalf blue, GLhalf alpha);
+typedef void (APIENTRY * PFNGLCOLOR4HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLTEXCOORD1HNVPROC) (GLhalf s);
+typedef void (APIENTRY * PFNGLTEXCOORD1HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLTEXCOORD2HNVPROC) (GLhalf s, GLhalf t);
+typedef void (APIENTRY * PFNGLTEXCOORD2HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLTEXCOORD3HNVPROC) (GLhalf s, GLhalf t, GLhalf r);
+typedef void (APIENTRY * PFNGLTEXCOORD3HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLTEXCOORD4HNVPROC) (GLhalf s, GLhalf t, GLhalf r, GLhalf q);
+typedef void (APIENTRY * PFNGLTEXCOORD4HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalf s);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalf *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalf s, GLhalf t);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalf *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalf *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r, GLhalf q);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalf *v);
+typedef void (APIENTRY * PFNGLFOGCOORDHNVPROC) (GLhalf fog);
+typedef void (APIENTRY * PFNGLFOGCOORDHVNVPROC) (const GLhalf *fog);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue);
+typedef void (APIENTRY * PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalf *v);
+typedef void (APIENTRY * PFNGLVERTEXWEIGHTHNVPROC) (GLhalf weight);
+typedef void (APIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalf *weight);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalf x);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalf *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalf x, GLhalf y);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalf *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalf *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z, GLhalf w);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalf *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalf *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalf *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalf *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalf *v);
+#endif
+
+#ifndef GL_NV_light_max_exponent
+#define GL_NV_light_max_exponent 1
+#endif
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_NV_multisample_filter_hint 1
+#endif
+
+#ifndef GL_NV_occlusion_query
+#define GL_NV_occlusion_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glGenOcclusionQueriesNV(GLsizei n, GLuint *ids);
+extern void APIENTRY glDeleteOcclusionQueriesNV(GLsizei n, const GLuint *ids);
+extern void APIENTRY glIsOcclusionQueryNV(GLuint id);
+extern void APIENTRY glBeginOcclusionQueryNV(GLuint id);
+extern void APIENTRY glEndOcclusionQueryNV(GLvoid);
+extern void APIENTRY glGetOcclusionQueryivNV(GLuint id, GLenum pname, GLint *params);
+extern void APIENTRY glGetOcclusionQueryuivNV(GLuint id, GLenum pname, GLuint *params);
+#endif
+typedef void (APIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids);
+typedef void (APIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (GLvoid);
+typedef void (APIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_NV_packed_depth_stencil 1
+#endif
+
+#ifndef GL_NV_pixel_data_range
+#define GL_NV_pixel_data_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glPixelDataRangeNV(GLenum target, GLsizei length, GLvoid *pointer);
+extern void APIENTRY glFlushPixelDataRangeNV(GLenum target);
+#endif
+typedef void (APIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer);
+typedef void (APIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
+#endif
+
+#ifndef GL_NV_point_sprite
+#define GL_NV_point_sprite 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glPointParameteriNV(GLenum pname, int param);
+extern void APIENTRY glPointParameterivNV(GLenum pname, const int *params);
+#endif
+typedef void (APIENTRY * PFNGLPOINTPARAMETERINVPROC)  (GLenum pname, int param);
+typedef void (APIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const int *params);
+#endif
+
+#ifndef GL_NV_primitive_restart
+#define GL_NV_primitive_restart 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glPrimitiveRestartNV(GLvoid);
+extern void APIENTRY glPrimitiveRestartIndexNV(GLuint index);
+#endif
+typedef void (APIENTRY * PFNGLPRIMITIVERESTARTNVPROC) (GLvoid);
+typedef void (APIENTRY * PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);
+#endif
+
+#ifndef GL_NV_register_combiners
+#define GL_NV_register_combiners 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *);
+extern void APIENTRY glCombinerParameterfNV (GLenum, GLfloat);
+extern void APIENTRY glCombinerParameterivNV (GLenum, const GLint *);
+extern void APIENTRY glCombinerParameteriNV (GLenum, GLint);
+extern void APIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum);
+extern void APIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean);
+extern void APIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum);
+extern void APIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *);
+extern void APIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *);
+extern void APIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *);
+extern void APIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *);
+extern void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *);
+extern void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+typedef void (APIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_NV_register_combiners2
+#define GL_NV_register_combiners2 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void glCombinerStageParameterfvNV(GLenum stage, GLenum pname, const GLfloat *params);
+extern void glGetCombinerStageParameterfvNV(GLenum stage, GLenum pname, GLfloat *params);
+#endif
+typedef void (APIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params);
+typedef void (APIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_NV_stencil_two_side
+#define GL_NV_stencil_two_side 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glActiveStencilFaceNV(GLenum face);
+#endif
+typedef void (APIENTRY * PFNGLACTIVESTENCILFACENVPROC) (GLenum face);
+#endif
+
+#ifndef GL_NV_texgen_emboss
+#define GL_NV_texgen_emboss 1
+#endif
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NV_texgen_reflection 1
+#endif
+
+#ifndef GL_NV_texture_compression_vtc
+#define GL_NV_texture_compression_vtc 1
+#endif
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_NV_texture_env_combine4 1
+#endif
+
+#ifndef GL_NV_texture_rectangle
+#define GL_NV_texture_rectangle 1
+#endif
+
+#ifndef GL_NV_texture_shader
+#define GL_NV_texture_shader 1
+#endif
+
+#ifndef GL_NV_texture_shader2
+#define GL_NV_texture_shader2 1
+#endif
+
+#ifndef GL_NV_texture_shader3
+#define GL_NV_texture_shader3 1
+#endif
+
+#ifndef GL_NV_vertex_array_range
+#define GL_NV_vertex_array_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void APIENTRY glFlushVertexArrayRangeNV (void);
+extern void APIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
+typedef void (APIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei size, const GLvoid *pointer);
+#endif
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_NV_vertex_array_range2 1
+#endif
+
+#ifndef GL_NV_vertex_program
+#define GL_NV_vertex_program 1
+#ifdef GL_GLEXT_PROTOTYPES
+extern void glBindProgramNV(GLenum target, GLuint id);
+extern void glDeleteProgramsNV(GLsizei n, const GLuint *ids);
+extern void glExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params);
+extern void glGenProgramsNV(GLsizei n, GLuint *ids);
+extern GLboolean glAreProgramsResidentNV(GLsizei n, const GLuint *ids, GLboolean *residences);
+extern void glRequestResidentProgramsNV(GLsizei n, GLuint *ids);
+extern void glGetProgramParameterfvNV(GLenum target, GLuint index, GLenum pname, GLfloat *params);
+extern void glGetProgramParameterdvNV(GLenum target, GLuint index, GLenum pname, GLdouble *params);
+extern void glGetProgramivNV(GLuint id, GLenum pname, int *params);
+extern void glGetProgramStringNV(GLuint id, GLenum pname, GLubyte *program);
+extern void glGetTrackMatrixivNV(GLenum target, GLuint address, GLenum pname, int *params);
+extern void glGetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params);
+extern void glGetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params);
+extern void glGetVertexAttribivNV(GLuint index, GLenum pname, int *params);
+extern void glGetVertexAttribPointervNV(GLuint index, GLenum pname, void **pointer);
+extern GLboolean glIsProgramNV(GLuint id);
+extern void glLoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+extern void glProgramParameter4fNV(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern void glProgramParameter4dNV(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+extern void glProgramParameter4dvNV(GLenum target, GLuint index, const GLdouble *params);
+extern void glProgramParameter4fvNV(GLenum target, GLuint index, const GLfloat *params);
+extern void glProgramParameters4dvNV(GLenum target, GLuint index, GLuint num, const GLdouble *params);
+extern void glProgramParameters4fvNV(GLenum target, GLuint index, GLuint num, const GLfloat *params);
+extern void glTrackMatrixNV(GLenum target, GLuint address, GLenum matrix, GLenum transform);
+extern void glVertexAttribPointerNV(GLuint index, int size, GLenum type, GLsizei stride, const void *pointer);
+extern void glVertexAttrib1sNV(GLuint index, GLshort x);
+extern void glVertexAttrib1fNV(GLuint index, GLfloat x);
+extern void glVertexAttrib1dNV(GLuint index, GLdouble x);
+extern void glVertexAttrib2sNV(GLuint index, GLshort x, GLshort y);
+extern void glVertexAttrib2fNV(GLuint index, GLfloat x, GLfloat y);
+extern void glVertexAttrib2dNV(GLuint index, GLdouble x, GLdouble y);
+extern void glVertexAttrib3sNV(GLuint index, GLshort x, GLshort y, GLshort z);
+extern void glVertexAttrib3fNV(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+extern void glVertexAttrib3dNV(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+extern void glVertexAttrib4sNV(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+extern void glVertexAttrib4fNV(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern void glVertexAttrib4dNV(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+extern void glVertexAttrib4ubNV(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+extern void glVertexAttrib1svNV(GLuint index, const GLshort *v);
+extern void glVertexAttrib1fvNV(GLuint index, const GLfloat *v);
+extern void glVertexAttrib1dvNV(GLuint index, const GLdouble *v);
+extern void glVertexAttrib2svNV(GLuint index, const GLshort *v);
+extern void glVertexAttrib2fvNV(GLuint index, const GLfloat *v);
+extern void glVertexAttrib2dvNV(GLuint index, const GLdouble *v);
+extern void glVertexAttrib3svNV(GLuint index, const GLshort *v);
+extern void glVertexAttrib3fvNV(GLuint index, const GLfloat *v);
+extern void glVertexAttrib3dvNV(GLuint index, const GLdouble *v);
+extern void glVertexAttrib4svNV(GLuint index, const GLshort *v);
+extern void glVertexAttrib4fvNV(GLuint index, const GLfloat *v);
+extern void glVertexAttrib4dvNV(GLuint index, const GLdouble *v);
+extern void glVertexAttrib4ubvNV(GLuint index, const GLubyte *v);
+extern void glVertexAttribs1svNV(GLuint index, GLsizei n, const GLshort *v);
+extern void glVertexAttribs1fvNV(GLuint index, GLsizei n, const GLfloat *v);
+extern void glVertexAttribs1dvNV(GLuint index, GLsizei n, const GLdouble *v);
+extern void glVertexAttribs2svNV(GLuint index, GLsizei n, const GLshort *v);
+extern void glVertexAttribs2fvNV(GLuint index, GLsizei n, const GLfloat *v);
+extern void glVertexAttribs2dvNV(GLuint index, GLsizei n, const GLdouble *v);
+extern void glVertexAttribs3svNV(GLuint index, GLsizei n, const GLshort *v);
+extern void glVertexAttribs3fvNV(GLuint index, GLsizei n, const GLfloat *v);
+extern void glVertexAttribs3dvNV(GLuint index, GLsizei n, const GLdouble *v);
+extern void glVertexAttribs4svNV(GLuint index, GLsizei n, const GLshort *v);
+extern void glVertexAttribs4fvNV(GLuint index, GLsizei n, const GLfloat *v);
+extern void glVertexAttribs4dvNV(GLuint index, GLsizei n, const GLdouble *v);
+extern void glVertexAttribs4ubvNV(GLuint index, GLsizei n, const GLubyte *v);
+#endif
+typedef GLboolean (APIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences);
+typedef void (APIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params);
+typedef void (APIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program);
+typedef void (APIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id);
+typedef void (APIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v);
+typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v);
+typedef void (APIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v);
+#endif
+
+#ifndef GL_NV_vertex_program1_1
+#define GL_NV_vertex_program1_1 1
+#endif
+
+#ifndef GL_NV_vertex_program2
+#define GL_NV_vertex_program2 1
+#endif
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_SGIS_generate_mipmap 1
+#endif
+
+#ifndef GL_SGIS_texture_lod
+#define GL_SGIS_texture_lod 1
+#endif
+
+#ifndef GL_SGIX_depth_texture
+#define GL_SGIX_depth_texture 1
+#endif
+
+#ifndef GL_SGIX_shadow
+#define GL_SGIX_shadow 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GL/wglew.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GL/wglew.h	(revision 498)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GL/wglew.h	(revision 498)
@@ -0,0 +1,922 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2004, 2003, 2002, Milan Ikits <milan ikits[at]ieee org>
+** Copyright (C) 2004, 2003, 2002, Marcelo E. Magallon <mmagallo[at]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** All rights reserved.
+** 
+** Redistribution and use in source and binary forms, with or without 
+** modification, are permitted provided that the following conditions are met:
+** 
+** * Redistributions of source code must retain the above copyright notice, 
+**   this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright notice, 
+**   this list of conditions and the following disclaimer in the documentation 
+**   and/or other materials provided with the distribution.
+** * The name of the author may be used to endorse or promote products 
+**   derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+** THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+** 
+** http://oss.sgi.com/projects/FreeB
+** 
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+** 
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+** 
+** Additional Notice Provisions: This software was created using the
+** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has
+** not been independently verified as being compliant with the OpenGL(R)
+** version 1.2.1 Specification.
+*/
+
+#ifndef __wglew_h__
+#define __wglew_h__
+#define __WGLEW_H__
+
+#ifdef __wglext_h_
+#error wglext.h included before wglew.h
+#endif
+
+#define __wglext_h_
+
+#if !defined(APIENTRY) && !defined(__CYGWIN__)
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+/*
+ * GLEW_STATIC needs to be set when using the static version.
+ * GLEW_BUILD is set when building the DLL version.
+ */
+#ifdef GLEW_STATIC
+#  define GLEWAPI extern
+#else
+#  ifdef GLEW_BUILD
+#    define GLEWAPI extern __declspec(dllexport)
+#  else
+#    define GLEWAPI extern __declspec(dllimport)
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------------------------- WGL_3DFX_multisample ------------------------- */
+
+#ifndef WGL_3DFX_multisample
+#define WGL_3DFX_multisample 1
+
+#define WGL_SAMPLE_BUFFERS_3DFX 0x2060
+#define WGL_SAMPLES_3DFX 0x2061
+
+#define WGLEW_3DFX_multisample WGLEW_GET_VAR(__WGLEW_3DFX_multisample)
+
+#endif /* WGL_3DFX_multisample */
+
+/* ------------------------- WGL_ARB_buffer_region ------------------------- */
+
+#ifndef WGL_ARB_buffer_region
+#define WGL_ARB_buffer_region 1
+
+#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001
+#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002
+#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004
+#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008
+
+typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);
+typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion);
+typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
+typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height);
+
+#define wglCreateBufferRegionARB WGLEW_GET_FUN(__wglewCreateBufferRegionARB)
+#define wglDeleteBufferRegionARB WGLEW_GET_FUN(__wglewDeleteBufferRegionARB)
+#define wglRestoreBufferRegionARB WGLEW_GET_FUN(__wglewRestoreBufferRegionARB)
+#define wglSaveBufferRegionARB WGLEW_GET_FUN(__wglewSaveBufferRegionARB)
+
+#define WGLEW_ARB_buffer_region WGLEW_GET_VAR(__WGLEW_ARB_buffer_region)
+
+#endif /* WGL_ARB_buffer_region */
+
+/* ----------------------- WGL_ARB_extensions_string ----------------------- */
+
+#ifndef WGL_ARB_extensions_string
+#define WGL_ARB_extensions_string 1
+
+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
+
+#define wglGetExtensionsStringARB WGLEW_GET_FUN(__wglewGetExtensionsStringARB)
+
+#define WGLEW_ARB_extensions_string WGLEW_GET_VAR(__WGLEW_ARB_extensions_string)
+
+#endif /* WGL_ARB_extensions_string */
+
+/* ----------------------- WGL_ARB_make_current_read ----------------------- */
+
+#ifndef WGL_ARB_make_current_read
+#define WGL_ARB_make_current_read 1
+
+typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+
+#define wglGetCurrentReadDCARB WGLEW_GET_FUN(__wglewGetCurrentReadDCARB)
+#define wglMakeContextCurrentARB WGLEW_GET_FUN(__wglewMakeContextCurrentARB)
+
+#define WGLEW_ARB_make_current_read WGLEW_GET_VAR(__WGLEW_ARB_make_current_read)
+
+#endif /* WGL_ARB_make_current_read */
+
+/* -------------------------- WGL_ARB_multisample -------------------------- */
+
+#ifndef WGL_ARB_multisample
+#define WGL_ARB_multisample 1
+
+#define WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define WGL_SAMPLES_ARB 0x2042
+
+#define WGLEW_ARB_multisample WGLEW_GET_VAR(__WGLEW_ARB_multisample)
+
+#endif /* WGL_ARB_multisample */
+
+/* ---------------------------- WGL_ARB_pbuffer ---------------------------- */
+
+#ifndef WGL_ARB_pbuffer
+#define WGL_ARB_pbuffer 1
+
+#define WGL_DRAW_TO_PBUFFER_ARB 0x202D
+#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E
+#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030
+#define WGL_PBUFFER_LARGEST_ARB 0x2033
+#define WGL_PBUFFER_WIDTH_ARB 0x2034
+#define WGL_PBUFFER_HEIGHT_ARB 0x2035
+#define WGL_PBUFFER_LOST_ARB 0x2036
+
+DECLARE_HANDLE(HPBUFFERARB);
+
+typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
+typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
+typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
+typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int* piValue);
+typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);
+
+#define wglCreatePbufferARB WGLEW_GET_FUN(__wglewCreatePbufferARB)
+#define wglDestroyPbufferARB WGLEW_GET_FUN(__wglewDestroyPbufferARB)
+#define wglGetPbufferDCARB WGLEW_GET_FUN(__wglewGetPbufferDCARB)
+#define wglQueryPbufferARB WGLEW_GET_FUN(__wglewQueryPbufferARB)
+#define wglReleasePbufferDCARB WGLEW_GET_FUN(__wglewReleasePbufferDCARB)
+
+#define WGLEW_ARB_pbuffer WGLEW_GET_VAR(__WGLEW_ARB_pbuffer)
+
+#endif /* WGL_ARB_pbuffer */
+
+/* -------------------------- WGL_ARB_pixel_format ------------------------- */
+
+#ifndef WGL_ARB_pixel_format
+#define WGL_ARB_pixel_format 1
+
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_DRAW_TO_BITMAP_ARB 0x2002
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_NEED_PALETTE_ARB 0x2004
+#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
+#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
+#define WGL_SWAP_METHOD_ARB 0x2007
+#define WGL_NUMBER_OVERLAYS_ARB 0x2008
+#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
+#define WGL_TRANSPARENT_ARB 0x200A
+#define WGL_SHARE_DEPTH_ARB 0x200C
+#define WGL_SHARE_STENCIL_ARB 0x200D
+#define WGL_SHARE_ACCUM_ARB 0x200E
+#define WGL_SUPPORT_GDI_ARB 0x200F
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_STEREO_ARB 0x2012
+#define WGL_PIXEL_TYPE_ARB 0x2013
+#define WGL_COLOR_BITS_ARB 0x2014
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_RED_SHIFT_ARB 0x2016
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_GREEN_SHIFT_ARB 0x2018
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_BLUE_SHIFT_ARB 0x201A
+#define WGL_ALPHA_BITS_ARB 0x201B
+#define WGL_ALPHA_SHIFT_ARB 0x201C
+#define WGL_ACCUM_BITS_ARB 0x201D
+#define WGL_ACCUM_RED_BITS_ARB 0x201E
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_NO_ACCELERATION_ARB 0x2025
+#define WGL_GENERIC_ACCELERATION_ARB 0x2026
+#define WGL_FULL_ACCELERATION_ARB 0x2027
+#define WGL_SWAP_EXCHANGE_ARB 0x2028
+#define WGL_SWAP_COPY_ARB 0x2029
+#define WGL_SWAP_UNDEFINED_ARB 0x202A
+#define WGL_TYPE_RGBA_ARB 0x202B
+#define WGL_TYPE_COLORINDEX_ARB 0x202C
+#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
+#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
+#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
+#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
+#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
+
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, FLOAT *pfValues);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, int *piValues);
+
+#define wglChoosePixelFormatARB WGLEW_GET_FUN(__wglewChoosePixelFormatARB)
+#define wglGetPixelFormatAttribfvARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvARB)
+#define wglGetPixelFormatAttribivARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribivARB)
+
+#define WGLEW_ARB_pixel_format WGLEW_GET_VAR(__WGLEW_ARB_pixel_format)
+
+#endif /* WGL_ARB_pixel_format */
+
+/* ----------------------- WGL_ARB_pixel_format_float ---------------------- */
+
+#ifndef WGL_ARB_pixel_format_float
+#define WGL_ARB_pixel_format_float 1
+
+#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
+
+#define WGLEW_ARB_pixel_format_float WGLEW_GET_VAR(__WGLEW_ARB_pixel_format_float)
+
+#endif /* WGL_ARB_pixel_format_float */
+
+/* ------------------------- WGL_ARB_render_texture ------------------------ */
+
+#ifndef WGL_ARB_render_texture
+#define WGL_ARB_render_texture 1
+
+#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070
+#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
+#define WGL_TEXTURE_FORMAT_ARB 0x2072
+#define WGL_TEXTURE_TARGET_ARB 0x2073
+#define WGL_MIPMAP_TEXTURE_ARB 0x2074
+#define WGL_TEXTURE_RGB_ARB 0x2075
+#define WGL_TEXTURE_RGBA_ARB 0x2076
+#define WGL_NO_TEXTURE_ARB 0x2077
+#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078
+#define WGL_TEXTURE_1D_ARB 0x2079
+#define WGL_TEXTURE_2D_ARB 0x207A
+#define WGL_MIPMAP_LEVEL_ARB 0x207B
+#define WGL_CUBE_MAP_FACE_ARB 0x207C
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
+#define WGL_FRONT_LEFT_ARB 0x2083
+#define WGL_FRONT_RIGHT_ARB 0x2084
+#define WGL_BACK_LEFT_ARB 0x2085
+#define WGL_BACK_RIGHT_ARB 0x2086
+#define WGL_AUX0_ARB 0x2087
+#define WGL_AUX1_ARB 0x2088
+#define WGL_AUX2_ARB 0x2089
+#define WGL_AUX3_ARB 0x208A
+#define WGL_AUX4_ARB 0x208B
+#define WGL_AUX5_ARB 0x208C
+#define WGL_AUX6_ARB 0x208D
+#define WGL_AUX7_ARB 0x208E
+#define WGL_AUX8_ARB 0x208F
+#define WGL_AUX9_ARB 0x2090
+
+typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int* piAttribList);
+
+#define wglBindTexImageARB WGLEW_GET_FUN(__wglewBindTexImageARB)
+#define wglReleaseTexImageARB WGLEW_GET_FUN(__wglewReleaseTexImageARB)
+#define wglSetPbufferAttribARB WGLEW_GET_FUN(__wglewSetPbufferAttribARB)
+
+#define WGLEW_ARB_render_texture WGLEW_GET_VAR(__WGLEW_ARB_render_texture)
+
+#endif /* WGL_ARB_render_texture */
+
+/* ----------------------- WGL_ATI_pixel_format_float ---------------------- */
+
+#ifndef WGL_ATI_pixel_format_float
+#define WGL_ATI_pixel_format_float 1
+
+#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0
+#define GL_RGBA_FLOAT_MODE_ATI 0x8820
+#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835
+
+#define WGLEW_ATI_pixel_format_float WGLEW_GET_VAR(__WGLEW_ATI_pixel_format_float)
+
+#endif /* WGL_ATI_pixel_format_float */
+
+/* -------------------------- WGL_EXT_depth_float -------------------------- */
+
+#ifndef WGL_EXT_depth_float
+#define WGL_EXT_depth_float 1
+
+#define WGL_DEPTH_FLOAT_EXT 0x2040
+
+#define WGLEW_EXT_depth_float WGLEW_GET_VAR(__WGLEW_EXT_depth_float)
+
+#endif /* WGL_EXT_depth_float */
+
+/* ---------------------- WGL_EXT_display_color_table ---------------------- */
+
+#ifndef WGL_EXT_display_color_table
+#define WGL_EXT_display_color_table 1
+
+typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef void (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (GLushort* table, GLuint length);
+
+#define wglBindDisplayColorTableEXT WGLEW_GET_FUN(__wglewBindDisplayColorTableEXT)
+#define wglCreateDisplayColorTableEXT WGLEW_GET_FUN(__wglewCreateDisplayColorTableEXT)
+#define wglDestroyDisplayColorTableEXT WGLEW_GET_FUN(__wglewDestroyDisplayColorTableEXT)
+#define wglLoadDisplayColorTableEXT WGLEW_GET_FUN(__wglewLoadDisplayColorTableEXT)
+
+#define WGLEW_EXT_display_color_table WGLEW_GET_VAR(__WGLEW_EXT_display_color_table)
+
+#endif /* WGL_EXT_display_color_table */
+
+/* ----------------------- WGL_EXT_extensions_string ----------------------- */
+
+#ifndef WGL_EXT_extensions_string
+#define WGL_EXT_extensions_string 1
+
+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void);
+
+#define wglGetExtensionsStringEXT WGLEW_GET_FUN(__wglewGetExtensionsStringEXT)
+
+#define WGLEW_EXT_extensions_string WGLEW_GET_VAR(__WGLEW_EXT_extensions_string)
+
+#endif /* WGL_EXT_extensions_string */
+
+/* ----------------------- WGL_EXT_make_current_read ----------------------- */
+
+#ifndef WGL_EXT_make_current_read
+#define WGL_EXT_make_current_read 1
+
+typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+
+#define wglGetCurrentReadDCEXT WGLEW_GET_FUN(__wglewGetCurrentReadDCEXT)
+#define wglMakeContextCurrentEXT WGLEW_GET_FUN(__wglewMakeContextCurrentEXT)
+
+#define WGLEW_EXT_make_current_read WGLEW_GET_VAR(__WGLEW_EXT_make_current_read)
+
+#endif /* WGL_EXT_make_current_read */
+
+/* -------------------------- WGL_EXT_multisample -------------------------- */
+
+#ifndef WGL_EXT_multisample
+#define WGL_EXT_multisample 1
+
+#define WGL_SAMPLE_BUFFERS_EXT 0x2041
+#define WGL_SAMPLES_EXT 0x2042
+
+#define WGLEW_EXT_multisample WGLEW_GET_VAR(__WGLEW_EXT_multisample)
+
+#endif /* WGL_EXT_multisample */
+
+/* ---------------------------- WGL_EXT_pbuffer ---------------------------- */
+
+#ifndef WGL_EXT_pbuffer
+#define WGL_EXT_pbuffer 1
+
+#define WGL_DRAW_TO_PBUFFER_EXT 0x202D
+#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E
+#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030
+#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031
+#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032
+#define WGL_PBUFFER_LARGEST_EXT 0x2033
+#define WGL_PBUFFER_WIDTH_EXT 0x2034
+#define WGL_PBUFFER_HEIGHT_EXT 0x2035
+
+DECLARE_HANDLE(HPBUFFEREXT);
+
+typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
+typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer);
+typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer);
+typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int* piValue);
+typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC);
+
+#define wglCreatePbufferEXT WGLEW_GET_FUN(__wglewCreatePbufferEXT)
+#define wglDestroyPbufferEXT WGLEW_GET_FUN(__wglewDestroyPbufferEXT)
+#define wglGetPbufferDCEXT WGLEW_GET_FUN(__wglewGetPbufferDCEXT)
+#define wglQueryPbufferEXT WGLEW_GET_FUN(__wglewQueryPbufferEXT)
+#define wglReleasePbufferDCEXT WGLEW_GET_FUN(__wglewReleasePbufferDCEXT)
+
+#define WGLEW_EXT_pbuffer WGLEW_GET_VAR(__WGLEW_EXT_pbuffer)
+
+#endif /* WGL_EXT_pbuffer */
+
+/* -------------------------- WGL_EXT_pixel_format ------------------------- */
+
+#ifndef WGL_EXT_pixel_format
+#define WGL_EXT_pixel_format 1
+
+#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000
+#define WGL_DRAW_TO_WINDOW_EXT 0x2001
+#define WGL_DRAW_TO_BITMAP_EXT 0x2002
+#define WGL_ACCELERATION_EXT 0x2003
+#define WGL_NEED_PALETTE_EXT 0x2004
+#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005
+#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006
+#define WGL_SWAP_METHOD_EXT 0x2007
+#define WGL_NUMBER_OVERLAYS_EXT 0x2008
+#define WGL_NUMBER_UNDERLAYS_EXT 0x2009
+#define WGL_TRANSPARENT_EXT 0x200A
+#define WGL_TRANSPARENT_VALUE_EXT 0x200B
+#define WGL_SHARE_DEPTH_EXT 0x200C
+#define WGL_SHARE_STENCIL_EXT 0x200D
+#define WGL_SHARE_ACCUM_EXT 0x200E
+#define WGL_SUPPORT_GDI_EXT 0x200F
+#define WGL_SUPPORT_OPENGL_EXT 0x2010
+#define WGL_DOUBLE_BUFFER_EXT 0x2011
+#define WGL_STEREO_EXT 0x2012
+#define WGL_PIXEL_TYPE_EXT 0x2013
+#define WGL_COLOR_BITS_EXT 0x2014
+#define WGL_RED_BITS_EXT 0x2015
+#define WGL_RED_SHIFT_EXT 0x2016
+#define WGL_GREEN_BITS_EXT 0x2017
+#define WGL_GREEN_SHIFT_EXT 0x2018
+#define WGL_BLUE_BITS_EXT 0x2019
+#define WGL_BLUE_SHIFT_EXT 0x201A
+#define WGL_ALPHA_BITS_EXT 0x201B
+#define WGL_ALPHA_SHIFT_EXT 0x201C
+#define WGL_ACCUM_BITS_EXT 0x201D
+#define WGL_ACCUM_RED_BITS_EXT 0x201E
+#define WGL_ACCUM_GREEN_BITS_EXT 0x201F
+#define WGL_ACCUM_BLUE_BITS_EXT 0x2020
+#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021
+#define WGL_DEPTH_BITS_EXT 0x2022
+#define WGL_STENCIL_BITS_EXT 0x2023
+#define WGL_AUX_BUFFERS_EXT 0x2024
+#define WGL_NO_ACCELERATION_EXT 0x2025
+#define WGL_GENERIC_ACCELERATION_EXT 0x2026
+#define WGL_FULL_ACCELERATION_EXT 0x2027
+#define WGL_SWAP_EXCHANGE_EXT 0x2028
+#define WGL_SWAP_COPY_EXT 0x2029
+#define WGL_SWAP_UNDEFINED_EXT 0x202A
+#define WGL_TYPE_RGBA_EXT 0x202B
+#define WGL_TYPE_COLORINDEX_EXT 0x202C
+
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, FLOAT *pfValues);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues);
+
+#define wglChoosePixelFormatEXT WGLEW_GET_FUN(__wglewChoosePixelFormatEXT)
+#define wglGetPixelFormatAttribfvEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvEXT)
+#define wglGetPixelFormatAttribivEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribivEXT)
+
+#define WGLEW_EXT_pixel_format WGLEW_GET_VAR(__WGLEW_EXT_pixel_format)
+
+#endif /* WGL_EXT_pixel_format */
+
+/* -------------------------- WGL_EXT_swap_control ------------------------- */
+
+#ifndef WGL_EXT_swap_control
+#define WGL_EXT_swap_control 1
+
+typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);
+typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
+
+#define wglGetSwapIntervalEXT WGLEW_GET_FUN(__wglewGetSwapIntervalEXT)
+#define wglSwapIntervalEXT WGLEW_GET_FUN(__wglewSwapIntervalEXT)
+
+#define WGLEW_EXT_swap_control WGLEW_GET_VAR(__WGLEW_EXT_swap_control)
+
+#endif /* WGL_EXT_swap_control */
+
+/* --------------------- WGL_I3D_digital_video_control --------------------- */
+
+#ifndef WGL_I3D_digital_video_control
+#define WGL_I3D_digital_video_control 1
+
+#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050
+#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051
+#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052
+#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053
+
+typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue);
+typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue);
+
+#define wglGetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewGetDigitalVideoParametersI3D)
+#define wglSetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewSetDigitalVideoParametersI3D)
+
+#define WGLEW_I3D_digital_video_control WGLEW_GET_VAR(__WGLEW_I3D_digital_video_control)
+
+#endif /* WGL_I3D_digital_video_control */
+
+/* ----------------------------- WGL_I3D_gamma ----------------------------- */
+
+#ifndef WGL_I3D_gamma
+#define WGL_I3D_gamma 1
+
+#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E
+#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F
+
+typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT* puRed, USHORT *puGreen, USHORT *puBlue);
+typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue);
+typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT* puRed, const USHORT *puGreen, const USHORT *puBlue);
+typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue);
+
+#define wglGetGammaTableI3D WGLEW_GET_FUN(__wglewGetGammaTableI3D)
+#define wglGetGammaTableParametersI3D WGLEW_GET_FUN(__wglewGetGammaTableParametersI3D)
+#define wglSetGammaTableI3D WGLEW_GET_FUN(__wglewSetGammaTableI3D)
+#define wglSetGammaTableParametersI3D WGLEW_GET_FUN(__wglewSetGammaTableParametersI3D)
+
+#define WGLEW_I3D_gamma WGLEW_GET_VAR(__WGLEW_I3D_gamma)
+
+#endif /* WGL_I3D_gamma */
+
+/* ---------------------------- WGL_I3D_genlock ---------------------------- */
+
+#ifndef WGL_I3D_genlock
+#define WGL_I3D_genlock 1
+
+#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044
+#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045
+#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046
+#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047
+#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048
+#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049
+#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A
+#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B
+#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C
+
+typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC);
+typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT* uRate);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT* uDelay);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT* uEdge);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT* uSource);
+typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL* pFlag);
+typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT* uMaxLineDelay, UINT *uMaxPixelDelay);
+
+#define wglDisableGenlockI3D WGLEW_GET_FUN(__wglewDisableGenlockI3D)
+#define wglEnableGenlockI3D WGLEW_GET_FUN(__wglewEnableGenlockI3D)
+#define wglGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGenlockSampleRateI3D)
+#define wglGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGenlockSourceDelayI3D)
+#define wglGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGenlockSourceEdgeI3D)
+#define wglGenlockSourceI3D WGLEW_GET_FUN(__wglewGenlockSourceI3D)
+#define wglGetGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGetGenlockSampleRateI3D)
+#define wglGetGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGetGenlockSourceDelayI3D)
+#define wglGetGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGetGenlockSourceEdgeI3D)
+#define wglGetGenlockSourceI3D WGLEW_GET_FUN(__wglewGetGenlockSourceI3D)
+#define wglIsEnabledGenlockI3D WGLEW_GET_FUN(__wglewIsEnabledGenlockI3D)
+#define wglQueryGenlockMaxSourceDelayI3D WGLEW_GET_FUN(__wglewQueryGenlockMaxSourceDelayI3D)
+
+#define WGLEW_I3D_genlock WGLEW_GET_VAR(__WGLEW_I3D_genlock)
+
+#endif /* WGL_I3D_genlock */
+
+/* -------------------------- WGL_I3D_image_buffer ------------------------- */
+
+#ifndef WGL_I3D_image_buffer
+#define WGL_I3D_image_buffer 1
+
+#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001
+#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002
+
+typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, HANDLE* pEvent, LPVOID *pAddress, DWORD *pSize, UINT count);
+typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags);
+typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress);
+typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, LPVOID* pAddress, UINT count);
+
+#define wglAssociateImageBufferEventsI3D WGLEW_GET_FUN(__wglewAssociateImageBufferEventsI3D)
+#define wglCreateImageBufferI3D WGLEW_GET_FUN(__wglewCreateImageBufferI3D)
+#define wglDestroyImageBufferI3D WGLEW_GET_FUN(__wglewDestroyImageBufferI3D)
+#define wglReleaseImageBufferEventsI3D WGLEW_GET_FUN(__wglewReleaseImageBufferEventsI3D)
+
+#define WGLEW_I3D_image_buffer WGLEW_GET_VAR(__WGLEW_I3D_image_buffer)
+
+#endif /* WGL_I3D_image_buffer */
+
+/* ------------------------ WGL_I3D_swap_frame_lock ------------------------ */
+
+#ifndef WGL_I3D_swap_frame_lock
+#define WGL_I3D_swap_frame_lock 1
+
+typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL* pFlag);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL* pFlag);
+
+#define wglDisableFrameLockI3D WGLEW_GET_FUN(__wglewDisableFrameLockI3D)
+#define wglEnableFrameLockI3D WGLEW_GET_FUN(__wglewEnableFrameLockI3D)
+#define wglIsEnabledFrameLockI3D WGLEW_GET_FUN(__wglewIsEnabledFrameLockI3D)
+#define wglQueryFrameLockMasterI3D WGLEW_GET_FUN(__wglewQueryFrameLockMasterI3D)
+
+#define WGLEW_I3D_swap_frame_lock WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_lock)
+
+#endif /* WGL_I3D_swap_frame_lock */
+
+/* ------------------------ WGL_I3D_swap_frame_usage ----------------------- */
+
+#ifndef WGL_I3D_swap_frame_usage
+#define WGL_I3D_swap_frame_usage 1
+
+typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float* pUsage);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD* pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);
+
+#define wglBeginFrameTrackingI3D WGLEW_GET_FUN(__wglewBeginFrameTrackingI3D)
+#define wglEndFrameTrackingI3D WGLEW_GET_FUN(__wglewEndFrameTrackingI3D)
+#define wglGetFrameUsageI3D WGLEW_GET_FUN(__wglewGetFrameUsageI3D)
+#define wglQueryFrameTrackingI3D WGLEW_GET_FUN(__wglewQueryFrameTrackingI3D)
+
+#define WGLEW_I3D_swap_frame_usage WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_usage)
+
+#endif /* WGL_I3D_swap_frame_usage */
+
+/* -------------------------- WGL_NV_float_buffer -------------------------- */
+
+#ifndef WGL_NV_float_buffer
+#define WGL_NV_float_buffer 1
+
+#define WGL_FLOAT_COMPONENTS_NV 0x20B0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4
+#define WGL_TEXTURE_FLOAT_R_NV 0x20B5
+#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6
+#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7
+#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8
+
+#define WGLEW_NV_float_buffer WGLEW_GET_VAR(__WGLEW_NV_float_buffer)
+
+#endif /* WGL_NV_float_buffer */
+
+/* ---------------------- WGL_NV_render_depth_texture ---------------------- */
+
+#ifndef WGL_NV_render_depth_texture
+#define WGL_NV_render_depth_texture 1
+
+#define WGL_NO_TEXTURE_ARB 0x2077
+#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4
+#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5
+#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6
+#define WGL_DEPTH_COMPONENT_NV 0x20A7
+
+#define WGLEW_NV_render_depth_texture WGLEW_GET_VAR(__WGLEW_NV_render_depth_texture)
+
+#endif /* WGL_NV_render_depth_texture */
+
+/* -------------------- WGL_NV_render_texture_rectangle -------------------- */
+
+#ifndef WGL_NV_render_texture_rectangle
+#define WGL_NV_render_texture_rectangle 1
+
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
+#define WGL_TEXTURE_RECTANGLE_NV 0x20A2
+
+#define WGLEW_NV_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_NV_render_texture_rectangle)
+
+#endif /* WGL_NV_render_texture_rectangle */
+
+/* ----------------------- WGL_NV_vertex_array_range ----------------------- */
+
+#ifndef WGL_NV_vertex_array_range
+#define WGL_NV_vertex_array_range 1
+
+typedef void * (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority);
+typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer);
+
+#define wglAllocateMemoryNV WGLEW_GET_FUN(__wglewAllocateMemoryNV)
+#define wglFreeMemoryNV WGLEW_GET_FUN(__wglewFreeMemoryNV)
+
+#define WGLEW_NV_vertex_array_range WGLEW_GET_VAR(__WGLEW_NV_vertex_array_range)
+
+#endif /* WGL_NV_vertex_array_range */
+
+/* -------------------------- WGL_OML_sync_control ------------------------- */
+
+#ifndef WGL_OML_sync_control
+#define WGL_OML_sync_control 1
+
+typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32* numerator, INT32 *denominator);
+typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64* ust, INT64 *msc, INT64 *sbc);
+typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
+typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
+typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64* ust, INT64 *msc, INT64 *sbc);
+typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64* ust, INT64 *msc, INT64 *sbc);
+
+#define wglGetMscRateOML WGLEW_GET_FUN(__wglewGetMscRateOML)
+#define wglGetSyncValuesOML WGLEW_GET_FUN(__wglewGetSyncValuesOML)
+#define wglSwapBuffersMscOML WGLEW_GET_FUN(__wglewSwapBuffersMscOML)
+#define wglSwapLayerBuffersMscOML WGLEW_GET_FUN(__wglewSwapLayerBuffersMscOML)
+#define wglWaitForMscOML WGLEW_GET_FUN(__wglewWaitForMscOML)
+#define wglWaitForSbcOML WGLEW_GET_FUN(__wglewWaitForSbcOML)
+
+#define WGLEW_OML_sync_control WGLEW_GET_VAR(__WGLEW_OML_sync_control)
+
+#endif /* WGL_OML_sync_control */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef GLEW_MX
+#define WGLEW_EXPORT
+#else
+#define WGLEW_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#ifdef GLEW_MX
+struct WGLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+WGLEW_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB;
+WGLEW_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB;
+WGLEW_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB;
+WGLEW_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB;
+
+WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB;
+
+WGLEW_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB;
+WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB;
+
+WGLEW_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB;
+WGLEW_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB;
+WGLEW_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB;
+WGLEW_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB;
+WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB;
+
+WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB;
+
+WGLEW_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB;
+WGLEW_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB;
+WGLEW_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB;
+
+WGLEW_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT;
+WGLEW_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT;
+WGLEW_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT;
+WGLEW_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT;
+
+WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT;
+
+WGLEW_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT;
+WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT;
+
+WGLEW_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT;
+WGLEW_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT;
+WGLEW_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT;
+WGLEW_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT;
+WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT;
+
+WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT;
+
+WGLEW_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT;
+WGLEW_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT;
+
+WGLEW_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D;
+WGLEW_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D;
+
+WGLEW_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D;
+WGLEW_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D;
+WGLEW_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D;
+WGLEW_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D;
+
+WGLEW_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D;
+WGLEW_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D;
+WGLEW_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D;
+WGLEW_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D;
+
+WGLEW_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D;
+WGLEW_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D;
+WGLEW_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D;
+WGLEW_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D;
+
+WGLEW_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D;
+WGLEW_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D;
+WGLEW_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D;
+WGLEW_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D;
+
+WGLEW_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D;
+WGLEW_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D;
+WGLEW_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D;
+WGLEW_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D;
+
+WGLEW_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV;
+WGLEW_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV;
+
+WGLEW_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML;
+WGLEW_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML;
+WGLEW_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML;
+WGLEW_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML;
+WGLEW_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML;
+WGLEW_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML;
+WGLEW_EXPORT GLboolean __WGLEW_3DFX_multisample;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_buffer_region;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_extensions_string;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_make_current_read;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_multisample;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_pbuffer;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format_float;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_render_texture;
+WGLEW_EXPORT GLboolean __WGLEW_ATI_pixel_format_float;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_depth_float;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_display_color_table;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_extensions_string;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_make_current_read;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_multisample;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_pbuffer;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_digital_video_control;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_gamma;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_genlock;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_image_buffer;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage;
+WGLEW_EXPORT GLboolean __WGLEW_NV_float_buffer;
+WGLEW_EXPORT GLboolean __WGLEW_NV_render_depth_texture;
+WGLEW_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle;
+WGLEW_EXPORT GLboolean __WGLEW_NV_vertex_array_range;
+WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control;
+
+#ifdef GLEW_MX
+}; /* WGLEWContextStruct */
+#endif /* GLEW_MX */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef GLEW_MX
+
+typedef struct WGLEWContextStruct WGLEWContext;
+GLEWAPI GLenum wglewContextInit (WGLEWContext* ctx);
+
+#define WGLEW_GET_VAR(x) wglewGetContext()->x
+#define WGLEW_GET_FUN(x) wglewGetContext()->x
+
+#else /* GLEW_MX */
+
+#define WGLEW_GET_VAR(x) x
+#define WGLEW_GET_FUN(x) x
+
+#endif /* GLEW_MX */
+
+GLEWAPI GLboolean wglewGetExtension (const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#undef GLEWAPI
+
+#endif /* __wglew_h__ */
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GL/glxew.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GL/glxew.h	(revision 498)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GL/glxew.h	(revision 498)
@@ -0,0 +1,1055 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2004, 2003, 2002, Milan Ikits <milan ikits[at]ieee org>
+** Copyright (C) 2004, 2003, 2002, Marcelo E. Magallon <mmagallo[at]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** All rights reserved.
+** 
+** Redistribution and use in source and binary forms, with or without 
+** modification, are permitted provided that the following conditions are met:
+** 
+** * Redistributions of source code must retain the above copyright notice, 
+**   this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright notice, 
+**   this list of conditions and the following disclaimer in the documentation 
+**   and/or other materials provided with the distribution.
+** * The name of the author may be used to endorse or promote products 
+**   derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+** THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+** The contents of this file are subject to the GLX Public License Version 1.0
+** (the "License"). You may not use this file except in compliance with the
+** License. You may obtain a copy of the License at Silicon Graphics, Inc.,
+** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043
+** or at http://www.sgi.com/software/opensource/glx/license.html.
+**
+** Software distributed under the License is distributed on an "AS IS"
+** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY
+** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
+** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific
+** language governing rights and limitations under the License.
+**
+** The Original Software is GLX version 1.2 source code, released February,
+** 1999. The developer of the Original Software is Silicon Graphics, Inc.
+** Those portions of the Subject Software created by Silicon Graphics, Inc.
+** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved.
+*/
+
+#ifndef __glxew_h__
+#define __glxew_h__
+#define __GLXEW_H__
+
+#ifdef __glxext_h_
+#error glxext.h included before glxew.h
+#endif
+
+#define __glxext_h_
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xmd.h>
+#include <GL/glew.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ---------------------------- GLX_VERSION_1_0 --------------------------- */
+
+#ifndef GLX_VERSION_1_0
+#define GLX_VERSION_1_0 1
+
+#define GLX_USE_GL 1
+#define GLX_BUFFER_SIZE 2
+#define GLX_LEVEL 3
+#define GLX_RGBA 4
+#define GLX_DOUBLEBUFFER 5
+#define GLX_STEREO 6
+#define GLX_AUX_BUFFERS 7
+#define GLX_RED_SIZE 8
+#define GLX_GREEN_SIZE 9
+#define GLX_BLUE_SIZE 10
+#define GLX_ALPHA_SIZE 11
+#define GLX_DEPTH_SIZE 12
+#define GLX_STENCIL_SIZE 13
+#define GLX_ACCUM_RED_SIZE 14
+#define GLX_ACCUM_GREEN_SIZE 15
+#define GLX_ACCUM_BLUE_SIZE 16
+#define GLX_ACCUM_ALPHA_SIZE 17
+#define GLX_BAD_SCREEN 1
+#define GLX_BAD_ATTRIBUTE 2
+#define GLX_NO_EXTENSION 3
+#define GLX_BAD_VISUAL 4
+#define GLX_BAD_CONTEXT 5
+#define GLX_BAD_VALUE 6
+#define GLX_BAD_ENUM 7
+
+typedef XID GLXDrawable;
+typedef XID GLXPixmap;
+typedef struct __GLXcontextRec *GLXContext;
+
+extern Bool glXQueryExtension (Display *dpy, int *errorBase, int *eventBase);
+extern Bool glXQueryVersion (Display *dpy, int *major, int *minor);
+extern int glXGetConfig (Display *dpy, XVisualInfo *vis, int attrib, int *value);
+extern XVisualInfo* glXChooseVisual (Display *dpy, int screen, int *attribList);
+extern GLXPixmap glXCreateGLXPixmap (Display *dpy, XVisualInfo *vis, Pixmap pixmap);
+extern void glXDestroyGLXPixmap (Display *dpy, GLXPixmap pix);
+extern GLXContext glXCreateContext (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
+extern void glXDestroyContext (Display *dpy, GLXContext ctx);
+extern Bool glXIsDirect (Display *dpy, GLXContext ctx);
+extern void glXCopyContext (Display *dpy, GLXContext src, GLXContext dst, GLuint mask);
+extern Bool glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx);
+extern GLXContext glXGetCurrentContext (void);
+extern GLXDrawable glXGetCurrentDrawable (void);
+extern void glXWaitGL (void);
+extern void glXWaitX (void);
+extern void glXSwapBuffers (Display *dpy, GLXDrawable drawable);
+extern void glXUseXFont (Font font, int first, int count, int listBase);
+
+#define GLXEW_VERSION_1_0 GLXEW_GET_VAR(__GLXEW_VERSION_1_0)
+
+#endif /* GLX_VERSION_1_0 */
+
+/* ---------------------------- GLX_VERSION_1_1 --------------------------- */
+
+#ifndef GLX_VERSION_1_1
+#define GLX_VERSION_1_1
+
+#define GLX_VENDOR 0x1
+#define GLX_VERSION 0x2
+#define GLX_EXTENSIONS 0x3
+
+extern const char* glXQueryExtensionsString (Display *dpy, int screen);
+extern const char* glXGetClientString (Display *dpy, int name);
+extern const char* glXQueryServerString (Display *dpy, int screen, int name);
+
+#define GLXEW_VERSION_1_1 GLXEW_GET_VAR(__GLXEW_VERSION_1_1)
+
+#endif /* GLX_VERSION_1_1 */
+
+/* ---------------------------- GLX_VERSION_1_2 ---------------------------- */
+
+#ifndef GLX_VERSION_1_2
+#define GLX_VERSION_1_2 1
+
+typedef Display* ( * PFNGLXGETCURRENTDISPLAYPROC) (void);
+
+#define glXGetCurrentDisplay GLXEW_GET_FUN(__glewXGetCurrentDisplay)
+
+#define GLXEW_VERSION_1_2 GLXEW_GET_VAR(__GLXEW_VERSION_1_2)
+
+#endif /* GLX_VERSION_1_2 */
+
+/* ---------------------------- GLX_VERSION_1_3 ---------------------------- */
+
+#ifndef GLX_VERSION_1_3
+#define GLX_VERSION_1_3 1
+
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_COLOR_INDEX_BIT 0x00000002
+#define GLX_PIXMAP_BIT 0x00000002
+#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
+#define GLX_PBUFFER_BIT 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
+#define GLX_AUX_BUFFERS_BIT 0x00000010
+#define GLX_CONFIG_CAVEAT 0x20
+#define GLX_DEPTH_BUFFER_BIT 0x00000020
+#define GLX_X_VISUAL_TYPE 0x22
+#define GLX_TRANSPARENT_TYPE 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE 0x24
+#define GLX_TRANSPARENT_RED_VALUE 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
+#define GLX_STENCIL_BUFFER_BIT 0x00000040
+#define GLX_ACCUM_BUFFER_BIT 0x00000080
+#define GLX_NONE 0x8000
+#define GLX_SLOW_CONFIG 0x8001
+#define GLX_TRUE_COLOR 0x8002
+#define GLX_DIRECT_COLOR 0x8003
+#define GLX_PSEUDO_COLOR 0x8004
+#define GLX_STATIC_COLOR 0x8005
+#define GLX_GRAY_SCALE 0x8006
+#define GLX_STATIC_GRAY 0x8007
+#define GLX_TRANSPARENT_RGB 0x8008
+#define GLX_TRANSPARENT_INDEX 0x8009
+#define GLX_VISUAL_ID 0x800B
+#define GLX_SCREEN 0x800C
+#define GLX_NON_CONFORMANT_CONFIG 0x800D
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_X_RENDERABLE 0x8012
+#define GLX_FBCONFIG_ID 0x8013
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_COLOR_INDEX_TYPE 0x8015
+#define GLX_MAX_PBUFFER_WIDTH 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT 0x8017
+#define GLX_MAX_PBUFFER_PIXELS 0x8018
+#define GLX_PRESERVED_CONTENTS 0x801B
+#define GLX_LARGEST_PBUFFER 0x801C
+#define GLX_WIDTH 0x801D
+#define GLX_HEIGHT 0x801E
+#define GLX_EVENT_MASK 0x801F
+#define GLX_DAMAGED 0x8020
+#define GLX_SAVED 0x8021
+#define GLX_WINDOW 0x8022
+#define GLX_PBUFFER 0x8023
+#define GLX_PBUFFER_HEIGHT 0x8040
+#define GLX_PBUFFER_WIDTH 0x8041
+#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
+#define GLX_DONT_CARE 0xFFFFFFFF
+
+typedef XID GLXFBConfigID;
+typedef XID GLXWindow;
+typedef XID GLXPbuffer;
+typedef struct __GLXFBConfigRec *GLXFBConfig;
+typedef struct { int event_type; int draw_type; unsigned long serial; Bool send_event; Display *display; GLXDrawable drawable; unsigned int buffer_mask; unsigned int aux_buffer; int x, y; int width, height; int count; } GLXPbufferClobberEvent;
+typedef union __GLXEvent { GLXPbufferClobberEvent glxpbufferclobber; long pad[24]; } GLXEvent;
+
+typedef GLXFBConfig* ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);
+typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list);
+typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
+typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list);
+typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf);
+typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap);
+typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win);
+typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void);
+typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value);
+typedef GLXFBConfig* ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements);
+typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask);
+typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config);
+typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value);
+typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
+typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask);
+
+#define glXChooseFBConfig GLXEW_GET_FUN(__glewXChooseFBConfig)
+#define glXCreateNewContext GLXEW_GET_FUN(__glewXCreateNewContext)
+#define glXCreatePbuffer GLXEW_GET_FUN(__glewXCreatePbuffer)
+#define glXCreatePixmap GLXEW_GET_FUN(__glewXCreatePixmap)
+#define glXCreateWindow GLXEW_GET_FUN(__glewXCreateWindow)
+#define glXDestroyPbuffer GLXEW_GET_FUN(__glewXDestroyPbuffer)
+#define glXDestroyPixmap GLXEW_GET_FUN(__glewXDestroyPixmap)
+#define glXDestroyWindow GLXEW_GET_FUN(__glewXDestroyWindow)
+#define glXGetCurrentReadDrawable GLXEW_GET_FUN(__glewXGetCurrentReadDrawable)
+#define glXGetFBConfigAttrib GLXEW_GET_FUN(__glewXGetFBConfigAttrib)
+#define glXGetFBConfigs GLXEW_GET_FUN(__glewXGetFBConfigs)
+#define glXGetSelectedEvent GLXEW_GET_FUN(__glewXGetSelectedEvent)
+#define glXGetVisualFromFBConfig GLXEW_GET_FUN(__glewXGetVisualFromFBConfig)
+#define glXMakeContextCurrent GLXEW_GET_FUN(__glewXMakeContextCurrent)
+#define glXQueryContext GLXEW_GET_FUN(__glewXQueryContext)
+#define glXQueryDrawable GLXEW_GET_FUN(__glewXQueryDrawable)
+#define glXSelectEvent GLXEW_GET_FUN(__glewXSelectEvent)
+
+#define GLXEW_VERSION_1_3 GLXEW_GET_VAR(__GLXEW_VERSION_1_3)
+
+#endif /* GLX_VERSION_1_3 */
+
+/* ---------------------------- GLX_VERSION_1_4 ---------------------------- */
+
+#ifndef GLX_VERSION_1_4
+#define GLX_VERSION_1_4 1
+
+#define GLX_SAMPLE_BUFFERS 100000
+#define GLX_SAMPLES 100001
+
+extern void ( * glXGetProcAddress (const GLubyte *procName)) (void);
+
+#define GLXEW_VERSION_1_4 GLXEW_GET_VAR(__GLXEW_VERSION_1_4)
+
+#endif /* GLX_VERSION_1_4 */
+
+/* -------------------------- GLX_3DFX_multisample ------------------------- */
+
+#ifndef GLX_3DFX_multisample
+#define GLX_3DFX_multisample 1
+
+#define GLX_SAMPLE_BUFFERS_3DFX 0x8050
+#define GLX_SAMPLES_3DFX 0x8051
+
+#define GLXEW_3DFX_multisample GLXEW_GET_VAR(__GLXEW_3DFX_multisample)
+
+#endif /* GLX_3DFX_multisample */
+
+/* ------------------------- GLX_ARB_fbconfig_float ------------------------ */
+
+#ifndef GLX_ARB_fbconfig_float
+#define GLX_ARB_fbconfig_float 1
+
+#define GLX_RGBA_FLOAT_BIT 0x00000004
+#define GLX_RGBA_FLOAT_TYPE 0x20B9
+
+#define GLXEW_ARB_fbconfig_float GLXEW_GET_VAR(__GLXEW_ARB_fbconfig_float)
+
+#endif /* GLX_ARB_fbconfig_float */
+
+/* ------------------------ GLX_ARB_get_proc_address ----------------------- */
+
+#ifndef GLX_ARB_get_proc_address
+#define GLX_ARB_get_proc_address 1
+
+extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void);
+
+#define GLXEW_ARB_get_proc_address GLXEW_GET_VAR(__GLXEW_ARB_get_proc_address)
+
+#endif /* GLX_ARB_get_proc_address */
+
+/* -------------------------- GLX_ARB_multisample -------------------------- */
+
+#ifndef GLX_ARB_multisample
+#define GLX_ARB_multisample 1
+
+#define GLX_SAMPLE_BUFFERS_ARB 100000
+#define GLX_SAMPLES_ARB 100001
+
+#define GLXEW_ARB_multisample GLXEW_GET_VAR(__GLXEW_ARB_multisample)
+
+#endif /* GLX_ARB_multisample */
+
+/* ----------------------- GLX_ATI_pixel_format_float ---------------------- */
+
+#ifndef GLX_ATI_pixel_format_float
+#define GLX_ATI_pixel_format_float 1
+
+#define GLX_RGBA_FLOAT_ATI_BIT 0x00000100
+
+#define GLXEW_ATI_pixel_format_float GLXEW_GET_VAR(__GLXEW_ATI_pixel_format_float)
+
+#endif /* GLX_ATI_pixel_format_float */
+
+/* ------------------------- GLX_ATI_render_texture ------------------------ */
+
+#ifndef GLX_ATI_render_texture
+#define GLX_ATI_render_texture 1
+
+#define GLX_BIND_TO_TEXTURE_RGB_ATI 0x9800
+#define GLX_BIND_TO_TEXTURE_RGBA_ATI 0x9801
+#define GLX_TEXTURE_FORMAT_ATI 0x9802
+#define GLX_TEXTURE_TARGET_ATI 0x9803
+#define GLX_MIPMAP_TEXTURE_ATI 0x9804
+#define GLX_TEXTURE_RGB_ATI 0x9805
+#define GLX_TEXTURE_RGBA_ATI 0x9806
+#define GLX_NO_TEXTURE_ATI 0x9807
+#define GLX_TEXTURE_CUBE_MAP_ATI 0x9808
+#define GLX_TEXTURE_1D_ATI 0x9809
+#define GLX_TEXTURE_2D_ATI 0x980A
+#define GLX_MIPMAP_LEVEL_ATI 0x980B
+#define GLX_CUBE_MAP_FACE_ATI 0x980C
+#define GLX_TEXTURE_CUBE_MAP_POSITIVE_X_ATI 0x980D
+#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_X_ATI 0x980E
+#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Y_ATI 0x980F
+#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Y_ATI 0x9810
+#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Z_ATI 0x9811
+#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Z_ATI 0x9812
+#define GLX_FRONT_LEFT_ATI 0x9813
+#define GLX_FRONT_RIGHT_ATI 0x9814
+#define GLX_BACK_LEFT_ATI 0x9815
+#define GLX_BACK_RIGHT_ATI 0x9816
+#define GLX_AUX0_ATI 0x9817
+#define GLX_AUX1_ATI 0x9818
+#define GLX_AUX2_ATI 0x9819
+#define GLX_AUX3_ATI 0x981A
+#define GLX_AUX4_ATI 0x981B
+#define GLX_AUX5_ATI 0x981C
+#define GLX_AUX6_ATI 0x981D
+#define GLX_AUX7_ATI 0x981E
+#define GLX_AUX8_ATI 0x981F
+#define GLX_AUX9_ATI 0x9820
+#define GLX_BIND_TO_TEXTURE_LUMINANCE_ATI 0x9821
+#define GLX_BIND_TO_TEXTURE_INTENSITY_ATI 0x9822
+
+typedef void ( * PFNGLXBINDTEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer);
+typedef void ( * PFNGLXDRAWABLEATTRIBATIPROC) (Display *dpy, GLXDrawable draw, const int *attrib_list);
+typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer);
+
+#define glXBindTexImageATI GLXEW_GET_FUN(__glewXBindTexImageATI)
+#define glXDrawableAttribATI GLXEW_GET_FUN(__glewXDrawableAttribATI)
+#define glXReleaseTexImageATI GLXEW_GET_FUN(__glewXReleaseTexImageATI)
+
+#define GLXEW_ATI_render_texture GLXEW_GET_VAR(__GLXEW_ATI_render_texture)
+
+#endif /* GLX_ATI_render_texture */
+
+/* ------------------------- GLX_EXT_import_context ------------------------ */
+
+#ifndef GLX_EXT_import_context
+#define GLX_EXT_import_context 1
+
+#define GLX_SHARE_CONTEXT_EXT 0x800A
+#define GLX_VISUAL_ID_EXT 0x800B
+#define GLX_SCREEN_EXT 0x800C
+
+typedef XID GLXContextID;
+
+typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display* dpy, GLXContext context);
+typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context);
+typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display* dpy, GLXContextID contextID);
+typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display* dpy, GLXContext context, int attribute,int *value);
+
+#define glXFreeContextEXT GLXEW_GET_FUN(__glewXFreeContextEXT)
+#define glXGetContextIDEXT GLXEW_GET_FUN(__glewXGetContextIDEXT)
+#define glXImportContextEXT GLXEW_GET_FUN(__glewXImportContextEXT)
+#define glXQueryContextInfoEXT GLXEW_GET_FUN(__glewXQueryContextInfoEXT)
+
+#define GLXEW_EXT_import_context GLXEW_GET_VAR(__GLXEW_EXT_import_context)
+
+#endif /* GLX_EXT_import_context */
+
+/* -------------------------- GLX_EXT_scene_marker ------------------------- */
+
+#ifndef GLX_EXT_scene_marker
+#define GLX_EXT_scene_marker 1
+
+#define GLXEW_EXT_scene_marker GLXEW_GET_VAR(__GLXEW_EXT_scene_marker)
+
+#endif /* GLX_EXT_scene_marker */
+
+/* -------------------------- GLX_EXT_visual_info -------------------------- */
+
+#ifndef GLX_EXT_visual_info
+#define GLX_EXT_visual_info 1
+
+#define GLX_X_VISUAL_TYPE_EXT 0x22
+#define GLX_TRANSPARENT_TYPE_EXT 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24
+#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28
+#define GLX_NONE_EXT 0x8000
+#define GLX_TRUE_COLOR_EXT 0x8002
+#define GLX_DIRECT_COLOR_EXT 0x8003
+#define GLX_PSEUDO_COLOR_EXT 0x8004
+#define GLX_STATIC_COLOR_EXT 0x8005
+#define GLX_GRAY_SCALE_EXT 0x8006
+#define GLX_STATIC_GRAY_EXT 0x8007
+#define GLX_TRANSPARENT_RGB_EXT 0x8008
+#define GLX_TRANSPARENT_INDEX_EXT 0x8009
+
+#define GLXEW_EXT_visual_info GLXEW_GET_VAR(__GLXEW_EXT_visual_info)
+
+#endif /* GLX_EXT_visual_info */
+
+/* ------------------------- GLX_EXT_visual_rating ------------------------- */
+
+#ifndef GLX_EXT_visual_rating
+#define GLX_EXT_visual_rating 1
+
+#define GLX_VISUAL_CAVEAT_EXT 0x20
+#define GLX_SLOW_VISUAL_EXT 0x8001
+#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
+
+#define GLXEW_EXT_visual_rating GLXEW_GET_VAR(__GLXEW_EXT_visual_rating)
+
+#endif /* GLX_EXT_visual_rating */
+
+/* -------------------------- GLX_MESA_agp_offset -------------------------- */
+
+#ifndef GLX_MESA_agp_offset
+#define GLX_MESA_agp_offset 1
+
+typedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void* pointer);
+
+#define glXGetAGPOffsetMESA GLXEW_GET_FUN(__glewXGetAGPOffsetMESA)
+
+#define GLXEW_MESA_agp_offset GLXEW_GET_VAR(__GLXEW_MESA_agp_offset)
+
+#endif /* GLX_MESA_agp_offset */
+
+/* ------------------------ GLX_MESA_copy_sub_buffer ----------------------- */
+
+#ifndef GLX_MESA_copy_sub_buffer
+#define GLX_MESA_copy_sub_buffer 1
+
+typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display* dpy, GLXDrawable drawable, int x, int y, int width, int height);
+
+#define glXCopySubBufferMESA GLXEW_GET_FUN(__glewXCopySubBufferMESA)
+
+#define GLXEW_MESA_copy_sub_buffer GLXEW_GET_VAR(__GLXEW_MESA_copy_sub_buffer)
+
+#endif /* GLX_MESA_copy_sub_buffer */
+
+/* ------------------------ GLX_MESA_pixmap_colormap ----------------------- */
+
+#ifndef GLX_MESA_pixmap_colormap
+#define GLX_MESA_pixmap_colormap 1
+
+typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display* dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap);
+
+#define glXCreateGLXPixmapMESA GLXEW_GET_FUN(__glewXCreateGLXPixmapMESA)
+
+#define GLXEW_MESA_pixmap_colormap GLXEW_GET_VAR(__GLXEW_MESA_pixmap_colormap)
+
+#endif /* GLX_MESA_pixmap_colormap */
+
+/* ------------------------ GLX_MESA_release_buffers ----------------------- */
+
+#ifndef GLX_MESA_release_buffers
+#define GLX_MESA_release_buffers 1
+
+typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display* dpy, GLXDrawable d);
+
+#define glXReleaseBuffersMESA GLXEW_GET_FUN(__glewXReleaseBuffersMESA)
+
+#define GLXEW_MESA_release_buffers GLXEW_GET_VAR(__GLXEW_MESA_release_buffers)
+
+#endif /* GLX_MESA_release_buffers */
+
+/* ------------------------- GLX_MESA_set_3dfx_mode ------------------------ */
+
+#ifndef GLX_MESA_set_3dfx_mode
+#define GLX_MESA_set_3dfx_mode 1
+
+#define GLX_3DFX_WINDOW_MODE_MESA 0x1
+#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2
+
+typedef GLboolean ( * PFNGLXSET3DFXMODEMESAPROC) (GLint mode);
+
+#define glXSet3DfxModeMESA GLXEW_GET_FUN(__glewXSet3DfxModeMESA)
+
+#define GLXEW_MESA_set_3dfx_mode GLXEW_GET_VAR(__GLXEW_MESA_set_3dfx_mode)
+
+#endif /* GLX_MESA_set_3dfx_mode */
+
+/* -------------------------- GLX_NV_float_buffer -------------------------- */
+
+#ifndef GLX_NV_float_buffer
+#define GLX_NV_float_buffer 1
+
+#define GLX_FLOAT_COMPONENTS_NV 0x20B0
+
+#define GLXEW_NV_float_buffer GLXEW_GET_VAR(__GLXEW_NV_float_buffer)
+
+#endif /* GLX_NV_float_buffer */
+
+/* ----------------------- GLX_NV_vertex_array_range ----------------------- */
+
+#ifndef GLX_NV_vertex_array_range
+#define GLX_NV_vertex_array_range 1
+
+typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority);
+typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *pointer);
+
+#define glXAllocateMemoryNV GLXEW_GET_FUN(__glewXAllocateMemoryNV)
+#define glXFreeMemoryNV GLXEW_GET_FUN(__glewXFreeMemoryNV)
+
+#define GLXEW_NV_vertex_array_range GLXEW_GET_VAR(__GLXEW_NV_vertex_array_range)
+
+#endif /* GLX_NV_vertex_array_range */
+
+/* -------------------------- GLX_OML_swap_method -------------------------- */
+
+#ifndef GLX_OML_swap_method
+#define GLX_OML_swap_method 1
+
+#define GLX_SWAP_METHOD_OML 0x8060
+#define GLX_SWAP_EXCHANGE_OML 0x8061
+#define GLX_SWAP_COPY_OML 0x8062
+#define GLX_SWAP_UNDEFINED_OML 0x8063
+
+#define GLXEW_OML_swap_method GLXEW_GET_VAR(__GLXEW_OML_swap_method)
+
+#endif /* GLX_OML_swap_method */
+
+/* -------------------------- GLX_OML_sync_control ------------------------- */
+
+#if !defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#include <inttypes.h>
+#define GLX_OML_sync_control 1
+
+typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator);
+typedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc);
+typedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder);
+typedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc);
+typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc);
+
+#define glXGetMscRateOML GLXEW_GET_FUN(__glewXGetMscRateOML)
+#define glXGetSyncValuesOML GLXEW_GET_FUN(__glewXGetSyncValuesOML)
+#define glXSwapBuffersMscOML GLXEW_GET_FUN(__glewXSwapBuffersMscOML)
+#define glXWaitForMscOML GLXEW_GET_FUN(__glewXWaitForMscOML)
+#define glXWaitForSbcOML GLXEW_GET_FUN(__glewXWaitForSbcOML)
+
+#define GLXEW_OML_sync_control GLXEW_GET_VAR(__GLXEW_OML_sync_control)
+
+#endif /* GLX_OML_sync_control */
+
+/* ------------------------ GLX_SGIS_blended_overlay ----------------------- */
+
+#ifndef GLX_SGIS_blended_overlay
+#define GLX_SGIS_blended_overlay 1
+
+#define GLX_BLENDED_RGBA_SGIS 0x8025
+
+#define GLXEW_SGIS_blended_overlay GLXEW_GET_VAR(__GLXEW_SGIS_blended_overlay)
+
+#endif /* GLX_SGIS_blended_overlay */
+
+/* -------------------------- GLX_SGIS_color_range ------------------------- */
+
+#ifndef GLX_SGIS_color_range
+#define GLX_SGIS_color_range 1
+
+#define GLX_MIN_RED_SGIS 0
+#define GLX_MAX_GREEN_SGIS 0
+#define GLX_MIN_BLUE_SGIS 0
+#define GLX_MAX_ALPHA_SGIS 0
+#define GLX_MIN_GREEN_SGIS 0
+#define GLX_MIN_ALPHA_SGIS 0
+#define GLX_MAX_RED_SGIS 0
+#define GLX_EXTENDED_RANGE_SGIS 0
+#define GLX_MAX_BLUE_SGIS 0
+
+#define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range)
+
+#endif /* GLX_SGIS_color_range */
+
+/* -------------------------- GLX_SGIS_multisample ------------------------- */
+
+#ifndef GLX_SGIS_multisample
+#define GLX_SGIS_multisample 1
+
+#define GLX_SAMPLE_BUFFERS_SGIS 100000
+#define GLX_SAMPLES_SGIS 100001
+
+#define GLXEW_SGIS_multisample GLXEW_GET_VAR(__GLXEW_SGIS_multisample)
+
+#endif /* GLX_SGIS_multisample */
+
+/* ---------------------- GLX_SGIS_shared_multisample ---------------------- */
+
+#ifndef GLX_SGIS_shared_multisample
+#define GLX_SGIS_shared_multisample 1
+
+#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026
+#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027
+
+#define GLXEW_SGIS_shared_multisample GLXEW_GET_VAR(__GLXEW_SGIS_shared_multisample)
+
+#endif /* GLX_SGIS_shared_multisample */
+
+/* --------------------------- GLX_SGIX_fbconfig --------------------------- */
+
+#ifndef GLX_SGIX_fbconfig
+#define GLX_SGIX_fbconfig 1
+
+#define GLX_WINDOW_BIT_SGIX 0x00000001
+#define GLX_RGBA_BIT_SGIX 0x00000001
+#define GLX_PIXMAP_BIT_SGIX 0x00000002
+#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002
+#define GLX_SCREEN_EXT 0x800C
+#define GLX_DRAWABLE_TYPE_SGIX 0x8010
+#define GLX_RENDER_TYPE_SGIX 0x8011
+#define GLX_X_RENDERABLE_SGIX 0x8012
+#define GLX_FBCONFIG_ID_SGIX 0x8013
+#define GLX_RGBA_TYPE_SGIX 0x8014
+#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015
+
+typedef XID GLXFBConfigIDSGIX;
+typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
+
+typedef GLXFBConfigSGIX* ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);
+typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, Pixmap pixmap);
+typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display* dpy, GLXFBConfigSGIX config, int attribute, int *value);
+typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display* dpy, XVisualInfo *vis);
+typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfig config);
+
+#define glXChooseFBConfigSGIX GLXEW_GET_FUN(__glewXChooseFBConfigSGIX)
+#define glXCreateContextWithConfigSGIX GLXEW_GET_FUN(__glewXCreateContextWithConfigSGIX)
+#define glXCreateGLXPixmapWithConfigSGIX GLXEW_GET_FUN(__glewXCreateGLXPixmapWithConfigSGIX)
+#define glXGetFBConfigAttribSGIX GLXEW_GET_FUN(__glewXGetFBConfigAttribSGIX)
+#define glXGetFBConfigFromVisualSGIX GLXEW_GET_FUN(__glewXGetFBConfigFromVisualSGIX)
+#define glXGetVisualFromFBConfigSGIX GLXEW_GET_FUN(__glewXGetVisualFromFBConfigSGIX)
+
+#define GLXEW_SGIX_fbconfig GLXEW_GET_VAR(__GLXEW_SGIX_fbconfig)
+
+#endif /* GLX_SGIX_fbconfig */
+
+/* ---------------------------- GLX_SGIX_pbuffer --------------------------- */
+
+#ifndef GLX_SGIX_pbuffer
+#define GLX_SGIX_pbuffer 1
+
+#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002
+#define GLX_PBUFFER_BIT_SGIX 0x00000004
+#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008
+#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010
+#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020
+#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040
+#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080
+#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100
+#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017
+#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018
+#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019
+#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A
+#define GLX_PRESERVED_CONTENTS_SGIX 0x801B
+#define GLX_LARGEST_PBUFFER_SGIX 0x801C
+#define GLX_WIDTH_SGIX 0x801D
+#define GLX_HEIGHT_SGIX 0x801E
+#define GLX_EVENT_MASK_SGIX 0x801F
+#define GLX_DAMAGED_SGIX 0x8020
+#define GLX_SAVED_SGIX 0x8021
+#define GLX_WINDOW_SGIX 0x8022
+#define GLX_PBUFFER_SGIX 0x8023
+#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000
+
+typedef XID GLXPbufferSGIX;
+typedef struct { int type; unsigned long serial; Bool send_event; Display *display; GLXDrawable drawable; int event_type; int draw_type; unsigned int mask; int x, y; int width, height; int count; } GLXBufferClobberEventSGIX;
+
+typedef GLXPbuffer ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display* dpy, GLXFBConfig config, unsigned int width, unsigned int height, int *attrib_list);
+typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf);
+typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long *mask);
+typedef void ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf, int attribute, unsigned int *value);
+typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long mask);
+
+#define glXCreateGLXPbufferSGIX GLXEW_GET_FUN(__glewXCreateGLXPbufferSGIX)
+#define glXDestroyGLXPbufferSGIX GLXEW_GET_FUN(__glewXDestroyGLXPbufferSGIX)
+#define glXGetSelectedEventSGIX GLXEW_GET_FUN(__glewXGetSelectedEventSGIX)
+#define glXQueryGLXPbufferSGIX GLXEW_GET_FUN(__glewXQueryGLXPbufferSGIX)
+#define glXSelectEventSGIX GLXEW_GET_FUN(__glewXSelectEventSGIX)
+
+#define GLXEW_SGIX_pbuffer GLXEW_GET_VAR(__GLXEW_SGIX_pbuffer)
+
+#endif /* GLX_SGIX_pbuffer */
+
+/* ------------------------- GLX_SGIX_swap_barrier ------------------------- */
+
+#ifndef GLX_SGIX_swap_barrier
+#define GLX_SGIX_swap_barrier 1
+
+typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier);
+typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max);
+
+#define glXBindSwapBarrierSGIX GLXEW_GET_FUN(__glewXBindSwapBarrierSGIX)
+#define glXQueryMaxSwapBarriersSGIX GLXEW_GET_FUN(__glewXQueryMaxSwapBarriersSGIX)
+
+#define GLXEW_SGIX_swap_barrier GLXEW_GET_VAR(__GLXEW_SGIX_swap_barrier)
+
+#endif /* GLX_SGIX_swap_barrier */
+
+/* -------------------------- GLX_SGIX_swap_group -------------------------- */
+
+#ifndef GLX_SGIX_swap_group
+#define GLX_SGIX_swap_group 1
+
+typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member);
+
+#define glXJoinSwapGroupSGIX GLXEW_GET_FUN(__glewXJoinSwapGroupSGIX)
+
+#define GLXEW_SGIX_swap_group GLXEW_GET_VAR(__GLXEW_SGIX_swap_group)
+
+#endif /* GLX_SGIX_swap_group */
+
+/* ------------------------- GLX_SGIX_video_resize ------------------------- */
+
+#ifndef GLX_SGIX_video_resize
+#define GLX_SGIX_video_resize 1
+
+#define GLX_SYNC_FRAME_SGIX 0x00000000
+#define GLX_SYNC_SWAP_SGIX 0x00000001
+
+typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display* display, int screen, int channel, Window window);
+typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int x, int y, int w, int h);
+typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display* display, int screen, int channel, GLenum synctype);
+typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display* display, int screen, int channel, int *x, int *y, int *w, int *h);
+typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int *dx, int *dy, int *dw, int *dh);
+
+#define glXBindChannelToWindowSGIX GLXEW_GET_FUN(__glewXBindChannelToWindowSGIX)
+#define glXChannelRectSGIX GLXEW_GET_FUN(__glewXChannelRectSGIX)
+#define glXChannelRectSyncSGIX GLXEW_GET_FUN(__glewXChannelRectSyncSGIX)
+#define glXQueryChannelDeltasSGIX GLXEW_GET_FUN(__glewXQueryChannelDeltasSGIX)
+#define glXQueryChannelRectSGIX GLXEW_GET_FUN(__glewXQueryChannelRectSGIX)
+
+#define GLXEW_SGIX_video_resize GLXEW_GET_VAR(__GLXEW_SGIX_video_resize)
+
+#endif /* GLX_SGIX_video_resize */
+
+/* ---------------------- GLX_SGIX_visual_select_group --------------------- */
+
+#ifndef GLX_SGIX_visual_select_group
+#define GLX_SGIX_visual_select_group 1
+
+#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028
+
+#define GLXEW_SGIX_visual_select_group GLXEW_GET_VAR(__GLXEW_SGIX_visual_select_group)
+
+#endif /* GLX_SGIX_visual_select_group */
+
+/* ---------------------------- GLX_SGI_cushion ---------------------------- */
+
+#ifndef GLX_SGI_cushion
+#define GLX_SGI_cushion 1
+
+typedef void ( * PFNGLXCUSHIONSGIPROC) (Display* dpy, Window window, float cushion);
+
+#define glXCushionSGI GLXEW_GET_FUN(__glewXCushionSGI)
+
+#define GLXEW_SGI_cushion GLXEW_GET_VAR(__GLXEW_SGI_cushion)
+
+#endif /* GLX_SGI_cushion */
+
+/* ----------------------- GLX_SGI_make_current_read ----------------------- */
+
+#ifndef GLX_SGI_make_current_read
+#define GLX_SGI_make_current_read 1
+
+typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void);
+typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display* dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+
+#define glXGetCurrentReadDrawableSGI GLXEW_GET_FUN(__glewXGetCurrentReadDrawableSGI)
+#define glXMakeCurrentReadSGI GLXEW_GET_FUN(__glewXMakeCurrentReadSGI)
+
+#define GLXEW_SGI_make_current_read GLXEW_GET_VAR(__GLXEW_SGI_make_current_read)
+
+#endif /* GLX_SGI_make_current_read */
+
+/* -------------------------- GLX_SGI_swap_control ------------------------- */
+
+#ifndef GLX_SGI_swap_control
+#define GLX_SGI_swap_control 1
+
+typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);
+
+#define glXSwapIntervalSGI GLXEW_GET_FUN(__glewXSwapIntervalSGI)
+
+#define GLXEW_SGI_swap_control GLXEW_GET_VAR(__GLXEW_SGI_swap_control)
+
+#endif /* GLX_SGI_swap_control */
+
+/* --------------------------- GLX_SGI_video_sync -------------------------- */
+
+#ifndef GLX_SGI_video_sync
+#define GLX_SGI_video_sync 1
+
+typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (uint* count);
+typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int* count);
+
+#define glXGetVideoSyncSGI GLXEW_GET_FUN(__glewXGetVideoSyncSGI)
+#define glXWaitVideoSyncSGI GLXEW_GET_FUN(__glewXWaitVideoSyncSGI)
+
+#define GLXEW_SGI_video_sync GLXEW_GET_VAR(__GLXEW_SGI_video_sync)
+
+#endif /* GLX_SGI_video_sync */
+
+/* --------------------- GLX_SUN_get_transparent_index --------------------- */
+
+#ifndef GLX_SUN_get_transparent_index
+#define GLX_SUN_get_transparent_index 1
+
+typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display* dpy, Window overlay, Window underlay, unsigned long *pTransparentIndex);
+
+#define glXGetTransparentIndexSUN GLXEW_GET_FUN(__glewXGetTransparentIndexSUN)
+
+#define GLXEW_SUN_get_transparent_index GLXEW_GET_VAR(__GLXEW_SUN_get_transparent_index)
+
+#endif /* GLX_SUN_get_transparent_index */
+
+/* -------------------------- GLX_SUN_video_resize ------------------------- */
+
+#ifndef GLX_SUN_video_resize
+#define GLX_SUN_video_resize 1
+
+#define GLX_VIDEO_RESIZE_SUN 0x8171
+#define GL_VIDEO_RESIZE_COMPENSATION_SUN 0x85CD
+
+typedef int ( * PFNGLXGETVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float* factor);
+typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float factor);
+
+#define glXGetVideoResizeSUN GLXEW_GET_FUN(__glewXGetVideoResizeSUN)
+#define glXVideoResizeSUN GLXEW_GET_FUN(__glewXVideoResizeSUN)
+
+#define GLXEW_SUN_video_resize GLXEW_GET_VAR(__GLXEW_SUN_video_resize)
+
+#endif /* GLX_SUN_video_resize */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef GLEW_MX
+#define GLXEW_EXPORT
+#else
+#define GLXEW_EXPORT extern
+#endif /* GLEW_MX */
+
+extern PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay;
+
+extern PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig;
+extern PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext;
+extern PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer;
+extern PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap;
+extern PFNGLXCREATEWINDOWPROC __glewXCreateWindow;
+extern PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer;
+extern PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap;
+extern PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow;
+extern PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable;
+extern PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib;
+extern PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs;
+extern PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent;
+extern PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig;
+extern PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent;
+extern PFNGLXQUERYCONTEXTPROC __glewXQueryContext;
+extern PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable;
+extern PFNGLXSELECTEVENTPROC __glewXSelectEvent;
+
+extern PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI;
+extern PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI;
+extern PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI;
+
+extern PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT;
+extern PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT;
+extern PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT;
+extern PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT;
+
+extern PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA;
+
+extern PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA;
+
+extern PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA;
+
+extern PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA;
+
+extern PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA;
+
+extern PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV;
+extern PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV;
+
+#ifdef GLX_OML_sync_control
+extern PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML;
+extern PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML;
+extern PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML;
+extern PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML;
+extern PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML;
+#endif
+
+extern PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX;
+extern PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX;
+extern PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX;
+extern PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX;
+extern PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX;
+extern PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX;
+
+extern PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX;
+extern PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX;
+extern PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX;
+extern PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX;
+extern PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX;
+
+extern PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX;
+extern PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX;
+
+extern PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX;
+
+extern PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX;
+extern PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX;
+extern PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX;
+extern PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX;
+extern PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX;
+
+extern PFNGLXCUSHIONSGIPROC __glewXCushionSGI;
+
+extern PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI;
+extern PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI;
+
+extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI;
+
+extern PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI;
+extern PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI;
+
+extern PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN;
+
+extern PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN;
+extern PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN;
+
+#if defined(GLEW_MX)
+struct GLXEWContextStruct
+{
+#endif /* GLEW_MX */
+
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_0;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_1;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_2;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_3;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_4;
+GLXEW_EXPORT GLboolean __GLXEW_3DFX_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_fbconfig_float;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_get_proc_address;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_ATI_pixel_format_float;
+GLXEW_EXPORT GLboolean __GLXEW_ATI_render_texture;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_import_context;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_scene_marker;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_info;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_rating;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_agp_offset;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_release_buffers;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode;
+GLXEW_EXPORT GLboolean __GLXEW_NV_float_buffer;
+GLXEW_EXPORT GLboolean __GLXEW_NV_vertex_array_range;
+GLXEW_EXPORT GLboolean __GLXEW_OML_swap_method;
+GLXEW_EXPORT GLboolean __GLXEW_OML_sync_control;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_blended_overlay;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_color_range;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_shared_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_fbconfig;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_pbuffer;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_barrier;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_group;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_video_resize;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_visual_select_group;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_cushion;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_make_current_read;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_swap_control;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_video_sync;
+GLXEW_EXPORT GLboolean __GLXEW_SUN_get_transparent_index;
+GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize;
+
+#ifdef GLEW_MX
+}; /* GLXEWContextStruct */
+#endif /* GLEW_MX */
+
+/* ------------------------------------------------------------------------ */
+
+#ifdef GLEW_MX
+
+typedef struct GLXEWContextStruct GLXEWContext;
+extern GLenum glxewContextInit (GLXEWContext* ctx);
+
+#define GLXEW_GET_VAR(x) glxewGetContext()->x
+#define GLXEW_GET_FUN(x) x
+
+#else /* GLEW_MX */
+
+#define GLXEW_GET_VAR(x) x
+#define GLXEW_GET_FUN(x) x
+
+#endif /* GLEW_MX */
+
+extern GLboolean glxewGetExtension (const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __glxew_h__ */
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.h	(revision 576)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.h	(revision 576)
@@ -0,0 +1,143 @@
+#ifndef _RssPreprocessor_H__
+#define _RssPreprocessor_H__
+
+#include <fstream>
+using namespace std;
+
+
+#include "Preprocessor.h"
+#include "VssRay.h"
+class RssTree;
+class RssTreeLeaf;
+
+
+/** Sampling based visibility preprocessing. The implementation is based on heuristical
+    sampling of view space */
+class RssPreprocessor : public Preprocessor {
+  
+public:
+  int mPass;
+  int mSamplesPerPass;
+  int mRssSamplesPerPass;
+  int mInitialSamples;
+  int mRssSamples;
+  bool mUseImportanceSampling;
+
+  bool mExportPvs;
+  bool mExportRssTree;
+  bool mExportRays;
+  int mExportNumRays;
+
+  bool mUseViewcells;
+  bool mUpdateSubdivision;
+
+  bool mObjectBasedSampling;
+  bool mDirectionalSampling;
+  
+  AxisAlignedBox3 *mViewSpaceBox;
+
+  ofstream mStats;
+  RssTree *mRssTree;
+
+  // rays cast during the processing
+  VssRayContainer mVssRays;
+	
+   /// if initial samples should be loaded from file
+  bool mLoadInitialSamples;
+  /// if initial samples should be stored in file
+  bool mStoreInitialSamples;
+
+  RssPreprocessor();
+  ~RssPreprocessor();
+
+  virtual bool ComputeVisibility();
+
+
+  void
+  SetupRay(Ray &ray, 
+		   const Vector3 &point, 
+		   const Vector3 &direction
+		   );
+
+
+	
+  int
+  CastRay(
+		  Vector3 &viewPoint,
+		  Vector3 &direction,
+		  const float probability,
+		  VssRayContainer &vssRays
+
+		  );
+		
+
+	
+  virtual bool BuildBspTree() { return false; }
+  
+  void
+  CastRays(
+		   SimpleRayContainer &rays,
+		   VssRayContainer &vssRays
+		   );
+
+  bool
+  ExportRays(const char *filename,
+			 const VssRayContainer &vssRays,
+			 const int number
+			 );
+
+  void
+  ExportObjectRays(VssRayContainer &rays,
+				   const int objectId);
+	
+  int
+  GenerateImportanceRays(RssTree *vssTree,
+						 const int desiredSamples,
+						 SimpleRayContainer &rays
+						 );
+
+
+  bool
+  ExportRssTreeLeaf(char *filename,
+					RssTree *tree,
+					RssTreeLeaf *leaf);
+
+  void
+  ExportRssTreeLeaves(RssTree *tree, const int number);
+	
+
+  bool
+  ExportRssTree(char *filename,
+				RssTree *tree,
+				const Vector3 &dir
+				);
+
+
+  float
+  GetAvgPvsSize(RssTree *tree,
+				const vector<AxisAlignedBox3> &viewcells
+				);
+  
+
+  void
+  ExportPvs(char *filename,
+			RssTree *rssTree
+			);
+
+
+  void
+  ComputeRenderError();
+
+  /** Redefininition of the get sample rays method from the preprocessor */
+  bool
+  GenerateRays(
+			   const int number,
+			   const int sampleType,
+			   SimpleRayContainer &rays
+			   );
+
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.cpp	(revision 557)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.cpp	(revision 557)
@@ -0,0 +1,2086 @@
+
+// GOLEM library
+#include <assert.h>
+#include <iostream>
+using namespace std;
+#include "AxisAlignedBox3.h"
+#include "Ray.h"
+#include "Polygon3.h"
+#include "Mesh.h"
+
+#define FATAL Debug
+#define FATAL_ABORT exit(1)
+
+
+// AxisAlignedBox3 implementations
+
+// Overload << operator for C++-style output
+ostream&
+operator<< (ostream &s, const AxisAlignedBox3 &A)
+{
+  return s << '[' << A.mMin.x << ", " << A.mMin.y << ", " << A.mMin.z << "]["
+	   << A.mMax.x << ", " << A.mMax.y << ", " << A.mMax.z << ']';
+}
+
+// Overload >> operator for C++-style input
+istream&
+operator>> (istream &s, AxisAlignedBox3 &A)
+{
+  char a;
+  // read "[min.x, min.y, min.z][mMax.x, mMax.y, mMax.z]"
+  return s >> a >> A.mMin.x >> a >> A.mMin.y >> a >> A.mMin.z >> a >> a
+    >> A.mMax.x >> a >> A.mMax.y >> a >> A.mMax.z >> a;
+}
+
+bool
+AxisAlignedBox3::Unbounded() const
+{
+  return (mMin == Vector3(-MAXFLOAT)) || 
+         (mMax == Vector3(-MAXFLOAT));
+}
+
+void
+AxisAlignedBox3::Include(const Vector3 &newpt)
+{
+  Minimize(mMin, newpt);
+  Maximize(mMax, newpt);
+}
+
+void
+AxisAlignedBox3::Include(const Polygon3 &newpoly)
+{
+	VertexContainer::const_iterator it, it_end = newpoly.mVertices.end();
+
+	for (it = newpoly.mVertices.begin(); it != it_end; ++ it)
+		Include(*it);
+}
+
+void
+AxisAlignedBox3::Include(Mesh *mesh)
+{
+	VertexContainer::const_iterator it, it_end = mesh->mVertices.end();
+
+	for (it = mesh->mVertices.begin(); it != it_end; ++ it)
+		Include(*it);
+}
+
+
+void
+AxisAlignedBox3::Include(const AxisAlignedBox3 &bbox)
+{
+  Minimize(mMin, bbox.mMin);
+  Maximize(mMax, bbox.mMax);
+}
+
+bool
+AxisAlignedBox3::IsCorrect()
+{
+  if ( (mMin.x > mMax.x) ||
+       (mMin.y > mMax.y) ||
+       (mMin.z > mMax.z) )
+    return false; // box is not formed
+  return true;
+}
+
+void
+AxisAlignedBox3::GetEdge(const int edge, Vector3 *a, Vector3 *b) const
+{
+  switch(edge) {
+  case 0:
+    a->SetValue(mMin.x, mMin.y, mMin.z);
+    b->SetValue(mMin.x, mMin.y, mMax.z);
+    break;
+  case 1:
+    a->SetValue(mMin.x, mMin.y, mMin.z);
+    b->SetValue(mMin.x, mMax.y, mMin.z);
+    break;
+  case 2:
+    a->SetValue(mMin.x, mMin.y, mMin.z);
+    b->SetValue(mMax.x, mMin.y, mMin.z);
+    break;
+  case 3:
+    a->SetValue(mMax.x, mMax.y, mMax.z);
+    b->SetValue(mMax.x, mMax.y, mMin.z);
+    break;
+  case 4:
+    a->SetValue(mMax.x, mMax.y, mMax.z);
+    b->SetValue(mMax.x, mMin.y, mMax.z);
+    break;
+  case 5:
+    a->SetValue(mMax.x, mMax.y, mMax.z);
+    b->SetValue(mMin.x, mMax.y, mMax.z);
+    break;
+    
+  case 6:
+    a->SetValue(mMin.x, mMin.y, mMax.z);
+    b->SetValue(mMin.x, mMax.y, mMax.z);
+    break;
+  case 7:
+    a->SetValue(mMin.x, mMin.y, mMax.z);
+    b->SetValue(mMax.x, mMin.y, mMax.z);
+    break;
+  case 8:
+    a->SetValue(mMin.x, mMax.y, mMin.z);
+    b->SetValue(mMin.x, mMax.y, mMax.z);
+    break;
+  case 9:
+    a->SetValue(mMin.x, mMax.y, mMin.z);
+    b->SetValue(mMax.x, mMax.y, mMin.z);
+    break;
+  case 10:
+    a->SetValue(mMax.x, mMin.y, mMin.z);
+    b->SetValue(mMax.x, mMax.y, mMin.z);
+    break;
+  case 11:
+    a->SetValue(mMax.x, mMin.y, mMin.z);
+    b->SetValue(mMax.x, mMin.y, mMax.z);
+    break;
+  }
+}
+
+// returns the vertex indices in the range <0..7>, v = 4.x + 2.y + z, where
+// x,y,z are either 0 or 1; (0 .. min coordinate, 1 .. max coordinate)
+void
+AxisAlignedBox3::GetEdge(const int edge, int  &aIdx, int &bIdx) const
+{
+  switch(edge) {
+  case 0: aIdx = 0; bIdx = 1; break;
+  case 1: aIdx = 0; bIdx = 2; break;
+  case 2: aIdx = 0; bIdx = 4; break;
+  case 3: aIdx = 7; bIdx = 6; break;
+  case 4: aIdx = 7; bIdx = 5; break;
+  case 5: aIdx = 7; bIdx = 3; break;
+  case 6: aIdx = 1; bIdx = 3; break;
+  case 7: aIdx = 1; bIdx = 5; break;
+  case 8: aIdx = 2; bIdx = 3; break;
+  case 9: aIdx = 2; bIdx = 6; break;
+  case 10: aIdx = 4; bIdx = 6; break;
+  case 11: aIdx = 4; bIdx = 5; break;
+  }
+}
+
+void
+AxisAlignedBox3::Include(const int &axis, const float &newBound)
+{
+  switch (axis) {
+    case 0: { // x-axis
+      if (mMin.x > newBound)
+	mMin.x = newBound;
+      if (mMax.x < newBound)
+	mMax.x = newBound;
+      break;
+    }
+    case 1: { // y-axis
+      if (mMin.y > newBound)
+        mMin.y = newBound;
+      if (mMax.y < newBound)
+	mMax.y = newBound;
+      break;
+    }
+    case 2: { // z-axis
+      if (mMin.z > newBound)
+	mMin.z = newBound;
+      if (mMax.z < newBound)
+	mMax.z = newBound;
+      break;
+    }
+  }
+}
+
+#if 0
+// ComputeMinMaxT computes the minimum and maximum signed distances
+// of intersection with the ray; it returns 1 if the ray hits
+// the bounding box and 0 if it does not.
+int
+AxisAlignedBox3::ComputeMinMaxT(const Ray &ray,
+				float *tmin,
+				float *tmax) const
+{
+  float minx, maxx, miny, maxy, minz, maxz;
+
+  if (fabs(ray.dir.x) < 0.001) {
+    if (mMin.x < ray.loc.x && mMax.x > ray.loc.x) {
+      minx = -MAXFLOAT;
+      maxx = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.x - ray.loc.x) / ray.dir.x;
+    float t2 = (mMax.x - ray.loc.x) / ray.dir.x;
+    if (t1 < t2) {
+      minx = t1;
+      maxx = t2;
+    }
+    else {
+      minx = t2;
+      maxx = t1;
+    }
+    if (maxx < 0)
+      return 0;
+  }
+
+  if (fabs(ray.dir.y) < 0.001) {
+    if (mMin.y < ray.loc.y && mMax.y > ray.loc.y) {
+      miny = -MAXFLOAT;
+      maxy = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.y - ray.loc.y) / ray.dir.y;
+    float t2 = (mMax.y - ray.loc.y) / ray.dir.y;
+    if (t1 < t2) {
+      miny = t1;
+      maxy = t2;
+    }
+    else {
+      miny = t2;
+      maxy = t1;
+    }
+    if (maxy < 0.0)
+      return 0;
+  }
+
+  if (fabs(ray.dir.z) < 0.001) {
+    if (mMin.z < ray.loc.z && mMax.z > ray.loc.z) {
+      minz = -MAXFLOAT;
+      maxz = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.z - ray.loc.z) / ray.dir.z;
+    float t2 = (mMax.z - ray.loc.z) / ray.dir.z;
+    if (t1 < t2) {
+      minz = t1;
+      maxz = t2;
+    }
+    else {
+      minz = t2;
+      maxz = t1;
+    }
+    if (maxz < 0.0)
+      return 0;
+  }
+
+  *tmin = minx;
+  if (miny > *tmin)
+    *tmin = miny;
+  if (minz > *tmin)
+    *tmin = minz;
+
+  *tmax = maxx;
+  if (maxy < *tmax)
+    *tmax = maxy;
+  if (maxz < *tmax)
+    *tmax = maxz;
+
+  return 1; // yes, intersection was found
+}
+#else
+// another variant of the same, with less variables
+int
+AxisAlignedBox3::ComputeMinMaxT(const Ray &ray,
+				float *tmin,
+				float *tmax) const
+{
+  const float dirEps = 1e-8f;
+  register float minx, maxx;
+  ray.ComputeInvertedDir();
+  
+  if (fabs(ray.dir.x) < dirEps) {
+    if (mMin.x < ray.loc.x && mMax.x > ray.loc.x) {
+      minx = -MAXFLOAT;
+      maxx = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.x - ray.loc.x) * ray.invDir.x;
+    float t2 = (mMax.x - ray.loc.x) * ray.invDir.x;
+    if (t1 < t2) {
+      minx = t1;
+      maxx = t2;
+    }
+    else {
+      minx = t2;
+      maxx = t1;
+    }
+	//    if (maxx < 0.0)
+	//      return 0;
+  }
+
+  *tmin = minx;
+  *tmax = maxx;
+  
+  if (fabs(ray.dir.y) < dirEps) {
+    if (mMin.y < ray.loc.y && mMax.y > ray.loc.y) {
+      minx = -MAXFLOAT;
+      maxx = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.y - ray.loc.y) * ray.invDir.y;
+    float t2 = (mMax.y - ray.loc.y) * ray.invDir.y;
+    if (t1 < t2) {
+      minx = t1;
+      maxx = t2;
+    }
+    else {
+      minx = t2;
+      maxx = t1;
+    }
+	//    if (maxx < 0.0)
+	//      return 0;
+  }
+
+  if (minx > *tmin)
+    *tmin = minx;
+  if (maxx < *tmax)
+    *tmax = maxx;
+  
+  if (fabs(ray.dir.z) < dirEps) {
+    if (mMin.z < ray.loc.z && mMax.z > ray.loc.z) {
+      minx = -MAXFLOAT;
+      maxx = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.z - ray.loc.z) * ray.invDir.z;
+    float t2 = (mMax.z - ray.loc.z) * ray.invDir.z;
+    if (t1 < t2) {
+      minx = t1;
+      maxx = t2;
+    }
+    else {
+      minx = t2;
+      maxx = t1;
+    }
+	//    if (maxx < 0.0)
+	//      return 0;
+  }
+
+  if (minx > *tmin)
+    *tmin = minx;
+  if (maxx < *tmax)
+    *tmax = maxx;
+
+  return 1; // yes, intersection was found
+}
+#endif
+
+// ComputeMinMaxT computes the minimum and maximum parameters
+// of intersection with the ray; it returns 1 if the ray hits
+// the bounding box and 0 if it does not.
+int
+AxisAlignedBox3::ComputeMinMaxT(const Ray &ray, float *tmin, float *tmax,
+				EFaces &entryFace, EFaces &exitFace) const
+{
+  float minx, maxx, miny, maxy, minz, maxz;
+  int swapped[3];
+  
+  if (fabs(ray.dir.x) < 0.001) {
+    if (mMin.x < ray.loc.x && mMax.x > ray.loc.x) {
+      minx = -MAXFLOAT;
+      maxx = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.x - ray.loc.x) / ray.dir.x;
+    float t2 = (mMax.x - ray.loc.x) / ray.dir.x;
+    if (t1 < t2) {
+      minx = t1;
+      maxx = t2;
+      swapped[0] = 0;
+    }
+    else {
+      minx = t2;
+      maxx = t1;
+      swapped[0] = 1;
+    }
+    if (maxx < 0)
+      return 0;
+  }
+
+  if (fabs(ray.dir.y) < 0.001) {
+    if (mMin.y < ray.loc.y && mMax.y > ray.loc.y) {
+      miny = -MAXFLOAT;
+      maxy = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.y - ray.loc.y) / ray.dir.y;
+    float t2 = (mMax.y - ray.loc.y) / ray.dir.y;
+    if (t1 < t2) {
+      miny = t1;
+      maxy = t2;
+      swapped[1] = 0;
+    }
+    else {
+      miny = t2;
+      maxy = t1;
+      swapped[1] = 1;
+    }
+    if (maxy < 0.0)
+      return 0;
+  }
+
+  if (fabs(ray.dir.z) < 0.001) {
+    if (mMin.z < ray.loc.z && mMax.z > ray.loc.z) {
+      minz = -MAXFLOAT;
+      maxz = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.z - ray.loc.z) / ray.dir.z;
+    float t2 = (mMax.z - ray.loc.z) / ray.dir.z;
+    if (t1 < t2) {
+      minz = t1;
+      maxz = t2;
+      swapped[2] = 0;
+    }
+    else {
+      minz = t2;
+      maxz = t1;
+      swapped[2] = 1;
+    }
+    if (maxz < 0.0)
+      return 0;
+  }
+
+  *tmin = minx;
+  entryFace = ID_Back;
+  if (miny > *tmin) {
+    *tmin = miny;
+    entryFace = ID_Left;
+  }
+  if (minz > *tmin) {
+    *tmin = minz;
+    entryFace = ID_Bottom;
+  }
+  
+  *tmax = maxx;
+  exitFace = ID_Back;
+  if (maxy < *tmax) {
+    *tmax = maxy;
+    exitFace = ID_Left;
+  }
+  if (maxz < *tmax) {
+    *tmax = maxz;
+    exitFace = ID_Bottom;
+  }
+
+  if (swapped[entryFace])
+    entryFace = (EFaces)(entryFace + 3);
+  
+  if (!swapped[exitFace])
+    exitFace = (EFaces)(exitFace + 3);
+  
+  return 1; // yes, intersection was found
+}
+
+void
+AxisAlignedBox3::Describe(ostream &app, int ind) const
+{
+  indent(app, ind);
+  app << "AxisAlignedBox3: min at(" << mMin << "), max at(" << mMax << ")\n";
+}
+
+// computes the passing through parameters for case tmin<tmax and tmax>0
+int
+AxisAlignedBox3::GetMinMaxT(const Ray &ray, float *tmin, float *tmax) const
+{
+  if (!ComputeMinMaxT(ray, tmin, tmax))
+    return 0;
+  if ( *tmax < *tmin)
+    return 0; // the ray passes outside the box
+
+  if ( *tmax < 0.0)
+    return 0; // the intersection is not on the positive halfline
+
+  return 1; // ray hits the box .. origin can be outside or inside the box
+}
+
+// computes the signed distances for case tmin<tmax and tmax>0
+int
+AxisAlignedBox3::GetMinMaxT(const Ray &ray, float *tmin, float *tmax,
+			    EFaces &entryFace, EFaces &exitFace) const
+{
+  if (!ComputeMinMaxT(ray, tmin, tmax, entryFace, exitFace))
+    return 0;
+  if ( *tmax < *tmin)
+    return 0; // the ray passes outside the box
+  
+  if ( *tmax < 0.0)
+    return 0; // the intersection is not on the positive halfline
+  
+  return 1; // ray hits the box .. origin can be outside or inside the box
+}
+
+#if 0
+int
+AxisAlignedBox3::IsInside(const Vector3 &point) const
+{
+  return (point.x >= mMin.x) && (point.x <= mMax.x) &&
+         (point.y >= mMin.y) && (point.y <= mMax.y) &&
+         (point.z >= mMin.z) && (point.z <= mMax.z);
+}
+#else
+int
+AxisAlignedBox3::IsInside(const Vector3 &v) const
+{
+  return ! (v.x < mMin.x ||
+	    v.x > mMax.x ||
+	    v.y < mMin.y ||
+	    v.y > mMax.y ||
+	    v.z < mMin.z ||
+	    v.z > mMax.z);
+}
+#endif
+
+bool
+AxisAlignedBox3::Includes(const AxisAlignedBox3 &b) const
+{
+  return (b.mMin.x >= mMin.x &&
+      b.mMin.y >= mMin.y &&
+      b.mMin.z >= mMin.z &&
+      b.mMax.x <= mMax.x &&
+      b.mMax.y <= mMax.y &&
+      b.mMax.z <= mMax.z);
+
+}
+
+
+// compute the coordinates of one vertex of the box
+Vector3
+AxisAlignedBox3::GetVertex(int xAxis, int yAxis, int zAxis) const
+{
+  Vector3 p;
+  if (xAxis)
+    p.x = mMax.x;
+  else
+    p.x = mMin.x;
+
+  if (yAxis)
+    p.y = mMax.y;
+  else
+    p.y = mMin.y;
+
+  if (zAxis)
+    p.z = mMax.z;
+  else
+    p.z = mMin.z;
+  return p;
+}
+
+// compute the vertex for number N = <0..7>, N = 4.x + 2.y + z, where
+// x,y,z are either 0 or 1; (0 .. min coordinate, 1 .. max coordinate)
+void
+AxisAlignedBox3::GetVertex(const int N, Vector3 &vertex) const
+{
+  switch (N) {
+    case 0: vertex = mMin; break;
+    case 1: vertex.SetValue(mMin.x, mMin.y, mMax.z); break;
+    case 2: vertex.SetValue(mMin.x, mMax.y, mMin.z); break;
+    case 3: vertex.SetValue(mMin.x, mMax.y, mMax.z); break;
+    case 4: vertex.SetValue(mMax.x, mMin.y, mMin.z); break;
+    case 5: vertex.SetValue(mMax.x, mMin.y, mMax.z); break;
+    case 6: vertex.SetValue(mMax.x, mMax.y, mMin.z); break;
+    case 7: vertex = mMax; break;
+    default: {
+      FATAL << "ERROR in AxisAlignedBox3::GetVertex N=" << N <<  "\n";
+      FATAL_ABORT;
+    }
+  }
+}
+
+// Returns region 0 .. 26 ; R = 9*x + 3*y + z ; (x,y,z) \in {0,1,2}
+int
+AxisAlignedBox3::GetRegionID(const Vector3 &point) const
+{
+  int ID = 0;
+
+  if (point.z >= mMin.z) {
+    if (point.z <= mMax.z)
+      ID += 1; // inside the two boundary planes
+    else
+      ID += 2; // outside
+  }
+
+  if (point.y >= mMin.y) {
+    if (point.y <= mMax.y)
+      ID += 3; // inside the two boundary planes
+    else
+      ID += 6; // outside
+  }
+
+  if (point.x >= mMin.x) {
+    if (point.x <= mMax.x)
+      ID += 9; // inside the two boundary planes
+    else
+      ID += 18; // outside
+  }
+  return ID;
+}
+
+
+
+// computes if a given box (smaller) lies at least in one
+// projection whole in the box (larger) = this encompasses given
+// ;-----;
+// | ;-; |
+// | '-' |
+// '-----'
+int
+AxisAlignedBox3::IsPiercedByBox(const AxisAlignedBox3 &box, int &axis) const
+{
+  // test on x-axis
+  if ( (mMax.x < box.mMin.x) ||
+       (mMin.x > box.mMax.x) )
+    return 0; // the boxes do not overlap at all at x-axis
+  if ( (box.mMin.y > mMin.y) &&
+       (box.mMax.y < mMax.y) &&
+       (box.mMin.z > mMin.z) &&
+       (box.mMax.z < mMax.z) ) {
+    axis = 0;
+    return 1; // the boxes overlap in x-axis
+  }
+  // test on y-axis
+  if ( (mMax.y < box.mMin.y) ||
+       (mMin.y > box.mMax.y) )
+    return 0; // the boxes do not overlap at all at y-axis
+  if ( (box.mMin.x > mMin.x) &&
+       (box.mMax.x < mMax.x) &&
+       (box.mMin.z > mMin.z) &&
+       (box.mMax.z < mMax.z) ) {
+    axis = 1;
+    return 1; // the boxes overlap in y-axis
+  }
+  // test on z-axis
+  if ( (mMax.z < box.mMin.z) ||
+       (mMin.z > box.mMax.z) )
+    return 0; // the boxes do not overlap at all at y-axis
+  if ( (box.mMin.x > mMin.x) &&
+       (box.mMax.x < mMax.x) &&
+       (box.mMin.y > mMin.y) &&
+       (box.mMax.y < mMax.y) ) {
+    axis = 2;
+    return 1; // the boxes overlap in z-axis
+  }
+  return 0;
+}
+
+float
+AxisAlignedBox3::SurfaceArea() const
+{
+  Vector3 ext = mMax - mMin;
+ 
+  return 2.0f * (ext.x * ext.y +
+	        ext.x * ext.z +
+	        ext.y * ext.z);
+}
+
+const int AxisAlignedBox3::bvertices[27][9] =
+{                   // region number.. position
+  {5,1,3,2,6,4,-1,-1,-1},      // 0 .. x=0 y=0 z=0
+  {4,5,1,3,2,0,-1,-1,-1},      // 1 .. x=0 y=0 z=1
+  {4,5,7,3,2,0,-1,-1,-1},      // 2 .. x=0 y=0 z=2
+
+  {0,1,3,2,6,4,-1,-1,-1},      // 3 .. x=0 y=1 z=0
+  {0,1,3,2,-1,-1,-1,-1,-1},    // 4 .. x=0 y=1 z=1
+  {1,5,7,3,2,0,-1,-1,-1},      // 5 .. x=0 y=1 z=2
+
+  {0,1,3,7,6,4,-1,-1,-1},      // 6 .. x=0 y=2 z=0
+  {0,1,3,7,6,2,-1,-1,-1},      // 7 .. x=0 y=2 z=1
+  {1,5,7,6,2,0,-1,-1,-1},      // 8 .. x=0 y=2 z=2
+
+  // the regions number <9,17>
+  {5,1,0,2,6,4,-1,-1,-1},      // 9  .. x=1 y=0 z=0
+  {5,1,0,4,-1,-1,-1,-1,-1},    // 10 .. x=1 y=0 z=1
+  {7,3,1,0,4,5,-1,-1,-1},      // 11 .. x=1 y=0 z=2
+
+  {4,0,2,6,-1,-1,-1,-1,-1},    // 12 .. x=1 y=1 z=0
+  {0,2,3,1,5,4,6,7,-1},        // 13 .. x=1 y=1 z=1 .. inside the box
+  {1,5,7,3,-1,-1,-1,-1,-1},    // 14 .. x=1 y=1 z=2
+
+  {4,0,2,3,7,6,-1,-1,-1},      // 15 .. x=1 y=2 z=0
+  {6,2,3,7,-1,-1,-1,-1,-1},    // 16 .. x=1 y=2 z=1
+  {1,5,7,6,2,3,-1,-1,-1},      // 17 .. x=1 y=2 z=2
+
+  // the regions number <18,26>
+  {1,0,2,6,7,5,-1,-1,-1},      // 18 .. x=2 y=0 z=0
+  {1,0,4,6,7,5,-1,-1,-1},      // 19 .. x=2 y=0 z=1
+  {0,4,6,7,3,1,-1,-1,-1},      // 20 .. x=2 y=0 z=2
+
+  {4,0,2,6,7,5,-1,-1,-1},      // 21 .. x=2 y=1 z=0
+  {5,4,6,7,-1,-1,-1,-1,-1},    // 22 .. x=2 y=1 z=1
+  {5,4,6,7,3,1,-1,-1,-1},      // 23 .. x=2 y=1 z=2
+
+  {4,0,2,3,7,5,-1,-1,-1},      // 24 .. x=2 y=2 z=0
+  {5,4,6,2,3,7,-1,-1,-1},      // 25 .. x=2 y=2 z=1
+  {5,4,6,2,3,1,-1,-1,-1},      // 26 .. x=2 y=2 z=2
+};
+
+// the visibility of boundary faces from a given region
+// one to three triples: (axis, min_vertex, max_vertex), axis==-1(terminator)
+const int AxisAlignedBox3::bfaces[27][10] =
+{                              // region number .. position
+  {0,0,3,1,0,5,2,0,6,-1},      // 0 .. x=0 y=0 z=0
+  {0,0,3,1,0,5,-1,-1,-1,-1},   // 1 .. x=0 y=0 z=1
+  {0,0,3,1,0,5,2,1,7,-1},      // 2 .. x=0 y=0 z=2
+
+  {0,0,3,2,0,6,-1,-1,-1,-1},   // 3 .. x=0 y=1 z=0
+  {0,0,3,-1,-1,-1,-1,-1,-1,-1},// 4 .. x=0 y=1 z=1
+  {0,0,3,2,1,7,-1,-1,-1,-1},   // 5 .. x=0 y=1 z=2
+
+  {0,0,3,1,2,7,2,0,6,-1},      // 6 .. x=0 y=2 z=0
+  {0,0,3,1,2,7,-1,-1,-1,-1},   // 7 .. x=0 y=2 z=1
+  {0,0,3,1,2,7,2,1,7,-1},      // 8 .. x=0 y=2 z=2
+
+  // the regions number <9,17>
+  {1,0,5,2,0,6,-1,-1,-1,-1},   // 9  .. x=1 y=0 z=0
+  {1,0,5,-1,-1,-1,-1,-1,-1,-1},// 10 .. x=1 y=0 z=1
+  {1,0,5,2,1,7,-1,-1,-1,-1},   // 11 .. x=1 y=0 z=2
+
+  {2,0,6,-1,-1,-1,-1,-1,-1,-1},// 12 .. x=1 y=1 z=0
+  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},// 13 .. x=1 y=1 z=1 .. inside the box
+  {2,1,7,-1,-1,-1,-1,-1,-1,-1},// 14 .. x=1 y=1 z=2
+
+  {1,2,7,2,0,6,-1,-1,-1,-1},   // 15 .. x=1 y=2 z=0
+  {1,2,7,-1,-1,-1,-1,-1,-1,-1},// 16 .. x=1 y=2 z=1
+  {1,2,7,2,1,7,-1,-1,-1,-1},   // 17 .. x=1 y=2 z=2
+
+  // the region number <18,26>
+  {0,4,7,1,0,5,2,0,6,-1},      // 18 .. x=2 y=0 z=0
+  {0,4,7,1,0,5,-1,-1,-1,-1},   // 19 .. x=2 y=0 z=1
+  {0,4,7,1,0,5,2,1,7,-1},      // 20 .. x=2 y=0 z=2
+
+  {0,4,7,2,0,6,-1,-1,-1,-1},   // 21 .. x=2 y=1 z=0
+  {0,4,7,-1,-1,-1,-1,-1,-1,-1},// 22 .. x=2 y=1 z=1
+  {0,4,7,2,1,7,-1,-1,-1,-1},   // 23 .. x=2 y=1 z=2
+
+  {0,4,7,1,2,7,2,0,6,-1},      // 24 .. x=2 y=2 z=0
+  {0,4,7,1,2,7,-1,-1,-1,-1},   // 25 .. x=2 y=2 z=1
+  {0,4,7,1,2,7,2,1,7,-1},      // 26 .. x=2 y=2 z=2
+};
+
+// the correct corners indexing from entry face to exit face
+// first index determines entry face, second index exit face, and
+// the two numbers (indx, inc) determines: ind = the index on the exit
+// face, when starting from the vertex 0 on entry face, 'inc' is
+// the increment when we go on entry face in order 0,1,2,3 to create
+// convex shaft with the rectangle on exit face. That is, inc = -1 or 1.
+const int AxisAlignedBox3::pairFaceRects[6][6][2] = {
+  { // entry face = 0
+    {-1,0}, // exit face 0 .. no meaning
+    {0,-1}, // 1
+    {0,-1}, // 2
+    {0,1}, // 3 .. opposite face
+    {3,1}, // 4
+    {1,1} // 5
+  }, 
+  { // entry face = 1
+    {0,-1}, // exit face 0
+    {-1,0}, // 1 .. no meaning
+    {0,-1}, // 2
+    {1,1}, // 3
+    {0,1}, // 4 .. opposite face
+    {3,1} // 5
+  },
+  { // entry face = 2
+    {0,-1}, // 0
+    {0,-1}, // 1 
+    {-1,0}, // 2 .. no meaning
+    {3,1}, // 3
+    {1,1}, // 4
+    {0,1} // 5 .. opposite face
+  },
+  { // entry face = 3
+    {0,1}, // 0 .. opposite face
+    {3,-1}, // 1 
+    {1,1}, // 2
+    {-1,0}, // 3  .. no meaning
+    {0,-1}, // 4
+    {0,-1} // 5
+  },
+  { // entry face = 4
+    {1,1}, // 0
+    {0,1}, // 1 .. opposite face
+    {3,1}, // 2
+    {0,-1}, // 3
+    {-1,0}, // 4 .. no meaning
+    {0,-1} // 5
+  },
+  { // entry face = 5
+    {3,-1}, // 0
+    {1,1}, // 1
+    {0,1}, // 2  .. opposite face
+    {0,-1}, // 3
+    {0,-1}, // 4
+    {-1,0} // 5 .. no meaning
+  }
+};
+
+
+// ------------------------------------------------------------
+// The vertices that form CLOSEST points with respect to the region
+// for all the regions possible, number of regions is 3^3 = 27,
+// since two parallel sides of bbox forms three disjoint spaces.
+// The vertices are given in anti-clockwise order, stopped by value 15,
+// at most 8 points, at least 1 point.
+// The table includes the closest 1/2/4/8 points, followed possibly
+// by the set of coordinates that should be used for testing for
+// the proximity queries. The coordinates to be tested are described by
+// the pair (a,b), when a=0, we want to test min vector of the box,
+//                 when a=1, we want to test max vector of the box
+//                 b=0,1,2 corresponds to the axis (0=x,1=y,2=z)
+// The sequence is ended by 15, number -1 is used as the separator
+// between the vertices and coordinates.
+const int
+AxisAlignedBox3::cvertices[27][9] = 
+{                   // region number.. position
+  {0,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D one vertex
+  {0,1,-1,0,0,0,1,15,15},      // 1 .. x=0 y=0 z=1 D two vertices foll. by 2
+  {1,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D one vertex
+
+  {0,2,-1,0,0,0,2,15,15},      // 3 .. x=0 y=1 z=0 D
+  {0,1,3,2,-1,0,0,15,15},      // 4 .. x=0 y=1 z=1 D
+  {1,3,-1,0,0,1,2,15,15},      // 5 .. x=0 y=1 z=2 D
+
+  {2,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D
+  {2,3,-1,0,0,1,1,15,15},      // 7 .. x=0 y=2 z=1 D
+  {3,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D
+
+  // the regions number <9,17>
+  {0,4,-1,0,1,0,2,15,15},      // 9  .. x=1 y=0 z=0 D
+  {5,1,0,4,-1,0,1,15,15},      // 10 .. x=1 y=0 z=1 D
+  {1,5,-1,0,1,1,2,15,15},      // 11 .. x=1 y=0 z=2 D
+
+  {4,0,2,6,-1,0,2,15,15},      // 12 .. x=1 y=1 z=0 D
+  {0,2,3,1,5,4,6,7,15},        // 13 .. x=1 y=1 z=1 .. inside the box
+  {1,5,7,3,-1,1,2,15,15},      // 14 .. x=1 y=1 z=2 D
+
+  {6,2,-1,0,2,1,1,15,15},      // 15 .. x=1 y=2 z=0 D
+  {6,2,3,7,-1,1,1,15,15},      // 16 .. x=1 y=2 z=1 D
+  {3,7,-1,1,1,1,2,15,15},      // 17 .. x=1 y=2 z=2 D
+
+  // the regions number <18,26>
+  {4,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D
+  {4,5,-1,0,1,1,0,15,15},      // 19 .. x=2 y=0 z=1 D
+  {5,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D
+
+  {4,6,-1,0,2,1,0,15,15},      // 21 .. x=2 y=1 z=0 D
+  {5,4,6,7,-1,1,0,15,15},      // 22 .. x=2 y=1 z=1 D
+  {7,5,-1,1,0,1,2,15,15},      // 23 .. x=2 y=1 z=2 D
+
+  {6,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D
+  {6,7,-1,1,0,1,1,15,15},      // 25 .. x=2 y=2 z=1 D
+  {7,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D
+};
+
+// Table for Sphere-AABB intersection based on the region knowledge
+// Similar array to previous cvertices, but we omit the surfaces
+// which are not necessary for testing. First are vertices,
+// they are finished with -1. Second, there are indexes in
+// the pair (a,b), when a=0, we want to test min vector of the box,
+//                 when a=1, we want to test max vector of the box
+//                 b=0,1,2 corresponds to the axis (0=x,1=y,2=z)
+//
+// So either we check the vertices or only the distance in specified
+// dimensions. There are at all four possible cases:
+//
+//   1) we check one vertex - then sequence start with non-negative index
+//      and is finished with 15
+//   2) we check two coordinates of min/max vector describe by the pair
+//         (a,b) .. a=min/max(0/1) b=x/y/z (0/1/2), sequence starts with 8
+//      and finishes with 15
+//   3) we check only one coordinate of min/max, as for 2), sequence start
+//      with 9 and ends with 15
+//   4) Position 13 - sphere is inside the box, intersection always exist
+//        the sequence start with 15 .. no further testing is necessary
+//        in this case
+const int
+AxisAlignedBox3::csvertices[27][6] = 
+{                   // region number.. position
+  {0,15,15,15,15,15},  // 0 .. x=0 y=0 z=0 D vertex only
+  {8,0,0,0,1,15},      // 1 .. x=0 y=0 z=1 D two coords.
+  {1,15,15,15,15,15},  // 2 .. x=0 y=0 z=2 D vertex only
+
+  {8,0,0,0,2,15},      // 3 .. x=0 y=1 z=0 D two coords
+  {9,0,0,15,15,15},    // 4 .. x=0 y=1 z=1 D one coord
+  {8,0,0,1,2,15},      // 5 .. x=0 y=1 z=2 D two coords.
+
+  {2,15,15,15,15,15},  // 6 .. x=0 y=2 z=0 D one vertex
+  {8,0,0,1,1,15},      // 7 .. x=0 y=2 z=1 D two coords
+  {3,15,15,15,15,15},  // 8 .. x=0 y=2 z=2 D one vertex
+
+  // the regions number <9,17>
+  {8,0,1,0,2,15},      // 9  .. x=1 y=0 z=0 D two coords
+  {9,0,1,15,15,15},    // 10 .. x=1 y=0 z=1 D one coord
+  {8,0,1,1,2,15},      // 11 .. x=1 y=0 z=2 D two coords
+
+  {9,0,2,15,15,15},    // 12 .. x=1 y=1 z=0 D one coord
+  {15,15,15,15,15,15}, // 13 .. x=1 y=1 z=1 inside the box, special case/value
+  {9,1,2,15,15,15},    // 14 .. x=1 y=1 z=2 D one corrd
+
+  {8,0,2,1,1,15},      // 15 .. x=1 y=2 z=0 D two coords
+  {9,1,1,15,15},       // 16 .. x=1 y=2 z=1 D one coord
+  {8,1,1,1,2,15},      // 17 .. x=1 y=2 z=2 D two coords
+
+  // the regions number <18,26>
+  {4,15,15,15,15,15},  // 18 .. x=2 y=0 z=0 D one vertex
+  {8,0,1,1,0,15},      // 19 .. x=2 y=0 z=1 D two coords
+  {5,15,15,15,15,15},  // 20 .. x=2 y=0 z=2 D one vertex
+
+  {8,0,2,1,0,15},      // 21 .. x=2 y=1 z=0 D two coords
+  {9,1,0,15,15,15},    // 22 .. x=2 y=1 z=1 D one coord
+  {8,1,0,1,2,15},      // 23 .. x=2 y=1 z=2 D two coords
+
+  {6,15,15,15,15,15},  // 24 .. x=2 y=2 z=0 D one vertex
+  {8,1,0,1,1,15},      // 25 .. x=2 y=2 z=1 D two coords
+  {7,15,15,15,15,15},  // 26 .. x=2 y=2 z=2 D one vertex
+};
+
+
+// The vertices that form all FARTHEST points with respect to the region
+// for all the regions possible, number of regions is 3^3 = 27,
+// since two parallel sides of bbox forms three disjoint spaces.
+// The vertices are given in anti-clockwise order, stopped by value 15,
+// at most 8 points, at least 1 point.
+// For testing, if the AABB is whole in the sphere, it is enough
+// to test only vertices, either 1,2,4, or 8.
+const int
+AxisAlignedBox3::fvertices[27][9] = 
+{                   // region number.. position
+  {7,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D
+  {6,7,15,15,15,15,15,15,15},  // 1 .. x=0 y=0 z=1 D
+  {6,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D
+
+  {5,7,15,15,15,15,15,15,15},  // 3 .. x=0 y=1 z=0 D
+  {4,5,7,6,15,15,15,15,15},    // 4 .. x=0 y=1 z=1 D
+  {4,6,15,15,15,15,15,15,15},  // 5 .. x=0 y=1 z=2 D
+
+  {5,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D
+  {4,5,15,15,15,15,15,15,15},  // 7 .. x=0 y=2 z=1 D
+  {4,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D
+
+  // the regions number <9,17>
+  {3,7,15,15,15,15,15,15,15},  // 9  .. x=1 y=0 z=0 D
+  {7,3,2,6,15,15,15,15,15},    // 10 .. x=1 y=0 z=1 D
+  {2,6,15,15,15,15,15,15,15},  // 11 .. x=1 y=0 z=2 D
+
+  {5,1,3,7,15,15,15,15,15},    // 12 .. x=1 y=1 z=0 D
+  {0,7,1,6,3,4,5,2,15},        // 13 .. x=1 y=1 z=1 .. inside the box
+  {0,4,6,2,15,15,15,15,15},    // 14 .. x=1 y=1 z=2 D
+
+  {5,1,15,15,15,15,15,15,15},  // 15 .. x=1 y=2 z=0 D
+  {4,0,1,5,15,15,15,15,15},    // 16 .. x=1 y=2 z=1 D
+  {4,0,15,15,15,15,15,15,15},  // 17 .. x=1 y=2 z=2 D
+
+  // the regions number <18,26>
+  {3,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D
+  {2,3,15,15,15,15,15,15,15},  // 19 .. x=2 y=0 z=1 D
+  {2,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D
+
+  {1,3,15,15,15,15,15,15,15},  // 21 .. x=2 y=1 z=0 D
+  {1,0,2,3,15,15,15,15,15},    // 22 .. x=2 y=1 z=1 D
+  {2,0,15,15,15,15,15,15,15},  // 23 .. x=2 y=1 z=2 D
+
+  {1,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D
+  {0,1,15,15,15,15,15,15,15},  // 25 .. x=2 y=2 z=1 D
+  {0,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D
+};
+
+// Similar table as above, farthest points, but only the ones
+// necessary for testing the intersection problem. If we do
+// not consider the case 13, center of the sphere is inside the
+// box, then we can always test at most 2 box vertices to say whether
+// the whole box is inside the sphere.
+// The number of vertices is minimized using some assumptions
+// about the ortogonality of vertices and sphere properties.
+const int
+AxisAlignedBox3::fsvertices[27][9] = 
+{                   // region number.. position
+  {7,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D 1 vertex
+  {6,7,15,15,15,15,15,15,15},  // 1 .. x=0 y=0 z=1 D 2 vertices
+  {6,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D 1 vertex
+
+  {5,7,15,15,15,15,15,15,15},  // 3 .. x=0 y=1 z=0 D 2 vertices
+  {4,7,15,5,6,15,15,15,15},    // 4 .. x=0 y=1 z=1 D 4/2 vertices
+  {4,6,15,15,15,15,15,15,15},  // 5 .. x=0 y=1 z=2 D 2 vertices
+
+  {5,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D 1 vertex
+  {4,5,15,15,15,15,15,15,15},  // 7 .. x=0 y=2 z=1 D 2 vertices
+  {4,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D 1 vertex
+
+  // the regions number <9,17>
+  {3,7,15,15,15,15,15,15,15},  // 9  .. x=1 y=0 z=0 D 2 vertices
+  {7,2,15,3,6,15,15,15,15},    // 10 .. x=1 y=0 z=1 D 4/2 vertices
+  {2,6,15,15,15,15,15,15,15},  // 11 .. x=1 y=0 z=2 D 2 vertices
+
+  {5,3,15,1,7,15,15,15,15},    // 12 .. x=1 y=1 z=0 D 4/2 vertices
+  {0,7,1,6,3,4,5,2,15},        // 13 .. x=1 y=1 z=1 .. inside the box
+  {0,6,15,4,2,15,15,15,15},    // 14 .. x=1 y=1 z=2 D 4/2 vertices
+
+  {5,1,15,15,15,15,15,15,15},  // 15 .. x=1 y=2 z=0 D 2 vertices
+  {4,1,15,0,5,15,15,15,15},    // 16 .. x=1 y=2 z=1 D 4/2 vertices
+  {4,0,15,15,15,15,15,15,15},  // 17 .. x=1 y=2 z=2 D 2 vertices
+
+  // the regions number <18,26>
+  {3,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D 1 vertex
+  {2,3,15,15,15,15,15,15,15},  // 19 .. x=2 y=0 z=1 D 2 vertices
+  {2,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D 1 vertex
+
+  {1,3,15,15,15,15,15,15,15},  // 21 .. x=2 y=1 z=0 D 2 vertices
+  {1,2,15,0,3,15,15,15,15},    // 22 .. x=2 y=1 z=1 D 4/2 vertices
+  {2,0,15,15,15,15,15,15,15},  // 23 .. x=2 y=1 z=2 D 2 vertices
+
+  {1,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D 1 vertex
+  {0,1,15,15,15,15,15,15,15},  // 25 .. x=2 y=2 z=1 D 2 vertices
+  {0,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D 1 vertex
+};
+
+
+// The fast computation of arctangent .. the maximal error is less
+// than 4.1 degrees, according to Graphics GEMSII, 1991, pages 389--391
+// Ron Capelli: "Fast approximation to the arctangent"
+float
+atan22(const float& y)
+{
+  const float x = 1.0;
+  const float c = (float)(M_PI * 0.25);
+  
+  if (y < 0.0) {
+    if (y < -1.0)
+      return c * (-2.0f + x / y); // for angle in <-PI/2, -PI/4)
+    else
+      return c * (y / x); // for angle in <-PI/4 , 0>
+  }
+  else {
+    if (y > 1.0)
+      return c * (2.0f - x / y); // for angle in <PI/4, PI/2>
+    else
+      return c * (y / x); // for angle in <0, PI/2>
+  }
+}
+
+
+float
+AxisAlignedBox3::ProjectToSphereSA(const Vector3 &viewpoint, int *tcase) const
+{
+  int id = GetRegionID(viewpoint);
+  *tcase = id;
+
+  // spherical projection .. SA represents solid angle
+  if (id == 13) // .. inside the box
+    return (float)(4.0*M_PI); // the whole sphere
+  float SA = 0.0; // inital value
+    
+  int i = 0; // the pointer in the array of vertices
+  while (bfaces[id][i] >= 0) {
+    int axisO = bfaces[id][i++];
+    int minvIdx = bfaces[id][i++];
+    int maxvIdx = bfaces[id][i++];
+    Vector3 vmin, vmax;
+    GetVertex(minvIdx, vmin);
+    GetVertex(maxvIdx, vmax);
+    float h = fabs(vmin[axisO] - viewpoint[axisO]);
+    int axis = (axisO + 1) % 3; // next axis 
+    float a = (vmin[axis] - viewpoint[axis]) / h; // minimum for v-range
+    float b = (vmax[axis] - viewpoint[axis]) / h; // maximum for v-range
+    //if (a > b) {
+    //  FATAL << "ProjectToSphereSA::Error a > b\n";
+    //  FATAL_ABORT;
+    //}
+    //if (vmin[axisO] != vmax[axisO]) {
+    //  FATAL << "ProjectToSphereSA::Error a-axis != b-axis\n";
+    //  FATAL_ABORT;     
+    //}
+    axis = (axisO + 2) % 3; // next second axis       
+    float c = (vmin[axis] - viewpoint[axis]) / h; // minimum for u-range
+    float d = (vmax[axis] - viewpoint[axis]) / h; // maximum for u-range
+    //if (c > d) {
+    //  FATAL << "ProjectToSphereSA::Error c > d\n";
+    //  FATAL_ABORT;
+    //}
+    SA +=atan22(d*b/sqrt(b*b + d*d + 1.0f)) - atan22(b*c/sqrt(b*b + c*c + 1.0f))
+      - atan22(d*a/sqrt(a*a + d*d + 1.0f)) + atan22(a*c/sqrt(a*a + c*c + 1.0f));
+  }
+
+#if 0
+  if ((SA > 2.0*M_PI) ||
+      (SA < 0.0)) {
+    FATAL << "The solid angle has strange value: ";
+    FATAL << "SA = "<< SA << endl;
+    FATAL_ABORT;
+  }
+#endif
+  
+  return SA;
+}
+
+// Projects the box to a plane given a normal vector only and
+// computes the surface area of the projected silhouette
+// no clipping of the box is performed.
+float
+AxisAlignedBox3::ProjectToPlaneSA(const Vector3 &normal) const
+{
+  Vector3 size = Size();
+
+  // the surface area of the box to a yz-plane - perpendicular to x-axis
+  float sax = size.y * size.z;
+
+  // the surface area of the box to a zx-plane - perpendicular to y-axis
+  float say = size.z * size.x;
+
+  // the surface area of the box to a xy-plane - perpendicular to z-axis
+  float saz = size.x * size.y;
+  
+  return sax * fabs(normal.x) + say * fabs(normal.y) + saz * fabs(normal.z);
+}
+
+
+
+// This definition allows to be a point when answering true
+bool
+AxisAlignedBox3::IsCorrectAndNotPoint() const
+{
+  if ( (mMin.x > mMax.x) ||
+       (mMin.y > mMax.y) ||
+       (mMin.z > mMax.z) )
+    return false; // box is not formed
+
+  if ( (mMin.x == mMax.x) &&
+       (mMin.y == mMax.y) &&
+       (mMin.z == mMax.z) )
+    return false; // degenerates to a point
+  
+  return true;
+}
+
+// This definition allows to be a point when answering true
+bool
+AxisAlignedBox3::IsPoint() const
+{
+  if ( (mMin.x == mMax.x) &&
+       (mMin.y == mMax.y) &&
+       (mMin.z == mMax.z) )
+    return true; // degenerates to a point
+  
+  return false;
+}
+
+// This definition requires shape of non-zero volume
+bool
+AxisAlignedBox3::IsSingularOrIncorrect() const
+{
+  if ( (mMin.x >= mMax.x) ||
+       (mMin.y >= mMax.y) ||
+       (mMin.z >= mMax.z) )
+    return true; // box is not formed
+
+  return false; // has non-zero volume
+}
+
+// returns true, when the sphere specified by the origin and radius
+// fully contains the box
+bool
+AxisAlignedBox3::IsFullyContainedInSphere(const Vector3 &center, float rad) const
+{
+  int region = GetRegionID(center);
+  float rad2 = rad*rad;
+
+  // vertex of the box
+  Vector3 vertex;
+
+  int i = 0;
+  for (i = 0 ; ; i++) {
+    int a = fsvertices[region][i];
+    if (a == 15)
+      return true; // if was not false untill now, it must be contained
+
+    assert( (a>=0) && (a<8) );
+    
+    // normal vertex
+    GetVertex(a, vertex);
+
+    if (SqrMagnitude(vertex - center) > rad2)
+      return false;    
+  } // for
+  
+}
+
+// returns true, when the volume of the sphere and volume of the
+// axis aligned box has no intersection
+bool
+AxisAlignedBox3::HasNoIntersectionWithSphere(const Vector3 &center, float rad) const
+{
+  int region = GetRegionID(center);
+  float rad2 = rad*rad;
+
+  // vertex of the box
+  Vector3 vertex;
+
+  switch (csvertices[region][0]) {
+  case 8: {
+    // test two coordinates described within the field
+    int face = 3*csvertices[region][1] + csvertices[region][2];
+    float dist = GetExtent(face) - center[csvertices[region][2]];
+    dist *= dist;
+    face = 3 * (csvertices[region][3]) + csvertices[region][4];
+    float dist2 = GetExtent(face) - center[csvertices[region][4]];
+    dist += (dist2 * dist2);
+    if (dist > rad2)
+      return true; // no intersection is possible
+  }
+  case 9: {
+    // test one coordinate described within the field
+    int face = 3*csvertices[region][1] + csvertices[region][2];
+    float dist = fabs(GetExtent(face) - center[csvertices[region][2]]);
+    if (dist > rad)
+      return true; // no intersection is possible
+  }
+  case 15:
+    return false; // box and sphere surely has intersection
+  default: {
+    // test using normal vertices 
+    assert( (csvertices[region][0]>=0) && (csvertices[region][0]<8) );
+
+    // normal vertex
+    GetVertex(csvertices[region][0], vertex);
+
+    if (SqrMagnitude(vertex - center) > rad2)
+      return true; // no intersectino is possible    
+    }
+  } // switch
+
+  return false; // partial or full containtment
+}
+
+#if 0
+// Given the sphere, determine the mutual position between the
+// sphere and box
+
+// SOME BUG IS INSIDE !!!! V.H. 25/4/2001
+int
+AxisAlignedBox3::MutualPositionWithSphere(const Vector3 &center, float rad) const
+{
+  int region = GetRegionID(center);
+  float rad2 = rad*rad;
+
+  // vertex of the box
+  Vector3 vertex;
+
+  // first testing for  full containtment - whether sphere fully
+  // contains the box
+  int countInside = 0; // how many points were found inside
+  
+  int i = 0;
+  for (i = 0 ; ; i++) {
+    int a = fsvertices[region][i];
+    if (a == 15)
+      return 1; // the sphere fully contain the box
+
+    assert( (a>=0) && (a<8) );
+    
+    // normal vertex
+    GetVertex(a, vertex);
+
+    if (SqrMagnitude(vertex - center) <= rad2)
+      countInside++; // the number of vertices inside the sphere
+    else {
+      if (countInside)
+	return 0; // partiall overlap has been found
+      // the sphere does not fully contain the box .. only way to break
+      // this loop and go for other testing
+      break;
+    }
+  } // for
+
+  // now only box and sphere can partially overlap or no intersection
+  switch (csvertices[region][0]) {
+  case 8: {
+    // test two coordinates described within the field
+    int face = 3*csvertices[region][1] + csvertices[region][2];
+    float dist = GetExtent(face) - center[csvertices[region][2]];
+    dist *= dist;
+    face = 3 * (csvertices[region][3]) + csvertices[region][4];
+    float dist2 = GetExtent(face) - center[csvertices[region][4]];
+    dist += (dist2 * dist2);
+    if (dist > rad2 )
+      return -1; // no intersection is possible
+  }
+  case 9: {
+    // test one coordinate described within the field
+    int face = 3*csvertices[region][1] + csvertices[region][2];
+    float dist = fabs(GetExtent(face) - center[csvertices[region][2]]);
+    if (dist > rad)
+      return -1; // no intersection is possible
+  }
+  case 15:
+    return 0 ; // partial overlap is now guaranteed
+  default: {
+    // test using normal vertices 
+    assert( (csvertices[region][0]>=0) && (csvertices[region][0]<8) );
+    
+    // normal vertex
+    GetVertex(csvertices[region][0], vertex);
+
+    if (SqrMagnitude(vertex - center) > rad2)
+      return -1; // no intersection is possible    
+    }
+  } // switch
+
+  return 0; // partial intersection is guaranteed
+}
+#else
+
+// Some maybe smarter version, extendible easily to d-dimensional
+// space!
+// Given a sphere described by the center and radius,
+// the fullowing function returns:
+//   -1 ... the sphere and the box are completely separate
+//    0 ... the sphere and the box only partially overlap
+//    1 ... the sphere contains fully the box
+//  Note: the case when box fully contains the sphere is not reported
+//        since it was not required.
+int
+AxisAlignedBox3::MutualPositionWithSphere(const Vector3 &center, float rad) const
+{
+//#define SPEED_UP
+
+#ifndef SPEED_UP
+  // slow version, instructively written  
+#if 0
+  // does it make sense to test
+  // checking the sides of the box for possible non-intersection
+  if ( ((center.x + rad) < mMin.x) ||
+       ((center.x - rad) > mMax.x) ||
+       ((center.y + rad) < mMin.y) ||
+       ((center.y - rad) > mMax.y) ||
+       ((center.z + rad) < mMin.z) ||
+       ((center.z - rad) > mMax.z) ) {
+    // cout << "r ";
+    return -1;  // no overlap is possible
+  }
+#endif
+  
+  // someoverlap is possible, check the distance of vertices
+  rad = rad*rad;
+  float sumMin = 0;
+  // Try to minimize the function of a distance
+  // from the sphere center
+
+  // for x-axis
+  float minSqrX = sqr(mMin.x - center.x);
+  float maxSqrX = sqr(mMax.x - center.x);
+  if (center.x < mMin.x)
+    sumMin = minSqrX; 
+  else
+    if (center.x > mMax.x)
+      sumMin = maxSqrX;
+
+  // for y-axis
+  float minSqrY = sqr(mMin.y - center.y);
+  float maxSqrY = sqr(mMax.y - center.y);
+  if (center.y < mMin.y)
+    sumMin += minSqrY; 
+  else
+    if (center.y > mMax.y)
+      sumMin += maxSqrY;
+
+  // for z-axis
+  float minSqrZ = sqr(mMin.z - center.z);
+  float maxSqrZ = sqr(mMax.z - center.z);
+  if (center.z < mMin.z)
+    sumMin += minSqrZ; 
+  else
+    if (center.z > mMax.z)
+      sumMin += maxSqrZ;
+
+  if (sumMin > rad)
+    return -1; // no intersection between sphere and box
+
+  // try to find out the maximum distance between the
+  // sphere center and vertices
+  float sumMax = 0;
+  
+  if (minSqrX > maxSqrX)
+    sumMax = minSqrX;
+  else
+    sumMax = maxSqrX;
+  
+  if (minSqrY > maxSqrY)
+    sumMax += minSqrY;
+  else
+    sumMax += maxSqrY;
+  
+  if (minSqrZ > maxSqrZ)
+    sumMax += minSqrZ;
+  else
+    sumMax += maxSqrZ;
+  
+  // sumMin < rad
+  if (sumMax < rad)
+    return 1; // the sphere contains the box completely
+
+  // partial intersection, part of the box is outside the sphere
+  return 0;
+#else
+
+  // Optimized version of the test
+  
+#ifndef __VECTOR_HACK
+#error "__VECTOR_HACK for Vector3 was not defined"
+#endif
+
+  // some overlap is possible, check the distance of vertices
+  rad = rad*rad;
+  float sumMin = 0;
+  float sumMax = 0;
+  // Try to minimize the function of a distance
+  // from the sphere center
+
+  const float *minp = &(min[0]);
+  const float *maxp = &(max[0]);
+  const float *pcenter = &(center[0]);
+  
+  // for x-axis
+  for (int i = 0; i < 3; i++, minp++, maxp++, pcenter++) {
+    float minsqr = sqr(*minp - *pcenter);
+    float maxsqr = sqr(*maxp - *pcenter);
+    if (*pcenter < *minp)
+      sumMin += minsqr;
+    else
+      if (*pcenter > *maxp)
+	sumMin += maxsqr;
+    sumMax += (minsqr > maxsqr) ? minsqr : maxsqr;
+  }
+
+  if (sumMin > rad)
+    return -1; // no intersection between sphere and box
+
+  // sumMin < rad
+  if (sumMax < rad)
+    return 1; // the sphere contains the box completely
+
+  // partial intersection, part of the box is outside the sphere
+  return 0;
+#endif
+}
+#endif
+
+// Given the cube describe by the center and the half-sie,
+// determine the mutual position between the cube and the box
+int
+AxisAlignedBox3::MutualPositionWithCube(const Vector3 &center, float radius) const
+{
+  // the cube is described by the center and the distance to the any face
+  // along the axes
+
+  // Note on efficiency!
+  // Can be quite optimized using tables, but I do not have time
+  // V.H. 18/11/2001
+
+  AxisAlignedBox3 a = 
+    AxisAlignedBox3(Vector3(center.x - radius, center.y - radius, center.z - radius),
+	   Vector3(center.x + radius, center.y + radius, center.z + radius));
+
+  if (a.Includes(*this))
+    return 1; // cube contains the box
+
+  if (OverlapS(a,*this))
+    return 0; // cube partially overlap the box
+
+  return -1; // completely separate  
+}
+
+void
+AxisAlignedBox3::GetSqrDistances(const Vector3 &point,
+				 float &minDistance,
+				 float &maxDistance
+				 ) const
+{
+
+  
+#ifndef __VECTOR_HACK
+#error "__VECTOR_HACK for Vector3 was not defined"
+#endif
+
+  // some overlap is possible, check the distance of vertices
+  float sumMin = 0;
+  float sumMax = 0;
+
+  // Try to minimize the function of a distance
+  // from the sphere center
+
+  const float *minp = &(mMin[0]);
+  const float *maxp = &(mMax[0]);
+  const float *pcenter = &(point[0]);
+  
+  // for x-axis
+  for (int i = 0; i < 3; i++, minp++, maxp++, pcenter++) {
+    float minsqr = sqr(*minp - *pcenter);
+    float maxsqr = sqr(*maxp - *pcenter);
+    if (*pcenter < *minp)
+      sumMin += minsqr;
+    else
+      if (*pcenter > *maxp)
+	sumMin += maxsqr;
+    sumMax += (minsqr > maxsqr) ? minsqr : maxsqr;
+  }
+
+  minDistance = sumMin;
+  maxDistance = sumMax;
+}
+
+
+int
+AxisAlignedBox3::Side(const Plane3 &plane) const
+{
+  Vector3 v;
+  int i, m=3, M=-3, s;
+  
+  for (i=0;i<8;i++) {
+    GetVertex(i, v);
+    if((s = plane.Side(v)) < m)
+      m=s;
+    if(s > M)
+      M=s;
+    if (m && m==-M)
+      return 0;
+  }
+  
+  return (m == M) ? m : m + M;
+}
+
+int
+AxisAlignedBox3::GetFaceVisibilityMask(const Rectangle3 &rectangle) const
+{
+  int mask = 0;
+  for (int i=0; i < 4; i++)
+    mask |= GetFaceVisibilityMask(rectangle.mVertices[i]);
+  return mask;
+}
+
+int
+AxisAlignedBox3::GetFaceVisibilityMask(const Vector3 &position) const {
+  
+  // assume that we are not inside the box
+  int c=0;
+  
+  if (position.x<(mMin.x-Limits::Small))
+    c|=1;
+  else
+    if (position.x>(mMax.x+Limits::Small))
+      c|=2;
+  
+  if (position.y<(mMin.y-Limits::Small))
+    c|=4;
+  else
+    if (position.y>(mMax.y+Limits::Small))
+      c|=8;
+  
+  if (position.z<(mMin.z-Limits::Small))
+    c|=16;
+  else
+    if (position.z>(mMax.z+Limits::Small))
+      c|=32;
+  
+  return c;
+}
+
+
+Rectangle3
+AxisAlignedBox3::GetFace(const int face) const
+{
+  Vector3 v[4];
+  switch (face) {
+    
+  case 0:
+    v[3].SetValue(mMin.x,mMin.y,mMin.z);
+    v[2].SetValue(mMin.x,mMax.y,mMin.z);
+    v[1].SetValue(mMin.x,mMax.y,mMax.z);
+    v[0].SetValue(mMin.x,mMin.y,mMax.z);
+    break;
+    
+  case 1: 
+    v[0].SetValue(mMax.x,mMin.y,mMin.z);
+    v[1].SetValue(mMax.x,mMax.y,mMin.z);
+    v[2].SetValue(mMax.x,mMax.y,mMax.z);
+    v[3].SetValue(mMax.x,mMin.y,mMax.z);
+    break;
+    
+  case 2:
+    v[3].SetValue(mMin.x,mMin.y,mMin.z);
+    v[2].SetValue(mMin.x,mMin.y,mMax.z);
+    v[1].SetValue(mMax.x,mMin.y,mMax.z);
+    v[0].SetValue(mMax.x,mMin.y,mMin.z);
+    break;
+  
+  case 3:
+    v[0].SetValue(mMin.x,mMax.y,mMin.z);
+    v[1].SetValue(mMin.x,mMax.y,mMax.z);
+    v[2].SetValue(mMax.x,mMax.y,mMax.z);
+    v[3].SetValue(mMax.x,mMax.y,mMin.z);
+    break;
+
+  case 4:
+    v[3].SetValue(mMin.x,mMin.y,mMin.z);
+    v[2].SetValue(mMax.x,mMin.y,mMin.z);
+    v[1].SetValue(mMax.x,mMax.y,mMin.z);
+    v[0].SetValue(mMin.x,mMax.y,mMin.z);
+    break;
+  
+  case 5:
+    v[0].SetValue(mMin.x,mMin.y,mMax.z);
+    v[1].SetValue(mMax.x,mMin.y,mMax.z);
+    v[2].SetValue(mMax.x,mMax.y,mMax.z);
+    v[3].SetValue(mMin.x,mMax.y,mMax.z);
+    break;
+  }
+  
+  return Rectangle3(v[0], v[1], v[2], v[3]);
+}
+
+struct VertexData
+{
+	Vector3 mVertex;
+	float mAngle;
+	
+	VertexData(Vector3 vtx, float angle): mVertex(vtx), mAngle(angle)
+	{}
+
+	bool operator<(const VertexData &b) const 
+	{
+		return mAngle > b.mAngle;
+	}
+};
+
+// TODO: use a table to avoid normal and distance computations
+Polygon3 *AxisAlignedBox3::CrossSection(const Plane3 &plane) const
+{
+	Polygon3 *planePoly = new Polygon3();
+	
+	int side[8];
+	bool onFrontSide = false, onBackSide = false;
+	
+	Vector3 vtx;
+	//-- compute classification of vertices
+	for (int i = 0; i < 8; ++i)
+	{
+		GetVertex(i, vtx);
+		side[i] = plane.Side(vtx);
+		if (side[i] > 0)
+			onFrontSide = true;
+		else if (side[i] < 0)
+			onBackSide = true;
+		else // vertex coincident => push_back
+			planePoly->mVertices.push_back(vtx);
+	}
+
+	//-- find intersections
+	if (onFrontSide && onBackSide)
+	{
+		Vector3 ptA, ptB;
+		for (int i = 0; i < 12; ++ i)
+		{
+			int aIdx, bIdx;
+			GetEdge(i, aIdx, bIdx);
+
+			ptA = GetVertex(aIdx);
+			ptB = GetVertex(bIdx);
+
+			int sideA = side[aIdx];
+			int sideB = side[bIdx];
+
+			if (((sideA > 0) && (sideB < 0)) || (sideA < 0) && (sideB > 0))
+				planePoly->mVertices.push_back(plane.FindIntersection(ptA, ptB));	
+		}
+	}
+
+	// order intersections	
+	if (planePoly->mVertices.size() > 3)
+	{
+		Vector3 centerOfMass(0);
+		int i;
+		// compute center of mass
+		for (i = 0; i < (int)planePoly->mVertices.size(); ++ i)
+			centerOfMass += planePoly->mVertices[i];
+		
+		centerOfMass /= (float)planePoly->mVertices.size();
+
+		vector<VertexData> vertexData;
+		
+		Vector3 refVec = Normalize(centerOfMass - planePoly->mVertices[0]);
+
+		// compute angle to reference point
+		for (i = 1; i < (int)planePoly->mVertices.size(); ++ i)
+		  {
+		    float angle = 
+		      Angle(refVec, centerOfMass - planePoly->mVertices[i], plane.mNormal);
+		    
+		    vertexData.push_back(VertexData(planePoly->mVertices[i], angle));
+		  }
+		
+		std::stable_sort(vertexData.begin(), vertexData.end());
+
+		// update vertices
+		for (i = 1; i < (int)planePoly->mVertices.size(); ++ i)
+			planePoly->mVertices[i] = vertexData[i - 1].mVertex;
+	}
+	else if (planePoly->mVertices.size() == 3)
+	{
+		// fix orientation if needed
+		if (DotProd(planePoly->GetNormal(), plane.mNormal) < 0)
+		{
+			Vector3 v = planePoly->mVertices[1];
+			planePoly->mVertices[1] = planePoly->mVertices[2];
+			planePoly->mVertices[2] = v;
+		}
+	}
+	
+	return planePoly;
+}
+
+
+bool AxisAlignedBox3::GetRaySegment(const Ray &ray, 
+									float &minT, 
+									float &maxT) const
+{
+	maxT = 1e15;
+	minT = 0;
+	
+	// test with bounding box
+	if (!GetMinMaxT(ray, &minT, &maxT))
+		return false;
+
+	if (minT < 0)
+		minT = 0;
+
+	// bound ray or line segment
+	if (//(ray.GetType() == Ray::LOCAL_RAY) && 
+	    !ray.intersections.empty() && 
+		(ray.intersections[0].mT <= maxT))
+	{
+		maxT = ray.intersections[0].mT;
+	}
+
+	return true;
+}
+
+
+  // Compute tmin and tmax for a ray, whenever required .. need not pierce box
+int
+AxisAlignedBox3::ComputeMinMaxT(const Vector3 &origin,
+								const Vector3 &direction,
+								float *tmin,
+								float *tmax) const
+{
+
+  register float minx, maxx;
+
+  
+  Vector3 invDirection;
+  const float eps = 1e-6f;
+  const float invEps = 1e6f;
+  
+  // it does change the ray direction very slightly,
+  // but the size direction vector is not practically changed
+  
+  if (fabs(direction.x) < eps) {
+    if (direction.x < 0.0f)
+      invDirection.x = -invEps;
+    else
+      invDirection.x = invEps;
+  }
+  else
+    invDirection.x = 1.0f / direction.x;
+  
+  if (fabs(direction.y) < eps) {
+    if (direction.y < 0.0)
+      invDirection.y = -invEps;
+    else
+      invDirection.y = invEps;
+  }
+  else
+    invDirection.y = 1.0f / direction.y;
+  
+  if (fabs(direction.z) < eps) {
+    if (direction.z < 0.0f)
+      invDirection.z = -invEps;
+    else
+      invDirection.z = invEps;
+  }
+  else
+    invDirection.z = 1.0f / direction.z;
+
+
+  
+  if (fabs(direction.x) < 0.001f) {
+    if (mMin.x < origin.x && mMax.x > origin.x) {
+      minx = -MAXFLOAT;
+      maxx = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.x - origin.x) * invDirection.x;
+    float t2 = (mMax.x - origin.x) * invDirection.x;
+    if (t1 < t2) {
+      minx = t1;
+      maxx = t2;
+    }
+    else {
+      minx = t2;
+      maxx = t1;
+    }
+	//    if (maxx < 0.0)
+	//      return 0;
+  }
+
+  *tmin = minx;
+  *tmax = maxx;
+  
+  if (fabs(direction.y) < 0.001) {
+    if (mMin.y < origin.y && mMax.y > origin.y) {
+      minx = -MAXFLOAT;
+      maxx = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.y - origin.y) * invDirection.y;
+    float t2 = (mMax.y - origin.y) * invDirection.y;
+    if (t1 < t2) {
+      minx = t1;
+      maxx = t2;
+    }
+    else {
+      minx = t2;
+      maxx = t1;
+    }
+	//    if (maxx < 0.0)
+	//      return 0;
+  }
+
+  if (minx > *tmin)
+    *tmin = minx;
+  if (maxx < *tmax)
+    *tmax = maxx;
+  
+  if (fabs(direction.z) < 0.001) {
+    if (mMin.z < origin.z && mMax.z > origin.z) {
+      minx = -MAXFLOAT;
+      maxx = MAXFLOAT;
+    }
+    else
+      return 0;
+  }
+  else {
+    float t1 = (mMin.z - origin.z) * invDirection.z;
+    float t2 = (mMax.z - origin.z) * invDirection.z;
+    if (t1 < t2) {
+      minx = t1;
+      maxx = t2;
+    }
+    else {
+      minx = t2;
+      maxx = t1;
+    }
+	//    if (maxx < 0.0)
+	//      return 0;
+  }
+
+  if (minx > *tmin)
+    *tmin = minx;
+  if (maxx < *tmax)
+    *tmax = maxx;
+
+  return 1; // yes, intersection was found
+}
+
+
+bool AxisAlignedBox3::GetIntersectionFace(Rectangle3 &face, 
+										  const AxisAlignedBox3 &neighbour) const
+										   
+{ 
+	if (EpsilonEqual(mMin[0], neighbour.Max(0)))
+	{
+		float maxy = min(mMax.y, neighbour.mMax.y);
+		float maxz = min(mMax.z, neighbour.mMax.z);
+		float miny = max(mMin.y, neighbour.mMin.y);
+		float minz = max(mMin.z, neighbour.mMin.z);
+
+		face.mVertices[3].SetValue(mMin.x, miny, minz);
+		face.mVertices[2].SetValue(mMin.x, maxy, minz);
+		face.mVertices[1].SetValue(mMin.x, maxy, maxz);
+		face.mVertices[0].SetValue(mMin.x, miny, maxz);
+
+        return true;
+	}
+    if (EpsilonEqual(mMax[0], neighbour.Min(0)))
+	{
+		float maxy = min(mMax.y, neighbour.mMax.y);
+		float maxz = min(mMax.z, neighbour.mMax.z);
+		float miny = max(mMin.y, neighbour.mMin.y);
+		float minz = max(mMin.z, neighbour.mMin.z);
+
+		face.mVertices[0].SetValue(mMax.x, miny, minz);
+		face.mVertices[1].SetValue(mMax.x, maxy, minz);
+		face.mVertices[2].SetValue(mMax.x, maxy, maxz);
+		face.mVertices[3].SetValue(mMax.x, miny, maxz);
+
+		return true;
+	}
+    if (EpsilonEqual(mMin[1], neighbour.Max(1)))
+	{
+		float maxx = min(mMax.x, neighbour.mMax.x);
+		float maxz = min(mMax.z, neighbour.mMax.z);
+		float minx = max(mMin.x, neighbour.mMin.x);
+		float minz = max(mMin.z, neighbour.mMin.z);
+
+		face.mVertices[3].SetValue(minx, mMin.y, minz);
+		face.mVertices[2].SetValue(minx, mMin.y, maxz);
+		face.mVertices[1].SetValue(maxx, mMin.y, maxz);
+		face.mVertices[0].SetValue(maxx, mMin.y, minz);
+		
+		return true;
+	}
+	if (EpsilonEqual(mMax[1], neighbour.Min(1)))
+	{		
+		float maxx = min(mMax.x, neighbour.mMax.x);
+		float maxz = min(mMax.z, neighbour.mMax.z);
+		float minx = max(mMin.x, neighbour.mMin.x);
+		float minz = max(mMin.z, neighbour.mMin.z);
+
+		face.mVertices[0].SetValue(minx, mMax.y, minz);
+		face.mVertices[1].SetValue(minx, mMax.y, maxz);
+		face.mVertices[2].SetValue(maxx, mMax.y, maxz);
+		face.mVertices[3].SetValue(maxx, mMax.y, minz);
+
+		return true;
+	}
+	if (EpsilonEqual(mMin[2], neighbour.Max(2)))
+	{
+		float maxx = min(mMax.x, neighbour.mMax.x);
+		float maxy = min(mMax.y, neighbour.mMax.y);
+		float minx = max(mMin.x, neighbour.mMin.x);
+		float miny = max(mMin.y, neighbour.mMin.y);
+
+		face.mVertices[3].SetValue(minx, miny, mMin.z);
+		face.mVertices[2].SetValue(maxx, miny, mMin.z);
+		face.mVertices[1].SetValue(maxx, maxy, mMin.z);
+		face.mVertices[0].SetValue(minx, maxy, mMin.z);
+	
+		return true;
+	}
+	if (EpsilonEqual(mMax[2], neighbour.Min(2)))
+	{
+		float maxx = min(mMax.x, neighbour.mMax.x);
+		float maxy = min(mMax.y, neighbour.mMax.y);
+		float minx = max(mMin.x, neighbour.mMin.x);
+		float miny = max(mMin.y, neighbour.mMin.y);
+
+		face.mVertices[0].SetValue(minx, miny, mMax.z);
+		face.mVertices[1].SetValue(maxx, miny, mMax.z);
+		face.mVertices[2].SetValue(maxx, maxy, mMax.z);
+		face.mVertices[3].SetValue(minx, maxy, mMax.z);
+
+		return true;
+	}
+
+	return false;
+}
+
+
+void AxisAlignedBox3::AddBoxToMesh(Mesh *mesh) const
+{
+	// add 6 vertices of the box
+	int index = (int)mesh->mVertices.size();
+	
+	for (int i=0; i < 8; i++) 
+	{
+		Vector3 v;
+		GetVertex(i, v);
+		mesh->mVertices.push_back(v);
+	}
+	
+	mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) );
+	mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) );
+	mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) );
+	
+	mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) );
+	mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) );
+	mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) );
+}
+
+
+void AxisAlignedBox3::ExtractPolys(PolygonContainer &polys) const
+{
+	Polygon3 *face1 = new Polygon3();
+	polys.push_back(face1);   
+
+    face1->mVertices.push_back(Vector3(mMin.x, mMin.y, mMax.z));
+	face1->mVertices.push_back(Vector3(mMin.x, mMax.y, mMax.z));
+	face1->mVertices.push_back(Vector3(mMin.x, mMax.y ,mMin.z));
+	face1->mVertices.push_back(Vector3(mMin.x, mMin.y, mMin.z));
+
+	Polygon3 *face2 = new Polygon3();  
+	polys.push_back(face2);
+    
+    face2->mVertices.push_back(Vector3(mMax.x, mMin.y, mMin.z));
+    face2->mVertices.push_back(Vector3(mMax.x, mMax.y, mMin.z));
+    face2->mVertices.push_back(Vector3(mMax.x, mMax.y, mMax.z));
+    face2->mVertices.push_back(Vector3(mMax.x, mMin.y, mMax.z));
+  
+	Polygon3 *face3 = new Polygon3();  
+	polys.push_back(face3);
+
+    face3->mVertices.push_back(Vector3(mMax.x, mMin.y ,mMin.z));
+	face3->mVertices.push_back(Vector3(mMax.x, mMin.y, mMax.z));
+	face3->mVertices.push_back(Vector3(mMin.x, mMin.y, mMax.z));
+	face3->mVertices.push_back(Vector3(mMin.x, mMin.y, mMin.z));
+
+	Polygon3 *face4 = new Polygon3();  
+	polys.push_back(face4);
+
+	face4->mVertices.push_back(Vector3(mMin.x, mMax.y, mMin.z));
+	face4->mVertices.push_back(Vector3(mMin.x, mMax.y, mMax.z));
+	face4->mVertices.push_back(Vector3(mMax.x, mMax.y, mMax.z));
+	face4->mVertices.push_back(Vector3(mMax.x, mMax.y, mMin.z));
+    
+	Polygon3 *face5 = new Polygon3();  
+	polys.push_back(face5);
+
+	face5->mVertices.push_back(Vector3(mMin.x, mMax.y, mMin.z));
+    face5->mVertices.push_back(Vector3(mMax.x, mMax.y, mMin.z));
+    face5->mVertices.push_back(Vector3(mMax.x, mMin.y, mMin.z));
+	face5->mVertices.push_back(Vector3(mMin.x, mMin.y, mMin.z));
+
+	Polygon3 *face6 = new Polygon3();  
+	polys.push_back(face6);  
+  
+    face6->mVertices.push_back(Vector3(mMin.x, mMin.y, mMax.z));
+    face6->mVertices.push_back(Vector3(mMax.x, mMin.y, mMax.z));
+    face6->mVertices.push_back(Vector3(mMax.x, mMax.y, mMax.z));
+    face6->mVertices.push_back(Vector3(mMin.x, mMax.y, mMax.z));
+
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Rectangle3.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Rectangle3.cpp	(revision 223)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Rectangle3.cpp	(revision 223)
@@ -0,0 +1,38 @@
+#include "Rectangle3.h"
+
+
+void
+Rectangle3::Split(const int axis,
+		  Rectangle3 &r1,
+		  Rectangle3 &r2
+		  ) const
+{
+  if (axis==0) {
+    Vector3 v1 = (mVertices[0] + mVertices[1])*0.5f;
+    Vector3 v2 = (mVertices[2] + mVertices[3])*0.5f;
+    
+    r1.mVertices[0] = mVertices[0];
+    r1.mVertices[1] = v1;
+    r1.mVertices[2] = v2;
+    r1.mVertices[3] = mVertices[3];
+
+    r2.mVertices[0] = v1;
+    r2.mVertices[1] = mVertices[1];
+    r2.mVertices[2] = mVertices[2];
+    r2.mVertices[3] = v2;
+  } else {
+    Vector3 v1 = (mVertices[0] + mVertices[3])*0.5f;
+    Vector3 v2 = (mVertices[1] + mVertices[2])*0.5f;
+    
+    r1.mVertices[0] = mVertices[0];
+    r1.mVertices[1] = mVertices[1];
+    r1.mVertices[2] = v2;
+    r1.mVertices[3] = v1;
+    
+    r2.mVertices[0] = v1;
+    r2.mVertices[1] = v2;
+    r2.mVertices[2] = mVertices[2];
+    r2.mVertices[3] = mVertices[3];
+  }
+  
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.h	(revision 574)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.h	(revision 574)
@@ -0,0 +1,114 @@
+#ifndef _VssPreprocessor_H__
+#define _VssPreprocessor_H__
+
+#include <fstream>
+using namespace std;
+
+#include "Preprocessor.h"
+#include "VssRay.h"
+class VssTree;
+class VssTreeLeaf;
+
+
+/** Sampling based visibility preprocessing. The implementation is based on heuristical
+    sampling of view space */
+class VssPreprocessor : public Preprocessor {
+public:
+  int mPass;
+  int mSamplesPerPass;
+  int mVssSamplesPerPass;
+  int mInitialSamples;
+  int mVssSamples;
+  bool mUseImportanceSampling;
+
+  AxisAlignedBox3 *mViewSpaceBox;
+
+  ofstream mStats;
+	
+  ObjectContainer mObjects;
+
+  /// if initial samples should be loaded from file
+  bool mLoadInitialSamples;
+  /// if initial samples should be stored in file
+  bool mStoreInitialSamples;
+  /// if box around view space should be used
+  bool mUseViewSpaceBox;
+  // rays cast during the processing
+  VssRayContainer mVssRays;
+	
+  VssPreprocessor();
+  ~VssPreprocessor();
+
+  virtual bool ComputeVisibility();
+
+  Vector3
+  GetViewpoint(AxisAlignedBox3 *viewSpaceBox);
+
+  Vector3
+  GetDirection(const Vector3 &viewpoint,
+			   AxisAlignedBox3 *viewSpaceBox
+			   );
+	
+  void CastRays(SimpleRayContainer &rays, VssRayContainer &vssRays);
+
+  void
+  SetupRay(Ray &ray, 
+		   const Vector3 &point, 
+		   const Vector3 &direction
+		   );
+
+
+	
+  int
+  CastRay(
+		  Vector3 &viewPoint,
+		  Vector3 &direction,
+		  VssRayContainer &vssRays
+
+		  );
+
+
+  bool
+  ExportRays(const char *filename,
+			 const VssRayContainer &vssRays,
+			 const int number
+			 );
+
+  int
+  GenerateImportanceRays(VssTree *vssTree,
+						 const int desiredSamples,
+						 SimpleRayContainer &rays
+						 );
+
+
+  bool
+  ExportVssTreeLeaf(char *filename,
+					VssTree *tree,
+					VssTreeLeaf *leaf);
+
+  void
+  ExportVssTreeLeaves(VssTree *tree, const int number);
+	
+
+  bool
+  ExportVssTree(char *filename,
+				VssTree *tree,
+				const Vector3 &dir
+				);
+
+
+  float
+  GetAvgPvsSize(VssTree *tree,
+				const vector<AxisAlignedBox3> &viewcells
+				);
+  
+  void CastRay(const BspTree &tree, const VssRay & vssRay);
+
+  void TestBeamCasting(VssTree *tre, ViewCellsManager *vm, const ObjectContainer &objects);
+
+  bool mTestBeamSampling;
+};
+
+
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Camera.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Camera.cpp	(revision 492)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Camera.cpp	(revision 492)
@@ -0,0 +1,144 @@
+#include <algorithm>
+
+// the devil library
+#include <IL/il.h>
+#include <IL/ilu.h>
+#include <IL/ilut.h>
+
+#include "Camera.h"
+#include "Ray.h"
+#include "KdTree.h"
+#include "Mesh.h"
+#include "Exporter.h"
+#include "SceneGraph.h"
+
+
+
+
+void
+InitDevIl()
+{
+  ilInit();
+  ILuint ImageName;
+  ilGenImages(1, &ImageName);
+  ilBindImage(ImageName);
+  ilEnable(IL_FILE_OVERWRITE);
+
+  //  ilRegisterFormat(IL_RGBA);
+  //  ilRegisterType(IL_FLOAT);
+
+  //  ilEnable(IL_ORIGIN_SET);
+  //  ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
+}
+
+bool
+Camera::SnapImage(string filename,
+				  KdTree *tree,
+				  SceneGraph *sceneGraph
+				  )
+{
+  int x;
+  int y;
+
+  bool exportRays = true;
+
+  
+  InitDevIl();
+  int components = 4;
+  float *buffer = new float[components*mWidth*mHeight];
+  float *pbuffer = buffer;
+  //  - components*mWidth;
+  
+  vector<Ray *> rays;
+
+  long t1 = GetTime();
+
+  Ray ray;
+
+  for (y = 0; y < mHeight; y++) {
+    cout<<"+";
+    for (x = 0; x < mWidth; x++) {
+      SetupRay(ray, x, mHeight - (y + 1));
+      if (tree->CastRay(ray))
+		if (ray.intersections.size()) {
+		  sort(ray.intersections.begin(), ray.intersections.end());
+		  MeshInstance *mesh = (MeshInstance*)ray.intersections[0].mObject;
+		  RgbColor color(1,1,1);
+		  if (mesh->GetMesh()->mMaterial)
+			color = mesh->GetMesh()->mMaterial->mDiffuseColor;
+		  
+		  pbuffer[0] = color.r;
+		  pbuffer[1] = color.g;
+		  pbuffer[2] = color.b;
+		  pbuffer[3] = 1.0f;
+		  
+		}
+      pbuffer+=components;
+      
+	  //      if (exportRays && ( 1||(x==222) && (y==97))) {
+	  //	  if (exportRays && ((x%4==0) && (y%4==0))) {
+	  if (exportRays && ray.intersections.empty()) {
+		Ray *nray = new Ray(ray);
+		rays.push_back(nray);
+	  }
+    }
+    //    pbuffer-=2*components*mWidth;
+  }
+  
+  long t2 = GetTime();
+  cout<<"#RAY_CAST_TIME\n";
+  cout<<TimeDiff(t1, t2)<<"\n";
+  
+  
+  cout<<"Saving image"<<endl;
+  
+  ilRegisterType(IL_FLOAT);
+  ilTexImage(mWidth, mHeight, 1, 4, IL_RGBA, IL_FLOAT, buffer);
+  ilSaveImage((char *const)filename.c_str());
+  delete buffer;
+
+  cout<<"done."<<endl<<flush;
+  
+  Exporter *exporter = NULL;
+  if (1) {
+    exporter = Exporter::GetExporter(filename + "-rays" + ".x3d");
+    exporter->SetFilled();
+	if (sceneGraph)
+	  exporter->ExportScene(sceneGraph->mRoot);
+	
+    //exporter->ExportKdTree(*tree);
+	//exporter->ExportBspTree(*bsptree);
+    exporter->ExportRays(rays, 2000);
+    exporter->SetFilled();
+    int k =0;
+    for (int j=0; j < rays.size(); j++)
+      if (rays[j]->kdLeaves.size()) {
+		Ray *ray = rays[j];
+		int i;
+		if (0)
+		  for (i= 0; i < ray->kdLeaves.size(); i++)
+			exporter->ExportBox(tree->GetBox(ray->kdLeaves[i]));
+		if (0)
+		  for (i= 0; i < ray->testedObjects.size(); i++)
+			exporter->ExportIntersectable(ray->testedObjects[i]);
+		
+      }
+	
+    delete exporter;
+  }
+  
+  return true;
+}
+
+
+void
+Camera::SetupRay(Ray &ray, const int x, const int y)
+{
+  Vector3 xv = mRight*((x - mWidth/2)/(float)mWidth);
+  Vector3 yv = mUp*((y - mHeight/2)/(float)mHeight);
+  Vector3 target = xv + yv + mDirection;
+
+  ray.Clear();
+  ray.Init(mPosition, target, Ray::LOCAL_RAY);
+  
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 612)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 612)
@@ -0,0 +1,3520 @@
+#include "ViewCellsManager.h"
+#include "RenderSimulator.h"
+#include "Mesh.h"
+#include "Triangle3.h"
+#include "ViewCell.h"
+#include "Environment.h"
+#include "X3dParser.h"
+#include "ViewCellBsp.h"
+#include "KdTree.h"
+#include "VspKdTree.h"
+#include "Exporter.h"
+#include "VspBspTree.h"
+#include "ViewCellsParser.h"
+#include "Beam.h"
+#include "VssPreprocessor.h"
+#include "RssPreprocessor.h"
+
+#define SAMPLE_AFTER_SUBDIVISION 0
+
+
+ViewCellsManager::ViewCellsManager():
+mRenderer(NULL),
+mInitialSamples(0),
+mConstructionSamples(0),
+mPostProcessSamples(0),
+mVisualizationSamples(0),
+mTotalAreaValid(false),
+mTotalArea(0.0f),
+mViewCellsFinished(false),
+mMaxPvsSize(9999999),
+mMinPvsSize(0), // one means only empty view cells are invalid
+mMaxPvsRatio(1.0)
+{
+	mViewSpaceBox.Initialize();
+	ParseEnvironment();
+
+	mViewCellsTree = new ViewCellsTree(this);
+}
+
+
+void ViewCellsManager::ParseEnvironment()
+{
+	// visualization stuff
+	environment->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
+	environment->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
+	environment->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
+	bool emptyViewCells = false;
+	environment->GetBoolValue("ViewCells.pruneEmptyViewCells", emptyViewCells);
+	environment->GetBoolValue("ViewCells.processOnlyValidViewCells", mOnlyValidViewCells);
+
+	environment->GetIntValue("ViewCells.Construction.samples", mConstructionSamples);
+	environment->GetIntValue("ViewCells.PostProcess.samples", mPostProcessSamples);
+	environment->GetBoolValue("ViewCells.PostProcess.useRaysForMerge", mUseRaysForMerge);
+
+ 	environment->GetIntValue("ViewCells.Visualization.samples", mVisualizationSamples);
+
+	environment->GetIntValue("ViewCells.Construction.samplesPerPass", mSamplesPerPass);
+	environment->GetBoolValue("ViewCells.exportToFile", mExportViewCells);
+	
+	
+	environment->GetIntValue("ViewCells.active", mNumActiveViewCells);
+	environment->GetBoolValue("ViewCells.PostProcess.compress", mCompressViewCells);
+	environment->GetBoolValue("ViewCells.Visualization.useCuttingPlane", mUseCuttingPlaneForViz);
+
+	environment->GetBoolValue("ViewCells.PostProcess.merge", mMergeViewCells);
+
+	mMinPvsSize = emptyViewCells ? 1 : 0;
+
+	char buf[50];
+	environment->GetStringValue("ViewCells.Visualization.colorCode", buf);
+
+	if (strcmp(buf, "PVS") == 0)
+		mColorCode = 1;
+	else if (strcmp(buf, "MergedLeaves") == 0)
+		mColorCode = 2;
+	else if (strcmp(buf, "MergedTreeDiff") == 0)
+		mColorCode = 3;
+	else
+		mColorCode = 0;
+
+	Debug << "colorCode: " << mColorCode << endl;
+}
+
+
+ViewCellsManager::~ViewCellsManager()
+{
+	DEL_PTR(mRenderer);
+
+	if (!ViewCellsTreeConstructed())
+		CLEAR_CONTAINER(mViewCells);
+	else
+		DEL_PTR(mViewCellsTree);
+
+	CLEAR_CONTAINER(mMeshContainer);
+}
+
+
+int ViewCellsManager::CastPassSamples(const int samplesPerPass, 
+									  const int sampleType, 
+									  VssRayContainer &passSamples) const
+{
+	SimpleRayContainer simpleRays;
+
+	preprocessor->GenerateRays(samplesPerPass,
+							   sampleType,
+							   simpleRays);
+
+	// shoot simple ray and add it to importance samples
+	preprocessor->CastRays(simpleRays, passSamples);
+
+	return (int)passSamples.size();
+}
+
+
+
+/// helper function which destroys rays or copies them into the output ray container
+inline void addOutRays(VssRayContainer &rays, VssRayContainer *outRays)
+{
+	cout << "disposing samples ... ";
+	long startTime = GetTime();
+	int n = (int)rays.size();
+
+	if (outRays)
+	{
+		VssRayContainer::const_iterator it, it_end = rays.end();
+
+		for (it = rays.begin(); it != it_end; ++ it)
+		{
+			outRays->push_back(*it);
+		}
+	}
+	else
+	{
+		CLEAR_CONTAINER(rays);
+	}
+	cout << "finished" << endl;
+	Debug << "disposed " << n << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
+}
+
+
+int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays)
+{
+	int numSamples = 0;
+	SimpleRayContainer simpleRays;
+	
+	VssRayContainer initialSamples;
+
+	cout << "view cell construction: casting " << mInitialSamples << " initial samples ... ";
+	//-- construction rays => we use uniform samples for this
+	CastPassSamples(mInitialSamples, 
+					//Preprocessor::DIRECTION_BASED_DISTRIBUTION,
+					Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION, 
+					initialSamples);
+	
+	cout << "finished" << endl;
+
+	// construct view cells
+	const int numInitialSamples = 
+		ConstructSubdivision(preprocessor->mObjects, initialSamples);
+
+	numSamples += numInitialSamples;
+
+	// rays can be passed or deleted
+	addOutRays(initialSamples, outRays);
+	
+
+	//-- guided rays are used for further sampling
+	const int n = mConstructionSamples; //+initialSamples;
+
+	bool dirSamples = false;
+
+	while (numSamples < n)
+	{
+		cout << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
+		VssRayContainer constructionSamples;
+
+		const int samplingType = 
+			dirSamples ? 
+						Preprocessor::DIRECTION_BASED_DISTRIBUTION :
+				 		Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
+
+		if (0)
+		dirSamples = !dirSamples; // toggle sampling method
+		numSamples += CastPassSamples(mSamplesPerPass, 
+									  samplingType,
+									  constructionSamples);
+
+		cout << "finished" << endl;
+
+		cout << "computing sample contribution for " << (int)constructionSamples.size() << " samples ... ";
+
+		// TODO: leak?
+		if (SAMPLE_AFTER_SUBDIVISION)
+			ComputeSampleContributions(constructionSamples, true, false);
+		cout << "finished" << endl;
+
+
+		addOutRays(constructionSamples, outRays);
+
+		cout << "total samples: " << numSamples << endl;
+	}
+	
+
+	//-- post processing
+	VssRayContainer postProcessSamples;
+
+	//-- construction rays => we use uniform samples for this
+	CastPassSamples(mPostProcessSamples,
+				    Preprocessor::DIRECTION_BASED_DISTRIBUTION, 
+					postProcessSamples);
+	
+	cout << "starting post processing and visualization" << endl;
+
+	// store viewCells for postprocessing
+	const bool storeViewCells = true;
+
+	if (SAMPLE_AFTER_SUBDIVISION)
+		ComputeSampleContributions(postProcessSamples, true, storeViewCells);
+	// merge the view cells
+	PostProcess(preprocessor->mObjects, postProcessSamples);
+
+
+	//-- visualization
+	VssRayContainer visualizationSamples;
+
+	//-- construction rays => we use uniform samples for this
+	CastPassSamples(mVisualizationSamples,
+				    Preprocessor::DIRECTION_BASED_DISTRIBUTION, 
+					visualizationSamples);
+
+	if (SAMPLE_AFTER_SUBDIVISION)
+		ComputeSampleContributions(visualizationSamples, true, storeViewCells);
+
+	//Debug << "visualizationsamples: " << mVisualizationSamples << " " << visualizationSamples.size() << endl;
+	// different visualizations
+	Visualize(preprocessor->mObjects, visualizationSamples);
+
+	addOutRays(visualizationSamples, outRays);
+
+	return numSamples;
+}
+
+
+bool ViewCellsManager::CheckValidity(ViewCell *vc,
+									 int minPvsSize,
+									 int maxPvsSize) const
+{
+
+  if ((vc->GetPvs().GetSize() > maxPvsSize) ||
+	  (vc->GetPvs().GetSize() < minPvsSize))
+	{
+	  return false;
+	}
+
+  return true;
+}
+
+
+bool ViewCellsManager::ViewCellsTreeConstructed() const
+{
+	return mViewCellsTree->GetRoot();
+}
+
+
+void ViewCellsManager::SetValidity(ViewCell *vc,
+								   int minPvs,
+								   int maxPvs) const
+{
+	vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
+}
+
+
+void
+ViewCellsManager::SetValidity(
+							  int minPvsSize,
+							  int maxPvsSize) const
+{
+  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+
+  for (it = mViewCells.begin(); it != it_end; ++ it) {
+	SetValidity(*it, minPvsSize, maxPvsSize);
+  }
+}
+
+void
+ViewCellsManager::SetValidityPercentage(
+										const float minValid,
+										const float maxValid
+										)
+{
+  sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
+
+  int start = mViewCells.size()*minValid;
+  int end = mViewCells.size()*maxValid;
+
+  for (int i=0; i < mViewCells.size(); i++)
+	mViewCells[i]->SetValid(i >= start && i <= end);
+}
+
+int
+ViewCellsManager::CountValidViewcells() const
+{
+  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+  int valid = 0;
+  for (it = mViewCells.begin(); it != it_end; ++ it) {
+	if ((*it)->GetValid())
+	  valid++;
+  }
+  return valid;
+}
+
+
+bool ViewCellsManager::LoadViewCellsGeometry(const string filename)
+{
+	X3dParser parser;
+
+	environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
+
+	bool success = parser.ParseFile(filename, *this);
+	Debug << (int)mViewCells.size() << " view cells loaded" << endl;
+
+	return success;
+}
+
+
+bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
+{
+	viewPoint = mViewSpaceBox.GetRandomPoint();
+
+	return true;
+}
+
+
+float ViewCellsManager::GetViewSpaceVolume()
+{
+	return mViewSpaceBox.GetVolume() * (2.0f * sqr((float)M_PI));
+}
+
+
+bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
+{
+  if (!ViewCellsConstructed())
+	return mViewSpaceBox.IsInside(viewPoint);
+  else {
+	if (!mViewSpaceBox.IsInside(viewPoint))
+	  return false;
+	ViewCell *viewcell = GetViewCell(viewPoint);
+	if (!viewcell || !viewcell->GetValid())
+	  return false;
+  }
+  return true;
+}
+
+
+float
+ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
+											 const bool addRays,
+											 const bool storeViewCells
+											 )
+{
+  // view cells not yet constructed
+  if (!ViewCellsConstructed())
+	return 0.0f;
+
+  VssRayContainer::const_iterator it, it_end = rays.end();
+
+  float sum = 0.0f;
+  for (it = rays.begin(); it != it_end; ++ it) {
+	sum += ComputeSampleContributions(*(*it), addRays, storeViewCells);
+	//ComputeSampleContributions(*(*it), addRays);
+	//	sum += (*it)->mPvsContribution;
+  }
+  return sum;
+}
+
+
+void ViewCellsManager::EvaluateViewCellsStats()
+{
+	mViewCellsStats.Reset();
+
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+		mViewCellsTree->UpdateViewCellsStats(*it, mViewCellsStats);
+	}
+}
+
+
+void ViewCellsManager::EvaluateRenderStatistics(float &totalRenderCost,
+												float &expectedRenderCost, 
+												float &deviation,
+												float &variance,
+												int &totalPvs,
+												float &avgRenderCost)
+{
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+
+
+	//-- compute expected value
+
+	totalRenderCost = 0;
+	totalPvs = 0;
+
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+		ViewCell *vc = *it;
+		totalRenderCost += vc->GetPvs().GetSize() * vc->GetVolume();
+		totalPvs += (int)vc->GetPvs().GetSize();
+	}
+
+	// normalize with view space box
+	totalRenderCost /= mViewSpaceBox.GetVolume();
+	expectedRenderCost = totalRenderCost / (float)mViewCells.size();
+	avgRenderCost = totalPvs / (float)mViewCells.size();
+
+
+	//-- compute standard defiation
+	variance = 0;
+	deviation = 0;
+
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+		ViewCell *vc = *it;
+
+		float renderCost = vc->GetPvs().GetSize() * vc->GetVolume();
+		float dev;
+
+		if (1)
+			dev = fabs(avgRenderCost - (float)vc->GetPvs().GetSize());
+		else
+			dev = fabs(expectedRenderCost - renderCost);
+
+		deviation += dev;
+		variance += dev * dev;
+	}
+
+	variance /= (float)mViewCells.size();
+	deviation /= (float)mViewCells.size();
+}
+
+
+
+void ViewCellsManager::AddViewCell(ViewCell *viewCell)
+{
+	mViewCells.push_back(viewCell);
+}
+
+
+float ViewCellsManager::GetArea(ViewCell *viewCell) const
+{
+	return viewCell->GetArea();
+}
+
+
+float ViewCellsManager::GetVolume(ViewCell *viewCell) const
+{
+	return viewCell->GetVolume();
+}
+
+
+void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
+									   ViewCellContainer &viewCells,
+									   const int maxViewCells) const
+{
+	// maximal max viewcells
+	int limit = maxViewCells > 0 ?
+		Min((int)objects.size(), maxViewCells) : (int)objects.size();
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		Intersectable *object = objects[i];
+
+		// extract the mesh instances
+		if (object->Type() == Intersectable::MESH_INSTANCE)
+		{
+			MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
+
+			ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
+			viewCells.push_back(viewCell);
+		}
+		//TODO: transformed meshes
+	}
+}
+
+
+ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
+											const float height) const
+{
+	// one mesh per view cell
+	Mesh *mesh = new Mesh();
+
+	//-- construct prism
+
+	// bottom
+	mesh->mFaces.push_back(new Face(2,1,0));
+	// top
+    mesh->mFaces.push_back(new Face(3,4,5));
+	// sides
+	mesh->mFaces.push_back(new Face(1, 4, 3, 0));
+	mesh->mFaces.push_back(new Face(2, 5, 4, 1));
+	mesh->mFaces.push_back(new Face(3, 5, 2, 0));
+
+	//--- extrude new vertices for top of prism
+	Vector3 triNorm = baseTri.GetNormal();
+
+	Triangle3 topTri;
+
+	// add base vertices and calculate top vertices
+	for (int i = 0; i < 3; ++ i)
+		mesh->mVertices.push_back(baseTri.mVertices[i]);
+
+	// add top vertices
+	for (int i = 0; i < 3; ++ i)
+		mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
+
+	mesh->Preprocess();
+
+	return GenerateViewCell(mesh);
+}
+
+
+void ViewCellsManager::FinalizeViewCells(const bool createMesh)
+{
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+		Finalize(*it, createMesh);
+	}
+
+	mTotalAreaValid = false;
+}
+
+
+void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
+{
+	// implemented in subclasses
+}
+
+
+ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCell *left, ViewCell *right) const
+{
+	// generate parent view cell
+	ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
+
+	vc->GetPvs() = left->GetPvs();
+	// merge pvs
+	vc->GetPvs().Merge(right->GetPvs());
+
+	//-- merge ray sets
+	if (0)
+	{
+		stable_sort(left->mPiercingRays.begin(), left->mPiercingRays.end());
+		stable_sort(right->mPiercingRays.begin(), right->mPiercingRays.end());
+
+		std::merge(left->mPiercingRays.begin(), left->mPiercingRays.end(),
+				   right->mPiercingRays.begin(), right->mPiercingRays.end(),
+				   vc->mPiercingRays.begin());
+	}
+
+
+	vc->SetupChildLink(left);
+	vc->SetupChildLink(right);
+
+
+	return vc;
+}
+
+
+ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCellContainer &children) const
+{
+	ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
+
+	ViewCellContainer::const_iterator it, it_end = children.end();
+
+	for (it = children.begin(); it != it_end; ++ it)
+	{
+		// merge pvs
+		vc->GetPvs().Merge((*it)->GetPvs());
+
+		vc->SetupChildLink(*it);
+	}
+
+	return vc;
+}
+
+
+void ViewCellsManager::SetRenderer(Renderer *renderer)
+{
+	mRenderer = renderer;
+}
+
+
+ViewCellsTree *ViewCellsManager::GetViewCellsTree()
+{
+	return mViewCellsTree;
+}
+
+
+void ViewCellsManager::SetVisualizationSamples(const int visSamples)
+{
+	mVisualizationSamples = visSamples;
+}
+
+
+void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
+{
+	mConstructionSamples = constructionSamples;
+}
+
+
+void ViewCellsManager::SetInitialSamples(const int initialSamples)
+{
+	mInitialSamples = initialSamples;
+}
+
+
+void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
+{
+	mPostProcessSamples = postProcessSamples;
+}
+
+
+int ViewCellsManager::GetVisualizationSamples() const
+{
+	return mVisualizationSamples;
+}
+
+
+int ViewCellsManager::GetConstructionSamples() const
+{
+	return mConstructionSamples;
+}
+
+
+int ViewCellsManager::GetPostProcessSamples() const
+{
+	return mPostProcessSamples;
+}
+
+
+void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
+{
+  ViewCellContainer::const_iterator it = mViewCells.begin();
+  stat.viewcells = 0;
+  stat.minPvs = 100000000;
+  stat.maxPvs = 0;
+  stat.avgPvs = 0.0f;
+
+  for (; it != mViewCells.end(); ++it) {
+	ViewCell *viewcell = *it;
+	int pvsSize = viewcell->GetPvs().GetSize();
+	if ( pvsSize < stat.minPvs)
+	  stat.minPvs = pvsSize;
+	if (pvsSize > stat.maxPvs)
+	  stat.maxPvs = pvsSize;
+	stat.avgPvs += pvsSize;
+	stat.viewcells++;
+  }
+  if (stat.viewcells)
+	stat.avgPvs/=stat.viewcells;
+}
+
+
+void ViewCellsManager::PrintPvsStatistics(ostream &s)
+{
+  s<<"############# Viewcell PVS STAT ##################\n";
+  PvsStatistics pvsStat;
+  GetPvsStatistics(pvsStat);
+  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
+  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
+  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
+}
+
+
+int ViewCellsManager::CastBeam(Beam &beam)
+{
+	return 0;
+}
+
+
+ViewCellContainer &ViewCellsManager::GetViewCells()
+{
+	return mViewCells;
+}
+
+
+void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
+{
+	mViewSpaceBox = box;
+
+	CreateCuttingPlane();
+	
+	mTotalAreaValid = false;
+}
+
+
+void ViewCellsManager::CreateCuttingPlane()
+{
+	int axis = 0;
+
+	const float factor = 0.65;
+	Vector3 point = mViewSpaceBox.Min() +  mViewSpaceBox.Size() * factor;
+
+	if (mUseCuttingPlaneForViz)
+        environment->GetIntValue("ViewCells.Visualization.cuttingPlaneAxis", axis);
+
+	Vector3 normal(0,0,0);
+	normal[axis] = 1;
+
+	mCuttingPlane = Plane3(normal, point);
+}
+
+
+AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
+{
+	return mViewSpaceBox;
+}
+
+
+void ViewCellsManager::ResetViewCells()
+{
+	mViewCells.clear();
+	
+	CollectViewCells();
+	
+	mViewCellsStats.Reset();
+	EvaluateViewCellsStats();
+
+	// has to be recomputed
+	mTotalAreaValid = false;
+}
+
+
+int ViewCellsManager::GetMaxPvsSize() const
+{
+	return mMaxPvsSize;
+}
+
+
+void
+ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
+{
+  if (!ViewCellsConstructed())
+	return;
+
+  VssRayContainer::const_iterator it, it_end = rays.end();
+
+  for (it = rays.begin(); it != it_end; ++ it) {
+	AddSampleContributions(*(*it));
+  }
+}
+
+
+int ViewCellsManager::GetMinPvsSize() const
+{
+	return mMinPvsSize;
+}
+
+
+
+float ViewCellsManager::GetMaxPvsRatio() const
+{
+	return mMaxPvsRatio;
+}
+
+
+void
+ViewCellsManager::AddSampleContributions(VssRay &ray)
+{
+  // assumes viewcells have been stored...
+  ViewCellContainer *viewcells = &ray.mViewCells;
+  ViewCellContainer::const_iterator it;
+  for (it = viewcells->begin(); it != viewcells->end(); ++it) {
+	ViewCell *viewcell = *it;
+	if (viewcell->GetValid()) {
+	  // if ray not outside of view space
+	  viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
+	}
+  }
+}
+
+
+float ViewCellsManager::ComputeSampleContributions(VssRay &ray,
+												   const bool addRays,
+												   const bool storeViewCells)
+{
+	ViewCellContainer viewcells;
+
+	ray.mPvsContribution = 0;
+	ray.mRelativePvsContribution = 0.0f;
+
+	static Ray hray;
+	hray.Init(ray);
+	//hray.mFlags |= Ray::CULL_BACKFACES;
+	//Ray hray(ray);
+
+	float tmin = 0, tmax = 1.0;
+
+	if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
+		return 0;
+
+	Vector3 origin = hray.Extrap(tmin);
+	Vector3 termination = hray.Extrap(tmax);
+
+	CastLineSegment(origin, termination, viewcells);
+	//Debug << "constribution: " << (int)viewcells.size() << endl;
+
+	// copy viewcells memory efficiently
+	//const bool storeViewcells = !addRays;
+
+	if (storeViewCells)
+	{
+		ray.mViewCells.reserve(viewcells.size());
+		ray.mViewCells = viewcells;
+	}
+
+	ViewCellContainer::const_iterator it = viewcells.begin();
+
+
+  for (; it != viewcells.end(); ++it) {
+	ViewCell *viewcell = *it;
+	if (viewcell->GetValid()) {
+	  // if ray not outside of view space
+	  float contribution;
+	  if (viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
+												   ray.mPdf,
+												   contribution
+												   ))
+		ray.mPvsContribution++;
+	  ray.mRelativePvsContribution += contribution;
+	}
+  }
+
+  if (addRays)
+	for (it = viewcells.begin(); it != viewcells.end(); ++it) {
+	  ViewCell *viewcell = *it;
+	  if (viewcell->GetValid()) {
+		// if ray not outside of view space
+		viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
+	  }
+	}
+
+	return ray.mRelativePvsContribution;
+}
+
+
+void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
+								  const int maxSize,
+								  VssRayContainer &usedRays,
+								  VssRayContainer *savedRays) const
+{
+	const int limit = min(maxSize, (int)sourceRays.size());
+	const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
+
+	VssRayContainer::const_iterator it, it_end = sourceRays.end();
+	for (it = sourceRays.begin(); it != it_end; ++ it)
+	{
+		if (Random(1.0f) < prop)
+			usedRays.push_back(*it);
+		else if (savedRays)
+			savedRays->push_back(*it);
+	}
+}
+
+
+float ViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
+{
+	return mViewCellsTree->GetPvsSize(viewCell) * objRendercost;
+}
+
+
+float ViewCellsManager::GetAccVcArea()
+{
+	// if already computed
+	if (mTotalAreaValid)
+		return mTotalArea;
+
+	mTotalArea = 0;
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+		//Debug << "area: " << GetArea(*it);
+        mTotalArea += GetArea(*it);
+	}
+
+	mTotalAreaValid = true;
+
+	return mTotalArea;
+}
+
+
+void ViewCellsManager::PrintStatistics(ostream &s) const
+{
+	s << mViewCellsStats << endl;
+}
+
+
+void ViewCellsManager::CreateUniqueViewCellIds()
+{
+	for (int i = 0; i < (int)mViewCells.size(); ++ i)
+		mViewCells[i]->SetId(i);
+}
+
+
+void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter) const
+{
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+		if (!mOnlyValidViewCells || (*it)->GetValid())
+		{
+			ExportColor(exporter, *it);		
+			ExportViewCellGeometry(exporter, *it, 
+				mUseCuttingPlaneForViz ? &mCuttingPlane : NULL);
+		}
+	}
+
+}
+
+
+void ViewCellsManager::CreateViewCellMeshes()
+{
+	// convert to meshes
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+		if (!(*it)->GetMesh())
+			CreateMesh(*it);
+	}
+}
+
+
+bool ViewCellsManager::ExportViewCells(const string filename)
+{
+	return false;
+}
+
+
+void ViewCellsManager::CollectViewCells(const int n) 
+{
+	mNumActiveViewCells = n;
+	mViewCells.clear();
+	CollectViewCells();
+}
+
+
+
+/**********************************************************************/
+/*                   BspViewCellsManager implementation               */
+/**********************************************************************/
+
+
+BspViewCellsManager::BspViewCellsManager(BspTree *bspTree):
+ViewCellsManager(), mBspTree(bspTree)
+{
+	environment->GetIntValue("BspTree.Construction.samples", mInitialSamples);
+	mBspTree->SetViewCellsManager(this);
+	mBspTree->mViewCellsTree = mViewCellsTree;
+}
+
+
+bool BspViewCellsManager::ViewCellsConstructed() const
+{
+	return mBspTree->GetRoot() != NULL;
+}
+
+
+ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
+{
+	return new BspViewCell(mesh);
+}
+
+
+int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
+											  const VssRayContainer &rays)
+{
+	// if view cells were already constructed
+	if (ViewCellsConstructed())
+		return 0;
+
+	int sampleContributions = 0;
+
+	// construct view cells using the collected samples
+	RayContainer constructionRays;
+	VssRayContainer savedRays;
+
+	const int limit = min(mInitialSamples, (int)rays.size());
+
+	VssRayContainer::const_iterator it, it_end = rays.end();
+
+	const float prop = (float)limit / ((float)rays.size() + Limits::Small);
+
+	for (it = rays.begin(); it != it_end; ++ it)
+	{
+		if (Random(1.0f) < prop)
+			constructionRays.push_back(new Ray(*(*it)));
+		else
+			savedRays.push_back(*it);
+	}
+
+    if (mViewCells.empty())
+	{
+		// no view cells loaded
+		mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
+		// collect final view cells
+		mBspTree->CollectViewCells(mViewCells);
+	}
+	else
+	{
+		mBspTree->Construct(mViewCells);
+	}
+
+	// destroy rays created only for construction
+	CLEAR_CONTAINER(constructionRays);
+
+	Debug << mBspTree->GetStatistics() << endl;
+
+	//EvaluateViewCellsStats();
+	Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
+
+	// recast rest of the rays
+	ComputeSampleContributions(savedRays, true, false);
+
+
+	ResetViewCells();
+    
+	Debug << "\nView cells after " << (int)savedRays.size() 
+		  << " samples:\n" << mViewCellsStats << endl;
+
+	if (1) // export initial view cells
+	{
+		cout << "exporting initial view cells (=leaves) ... ";
+		Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
+
+		if (exporter)
+		{
+			
+			if (0 && mExportRays)
+				exporter->ExportRays(rays, RgbColor(1, 1, 1));
+
+			
+			if (mExportGeometry)
+				exporter->ExportGeometry(objects);
+
+			//exporter->SetWireframe();
+			exporter->SetFilled();
+			ExportViewCellsForViz(exporter);
+
+
+			delete exporter;
+		}
+		cout << "finished" << endl;
+	}
+
+
+	return sampleContributions;
+}
+
+
+void BspViewCellsManager::CollectViewCells()
+{
+	// view cells tree constructed
+	if (!ViewCellsTreeConstructed())
+	{		
+		mBspTree->CollectViewCells(mViewCells);
+	}
+	else 
+	{
+		// we can use the view cells tree hierarchy to get the right set
+		mViewCellsTree->CollectBestViewCellSet(mViewCells, 
+											   mNumActiveViewCells);
+	}
+}
+
+
+float BspViewCellsManager::GetProbability(ViewCell *viewCell)
+{
+	// compute view cell area as subsititute for probability
+	if (1)
+		return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
+	else
+		return GetArea(viewCell) / GetAccVcArea();
+}
+
+
+
+int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
+										 const Vector3 &termination,
+										 ViewCellContainer &viewcells)
+{
+	return mBspTree->CastLineSegment(origin, termination, viewcells);
+}
+
+
+int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
+									 const VssRayContainer &rays)
+{
+	if (!ViewCellsConstructed())
+	{
+		Debug << "view cells not constructed" << endl;
+		return 0;
+	}
+
+	
+	// view cells already finished before post processing step (i.e. because they were loaded)
+	if (mViewCellsFinished)
+	{
+		FinalizeViewCells(true);
+		EvaluateViewCellsStats();
+
+		return 0;
+	}
+
+	//-- post processing of bsp view cells
+
+    int vcSize = 0;
+	int pvsSize = 0;
+
+	EvaluateViewCellsStats();
+	Debug << "\noriginal view cell partition:\n" << mViewCellsStats << endl;
+
+	mRenderer->RenderScene();
+	SimulationStatistics ss;
+	dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
+
+    Debug << ss << endl;
+
+	
+
+	//-- merge view cells
+	int merged;
+	
+	if (mMergeViewCells)
+	{
+		cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
+		long startTime = GetTime();
+	
+		VssRayContainer postProcessRays;
+		GetRaySets(rays, mPostProcessSamples, postProcessRays);
+
+		merged = mViewCellsTree->ConstructMergeTree(rays, objects);
+
+		//-- stats and visualizations
+		cout << "finished" << endl;
+		cout << "merged " << merged << " view cells in "
+			 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
+
+		Debug << "Postprocessing: Merged " << merged << " view cells in "
+			<< TimeDiff(startTime, GetTime()) *1e-3 << " secs"
+			<< "using " << (int)rays.size() << " samples" << endl << endl;
+	}
+
+    // reset view cells and stats
+	ResetViewCells();
+	Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
+
+	int savedColorCode  = mColorCode;
+	
+	//BspLeaf::NewMail();
+	if (1) // export merged view cells
+	{
+		mColorCode = 0;
+		
+		Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
+		
+
+		cout << "exporting view cells after merge ... ";
+
+		if (exporter)
+		{
+			if (mExportGeometry)
+				exporter->ExportGeometry(objects);
+
+			//exporter->SetWireframe();
+			exporter->SetFilled();
+			ExportViewCellsForViz(exporter);
+
+
+			delete exporter;
+		}
+		cout << "finished" << endl;
+	}
+
+	if (1) // export merged view cells
+	{
+		mColorCode = 1;
+
+		Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
+	
+		cout << "exporting view cells after merge (pvs size) ... ";	
+
+		if (exporter)
+		{
+			//exporter->SetWireframe();
+			
+			if (mExportGeometry)
+				exporter->ExportGeometry(objects);
+
+			//exporter->SetWireframe();
+			exporter->SetFilled();
+			ExportViewCellsForViz(exporter);
+
+			delete exporter;
+		}
+		cout << "finished" << endl;
+	}
+
+	mColorCode = savedColorCode;
+
+	FinalizeViewCells(true);
+	
+	// write view cells to disc
+	if (mExportViewCells)
+	{
+		char buff[100];
+		environment->GetStringValue("ViewCells.filename", buff);
+		string vcFilename(buff);
+
+		ExportViewCells(buff);
+	}
+
+	return merged;
+}
+
+
+BspViewCellsManager::~BspViewCellsManager()
+{
+}
+
+
+int BspViewCellsManager::GetType() const
+{
+	return BSP;
+}
+
+
+void BspViewCellsManager::Visualize(const ObjectContainer &objects,
+									const VssRayContainer &sampleRays)
+{
+	if (!ViewCellsConstructed())
+		return;
+	
+	int savedColorCode = mColorCode;
+
+	
+	
+	if (1) // export final view cells
+	{
+		mColorCode = 1;
+
+		Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
+	
+		cout << "exporting view cells after merge (pvs size) ... ";	
+
+		if (exporter)
+		{
+			//exporter->SetWireframe();
+			
+			if (mExportGeometry)
+				exporter->ExportGeometry(objects);
+
+			//exporter->SetWireframe();
+			exporter->SetFilled();
+			ExportViewCellsForViz(exporter);
+
+			delete exporter;
+		}
+		cout << "finished" << endl;
+	}
+
+	mColorCode = savedColorCode;
+
+	//-- visualization of the BSP splits
+	bool exportSplits = false;
+	environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
+
+	if (exportSplits)
+	{
+		cout << "exporting splits ... ";
+	 	ExportSplits(objects);
+		cout << "finished" << endl;
+	}
+
+	// export single view cells
+	ExportBspPvs(objects);
+}
+
+
+inline bool vc_gt(ViewCell *a, ViewCell *b)
+{
+	return a->GetPvs().GetSize() > b->GetPvs().GetSize();
+}
+
+
+void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
+{
+	Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
+
+	if (exporter)
+	{
+		//exporter->SetFilled();
+
+		if (mExportGeometry)
+			exporter->ExportGeometry(objects);
+
+		Material m;
+		m.mDiffuseColor = RgbColor(1, 0, 0);
+		exporter->SetForcedMaterial(m);
+		exporter->SetWireframe();
+
+		exporter->ExportBspSplits(*mBspTree, true);
+
+		//NOTE: take forced material, else big scenes cannot be viewed
+		m.mDiffuseColor = RgbColor(0, 1, 0);
+		exporter->SetForcedMaterial(m);
+		//exporter->ResetForcedMaterial();
+
+		delete exporter;
+	}
+}
+
+
+void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
+{
+	const int leafOut = 10;
+
+	ViewCell::NewMail();
+
+	//-- some rays for output
+	const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
+
+	cout << "visualization using " << mVisualizationSamples << " samples" << endl;
+	Debug << "\nOutput view cells: " << endl;
+
+	// sort view cells to get largest view cells
+	if (0)
+		stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
+
+	int limit = min(leafOut, (int)mViewCells.size());
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		cout << "creating output for view cell " << i << " ... ";
+		VssRayContainer vcRays;
+		Intersectable::NewMail();
+		ViewCell *vc;
+
+		if (0)
+			vc = mViewCells[i];
+		else
+			vc = mViewCells[Random((int)mViewCells.size())];
+
+		cout << "creating output for view cell " << i << " ... ";
+
+		if(0)
+		{
+			// check whether we can add the current ray to the output rays
+			for (int k = 0; k < raysOut; ++ k)
+			{
+				BspRay *ray = mBspRays[k];
+				for	(int j = 0; j < (int)ray->intersections.size(); ++ j)
+				{
+					BspLeaf *leaf = ray->intersections[j].mLeaf;
+					if (vc == leaf->GetViewCell())
+						vcRays.push_back(ray->vssRay);
+				}
+			}
+		}
+
+		//bspLeaves[j]->Mail();
+		char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
+
+		Exporter *exporter = Exporter::GetExporter(s);
+
+		exporter->SetWireframe();
+
+		Material m;//= RandomMaterial();
+		m.mDiffuseColor = RgbColor(0, 1, 0);
+		exporter->SetForcedMaterial(m);
+
+		ExportViewCellGeometry(exporter, vc);
+		
+		// export rays piercing this view cell
+		exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
+
+		m.mDiffuseColor = RgbColor(1, 0, 0);
+		exporter->SetForcedMaterial(m);
+
+		ObjectPvsMap::const_iterator it,
+			it_end = vc->GetPvs().mEntries.end();
+
+		exporter->SetFilled();
+
+		// output PVS of view cell
+		for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
+		{
+			Intersectable *intersect = (*it).first;
+
+			if (!intersect->Mailed())
+			{
+				Material m = RandomMaterial();
+				exporter->SetForcedMaterial(m);
+
+				exporter->ExportIntersectable(intersect);
+				intersect->Mail();
+			}
+		}
+
+		DEL_PTR(exporter);
+		cout << "finished" << endl;
+	}
+
+	Debug << endl;
+}
+
+
+void BspViewCellsManager::ExportColor(Exporter *exporter,
+									  ViewCell *vc) const
+{
+	const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
+
+	float importance = 0;
+	static Material m;
+
+	switch (mColorCode)
+	{
+	case 0: // Random
+		{
+			if (vcValid)
+			{
+				m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
+				m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
+				m.mDiffuseColor.b = 0.5f + RandomValue(0.0f, 0.5f);
+			}
+			else
+			{
+				m.mDiffuseColor.r = 0.0f;
+				m.mDiffuseColor.g = 1.0f;
+				m.mDiffuseColor.b = 0.0f;
+			}
+
+			exporter->SetForcedMaterial(m);
+			return;
+		}
+		
+	case 1: // pvs
+		{
+			importance = (float)vc->GetPvs().GetSize() /
+				(float)mViewCellsStats.maxPvs;
+
+		}
+		break;
+	case 2: // merges
+		{
+            int lSize = mViewCellsTree->GetSize(vc);
+			importance = (float)lSize / (float)mViewCellsStats.maxLeaves;
+		}
+		//break;
+	case 3: // merge tree differene
+		{
+			// TODO
+			//importance = (float)GetMaxTreeDiff(vc) /
+			//	(float)(mVspBspTree->GetStatistics().maxDepth * 2);
+
+		}
+		break;
+	default:
+		break;
+	}
+
+	// special color code for invalid view cells
+	m.mDiffuseColor.r = importance;
+	m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
+	m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
+
+	//Debug << "importance: " << importance << endl;
+	exporter->SetForcedMaterial(m);
+}
+
+
+void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
+												 ViewCell *vc,
+												 const Plane3 *cuttingPlane) const
+{
+	if (vc->GetMesh())
+	{
+		exporter->ExportMesh(vc->GetMesh());
+		return;
+	}
+
+	BspNodeGeometry geom;
+	mBspTree->ConstructGeometry(vc, geom);
+
+
+	if (cuttingPlane)
+	{
+		BspNodeGeometry front;
+		BspNodeGeometry back;
+
+		geom.SplitGeometry(front,
+						   back,
+						   *cuttingPlane,
+						   mViewSpaceBox, 
+						   0.0001f);
+
+		if ((int)back.mPolys.size() >= 3)
+			exporter->ExportPolygons(back.mPolys);
+	}
+	else
+	{
+		
+		exporter->ExportPolygons(geom.mPolys);
+	}
+}
+
+
+void BspViewCellsManager::CreateMesh(ViewCell *vc)
+{
+	if (vc->GetMesh())
+		delete vc->GetMesh();
+
+	BspNodeGeometry geom;
+	
+	mBspTree->ConstructGeometry(vc, geom);
+
+	Mesh *mesh = new Mesh();
+	geom.AddToMesh(*mesh);
+	vc->SetMesh(mesh);
+	mMeshContainer.push_back(mesh);
+}
+
+
+void BspViewCellsManager::Finalize(ViewCell *viewCell, 
+								   const bool createMesh)
+{
+	CreateMesh(viewCell);
+
+	float area = 0;
+	float volume = 0;
+
+	ViewCellContainer leaves;
+	mViewCellsTree->CollectLeaves(viewCell, leaves);
+
+	ViewCellContainer::const_iterator it, it_end = leaves.end();
+
+	for (it = leaves.begin(); it != it_end; ++ it)
+	{
+		BspNodeGeometry geom;
+		BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
+		mBspTree->ConstructGeometry(leaf, geom);
+
+		area += geom.GetArea();
+		volume += geom.GetVolume();
+	}
+
+	viewCell->SetVolume(volume);
+	viewCell->SetArea(area);
+}
+
+
+ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point) const
+{
+	if (!mBspTree)
+		return NULL;
+
+	if (!mViewSpaceBox.IsInside(point))
+		return NULL;
+	
+	return mBspTree->GetViewCell(point);
+}
+
+
+void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays, 
+												 vector<MergeCandidate> &candidates)
+{
+	cout << "collecting merge candidates ... " << endl;
+
+	if (mUseRaysForMerge)
+	{
+		mBspTree->CollectMergeCandidates(rays, candidates);
+	}
+	else
+	{
+		vector<BspLeaf *> leaves;
+		mBspTree->CollectLeaves(leaves);
+		mBspTree->CollectMergeCandidates(leaves, candidates);
+	}
+
+	cout << "fininshed collecting candidates" << endl;
+}
+
+
+
+bool BspViewCellsManager::ExportViewCells(const string filename)
+{
+	cout << "exporting view cells to xml ... ";
+	std::ofstream stream;
+
+	// for output we need unique ids for each view cell
+	CreateUniqueViewCellIds();
+
+
+	stream.open(filename.c_str());
+	stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
+	stream << "<Visibility_Solution>" << endl;
+
+	//-- the view space bounding box
+	stream << "<ViewSpaceBox" 
+		   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
+		   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
+
+	//-- the type of the view cells hierarchy
+	//stream << "<Hierarchy name=\"bspTree\" />" << endl;
+	stream << "<Hierarchy name=\"vspBspTree\" />" << endl; // write vsp bsp here because can use same tree and is bug free
+	//-- load the view cells itself, i.e., the ids and the pvs
+	stream << "<ViewCells>" << endl;
+
+#if 0
+	
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+		
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+		ExportViewCell(*it, stream);
+#else
+	mViewCellsTree->Export(stream);
+#endif
+
+	stream << "</ViewCells>" << endl;
+
+	//-- load the hierarchy
+	stream << "<Hierarchy>" << endl;
+	mBspTree->Export(stream);
+	stream << endl << "</Hierarchy>" << endl;
+
+	stream << "</Visibility_Solution>" << endl;
+	stream.close();
+
+	cout << "finished" << endl;
+
+	return true;
+}
+
+
+void BspViewCellsManager::AddCurrentViewCellsToHierarchy()
+{
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+		ViewCell *vc = *it;
+		ViewCellContainer leaves;
+		mViewCellsTree->CollectLeaves(vc, leaves);
+		
+		ViewCellContainer::const_iterator lit, lit_end = leaves.end();
+
+		for (lit = leaves.begin(); lit != lit_end; ++ lit)
+		{
+			BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*lit);
+			bspVc->mLeaf->SetViewCell(vc);
+		}
+	}
+}
+
+
+void BspViewCellsManager::CreateMergeHierarchy()
+{
+	TraversalQueue tQueue;
+
+	tQueue.push(TraversalData(mBspTree->GetRoot(), NULL));
+
+	while (!tQueue.empty())
+	{
+		TraversalData tData = tQueue.top();
+		tQueue.pop();
+
+		if (tData.mNode->IsLeaf())
+		{
+			ViewCell *viewCell = dynamic_cast<BspLeaf *>(tData.mNode)->GetViewCell();
+			viewCell->SetMergeCost((float)tData.mNode->mTimeStamp);
+
+			if (tData.mParentViewCell)
+			{
+				tData.mParentViewCell->SetupChildLink(viewCell);
+				// probagate up pvs
+				mViewCellsTree->PropagateUpPvs(viewCell);
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(tData.mNode);
+			ViewCellInterior *viewCellInterior = new ViewCellInterior();
+			viewCellInterior->SetMergeCost((float)tData.mNode->mTimeStamp);
+
+
+			tQueue.push(TraversalData(interior->GetBack(), viewCellInterior));
+			tQueue.push(TraversalData(interior->GetFront(), viewCellInterior));
+
+			if (tData.mParentViewCell)
+				tData.mParentViewCell->SetupChildLink(viewCellInterior);
+		}
+	}
+}
+
+/************************************************************************/
+/*                   KdViewCellsManager implementation                  */
+/************************************************************************/
+
+
+
+KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
+ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
+{
+}
+
+
+float KdViewCellsManager::GetProbability(ViewCell *viewCell)
+{
+	// compute view cell area / volume as subsititute for probability
+	if (0)
+		return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
+	else
+		return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
+}
+
+
+
+
+void KdViewCellsManager::CollectViewCells()
+{
+	//mKdTree->CollectViewCells(mViewCells); TODO
+}
+
+
+int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
+								  const VssRayContainer &rays)
+{
+	// if view cells already constructed
+	if (ViewCellsConstructed())
+		return 0;
+
+	mKdTree->Construct();
+
+	mTotalAreaValid = false;
+	// create the view cells
+	mKdTree->CreateAndCollectViewCells(mViewCells);
+
+	// cast rays
+	ComputeSampleContributions(rays, true, false);
+
+	EvaluateViewCellsStats();
+	Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
+
+	return 0;
+}
+
+
+bool KdViewCellsManager::ViewCellsConstructed() const
+{
+	return mKdTree->GetRoot() != NULL;
+}
+
+int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
+									const VssRayContainer &rays)
+{
+	return 0;
+}
+
+void KdViewCellsManager::Visualize(const ObjectContainer &objects,
+								   const VssRayContainer &sampleRays)
+{
+	if (!ViewCellsConstructed())
+		return;
+
+	// using view cells instead of the kd PVS of objects
+	const bool useViewCells = true;
+	bool exportRays = false;
+
+	int limit = min(mVisualizationSamples, (int)sampleRays.size());
+	const int pvsOut = min((int)objects.size(), 10);
+	VssRayContainer *rays = new VssRayContainer[pvsOut];
+
+	if (useViewCells)
+	{
+		const int leafOut = 10;
+
+		ViewCell::NewMail();
+
+		//-- some rays for output
+		const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
+		Debug << "visualization using " << raysOut << " samples" << endl;
+
+		//-- some random view cells and rays for output
+		vector<KdLeaf *> kdLeaves;
+
+		for (int i = 0; i < leafOut; ++ i)
+			kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
+
+		for (int i = 0; i < kdLeaves.size(); ++ i)
+		{
+			KdLeaf *leaf = kdLeaves[i];
+			RayContainer vcRays;
+
+			cout << "creating output for view cell " << i << " ... ";
+#if 0
+			// check whether we can add the current ray to the output rays
+			for (int k = 0; k < raysOut; ++ k)
+			{
+				Ray *ray = sampleRays[k];
+
+				for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
+				{
+					BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
+
+					if (leaf->GetViewCell() == leaf2->GetViewCell())
+					{
+						vcRays.push_back(ray);
+					}
+				}
+			}
+#endif
+			Intersectable::NewMail();
+
+			ViewCell *vc = leaf->mViewCell;
+
+			//bspLeaves[j]->Mail();
+			char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
+
+			Exporter *exporter = Exporter::GetExporter(s);
+			exporter->SetFilled();
+
+			exporter->SetWireframe();
+			//exporter->SetFilled();
+
+			Material m;//= RandomMaterial();
+			m.mDiffuseColor = RgbColor(1, 1, 0);
+			exporter->SetForcedMaterial(m);
+
+			AxisAlignedBox3 box = mKdTree->GetBox(leaf);
+			exporter->ExportBox(box);
+
+			// export rays piercing this view cell
+			exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
+
+			m.mDiffuseColor = RgbColor(1, 0, 0);
+			exporter->SetForcedMaterial(m);
+
+			// exporter->SetWireframe();
+			exporter->SetFilled();
+
+			ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
+			// output PVS of view cell
+			for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
+			{
+				Intersectable *intersect = (*it).first;
+				if (!intersect->Mailed())
+				{
+					exporter->ExportIntersectable(intersect);
+					intersect->Mail();
+				}
+			}
+
+			DEL_PTR(exporter);
+			cout << "finished" << endl;
+		}
+
+		DEL_PTR(rays);
+	}
+	else // using kd PVS of objects
+	{
+		for (int i = 0; i < limit; ++ i)
+		{
+			VssRay *ray = sampleRays[i];
+
+			// check whether we can add this to the rays
+			for (int j = 0; j < pvsOut; j++)
+			{
+				if (objects[j] == ray->mTerminationObject)
+				{
+					rays[j].push_back(ray);
+				}
+			}
+		}
+
+		if (exportRays)
+		{
+			Exporter *exporter = NULL;
+			exporter = Exporter::GetExporter("sample-rays.x3d");
+			exporter->SetWireframe();
+			exporter->ExportKdTree(*mKdTree);
+
+			for (i=0; i < pvsOut; i++)
+				exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
+
+			exporter->SetFilled();
+
+			delete exporter;
+		}
+
+		for (int k=0; k < pvsOut; k++)
+		{
+			Intersectable *object = objects[k];
+			char s[64];
+			sprintf(s, "sample-pvs%04d.x3d", k);
+
+			Exporter *exporter = Exporter::GetExporter(s);
+			exporter->SetWireframe();
+
+			KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
+			Intersectable::NewMail();
+
+			// avoid adding the object to the list
+			object->Mail();
+			ObjectContainer visibleObjects;
+
+			for (; i != object->mKdPvs.mEntries.end(); i++)
+			{
+				KdNode *node = (*i).first;
+				exporter->ExportBox(mKdTree->GetBox(node));
+
+				mKdTree->CollectObjects(node, visibleObjects);
+			}
+
+			exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
+			exporter->SetFilled();
+
+			for (int j = 0; j < visibleObjects.size(); j++)
+				exporter->ExportIntersectable(visibleObjects[j]);
+
+			Material m;
+			m.mDiffuseColor = RgbColor(1, 0, 0);
+			exporter->SetForcedMaterial(m);
+			exporter->ExportIntersectable(object);
+
+			delete exporter;
+		}
+	}
+}
+
+
+void KdViewCellsManager::ExportColor(Exporter *exporter,
+									 ViewCell *vc) const
+{
+	// TODO
+}
+
+ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
+{
+	return new KdViewCell(mesh);
+}
+
+
+void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
+												ViewCell *vc,
+												const Plane3 *cuttingPlane) const
+{
+	ViewCellContainer leaves;
+
+	mViewCellsTree->CollectLeaves(vc, leaves);
+	ViewCellContainer::const_iterator it, it_end = leaves.end();
+
+	for (it = leaves.begin(); it != it_end; ++ it)
+	{
+		KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
+	
+		exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaf));
+	}
+}
+
+
+int KdViewCellsManager::GetType() const
+{
+	return ViewCellsManager::KD;
+}
+
+
+
+KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
+{
+	KdNode *node = leaf;
+
+	while (node->mParent && node->mDepth > mKdPvsDepth)
+		node = node->mParent;
+	return node;
+}
+
+int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
+										const Vector3 &termination,
+										ViewCellContainer &viewcells)
+{
+	return mKdTree->CastLineSegment(origin, termination, viewcells);
+}
+
+
+void KdViewCellsManager::CreateMesh(ViewCell *vc)
+{
+	// TODO
+}
+
+
+
+void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays, 
+												vector<MergeCandidate> &candidates)
+{
+	// TODO
+}
+
+
+/**********************************************************************/
+/*                   VspKdViewCellsManager implementation             */
+/**********************************************************************/
+
+
+VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree):
+ViewCellsManager(), mVspKdTree(vspKdTree)
+{
+	environment->GetIntValue("VspKdTree.Construction.samples", mInitialSamples);
+	mVspKdTree->SetViewCellsManager(this);
+}
+
+float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
+{
+	// compute view cell area / volume as subsititute for probability
+	if (0)
+		return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
+	else
+		return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
+}
+
+
+
+
+void VspKdViewCellsManager::CollectViewCells()
+{
+	mVspKdTree->CollectViewCells(mViewCells);
+}
+
+
+int VspKdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
+												const VssRayContainer &rays)
+{
+	// if view cells already constructed
+	if (ViewCellsConstructed())
+		return 0;
+
+	VssRayContainer constructionRays;
+	VssRayContainer savedRays;
+
+	GetRaySets(rays,
+			   mInitialSamples,
+			   constructionRays,
+			   &savedRays);
+
+	Debug << "constructing vsp kd tree using "
+		  << (int)constructionRays.size() << " samples" << endl;
+
+	mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
+	Debug << mVspKdTree->GetStatistics() << endl;
+
+	// export leaf building blocks
+	ExportLeaves(objects, rays);
+
+	// finally merge kd leaf building blocks to view cells
+	const int merged = mVspKdTree->MergeViewCells(rays);
+
+	// collapse siblings belonging to the same view cell
+	mVspKdTree->RefineViewCells(rays);
+
+	// collapse siblings belonging to the same view cell
+	mVspKdTree->CollapseTree();
+
+	// evaluale view cell stats
+	ResetViewCells();
+
+	Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
+
+	long startTime = GetTime();
+	// recast rest of rays
+	ComputeSampleContributions(savedRays, true, false);
+
+	Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
+		  << " secs" << endl;
+
+	return merged;
+}
+
+bool VspKdViewCellsManager::ViewCellsConstructed() const
+{
+	return mVspKdTree->GetRoot() != NULL;
+}
+
+
+ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
+{
+	return new VspKdViewCell(mesh);
+}
+
+int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
+									   const VssRayContainer &rays)
+{
+	if (!ViewCellsConstructed())
+		return 0;
+
+	// recalculate stats
+	EvaluateViewCellsStats();
+
+	return 0;
+}
+
+
+void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
+										 const VssRayContainer &sampleRays)
+{
+	if (!ViewCellsConstructed())
+		return;
+
+	//-- export leaf building blocks
+	Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
+	if (!exporter)
+		return;
+
+	if (mExportGeometry)
+		exporter->ExportGeometry(objects);
+	
+	//exporter->SetWireframe();
+	//exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
+	exporter->ExportVspKdTree(*mVspKdTree);
+
+	if (mExportRays)
+	{
+		const float prob = (float)mVisualizationSamples
+			/ ((float)sampleRays.size() + Limits::Small);
+
+		exporter->SetWireframe();
+
+		//-- collect uniformly distributed rays
+		VssRayContainer rays;
+
+		for (int i = 0; i < sampleRays.size(); ++ i)
+		{
+			if (RandomValue(0,1) < prob)
+				rays.push_back(sampleRays[i]);
+		}
+		exporter->ExportRays(rays, RgbColor(1, 0, 0));
+	}
+
+	delete exporter;
+}
+
+void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
+									  const VssRayContainer &sampleRays)
+{
+	if (!ViewCellsConstructed())
+		return;
+
+	//-- export single view cells
+	for (int i = 0; i < 10; ++ i)
+	{
+		char s[64];
+		sprintf(s, "vsp_viewcell%04d.x3d", i);
+		Exporter *exporter = Exporter::GetExporter(s);
+		const int idx =
+			(int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
+
+		VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
+
+		//-- export geometry
+		Material m;
+		m.mDiffuseColor = RgbColor(0, 1, 1);
+
+		exporter->SetForcedMaterial(m);
+		exporter->SetWireframe();
+
+		ExportViewCellGeometry(exporter, vc);
+
+		//-- export stored rays
+		
+		if (mExportRays)
+		{
+			ViewCellContainer leaves;
+			mViewCellsTree->CollectLeaves(vc, leaves);
+
+			ViewCellContainer::const_iterator it,
+				it_end = leaves.end();
+
+			for (it = leaves.begin(); it != it_end; ++ it)
+			{
+				VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(*it);
+				VspKdLeaf *leaf = vspKdVc->mLeaf;
+				AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
+
+				VssRayContainer vssRays;
+
+				VssRayContainer castRays;
+				VssRayContainer initRays;
+
+				leaf->GetRays(vssRays);
+
+				VssRayContainer::const_iterator it, it_end = vssRays.end();
+				const float prop = 200.0f / (float)vssRays.size();
+
+				for (it = vssRays.begin(); it != it_end; ++ it)
+				{
+					if (Random(1) < prop)
+						if ((*it)->mTerminationObject == NULL)
+							castRays.push_back(*it);
+						else
+							initRays.push_back(*it);
+				}
+
+				exporter->ExportRays(castRays, RgbColor(1, 0, 0));
+				exporter->ExportRays(initRays, RgbColor(0, 1, 0));
+			}
+		}
+	
+		//-- output PVS of view cell
+		m.mDiffuseColor = RgbColor(1, 0, 0);
+		exporter->SetForcedMaterial(m);
+
+		Intersectable::NewMail();
+
+		ObjectPvsMap::const_iterator it,
+			it_end = vc->GetPvs().mEntries.end();
+
+		exporter->SetFilled();
+
+		for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
+		{
+			Intersectable *intersect = (*it).first;
+
+			if (!intersect->Mailed())
+			{
+				Material m = RandomMaterial();
+				exporter->SetForcedMaterial(m);
+
+				exporter->ExportIntersectable(intersect);
+				intersect->Mail();
+			}
+		}
+
+		delete exporter;
+	}
+
+	//-- export final view cells
+	Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
+
+	//if (exportGeometry) exporter->SetWireframe();
+	//else exporter->SetFilled();
+
+	ExportViewCellsForViz(exporter);
+
+	if (mExportGeometry)
+	{
+		exporter->SetFilled();
+		exporter->ExportGeometry(objects);
+	}
+
+	if (mExportRays)
+	{
+		const float prob = (float)mVisualizationSamples
+			/ ((float)sampleRays.size() + Limits::Small);
+
+		exporter->SetWireframe();
+
+		VssRayContainer rays;
+
+		for (int i = 0; i < sampleRays.size(); ++ i)
+		{
+		  if (RandomValue(0,1) < prob)
+			rays.push_back(sampleRays[i]);
+		}
+		exporter->ExportRays(rays, RgbColor(1, 0, 0));
+	}
+
+	delete exporter;
+}
+
+int VspKdViewCellsManager::GetType() const
+{
+	return VSP_KD;
+}
+
+
+int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
+										   const Vector3 &termination,
+										   ViewCellContainer &viewcells)
+{
+	return mVspKdTree->CastLineSegment(origin, termination, viewcells);
+}
+
+
+void VspKdViewCellsManager::ExportColor(Exporter *exporter,
+										ViewCell *vc) const
+{
+	if (mColorCode == 0) // Random color
+		return;
+
+	float importance = 0;
+
+	switch (mColorCode)
+	{
+	case 1: // pvs
+		{
+			importance = (float)vc->GetPvs().GetSize() /
+				(float)mViewCellsStats.maxPvs;
+		}
+		break;
+	case 2: // merged leaves
+		{
+        	int lSize = mViewCellsTree->GetSize(vc);
+			importance = (float)lSize /
+				(float)mViewCellsStats.maxLeaves;
+		}
+		break;
+	case 3: // merged tree depth difference
+		{
+			//importance = (float)GetMaxTreeDiff(vc) /
+			//	(float)(mVspBspTree->GetStatistics().maxDepth * 2);
+		}
+		break;
+	default:
+		break;
+	}
+
+	Material m;
+	m.mDiffuseColor.b = 1.0f;
+	m.mDiffuseColor.r = importance;
+	m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
+	//Debug << "importance: " << importance << endl;
+	exporter->SetForcedMaterial(m);
+}
+
+
+void VspKdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
+												   ViewCell *vc,
+												   const Plane3 *cuttingPlane) const
+{
+	VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
+
+	Mesh m;
+
+	ViewCellContainer leaves;
+	mViewCellsTree->CollectLeaves(vc, leaves);
+
+	ViewCellContainer::const_iterator it, it_end = leaves.end();
+
+	for (it = leaves.begin(); it != it_end; ++ it)
+	{
+		VspKdLeaf *l = dynamic_cast<VspKdViewCell *>(*it)->mLeaf;
+		mVspKdTree->GetBBox(l).AddBoxToMesh(&m);
+	}
+
+	exporter->ExportMesh(&m);
+}
+
+
+void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
+{
+	//TODO
+}
+
+
+void VspKdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays, 
+												   vector<MergeCandidate> &candidates)
+{
+	// TODO
+}
+
+
+/**************************************************************************/
+/*                   VspBspViewCellsManager implementation                */
+/**************************************************************************/
+
+
+VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree):
+ViewCellsManager(), mVspBspTree(vspBspTree)
+{
+	environment->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
+	mVspBspTree->SetViewCellsManager(this);
+	mVspBspTree->mViewCellsTree = mViewCellsTree;
+}
+
+
+VspBspViewCellsManager::~VspBspViewCellsManager()
+{
+}
+
+
+float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
+{
+	if (0 && mVspBspTree->mUseAreaForPvs)
+		return GetArea(viewCell) / GetAccVcArea();
+	else
+		return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
+}
+
+
+void VspBspViewCellsManager::CollectViewCells()
+{
+	// view cells tree constructed
+	if (!ViewCellsTreeConstructed())
+	{
+		mVspBspTree->CollectViewCells(mViewCells, false);
+	}
+	else 
+	{
+		// we can use the view cells tree hierarchy to get the right set
+		mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
+	}
+
+}
+
+
+
+bool VspBspViewCellsManager::ViewCellsConstructed() const
+{
+	return mVspBspTree->GetRoot() != NULL;
+}
+
+
+ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
+{
+	return new BspViewCell(mesh);
+}
+
+
+/*void VspBspViewCellsManager::CollectNodes(ViewCell *vc, vector<BspNode *>nodes)
+{
+	void ViewCellsTree::CollectLeaves(ViewCell *vc, vector<BspNode *> &nodes) const
+	
+	if (vc->IsLeaf())
+	{
+		BspViewCell *bvc = dynamic_cast<BspViewCell *>(vc);
+		nodes->push_back(bvc->mLeaf);
+	}
+	else
+	{
+		ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+
+		for (it = interior->mChildren.begin; it != it_end; ++ it)
+		{
+			vector<BspNode *> mynodes;
+			CollectNodes(*it, mynodes);
+
+			if (mynodes[0]->GetParent() && (mynodes[0]->GetParent() == mynodes[1]->GetParent()))
+			{
+				nodes.push_back(nodes[0]->GetParent());
+			}
+
+		}
+	}
+}*/
+
+
+int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
+												 const VssRayContainer &rays)
+{
+	// if view cells were already constructed
+	if (ViewCellsConstructed())
+		return 0;
+
+	Debug << "Constructing bsp view cells" << endl;
+
+	int sampleContributions = 0;
+
+	VssRayContainer sampleRays;
+
+	int limit = min (mInitialSamples, (int)rays.size());
+
+	VssRayContainer constructionRays;
+	VssRayContainer savedRays;
+
+	Debug << "samples used for subdivision: " << mInitialSamples 
+		  << " rays: " << (int)rays.size() << endl;
+
+	GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
+
+	Debug << "initial rays: " << (int)constructionRays.size() << endl;
+	Debug << "saved rays: " << (int)savedRays.size() << endl;
+
+	mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
+
+	mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
+
+	Debug << mVspBspTree->GetStatistics() << endl;
+
+	// collapse invalid regions
+	cout << "collapsing invalid tree regions ... ";
+	long startTime = GetTime();
+	int collapsedLeaves = mVspBspTree->CollapseTree();
+	Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3 
+		  << " seconds" << endl;
+
+    cout << "finished" << endl;
+
+	cout << "reseting view cell stats ... ";
+	ResetViewCells();
+	cout << "finished" << endl;
+
+	Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
+
+	if (0) // export initial view cells
+	{
+		cout << "exporting initial view cells (=leaves) ... ";
+		Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
+
+		if (exporter)
+		{
+			if (0 && mExportRays)
+				exporter->ExportRays(rays, RgbColor(1, 1, 1));
+
+			if (mExportGeometry)
+				exporter->ExportGeometry(objects);
+
+			//exporter->SetWireframe();
+			exporter->SetFilled();
+			ExportViewCellsForViz(exporter);
+
+			delete exporter;
+		}
+		cout << "finished" << endl;
+	}
+
+	startTime = GetTime();
+
+	// reset view cells and stats
+	ResetViewCells();
+
+	cout << "Computing remaining ray contributions ... ";
+
+	// recast rest of rays
+	if (SAMPLE_AFTER_SUBDIVISION)
+		ComputeSampleContributions(savedRays, true, false);
+	cout << "finished" << endl;
+
+	Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
+		  << " secs" << endl;
+
+	cout << "construction finished" << endl;
+
+	return sampleContributions;
+}
+
+
+void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
+											const ObjectContainer &objects)
+{
+	//-- post processing of bsp view cells
+    int vcSize = 0;
+	int pvsSize = 0;
+
+	mRenderer->RenderScene();
+	SimulationStatistics ss;
+	dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
+    Debug << ss << endl;
+
+	//-- merge or subdivide view cells
+	int merged = 0;
+	if (mMergeViewCells)
+	{
+		cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
+		long startTime = GetTime();
+
+	
+		// TODO: should be done BEFORE the ray casting
+		merged = mViewCellsTree->ConstructMergeTree(rays, objects);
+
+		//-- stats and visualizations
+		cout << "finished merging" << endl;
+		cout << "merged " << merged << " view cells in "
+			 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
+
+		Debug << "Postprocessing: Merged " << merged << " view cells in "
+			  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
+	}
+
+	int savedColorCode = mColorCode;
+	
+	//BspLeaf::NewMail();
+	if (0) // export merged view cells
+	{
+		mColorCode = 0;
+		cout << "reseting view cells ... ";
+		ResetViewCells();
+
+		cout << "finished" << endl;
+
+		Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
+		Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
+
+		cout << "exporting view cells after merge ... ";
+
+		if (exporter)
+		{
+			if (0)
+				exporter->SetWireframe();
+			else
+				exporter->SetFilled();
+
+			ExportViewCellsForViz(exporter);
+
+			if (mExportGeometry)
+			{
+				Material m;
+				m.mDiffuseColor = RgbColor(0, 1, 0);
+				exporter->SetForcedMaterial(m);
+				exporter->SetFilled();
+
+				exporter->ExportGeometry(objects);
+			}
+
+			delete exporter;
+		}
+		cout << "finished" << endl;
+	}
+
+	if (0) // export merged view cells using pvs coding
+	{
+		mColorCode = 1;
+
+		Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
+	
+		cout << "exporting view cells after merge (pvs size) ... ";	
+
+		if (exporter)
+		{
+			if (0)
+				exporter->SetWireframe();
+			else
+				exporter->SetFilled();
+
+			ExportViewCellsForViz(exporter);
+
+			if (mExportGeometry)
+			{
+				Material m;
+				m.mDiffuseColor = RgbColor(0, 1, 0);
+				exporter->SetForcedMaterial(m);
+				exporter->SetFilled();
+
+				exporter->ExportGeometry(objects);
+			}
+
+			delete exporter;
+		}
+		cout << "finished" << endl;
+	}
+
+	mColorCode = savedColorCode;
+
+}
+
+
+bool VspBspViewCellsManager::EqualToSpatialNode(ViewCell *viewCell) const
+{
+	return GetSpatialNode(viewCell) != NULL;
+}
+
+
+BspNode *VspBspViewCellsManager::GetSpatialNode(ViewCell *viewCell) const
+{
+	if (!viewCell->IsLeaf())
+	{
+		BspViewCell *bspVc = dynamic_cast<BspViewCell *>(viewCell);
+
+		return bspVc->mLeaf;
+ 	}
+	else
+	{
+		ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
+
+		// cannot be node of binary tree
+		if (interior->mChildren.size() != 2)
+			return NULL;
+
+		ViewCell *left = interior->mChildren[0];
+		ViewCell *right = interior->mChildren[1];
+
+		BspNode *leftNode = GetSpatialNode(left);
+		BspNode *rightNode = GetSpatialNode(right);
+
+		if (leftNode && rightNode && leftNode->IsSibling(rightNode))
+		{
+			return leftNode->GetParent(); 
+		}
+	}
+
+	return NULL;
+}
+
+
+void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
+											 const ObjectContainer &objects)
+{
+	Debug << "render time before refine:" << endl;
+	mRenderer->RenderScene();
+	SimulationStatistics ss;
+	dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
+    Debug << ss << endl;
+
+	cout << "Refining the merged view cells ... ";
+	long startTime = GetTime();
+
+	// refining the merged view cells
+	const int refined = mViewCellsTree->RefineViewCells(rays, objects);
+
+	//-- stats and visualizations
+	cout << "finished" << endl;
+	cout << "refined " << refined << " view cells in "
+		 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
+
+	Debug << "Postprocessing: refined " << refined << " view cells in "
+		  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
+}
+
+
+int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
+										const VssRayContainer &rays)
+{
+	if (!ViewCellsConstructed())
+	{
+		Debug << "postprocess error: no view cells constructed" << endl;
+		return 0;
+	}
+
+
+	// view cells already finished before post processing step 
+	// (i.e. because they were loaded)
+	if (mViewCellsFinished)
+	{
+		FinalizeViewCells(true);
+		EvaluateViewCellsStats();
+
+		return 0;
+	}
+
+
+	// check if new view cells turned invalid
+	SetValidity(mMinPvsSize, mMaxPvsSize); 
+	// update valid view space according to valid view cells
+	mVspBspTree->ValidateTree();
+
+	// recompute view cell statistics
+	mViewCellsStats.Reset();
+	EvaluateViewCellsStats();
+
+	// has to be recomputed
+	mTotalAreaValid = false;
+
+
+	VssRayContainer postProcessRays;
+
+	GetRaySets(rays, mPostProcessSamples, postProcessRays);
+
+	Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
+
+	Debug << "\nview cell partition after sampling:\n" << mViewCellsStats << endl << endl;
+
+	// should maybe be done here to allow merge working with area or volume
+	// and to correct the rendering statistics
+	if (0)
+	{
+		FinalizeViewCells(false);
+	}
+
+	//-- merge the individual view cells
+	MergeViewCells(postProcessRays, objects);
+	
+
+	//-- refines the merged view cells
+	if (0)
+		RefineViewCells(postProcessRays, objects);
+
+	//-- render simulation after merge
+	cout << "\nevaluating bsp view cells render time before compress ... ";
+	dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
+	SimulationStatistics ss;
+	dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
+  
+
+	cout << " finished" << endl;
+	cout << ss << endl;
+	Debug << ss << endl;
+
+
+
+	//-- compression
+
+	if (ViewCellsTreeConstructed() && mCompressViewCells)
+	{
+		int pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
+		Debug << "number of entries before compress: " << pvsEntries << endl;
+
+		mViewCellsTree->CompressViewCellsPvs();
+
+		pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
+		Debug << "number of entries after compress: " << pvsEntries << endl;
+	}
+
+	// collapse sibling leaves that share the same view cell
+	if (0)
+		mVspBspTree->CollapseTree();
+
+	// recompute view cell list and statistics
+	ResetViewCells();
+
+	// real meshes are only contructed only at this stage
+	FinalizeViewCells(true);
+
+	// write view cells to disc
+	if (mExportViewCells)
+	{
+		char buff[100];
+		environment->GetStringValue("ViewCells.filename", buff);
+		string vcFilename(buff);
+
+		ExportViewCells(buff);
+	}
+
+	return 0;
+}
+
+
+int VspBspViewCellsManager::GetType() const
+{
+	return VSP_BSP;
+}
+
+
+void VspBspViewCellsManager::CreateMergeHierarchy()
+{
+	TraversalQueue tQueue;
+
+	tQueue.push(TraversalData(mVspBspTree->GetRoot(), NULL));
+
+	while (!tQueue.empty())
+	{
+		TraversalData tData = tQueue.top();
+		tQueue.pop();
+
+		if (tData.mNode->IsLeaf())
+		{
+			ViewCell *viewCell = dynamic_cast<BspLeaf *>(tData.mNode)->GetViewCell();
+
+			if (tData.mParentViewCell)
+			{
+				tData.mParentViewCell->SetupChildLink(viewCell);
+				// probagate up pvs
+				mViewCellsTree->PropagateUpPvs(viewCell);
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(tData.mNode);
+			ViewCellInterior *viewCellInterior = new ViewCellInterior();
+			
+			tQueue.push(TraversalData(interior->GetBack(), viewCellInterior));
+			tQueue.push(TraversalData(interior->GetFront(), viewCellInterior));
+
+			if (tData.mParentViewCell)
+				tData.mParentViewCell->SetupChildLink(viewCellInterior);
+		}
+	}
+}
+
+
+bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
+{
+	if (!ViewCellsConstructed())
+		return ViewCellsManager::GetViewPoint(viewPoint);
+
+	// TODO: set reasonable limit
+	const int limit = 20;
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		viewPoint = mViewSpaceBox.GetRandomPoint();
+		if (mVspBspTree->ViewPointValid(viewPoint))
+		{
+			return true;
+		}
+	}
+	Debug << "failed to find valid view point, taking " << viewPoint << endl;
+	return false;
+}
+
+
+bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
+{
+  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
+  // validy update in preprocessor for all managers)
+  return ViewCellsManager::ViewPointValid(viewPoint);
+
+  //	return mViewSpaceBox.IsInside(viewPoint) &&
+  //		   mVspBspTree->ViewPointValid(viewPoint);
+}
+
+
+void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
+									   const VssRayContainer &sampleRays)
+{
+	if (!ViewCellsConstructed())
+		return;
+
+	VssRayContainer visRays;
+	GetRaySets(sampleRays, mVisualizationSamples, visRays);
+
+	
+	if (0) // export view cells
+	{	// hack pvs
+		int savedColorCode = mColorCode;
+		mColorCode = 1;
+		Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
+		
+		if (exporter)
+		{
+			cout << "exporting view cells after post process ... ";
+
+			if (0)
+			{
+				exporter->SetWireframe();
+				exporter->ExportBox(mViewSpaceBox);
+				exporter->SetFilled();
+			}
+
+			if (mExportGeometry)
+			{
+				exporter->ExportGeometry(objects);
+			}
+
+			// export rays
+			if (mExportRays)
+			{
+				exporter->ExportRays(visRays, RgbColor(0, 1, 0));
+			}
+
+			ExportViewCellsForViz(exporter);
+			delete exporter;
+			cout << "finished" << endl;
+		}
+
+		mColorCode = savedColorCode;
+	}
+
+	if (0)
+	{
+		cout << "exporting depth map ... ";
+
+		Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
+		if (exporter)
+		{
+			if (1)
+			{
+				exporter->SetWireframe();
+				exporter->ExportBox(mViewSpaceBox);
+				exporter->SetFilled();
+			}
+
+			if (mExportGeometry)
+			{
+				exporter->ExportGeometry(objects);
+			}
+
+			const int maxDepth = mVspBspTree->mBspStats.maxDepth;
+
+			ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
+
+			for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
+			{
+				ViewCell *vc = *vit;
+
+				ViewCellContainer leaves;
+				mViewCellsTree->CollectLeaves(vc, leaves);
+
+				ViewCellContainer::const_iterator lit, lit_end = leaves.end();
+
+				for (lit = leaves.begin(); lit != lit_end; ++ lit)
+				{
+					BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
+
+					Material m; 
+
+					float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
+					m.mDiffuseColor.r = relDepth;
+					m.mDiffuseColor.g = 0.0f;
+					m.mDiffuseColor.b = 1.0f - relDepth;
+
+                    exporter->SetForcedMaterial(m);
+				
+
+					BspNodeGeometry geom;
+					mVspBspTree->ConstructGeometry(leaf, geom);
+					exporter->ExportPolygons(geom.mPolys);
+				}
+			}
+
+			delete exporter;
+		}
+
+
+		cout << "finished" << endl;
+	}
+
+	//-- visualization of the BSP splits
+	bool exportSplits = false;
+	environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
+
+	if (exportSplits)
+	{
+		cout << "exporting splits ... ";
+	 	ExportSplits(objects, visRays);
+		cout << "finished" << endl;
+	}
+
+	//-- export single view cells
+	ExportBspPvs(objects, visRays);
+}
+
+
+void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
+										  const VssRayContainer &rays)
+{
+	Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
+
+	if (exporter)
+	{
+		Material m;
+		m.mDiffuseColor = RgbColor(1, 0, 0);
+		exporter->SetForcedMaterial(m);
+		exporter->SetWireframe();
+
+		exporter->ExportBspSplits(*mVspBspTree, true);
+
+		// take forced material, else big scenes cannot be viewed
+		m.mDiffuseColor = RgbColor(0, 1, 0);
+		exporter->SetForcedMaterial(m);
+		exporter->SetFilled();
+
+		exporter->ResetForcedMaterial();
+
+		// export rays
+		if (mExportRays)
+			exporter->ExportRays(rays, RgbColor(1, 1, 0));
+
+		if (mExportGeometry)
+			exporter->ExportGeometry(objects);
+
+		delete exporter;
+	}
+}
+
+
+void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
+										  const VssRayContainer &rays)
+{
+	const int leafOut = 10;
+
+	ViewCell::NewMail();
+
+	cout << "visualization using " << mVisualizationSamples << " samples" << endl;
+	Debug << "\nOutput view cells: " << endl;
+
+	// sort view cells to visualize the largest view cells
+	if (0)
+		stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
+
+	int limit = min(leafOut, (int)mViewCells.size());
+
+	int raysOut;
+
+	//-- some rays for output
+	if (1)
+		raysOut = min((int)rays.size(), mVisualizationSamples);
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		cout << "creating output for view cell " << i << " ... ";
+
+		VssRayContainer vcRays;
+		Intersectable::NewMail();
+		ViewCell *vc;
+	
+		if (0) // largest view cell pvs first
+			vc = mViewCells[i];
+		else
+			vc = mViewCells[Random((int)mViewCells.size())];
+
+		vector<ViewCell *> leaves;
+		mViewCellsTree->CollectLeaves(vc, leaves);
+
+        if (1)
+		{
+			// check whether we can add the current ray to the output rays
+			for (int k = 0; k < raysOut; ++ k)
+			{
+				VssRay *ray = rays[k];
+				for	(int j = 0; j < (int)ray->mViewCells.size(); ++ j)
+				{
+					ViewCell *rayvc = ray->mViewCells[j];
+
+					if (leaves[0] == rayvc)
+						vcRays.push_back(ray);
+				}
+			}
+		}
+
+		//bspLeaves[j]->Mail();
+		char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
+		Exporter *exporter = Exporter::GetExporter(s);
+		exporter->SetWireframe();
+
+		Material m;//= RandomMaterial();
+		m.mDiffuseColor = RgbColor(0, 1, 0);
+		exporter->SetForcedMaterial(m);
+
+		ExportViewCellGeometry(exporter, vc);
+
+
+		Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc)
+			  << ", piercing rays=" << (int)vcRays.size() << endl;
+			//  << ", leaves=" << (int)vc->mLeaves.size() << endl;
+
+		
+		//-- export rays piercing this view cell
+		if (1)
+		{
+			exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
+		}
+		else
+		{
+
+			ViewCellContainer leaves;
+			mViewCellsTree->CollectLeaves(vc, leaves);
+
+			ViewCellContainer::const_iterator lit, lit_end = leaves.end();
+
+			for (lit = leaves.begin(); lit != lit_end; ++ lit)
+			{
+				BspLeaf *l = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
+				exporter->ExportRays(l->mVssRays);
+			}
+		}
+
+	
+		m.mDiffuseColor = RgbColor(1, 0, 0);
+		exporter->SetForcedMaterial(m);
+
+		ObjectPvsMap::const_iterator it,
+			it_end = vc->GetPvs().mEntries.end();
+
+		exporter->SetFilled();
+
+	
+		// output PVS of view cell
+		for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
+		{
+		
+			Intersectable *intersect = (*it).first;
+
+			if (!intersect->Mailed())
+			{
+				Material m = RandomMaterial();
+				exporter->SetForcedMaterial(m);
+
+				exporter->ExportIntersectable(intersect);
+				intersect->Mail();
+			}
+		}
+
+		
+		DEL_PTR(exporter);
+		cout << "finished" << endl;
+	}
+
+	Debug << endl;
+}
+
+
+int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
+											const Vector3 &termination,
+											ViewCellContainer &viewcells)
+{
+	return mVspBspTree->CastLineSegment(origin, termination, viewcells);
+}
+
+
+void VspBspViewCellsManager::ExportColor(Exporter *exporter,
+										 ViewCell *vc) const
+{
+	const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
+
+	float importance = 0;
+	static Material m;
+
+	switch (mColorCode)
+	{
+	case 0: // Random
+		{
+			if (vcValid)
+			{
+				m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
+				m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
+				m.mDiffuseColor.b = 0.5f + RandomValue(0.f, 0.5f);
+			}
+			else
+			{
+				m.mDiffuseColor.r = 0.0f;
+				m.mDiffuseColor.g = 1.0f;
+				m.mDiffuseColor.b = 0.0f;
+			}
+
+			exporter->SetForcedMaterial(m);
+			return;
+		}
+		
+	case 1: // pvs
+		{
+			importance = (float)vc->GetPvs().GetSize() /
+				(float)mViewCellsStats.maxPvs;
+
+		}
+		break;
+	case 2: // merges
+		{
+            int lSize = mViewCellsTree->GetSize(vc);
+			importance = (float)lSize / (float)mViewCellsStats.maxLeaves;
+		}
+		break;
+	case 3: // merge tree differene
+		{
+			importance = (float)GetMaxTreeDiff(vc) /
+				(float)(mVspBspTree->GetStatistics().maxDepth * 2);
+
+		}
+		break;
+	default:
+		break;
+	}
+
+	// special color code for invalid view cells
+	m.mDiffuseColor.r = importance;
+	m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
+	m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
+
+	//Debug << "importance: " << importance << endl;
+	exporter->SetForcedMaterial(m);
+}
+
+
+void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
+                                                    ViewCell *vc,
+													const Plane3 *cuttingPlane) const
+{
+	if (vc->GetMesh())
+	{
+		exporter->ExportMesh(vc->GetMesh());
+	
+		return;
+	}
+
+	
+	if (cuttingPlane)
+	{
+		ViewCellContainer leaves;
+		mViewCellsTree->CollectLeaves(vc, leaves);
+		ViewCellContainer::const_iterator it, it_end = leaves.end();
+
+		for (it = leaves.begin(); it != it_end; ++ it)
+		{
+			BspNodeGeometry geom;
+
+			BspNodeGeometry front;
+			BspNodeGeometry back;
+
+	
+			BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
+
+			mVspBspTree->ConstructGeometry(leaf, geom);
+			
+			geom.SplitGeometry(front,
+							   back,
+							   *cuttingPlane,
+							   mViewSpaceBox, 
+							   0.0001f);
+
+			if ((int)back.mPolys.size() >= 3)
+				exporter->ExportPolygons(back.mPolys);
+		}
+	}
+	else
+	{
+		BspNodeGeometry geom;
+		mVspBspTree->ConstructGeometry(vc, geom);
+			
+		exporter->ExportPolygons(geom.mPolys);
+	}
+}
+
+
+int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
+{
+	ViewCellContainer leaves;
+	mViewCellsTree->CollectLeaves(vc, leaves);
+
+	int maxDist = 0;
+	
+	// compute max height difference
+	for (int i = 0; i < (int)leaves.size(); ++ i)
+		for (int j = 0; j < (int)leaves.size(); ++ j)
+	{
+		BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
+
+		if (i != j)
+		{
+			BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
+			int dist = mVspBspTree->TreeDistance(leaf, leaf2);
+			if (dist > maxDist)
+				maxDist = dist;
+		}
+	}
+
+	return maxDist;
+}
+
+
+ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
+{
+	if (!mVspBspTree)
+		return NULL;
+
+	if (!mViewSpaceBox.IsInside(point))
+	  return NULL;
+
+	return mVspBspTree->GetViewCell(point);
+}
+
+
+void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
+{
+	if (vc->GetMesh())
+		delete vc->GetMesh();
+
+	
+	BspNodeGeometry geom;
+
+	mVspBspTree->ConstructGeometry(vc, geom);
+	
+	Mesh *mesh = new Mesh();
+	geom.AddToMesh(*mesh);
+	vc->SetMesh(mesh);
+	mMeshContainer.push_back(mesh);
+}
+
+
+ViewCellsManager *ViewCellsManager::LoadViewCells(const string filename, 
+												  ObjectContainer *objects)
+{
+	ViewCellsParser parser;
+
+	ViewCellsManager *vm = NULL;
+
+	if (parser.ParseFile(filename, &vm, objects))
+	{
+		//vm->PrepareLoadedViewCells();
+		vm->ResetViewCells();
+
+		vm->mViewCellsFinished = true;
+		vm->mMaxPvsSize = (int)objects->size();
+
+		vm->FinalizeViewCells(true);
+
+		Debug << (int)vm->mViewCells.size() << " view cells loaded" << endl;
+	}
+	else
+	{
+		Debug << "failed loading view cells" << endl;
+		DEL_PTR(vm);
+	}
+
+
+	return vm;
+}
+
+
+inline bool ilt(Intersectable *obj1, Intersectable *obj2)
+{
+	return obj1->mId < obj2->mId;
+}
+
+
+bool VspBspViewCellsManager::ExportViewCells(const string filename)
+{
+	cout << "exporting view cells to xml ... ";
+	std::ofstream stream;
+
+	// for output we need unique ids for each view cell
+	CreateUniqueViewCellIds();
+
+
+	stream.open(filename.c_str());
+	stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
+	stream << "<Visibility_Solution>" << endl;
+
+	//-- the view space bounding box
+	stream << "<ViewSpaceBox" 
+		   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
+		   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
+
+	//-- the type of the view cells hierarchy
+	stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
+
+	//-- load the view cells itself, i.e., the ids and the pvs
+	stream << "<ViewCells>" << endl;
+	
+#if 0
+	
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+		
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+		ExportViewCell(*it, stream);
+#else
+	mViewCellsTree->Export(stream);
+#endif
+
+	stream << "</ViewCells>" << endl;
+
+	//-- load the hierarchy
+	stream << "<Hierarchy>" << endl;
+	mVspBspTree->Export(stream);
+	stream << endl << "</Hierarchy>" << endl;
+
+	stream << "</Visibility_Solution>" << endl;
+	stream.close();
+
+	cout << "finished" << endl;
+
+	return true;
+}
+
+
+int VspBspViewCellsManager::CastBeam(Beam &beam)
+{
+	return mVspBspTree->CastBeam(beam);
+}
+
+
+void VspBspViewCellsManager::Finalize(ViewCell *viewCell, 
+									  const bool createMesh)
+{
+	CreateMesh(viewCell);
+
+	float area = 0;
+	float volume = 0;
+
+	ViewCellContainer leaves;
+	mViewCellsTree->CollectLeaves(viewCell, leaves);
+
+	ViewCellContainer::const_iterator it, it_end = leaves.end();
+
+	for (it = leaves.begin(); it != it_end; ++ it)
+	{
+		BspNodeGeometry geom;
+		BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
+		mVspBspTree->ConstructGeometry(leaf, geom);
+
+		area += geom.GetArea();
+		volume += geom.GetVolume();
+	}
+
+	viewCell->SetVolume(volume);
+	viewCell->SetArea(area);
+}
+
+
+void VspBspViewCellsManager::PrepareLoadedViewCells()
+{
+	// TODO: do I still need this here?
+	if (0)
+	mVspBspTree->RepairViewCellsLeafLists();
+}
+
+
+
+void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays, 
+													vector<MergeCandidate> &candidates)
+{	
+	cout << "collecting merge candidates ... " << endl;
+
+	if (mUseRaysForMerge)
+	{
+		mVspBspTree->CollectMergeCandidates(rays, candidates);
+	}
+	else
+	{
+		vector<BspLeaf *> leaves;
+		mVspBspTree->CollectLeaves(leaves);
+		mVspBspTree->CollectMergeCandidates(leaves, candidates);
+	}
+
+	cout << "fininshed collecting candidates" << endl;
+}
+
+
+void VspBspViewCellsManager::AddCurrentViewCellsToHierarchy()
+{
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+	}
+}
+
+//////////////////////////////////
+ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
+{
+	//TODO
+	return NULL;// new VspBspViewCellsManager();
+}
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 608)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 608)
@@ -0,0 +1,1567 @@
+#include "Mesh.h"
+#include "GlRenderer.h"
+#include "ViewCellsManager.h"
+#include "SceneGraph.h"
+#include "Pvs.h"
+#include "Viewcell.h"
+#include "Beam.h"
+#include "KdTree.h"
+#include "Environment.h"
+
+#include <GL/glext.h>
+#include <Cg/cg.h>
+#include <Cg/cgGL.h>
+
+#include <QVBoxLayout>
+
+static CGcontext sCgContext = NULL;
+static CGprogram sCgFragmentProgram = NULL;
+static CGprofile sCgFragmentProfile;
+
+GLuint frontDepthMap;
+GLuint backDepthMap;
+
+const int depthMapSize = 512;
+static vector<int> sQueries;
+
+GlRendererWidget *rendererWidget = NULL;
+GlDebuggerWidget *debuggerWidget = NULL;
+
+
+#ifdef _WIN32
+PFNGLGENOCCLUSIONQUERIESNVPROC glGenOcclusionQueriesNV;
+PFNGLBEGINOCCLUSIONQUERYNVPROC glBeginOcclusionQueryNV;
+PFNGLENDOCCLUSIONQUERYNVPROC glEndOcclusionQueryNV;
+PFNGLGETOCCLUSIONQUERYUIVNVPROC glGetOcclusionQueryuivNV;
+#endif
+
+GlRenderer::GlRenderer(SceneGraph *sceneGraph,
+					   ViewCellsManager *viewCellsManager,
+					   KdTree *tree):
+  Renderer(sceneGraph, viewCellsManager),
+  mKdTree(tree)
+{
+  mSceneGraph->CollectObjects(&mObjects);
+  mViewPoint = mSceneGraph->GetBox().Center();
+  mViewDirection = Vector3(0,0,1);
+
+  //  timerId = startTimer(10);
+  // debug coords for atlanta
+  //  mViewPoint = Vector3(3473, 6.778, -1699);
+  //  mViewDirection = Vector3(-0.2432, 0, 0.97);
+  
+  mFrame = 0;
+  mWireFrame = false;
+  environment->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace);
+  mSnapErrorFrames = false;
+  mSnapPrefix = "";
+
+}
+
+GlRenderer::~GlRenderer()
+{
+  cerr<<"gl renderer destructor..\n";
+  if (sCgFragmentProgram)
+	cgDestroyProgram(sCgFragmentProgram);
+  if (sCgContext)
+	cgDestroyContext(sCgContext);
+  cerr<<"done."<<endl;
+}
+
+
+static void handleCgError() 
+{
+    Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl;
+    exit(1);
+}
+
+void
+GlRenderer::RenderIntersectable(Intersectable *object)
+{
+
+  glPushAttrib(GL_CURRENT_BIT);
+  if (mUseFalseColors)
+	SetupFalseColor(object->mId);
+  
+
+  switch (object->Type()) {
+  case Intersectable::MESH_INSTANCE:
+	RenderMeshInstance((MeshInstance *)object);
+	break;
+  case Intersectable::VIEW_CELL:
+	  RenderViewCell(dynamic_cast<ViewCell *>(object));
+	  break;
+  default:
+	cerr<<"Rendering this object not yet implemented\n";
+	break;
+  }
+
+  glPopAttrib();
+}
+
+
+void
+GlRenderer::RenderViewCell(ViewCell *vc)
+{
+  if (vc->GetMesh()) {
+
+	if (!mUseFalseColors) {
+	  if (vc->GetValid()) 
+		glColor3f(0,1,0);
+	  else
+		glColor3f(0,0,1);
+	}
+	
+	RenderMesh(vc->GetMesh());
+  } else {
+	// render viewcells in the subtree
+	if (!vc->IsLeaf()) {
+	  ViewCellInterior *vci = (ViewCellInterior *) vc;
+
+	  ViewCellContainer::iterator it = vci->mChildren.begin();
+	  for (; it != vci->mChildren.end(); ++it) {
+		RenderViewCell(*it);
+	  }
+	}
+  }
+}
+
+
+void
+GlRenderer::RenderMeshInstance(MeshInstance *mi)
+{
+  RenderMesh(mi->GetMesh());
+}
+
+void
+GlRenderer::SetupFalseColor(const int id)
+{
+  // swap bits of the color
+  
+  glColor3ub(id&255, (id>>8)&255, (id>>16)&255);
+}
+
+
+int GlRenderer::GetId(int r, int g, int b) const
+{
+	return r + (g << 8) + (b << 16);
+}
+
+void
+GlRenderer::SetupMaterial(Material *m)
+{
+  if (m)
+	glColor3fv(&(m->mDiffuseColor.r));
+}
+
+void
+GlRenderer::RenderMesh(Mesh *mesh)
+{
+  int i = 0;
+
+  if (!mUseFalseColors)
+	SetupMaterial(mesh->mMaterial);
+  
+  for (i=0; i < mesh->mFaces.size(); i++) {
+	if (mWireFrame)
+	  glBegin(GL_LINE_LOOP);
+	else
+	  glBegin(GL_POLYGON);
+
+	Face *face = mesh->mFaces[i];
+	for (int j = 0; j < face->mVertexIndices.size(); j++) {
+	  glVertex3fv(&mesh->mVertices[face->mVertexIndices[j]].x);
+	}
+	glEnd();
+  }
+}
+	
+void
+GlRenderer::InitGL()
+{
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+  glEnable(GL_CULL_FACE);
+  glShadeModel(GL_FLAT);
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_CULL_FACE);
+  
+  glGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC)
+	wglGetProcAddress("glGenOcclusionQueriesNV");
+  glBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC)
+	wglGetProcAddress("glBeginOcclusionQueryNV");
+  glEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC)
+	wglGetProcAddress("glEndOcclusionQueryNV");
+  glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)
+	wglGetProcAddress("glGetOcclusionQueryuivNV");
+
+	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+
+}
+
+void
+GlRendererWidget::RenderInfo()
+{
+  QString s;
+  int vc = 0;
+  if (mViewCellsManager)
+	vc = mViewCellsManager->GetViewCells().size();
+  s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f) viewcells:%04d",
+			mFrame,
+			mViewPoint.x,
+			mViewPoint.y,
+			mViewPoint.z,
+			mViewDirection.x,
+			mViewDirection.y,
+			mViewDirection.z,
+			vc
+			);
+  renderText(0,20,s);
+}
+
+
+void
+GlRenderer::SetupProjection(const int w, const int h)
+{
+  glViewport(0, 0, w, h);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective(70.0, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
+  glMatrixMode(GL_MODELVIEW);
+}
+
+void
+GlRenderer::SetupCamera()
+{
+  Vector3 target = mViewPoint + mViewDirection;
+  Vector3 up(0,1,0);
+  
+  glLoadIdentity();
+  gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z,
+			target.x, target.y, target.z,
+			up.x, up.y, up.z);
+}
+
+void
+GlRendererBuffer::RandomViewPoint()
+{
+  
+  
+  // do not use this function since it could return different viewpoints for
+  // different executions of the algorithm
+
+  //mViewCellsManager->GetViewPoint(mViewPoint);
+
+  while (1) {
+	Vector3 pVector = Vector3(halton.GetNumber(1),
+							  halton.GetNumber(2),
+							  halton.GetNumber(3));
+	
+	mViewPoint =  mSceneGraph->GetBox().GetPoint(pVector);
+	ViewCell *v = mViewCellsManager->GetViewCell(mViewPoint);
+	if (v && v->GetValid())
+	  break;
+	// generate a new vector
+	halton.GenerateNext();
+  }
+  
+  
+  Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4),
+							M_PI*halton.GetNumber(5),
+							0.0f);
+  
+  mViewDirection = Normalize(Vector3(sin(dVector.x),
+									 //									 cos(dVector.y),
+									 0.0f,
+									 cos(dVector.x)));
+  halton.GenerateNext();
+}
+
+
+GlRendererBuffer::GlRendererBuffer(const int w,
+								   const int h,
+								   SceneGraph *sceneGraph,
+								   ViewCellsManager *viewcells,
+								   KdTree *tree):
+QGLPixelBuffer(QSize(w, h)), GlRenderer(sceneGraph, viewcells, tree) {
+ 
+ environment->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames);
+   mPvsErrorBuffer.resize(mPvsStatFrames);
+	 ClearErrorBuffer();
+	   
+	   InitGL();
+		 
+		 }
+
+float
+GlRendererBuffer::GetPixelError()
+{
+  float pErrorPixels = -1.0f;
+
+  glReadBuffer(GL_BACK);
+  
+  //  mUseFalseColors = true;
+  
+  mUseFalseColors = false;
+
+  static int query = -1;
+  unsigned int pixelCount;
+
+  if (query == -1)
+	glGenOcclusionQueriesNV(1, (unsigned int *)&query);
+
+  if (mDetectEmptyViewSpace) {
+	// now check whether any backfacing polygon would pass the depth test
+	SetupCamera();
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	glEnable( GL_CULL_FACE );
+	
+	RenderScene();
+	
+	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+	glDepthMask(GL_FALSE);
+	glDisable( GL_CULL_FACE );
+	
+	glBeginOcclusionQueryNV(query);
+	
+	RenderScene();
+	
+	glEndOcclusionQueryNV();
+	
+	// at this point, if possible, go and do some other computation
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	glDepthMask(GL_TRUE);
+	glEnable( GL_CULL_FACE );
+	
+	// reenable other state
+	glGetOcclusionQueryuivNV(query,
+							 GL_PIXEL_COUNT_NV,
+							 &pixelCount);
+	
+	if (pixelCount > 0)
+	  return -1.0f; // backfacing polygon found -> not a valid viewspace sample
+  } else
+	glDisable( GL_CULL_FACE );
+	
+
+  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
+	
+  if (viewcell) {
+	SetupCamera();
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
+
+	// Render PVS
+	std::map<Intersectable *,
+	  PvsData<Intersectable *>,
+	  LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
+	
+	for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
+	  Intersectable *object = (*it).first;
+	  RenderIntersectable(object);
+	}
+
+	//	glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	mUseFalseColors = true;
+
+	glBeginOcclusionQueryNV(query);
+
+	SetupCamera();
+
+	RenderScene();
+	
+	glEndOcclusionQueryNV();
+	
+
+	unsigned int pixelCount;
+	// reenable other state
+	glGetOcclusionQueryuivNV(query,
+							 GL_PIXEL_COUNT_NV,
+							 &pixelCount);
+	
+	pErrorPixels = ((float)pixelCount)/(GetWidth()*GetHeight());
+	if (mSnapErrorFrames && pErrorPixels > 0.01) {
+	  
+	  char filename[256];
+	  sprintf(filename, "error-frame-%04d-%0.5f.png", mFrame, pErrorPixels);
+	  QImage im = toImage();
+	  im.save(mSnapPrefix + filename, "PNG");
+	  if (1) { //0 && mFrame == 1543) {
+		int x,y;
+		int lastIndex = -1;
+		for (y=0; y < im.height(); y++)
+		  for (x=0; x < im.width(); x++) {
+			QRgb p = im.pixel(x,y);
+			int index = qRed(p) + (qGreen(p)<<8) + (qBlue(p)<<16);
+			if (qGreen(p) != 255 && index!=0) {
+			  if (index != lastIndex) {
+				Debug<<"ei="<<index<<" ";
+				lastIndex = index;
+			  }
+			}
+		  }
+	  }
+
+
+	  mUseFalseColors = false;
+	  glPushAttrib(GL_CURRENT_BIT);
+	  glColor3f(0,1,0);
+	  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	  SetupCamera();
+	  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	  
+	  // Render PVS
+	  std::map<Intersectable *,
+		PvsData<Intersectable *>,
+		LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
+	  
+	  for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
+		Intersectable *object = (*it).first;
+		RenderIntersectable(object);
+	  }
+
+	  im = toImage();
+	  sprintf(filename, "error-frame-%04d-%0.5f-pvs.png", mFrame, pErrorPixels);
+	  im.save(mSnapPrefix + filename, "PNG");
+	  glPopAttrib();
+	}
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+  }
+  
+  return pErrorPixels;
+}
+
+
+void
+GlRendererWidget::SetupProjection(const int w, const int h)
+{
+  if (!mTopView)
+	GlRenderer::SetupProjection(w, h);
+  else {
+	glViewport(0, 0, w, h);
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	gluPerspective(50.0, 1.0, 0.1, 20.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
+	glMatrixMode(GL_MODELVIEW);
+  }
+}
+
+float
+GlRendererWidget::RenderErrors()
+{
+  float pErrorPixels = -1.0f;
+
+  glReadBuffer(GL_BACK);
+  
+  mUseFalseColors = true;
+
+  SetupCamera();
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  
+  double eq[4];
+  eq[0] = mSceneCutPlane.mNormal.x;
+  eq[1] = mSceneCutPlane.mNormal.y;
+  eq[2] = mSceneCutPlane.mNormal.z;
+  eq[3] = mSceneCutPlane.mD;
+  
+  if (mCutScene) {
+	glClipPlane(GL_CLIP_PLANE0, eq);
+    glEnable(GL_CLIP_PLANE0);
+  }
+  
+  if (mDetectEmptyViewSpace) 
+	glEnable( GL_CULL_FACE );
+  else
+	glDisable( GL_CULL_FACE );
+
+  ObjectContainer::const_iterator oi = mObjects.begin();
+  for (; oi != mObjects.end(); oi++)
+	RenderIntersectable(*oi);
+
+  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
+  
+  QImage im1, im2;
+  QImage diff;
+  
+  if (viewcell) {
+	// read back the texture
+	im1 = grabFrameBuffer(true);
+	
+	SetupCamera();
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	
+	std::map<Intersectable *,
+	  PvsData<Intersectable *>,
+	  LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
+	
+	for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
+	  Intersectable *object = (*it).first;
+	  RenderIntersectable(object);
+	}
+
+	// read back the texture
+	im2 = grabFrameBuffer(true);
+	
+	diff = im1;
+	int x, y;
+	int errorPixels = 0;
+	
+	for (y = 0; y < im1.height(); y++)
+	  for (x = 0; x < im1.width(); x++)
+		if (im1.pixel(x, y) == im2.pixel(x, y))
+		  diff.setPixel(x, y, qRgba(0,0,0,0));
+		else {
+		  diff.setPixel(x, y, qRgba(255,128,128,255));
+		  errorPixels++;
+		  
+		}
+	pErrorPixels = ((float)errorPixels)/(im1.height()*im1.width());
+  }
+
+  // now render the pvs again
+  SetupCamera();
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  mUseFalseColors = false;
+	
+  oi = mObjects.begin();
+  for (; oi != mObjects.end(); oi++)
+	RenderIntersectable(*oi);
+
+  // now render im1
+  if (viewcell) {
+	if (1 || mTopView) {
+	  mWireFrame = true;
+	  RenderIntersectable(viewcell);
+	  mWireFrame = false;
+	}
+	
+	// init ortographic projection
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	
+	glLoadIdentity();
+	gluOrtho2D(0, 1.0f, 0, 1.0f);
+	
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+	
+	bindTexture(diff);
+	
+	glPushAttrib(GL_ENABLE_BIT);
+	glEnable( GL_ALPHA_TEST );
+	glDisable( GL_CULL_FACE );
+	glAlphaFunc( GL_GREATER, 0.5 );
+	
+	glEnable( GL_TEXTURE_2D );
+	glBegin(GL_QUADS);
+	
+	glTexCoord2f(0,0);
+	glVertex3f(0,0,0);
+	
+	glTexCoord2f(1,0);
+	glVertex3f( 1, 0, 0);
+	
+	glTexCoord2f(1,1);
+	glVertex3f( 1, 1, 0);
+	
+	glTexCoord2f(0,1);
+	glVertex3f(0, 1, 0);
+	glEnd();
+	
+	glPopAttrib();
+	
+	// restore the projection matrix
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+  }
+
+  glDisable(GL_CLIP_PLANE0);
+
+  return pErrorPixels;
+}
+
+
+bool
+GlRenderer::RenderScene()
+{
+  static int glList = -1;
+  if (glList == -1)
+  {
+	glList = glGenLists(1);
+	glNewList(glList, GL_COMPILE);
+	ObjectContainer::const_iterator oi = mObjects.begin();
+	for (; oi != mObjects.end(); oi++)
+	  RenderIntersectable(*oi);
+	glEndList();
+  }
+  
+  glCallList(glList);
+  
+  return true;
+}
+
+
+void
+GlRendererBuffer::ClearErrorBuffer()
+{
+  for (int i=0; i < mPvsStatFrames; i++) {
+	mPvsErrorBuffer[i] = 1.0f;
+  }
+}
+
+
+void
+GlRendererBuffer::EvalPvsStat()
+{
+  mPvsStat.Reset();
+  halton.Reset();
+
+  makeCurrent();
+  SetupProjection(GetWidth(), GetHeight());
+  
+  for (int i=0; i < mPvsStatFrames; i++) {
+	float err;
+	// set frame id for saving the error buffer
+	mFrame = i;
+	RandomViewPoint();
+
+	// atlanta problematic frames: 325 525 691 1543
+#if 0
+	if (mFrame != 325 &&
+		mFrame != 525 &&
+		mFrame != 691 &&
+		mFrame != 1543)
+	  mPvsErrorBuffer[i] = -1;
+	else {
+	  Debug<<"frame ="<<mFrame<<" vp="<<mViewPoint<<" vd="<<mViewDirection<<endl;
+	}
+#endif
+	if (mPvsErrorBuffer[i] > 0.0f) {
+	  mPvsErrorBuffer[i] = GetPixelError();
+	  cout<<"("<<i<<","<<mPvsErrorBuffer[i]<<")";
+	  //	  swapBuffers();
+	}
+	
+	err = mPvsErrorBuffer[i];
+	
+	if (err >= 0.0f) {
+	  if (err > mPvsStat.maxError)
+		mPvsStat.maxError = err;
+	  mPvsStat.sumError += err;
+	  if (err == 0.0f)
+		mPvsStat.errorFreeFrames++;
+	  mPvsStat.frames++;
+	}
+  }
+
+  glFinish();
+  doneCurrent();
+
+  cout<<endl<<flush;
+  //  mRenderingFinished.wakeAll();
+}
+
+
+
+
+
+void
+GlRendererWidget::mousePressEvent(QMouseEvent *e)
+{
+  int x = e->pos().x();
+  int y = e->pos().y();
+
+  mousePoint.x = x;
+  mousePoint.y = y;
+  
+}
+
+void
+GlRendererWidget::mouseMoveEvent(QMouseEvent *e)
+{
+  float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3;
+  float TURN_SENSITIVITY=0.1f;
+  float TILT_SENSITIVITY=32.0 ;
+  float TURN_ANGLE= M_PI/36.0 ;
+
+  int x = e->pos().x();
+  int y = e->pos().y();
+  
+  if (e->modifiers() & Qt::ControlModifier) {
+	mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0;
+	mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0;
+  } else {
+	mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY);
+	float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY;
+	float angle = atan2(mViewDirection.x, mViewDirection.z);
+	mViewDirection.x = sin(angle+adiff);
+	mViewDirection.z = cos(angle+adiff);
+  }
+  
+  mousePoint.x = x;
+  mousePoint.y = y;
+  
+  updateGL();
+}
+
+void
+GlRendererWidget::mouseReleaseEvent(QMouseEvent *)
+{
+
+
+}
+
+void
+GlRendererWidget::resizeGL(int w, int h)
+{
+  SetupProjection(w, h);
+  updateGL();
+}
+
+void
+GlRendererWidget::paintGL()
+{
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  
+  RenderErrors();
+  RenderInfo();
+
+    if (mRenderViewCells) 
+	RenderViewCells();
+
+  mFrame++;
+}
+
+
+void
+GlRendererWidget::SetupCamera()
+{
+  if (!mTopView)
+	GlRenderer::SetupCamera();
+  else {
+	if (0) {
+	  float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05;
+	  Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x,
+											  -1,
+											  mViewDirection.y);
+	  
+	  Vector3 target = mViewPoint + dist*mViewDirection;
+	  Vector3 up(0,1,0);
+	  
+	  glLoadIdentity();
+	  gluLookAt(pos.x, pos.y, pos.z,
+				target.x, target.y, target.z,
+				up.x, up.y, up.z);
+	} else {
+	  float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*mTopDistance;
+	  Vector3 pos = mViewPoint  + dist*Vector3(0,
+											   1,
+											   0);
+	  
+	  Vector3 target = mViewPoint;
+	  Vector3 up(mViewDirection.x, 0, mViewDirection.z);
+	  
+	  glLoadIdentity();
+	  gluLookAt(pos.x, pos.y, pos.z,
+				target.x, target.y, target.z,
+				up.x, up.y, up.z);
+	  
+	}
+  }
+
+}
+
+void
+GlRendererWidget::keyPressEvent ( QKeyEvent * e )
+{
+  switch (e->key()) {
+  case Qt::Key_T:
+	mTopView = !mTopView;
+	SetupProjection(width(), height());
+	updateGL();
+	break;
+  case Qt::Key_V:
+	mRenderViewCells = !mRenderViewCells;
+	updateGL();
+	break;
+  default:
+	e->ignore();
+	break;
+  }
+}
+
+  
+RendererControlWidget::RendererControlWidget(QWidget * parent, Qt::WFlags f):
+  QWidget(parent, f)
+{
+
+  QVBoxLayout *vl = new QVBoxLayout;
+  setLayout(vl);
+  
+  QWidget *vbox = new QGroupBox("ViewCells", this);
+  layout()->addWidget(vbox);
+  
+  vl = new QVBoxLayout;
+  vbox->setLayout(vl);
+  
+  QSlider *slider = new QSlider(Qt::Horizontal, vbox);
+  vl->addWidget(slider);
+  slider->show();
+  slider->setRange(1, 10000);
+  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+  slider->setValue(500);
+
+  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetViewCellGranularity(int)));
+
+
+
+  QWidget *hbox = new QWidget(vbox);
+  vl->addWidget(hbox);
+  QHBoxLayout *hlayout = new QHBoxLayout;
+  hbox->setLayout(hlayout);
+  
+  QCheckBox *cb = new QCheckBox("Show viewcells", hbox);
+  hlayout->addWidget(cb);
+  cb->setChecked(false);
+  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowViewCells(bool)));
+
+  vbox->resize(800,100);
+
+  
+  vbox = new QGroupBox("Rendering", this);
+  layout()->addWidget(vbox);
+  
+  vl = new QVBoxLayout;
+  vbox->setLayout(vl);
+  
+  slider = new QSlider(Qt::Horizontal, vbox);
+  vbox->layout()->addWidget(slider);
+  slider->show();
+  slider->setRange(0, 1000);
+  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+  slider->setValue(1000);
+
+  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSceneCut(int)));
+
+
+  cb = new QCheckBox("Cut view cells", vbox);
+  vbox->layout()->addWidget(cb);
+  cb->setChecked(false);
+  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutViewCells(bool)));
+
+  cb = new QCheckBox("Cut scene", vbox);
+  vbox->layout()->addWidget(cb);
+  cb->setChecked(false);
+  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutScene(bool)));
+
+  
+  slider = new QSlider(Qt::Horizontal, vbox);
+  vbox->layout()->addWidget(slider);
+  slider->show();
+  slider->setRange(1, 1000);
+  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+  slider->setValue(500);
+  
+  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetTopDistance(int)));
+
+  cb = new QCheckBox("Top View", vbox);
+  vbox->layout()->addWidget(cb);
+  cb->setChecked(false);
+  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetTopView(bool)));
+  
+
+  adjustSize();
+}
+
+GlRendererWidget::GlRendererWidget(SceneGraph *sceneGraph,
+								   ViewCellsManager *viewcells,
+								   KdTree *tree,
+								   QWidget * parent,
+								   const QGLWidget * shareWidget,
+								   Qt::WFlags f
+								   )
+  :
+  GlRenderer(sceneGraph, viewcells, tree), QGLWidget(parent, shareWidget, f)
+{
+  mTopView = false;
+  mRenderViewCells = false;
+  mTopDistance = 1.0f;
+  mCutViewCells = false;
+  mCutScene = false;
+  
+  RendererControlWidget *cw = new RendererControlWidget(NULL);
+  connect(cw, SIGNAL(SetViewCellGranularity(int)), this, SLOT(SetViewCellGranularity(int)));
+  connect(cw, SIGNAL(SetSceneCut(int)), this, SLOT(SetSceneCut(int)));
+  connect(cw, SIGNAL(SetTopDistance(int)), this, SLOT(SetTopDistance(int)));
+  connect(cw, SIGNAL(SetShowViewCells(bool)), this, SLOT(SetShowViewCells(bool)));
+  connect(cw, SIGNAL(SetTopView(bool)), this, SLOT(SetTopView(bool)));
+  connect(cw, SIGNAL(SetCutViewCells(bool)), this, SLOT(SetCutViewCells(bool)));
+  connect(cw, SIGNAL(SetCutScene(bool)), this, SLOT(SetCutScene(bool)));
+  
+  cw->show();
+}
+
+void
+GlRendererWidget::SetViewCellGranularity(int number)
+{
+  mViewCellsManager->CollectViewCells(number);
+  updateGL();
+}
+
+void
+GlRendererWidget::SetSceneCut(int number)
+{
+  // assume the cut plane can only be aligned with xz plane
+  // shift it along y according to number, which is percentage of the bounding
+  // box position
+  if (mViewCellsManager) {
+	AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
+	Vector3 p = box.Min() + (number/1000.0f)*box.Max();
+	mSceneCutPlane.mNormal = Vector3(0,-1,0);
+	mSceneCutPlane.mD = -DotProd(mSceneCutPlane.mNormal, p);
+	updateGL();
+  }
+}
+
+void
+GlRendererWidget::SetTopDistance(int number)
+{
+  mTopDistance = number/1000.0f;
+  updateGL();
+}
+
+void
+GlRendererWidget::RenderViewCells()
+{
+  mUseFalseColors = true;
+
+  SetupCamera();
+  glEnable(GL_CULL_FACE);
+  glCullFace(GL_FRONT);
+  double eq[4];
+  eq[0] = mSceneCutPlane.mNormal.x;
+  eq[1] = mSceneCutPlane.mNormal.y;
+  eq[2] = mSceneCutPlane.mNormal.z;
+  eq[3] = mSceneCutPlane.mD;
+
+  if (mCutViewCells) {
+	glClipPlane(GL_CLIP_PLANE0, eq);
+	glEnable(GL_CLIP_PLANE0);
+  }
+  
+  int i;
+  ViewCellContainer &viewcells = mViewCellsManager->GetViewCells();
+  for (i=0; i < viewcells.size(); i++) {
+	ViewCell *vc = viewcells[i];
+	//	Mesh *m = vc->GetMesh();
+	RgbColor c = vc->GetColor();
+	glColor3f(c.r, c.g, c.b);
+	RenderViewCell(vc);
+  }
+
+  glDisable(GL_CLIP_PLANE0);
+
+}
+
+void GlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject,
+											   Beam &beam,
+											   const int desiredSamples,
+											   BeamSampleStatistics &stat)
+{
+	// TODO: should be moved out of here (not to be done every time)
+	// only back faces are interesting for the depth pass
+	glShadeModel(GL_FLAT);
+	glDisable(GL_LIGHTING);
+
+	// needed to kill the fragments for the front buffer
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GREATER, 0);
+
+	// assumes that the beam is constructed and contains kd-tree nodes
+	// and viewcells which it intersects
+  
+  
+	// Get the number of viewpoints to be sampled
+	// Now it is a sqrt but in general a wiser decision could be made.
+	// The less viewpoints the better for rendering performance, since less passes
+	// over the beam is needed.
+	// The viewpoints could actually be generated outside of the bounding box which
+	// would distribute the 'efective viewpoints' of the object surface and thus
+	// with a few viewpoints better sample the viewpoint space....
+
+	//TODO: comment in
+	//int viewPointSamples = sqrt((float)desiredSamples);
+	int viewPointSamples = max(desiredSamples / (GetWidth() * GetHeight()), 1);
+	
+	// the number of direction samples per pass is given by the number of viewpoints
+	int directionalSamples = desiredSamples / viewPointSamples;
+	
+	Debug << "directional samples: " << directionalSamples << endl;
+	for (int i = 0; i < viewPointSamples; ++ i) 
+	{
+		Vector3 viewPoint = beam.mBox.GetRandomPoint();
+		
+		// perhaps the viewpoint should be shifted back a little bit so that it always lies
+		// inside the source object
+		// 'ideally' the viewpoints would be distributed on the soureObject surface, but this
+        // would require more complicated sampling (perhaps hierarchical rejection sampling of
+		// the object surface is an option here - only the mesh faces which are inside the box
+		// are considered as candidates) 
+		
+		SampleViewpointContributions(sourceObject,
+									 viewPoint,
+									 beam,
+									 directionalSamples,
+									 stat);
+	}
+
+
+	// note:
+	// this routine would be called only if the number of desired samples is sufficiently
+	// large - for other rss tree cells the cpu based sampling is perhaps more efficient
+	// distributing the work between cpu and gpu would also allow us to place more sophisticated
+	// sample distributions (silhouette ones) using the cpu and the jittered once on the GPU
+	// in order that thios scheme is working well the gpu render buffer should run in a separate
+	// thread than the cpu sampler, which would not be such a big problem....
+
+	// disable alpha test again
+	glDisable(GL_ALPHA_TEST);
+}
+
+
+void GlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject,
+													const Vector3 viewPoint,
+													Beam &beam,
+													const int samples,
+                                                    BeamSampleStatistics &stat)
+{
+    // 1. setup the view port to match the desired samples
+	glViewport(0, 0, samples, samples);
+
+	// 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox
+	SetupProjectionForViewPoint(viewPoint, beam, sourceObject);
+
+
+	// 3. reset z-buffer to 0 and render the source object for the beam
+	//    with glCullFace(Enabled) and glFrontFace(GL_CW)
+	//    save result to the front depth map
+	//    the front depth map holds ray origins
+
+
+	// front depth buffer must be initialised to 0
+	float clearDepth;
+	
+	glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
+	glClearDepth(0.0f);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+
+	//glFrontFace(GL_CW);
+	glEnable(GL_CULL_FACE);
+	glCullFace(GL_FRONT);
+	glColorMask(0, 0, 0, 0);
+	
+
+	// stencil is increased where the source object is located
+	glEnable(GL_STENCIL_TEST);	
+	glStencilFunc(GL_ALWAYS, 0x1, 0x1);
+	glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
+
+#if 0
+	static int glSourceObjList = -1;	 
+	if (glSourceObjList != -1) 
+	{
+		glSourceObjList = glGenLists(1);
+		glNewList(glSourceObjList, GL_COMPILE);
+
+		RenderIntersectable(sourceObject);
+	
+		glEndList();
+	}
+	glCallList(glSourceObjList);
+
+#else
+	RenderIntersectable(sourceObject);
+
+#endif	
+
+	 // copy contents of the front depth buffer into depth texture
+	glBindTexture(GL_TEXTURE_2D, frontDepthMap);	
+	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
+
+
+	// reset clear function
+	glClearDepth(clearDepth);
+
+	
+	
+	// 4. set up the termination depth buffer (= standard depth buffer)
+	//    only rays which have non-zero entry in the origin buffer are valid since
+	//    they realy start on the object surface (this is tagged by setting a
+	//    stencil buffer bit at step 3).
+	
+	glStencilFunc(GL_EQUAL, 0x1, 0x1);
+	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	glDepthMask(1);
+
+	glEnable(GL_DEPTH_TEST);
+		
+	glEnable(GL_CULL_FACE);
+	glCullFace(GL_BACK);
+
+	// setup front depth buffer
+	glEnable(GL_TEXTURE_2D);
+	
+	// bind pixel shader implementing the front depth buffer functionality
+	cgGLBindProgram(sCgFragmentProgram);
+	cgGLEnableProfile(sCgFragmentProfile);
+
+
+	// 5. render all objects inside the beam 
+	//    we can use id based false color to read them back for gaining the pvs
+
+	glColorMask(1, 1, 1, 1);
+
+	
+	// if objects not stored in beam => extract objects
+	if (beam.mFlags & !Beam::STORE_OBJECTS)
+	{
+		vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
+
+		Intersectable::NewMail();
+		for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
+		{
+			mKdTree->CollectObjects(*it, beam.mObjects);
+		}
+	}
+
+
+	//    (objects can be compiled to a gl list now so that subsequent rendering for
+	//    this beam is fast - the same hold for step 3)
+	//    Afterwards we have two depth buffers defining the ray origin and termination
+	
+
+#if 0
+	static int glObjList = -1; 
+	if (glObjList != -1) 
+	{
+		glObjList = glGenLists(1);
+		glNewList(glObjList, GL_COMPILE);
+	
+		ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
+		for (it = beam.mObjects.begin(); it != it_end; ++ it)
+		{
+			// render all objects except the source object
+			if (*it != sourceObject)
+				RenderIntersectable(*it);
+		}
+		
+		glEndList();
+	}
+
+	glCallList(glObjList);
+#else
+	ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
+	for (it = beam.mObjects.begin(); it != it_end; ++ it)
+	{	
+		// render all objects except the source object
+		if (*it != sourceObject)
+			RenderIntersectable(*it);
+	}
+#endif
+	
+   
+
+	// 6. Use occlusion queries for all viewcell meshes associated with the beam ->
+	//     a fragment passes if the corresponding stencil fragment is set and its depth is
+	//     between origin and termination buffer
+
+	// create new queries if necessary
+	GenQueries((int)beam.mViewCells.size());
+
+	// check whether any backfacing polygon would pass the depth test?
+	// matt: should check both back /front facing because of dual depth buffer
+	// and danger of cutting the near plane with front facing polys.
+	
+	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+	glDepthMask(GL_FALSE);
+	glDisable(GL_CULL_FACE);
+
+  
+	ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end();
+
+	int queryIdx = 0;
+
+	for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
+	{
+		glBeginOcclusionQueryNV(sQueries[queryIdx ++]);
+
+		RenderIntersectable(*vit);
+		
+		glEndOcclusionQueryNV();
+	}
+
+
+
+	// at this point, if possible, go and do some other computation
+
+
+	
+	// 7. The number of visible pixels is the number of sample rays which see the source
+	//    object from the corresponding viewcell -> remember these values for later update
+	//   of the viewcell pvs - or update immediately?
+
+	queryIdx = 0;
+	unsigned int pixelCount;
+
+	for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
+	{
+		// fetch queries
+		glGetOcclusionQueryuivNV(sQueries[queryIdx ++],
+								 GL_PIXEL_COUNT_NV,
+								 &pixelCount);
+		if (pixelCount)
+			Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl;
+	}
+	
+
+	// 8. Copmpute rendering statistics
+	// In general it is not neccessary to remember to extract all the rays cast. I hope it
+	// would be sufficient to gain only the intergral statistics about the new contributions
+	// and so the rss tree would actually store no new rays (only the initial ones)
+	// the subdivision of the tree would only be driven by the statistics (the glrender could
+	// evaluate the contribution entropy for example)
+	// However might be an option to extract/store only those the rays which made a contribution
+	// (new viewcell has been discovered) or relative contribution greater than a threshold ... 
+
+	ObjectContainer pvsObj;
+	stat.pvsSize = ComputePvs(beam.mObjects, pvsObj);
+	
+	// to gain ray source and termination
+	// copy contents of ray termination buffer into depth texture
+	// and compare with ray source buffer
+#if 0
+	VssRayContainer rays;
+
+	glBindTexture(GL_TEXTURE_2D, backDepthMap);	
+	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
+
+	ComputeRays(Intersectable *sourceObj, rays);
+
+#endif
+
+
+
+	//-- cleanup
+
+
+	// reset gl state
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	glDepthMask(GL_TRUE);
+	glEnable(GL_CULL_FACE);
+	glDisable(GL_STENCIL_TEST);
+	cgGLDisableProfile(sCgFragmentProfile);
+	glDisable(GL_TEXTURE_2D);
+
+	// remove objects from beam
+	if (beam.mFlags & !Beam::STORE_OBJECTS)
+		beam.mObjects.clear();
+}
+
+
+void GlRendererBuffer::GenQueries(const int numQueries)
+{
+	if ((int)sQueries.size() < numQueries)
+	{
+		const int n = numQueries - (int)sQueries.size();
+		unsigned int *newQueries = new unsigned int[n];
+
+		glGenOcclusionQueriesNV(n, (unsigned int *)newQueries);
+
+		for (int i = 0; i < n; ++ i)
+		{
+			sQueries.push_back(newQueries[i]);
+		}
+
+		delete [] newQueries;
+	}
+}
+
+
+void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint, 
+												   const Beam &beam, 
+												   Intersectable *sourceObject)
+{
+	float left, right, bottom, top, znear, zfar;
+
+	beam.ComputePerspectiveFrustum(left, right, bottom, top, znear, zfar,
+								   mSceneGraph->GetBox());
+
+	//Debug << left << " " << right << " " << bottom << " " << top << " " << znear << " " << zfar << endl;
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	glFrustum(left, right, bottom, top, znear, zfar);
+	//glFrustum(-1, 1, -1, 1, 1, 20000);
+
+    const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3f;
+	const Vector3 up = 
+		Normalize(CrossProd(beam.mPlanes[0].mNormal, beam.mPlanes[4].mNormal));
+
+#ifdef _DEBUG
+	Debug << "view point: " << viewPoint << endl;
+	Debug << "eye: " << center << endl;
+	Debug << "up: " << up << endl;
+#endif
+
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+	gluLookAt(viewPoint.x, viewPoint.y, viewPoint.z, 
+			  center.x, center.y, center.z,			  
+			  up.x, up.y, up.z);
+}		
+
+  
+void GlRendererBuffer::InitGL()
+{
+ makeCurrent(); 
+ GlRenderer::InitGL();
+#if 1
+	// initialise dual depth buffer textures
+	glGenTextures(1, &frontDepthMap);
+	glBindTexture(GL_TEXTURE_2D, frontDepthMap);
+	
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize, 
+		depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+	glGenTextures(1, &backDepthMap);
+	glBindTexture(GL_TEXTURE_2D, backDepthMap);
+	
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize, 
+		depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+	// cg initialization
+	cgSetErrorCallback(handleCgError);
+	sCgContext = cgCreateContext();
+	
+	if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
+		sCgFragmentProfile = CG_PROFILE_ARBFP1;
+	else 
+	{
+	  // try FP30
+	  if (cgGLIsProfileSupported(CG_PROFILE_FP30))
+            sCgFragmentProfile = CG_PROFILE_FP30;
+	  else 
+	  {
+		  Debug << "Neither arbfp1 or fp30 fragment profiles supported on this system" << endl;
+		  exit(1);
+	  }
+  }
+
+
+ sCgFragmentProgram = cgCreateProgramFromFile(sCgContext,
+											   CG_SOURCE, "../src/dual_depth.cg",
+											   sCgFragmentProfile,
+											   NULL, 
+											   NULL);
+
+  if (!cgIsProgramCompiled(sCgFragmentProgram))
+	  cgCompileProgram(sCgFragmentProgram);
+
+  cgGLLoadProgram(sCgFragmentProgram);
+  cgGLBindProgram(sCgFragmentProgram);
+
+  Debug << "---- PROGRAM BEGIN ----\n" <<
+	  cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
+
+#endif
+  doneCurrent();
+}
+
+
+void GlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays)
+{
+	for (int i = 0; i < depthMapSize * depthMapSize; ++ i)
+	{
+		//todo glGetTexImage()
+	}
+}
+
+
+
+inline bool ilt(Intersectable *obj1, Intersectable *obj2)
+{
+	return obj1->mId < obj2->mId;
+}
+
+
+int GlRendererBuffer::ComputePvs(ObjectContainer &objects, 
+								 ObjectContainer &pvs) const
+{
+	int pvsSize = 0;
+	QImage image = toImage();
+	Intersectable::NewMail();
+
+	std::stable_sort(objects.begin(), objects.end(), ilt);
+
+	MeshInstance dummy(NULL);
+
+	Intersectable *obj = NULL;
+			
+	for (int x = 0; x < image.width(); ++ x)
+	{
+		for (int y = 0; y < image.height(); ++ y)
+		{
+			QRgb pix = image.pixel(x, y);
+			const int id = GetId(qRed(pix), qGreen(pix), qBlue(pix));
+
+			dummy.SetId(id);
+
+			ObjectContainer::iterator oit =
+				lower_bound(objects.begin(), objects.end(), &dummy, ilt);
+			
+			
+			if (//(oit != oit.end()) && 
+				((*oit)->GetId() == id) && 
+				!obj->Mailed())
+			{
+				obj = *oit;
+				obj->Mail();
+				++ pvsSize;
+				pvs.push_back(obj);
+			}
+		}
+	}
+
+	return pvsSize;
+}
+
+/***********************************************************************/
+/*                     GlDebuggerWidget implementation				   */
+/***********************************************************************/
+
+
+GlDebuggerWidget::GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent)
+      : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf)
+{
+	// create the pbuffer
+    //pbuffer = new QGLPixelBuffer(QSize(512, 512), format(), this);
+    timerId = startTimer(20);
+    setWindowTitle(("OpenGL pbuffers"));
+}
+
+
+GlDebuggerWidget::~GlDebuggerWidget()
+{
+ mRenderBuffer->releaseFromDynamicTexture();
+   glDeleteTextures(1, &dynamicTexture);
+	 
+	 DEL_PTR(mRenderBuffer);
+}
+
+
+void GlDebuggerWidget::initializeGL()
+{
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+
+	glFrustum(-1, 1, -1, 1, 10, 100);
+	glTranslatef(-0.5f, -0.5f, -0.5f);
+	glTranslatef(0.0f, 0.0f, -15.0f);
+	glMatrixMode(GL_MODELVIEW);
+
+	glEnable(GL_CULL_FACE);
+	initCommon();
+	initPbuffer();
+
+}
+
+
+void GlDebuggerWidget::resizeGL(int w, int h)
+{
+	glViewport(0, 0, w, h);
+}
+
+
+void GlDebuggerWidget::paintGL()
+{
+	// draw a spinning cube into the pbuffer..
+	mRenderBuffer->makeCurrent();
+	
+	BeamSampleStatistics stats;
+	mRenderBuffer->SampleBeamContributions(mSourceObject, mBeam, mSamples, stats);
+
+	glFlush();
+
+	// rendering directly to a texture is not supported on X11, unfortunately
+    mRenderBuffer->updateDynamicTexture(dynamicTexture);
+   
+    // and use the pbuffer contents as a texture when rendering the
+    // background and the bouncing cubes
+    makeCurrent();
+    glBindTexture(GL_TEXTURE_2D, dynamicTexture);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    // draw the background
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glLoadIdentity();
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+    glLoadIdentity();
+
+  	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+}
+
+
+void GlDebuggerWidget::initPbuffer()
+{
+	// set up the pbuffer context
+    mRenderBuffer->makeCurrent();
+	/*mRenderBuffer->InitGL();
+
+	glViewport(0, 0, mRenderBuffer->size().width(), mRenderBuffer->size().height());
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	glOrtho(-1, 1, -1, 1, -99, 99);
+	glTranslatef(-0.5f, -0.5f, 0.0f);
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+
+	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/
+	
+	// generate a texture that has the same size/format as the pbuffer
+    dynamicTexture = mRenderBuffer->generateDynamicTexture();
+
+	// bind the dynamic texture to the pbuffer - this is a no-op under X11
+	mRenderBuffer->bindToDynamicTexture(dynamicTexture);
+	makeCurrent();
+}
+
+void GlDebuggerWidget::initCommon()
+{
+	glEnable(GL_TEXTURE_2D);
+	glEnable(GL_DEPTH_TEST);
+
+	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/X3dParserXerces.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/X3dParserXerces.h	(revision 490)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/X3dParserXerces.h	(revision 490)
@@ -0,0 +1,250 @@
+#ifndef _X3D_PARSER_XERCES__H
+#define _X3D_PARSER_XERCES__H
+
+// ---------------------------------------------------------------------------
+//  Includes
+// ---------------------------------------------------------------------------
+#include <xercesc/sax/HandlerBase.hpp>
+#include "Mesh.h"
+
+XERCES_CPP_NAMESPACE_USE
+XERCES_CPP_NAMESPACE_BEGIN
+class AttributeList;
+XERCES_CPP_NAMESPACE_END
+
+class SceneGraphNode;
+class Mesh;
+class Material;
+class ViewCellsManager;
+
+class X3dParseHandlers : public HandlerBase
+{
+public:
+  // -----------------------------------------------------------------------
+  //  Constructors and Destructor
+  // -----------------------------------------------------------------------
+  X3dParseHandlers(SceneGraphNode *root);
+  ~X3dParseHandlers();
+  
+  
+  // -----------------------------------------------------------------------
+  //  Getter methods
+  // -----------------------------------------------------------------------
+  unsigned int GetElementCount()
+  {
+    return mElementCount;
+  }
+  
+  unsigned int GetAttrCount()
+  {
+    return mAttrCount;
+  }
+  
+  unsigned int GetCharacterCount()
+  {
+    return mCharacterCount;
+  }
+  
+  unsigned int GetSpaceCount()
+  {
+    return mSpaceCount;
+  }
+
+
+  // -----------------------------------------------------------------------
+  //  Handlers for the SAX DocumentHandler interface
+  // -----------------------------------------------------------------------
+  void endElement(const XMLCh* const name);
+  void startElement(const XMLCh* const name, AttributeList& attributes);
+  void characters(const XMLCh* const chars, const unsigned int length);
+  void ignorableWhitespace(const XMLCh* const chars, const unsigned int length);
+  void resetDocument();
+
+  SceneGraphNode *mCurrentNode;
+  Mesh *mCurrentMesh;
+  Material *mCurrentMaterial;
+  //int mCurrentObjectId;
+
+  // Handlers for X3D
+  void
+  StartIndexedFaceSet(
+		      AttributeList&  attributes);
+  
+  void
+  EndShape();
+
+  void
+  StartCoordinate(
+		  AttributeList&  attributes);
+
+  void
+  StartMaterial(
+		AttributeList&  attributes);
+  
+  
+  // -----------------------------------------------------------------------
+  //  Handlers for the SAX ErrorHandler interface
+  // -----------------------------------------------------------------------
+  void warning(const SAXParseException& exc);
+  void error(const SAXParseException& exc);
+  void fatalError(const SAXParseException& exc);
+  
+  
+private:
+  // -----------------------------------------------------------------------
+  //  Private data members
+  //
+  //  fAttrCount
+  //  fCharacterCount
+  //  fElementCount
+  //  fSpaceCount
+  //      These are just counters that are run upwards based on the input
+  //      from the document handlers.
+  // -----------------------------------------------------------------------
+  unsigned int    mAttrCount;
+  unsigned int    mCharacterCount;
+  unsigned int    mElementCount;
+  unsigned int    mSpaceCount;
+};
+
+/** Parser handlers for view cell x3d files.
+*/
+class X3dViewCellsParseHandlers : public HandlerBase
+{
+public:
+  // -----------------------------------------------------------------------
+  //  Constructors and Destructor
+  // -----------------------------------------------------------------------
+  X3dViewCellsParseHandlers(ViewCellsManager *viewCellsManager, 
+							float viewCellHeight);
+  ~X3dViewCellsParseHandlers();
+  
+  
+  // -----------------------------------------------------------------------
+  //  Getter methods
+  // -----------------------------------------------------------------------
+  unsigned int GetElementCount()
+  {
+    return mElementCount;
+  }
+  
+  unsigned int GetAttrCount()
+  {
+    return mAttrCount;
+  }
+  
+  unsigned int GetCharacterCount()
+  {
+    return mCharacterCount;
+  }
+  
+  unsigned int GetSpaceCount()
+  {
+    return mSpaceCount;
+  }
+
+
+  // -----------------------------------------------------------------------
+  //  Handlers for the SAX DocumentHandler interface
+  // -----------------------------------------------------------------------
+  void endElement(const XMLCh* const name);
+  void startElement(const XMLCh* const name, AttributeList& attributes);
+  void characters(const XMLCh* const chars, const unsigned int length);
+  void ignorableWhitespace(const XMLCh* const chars, const unsigned int length);
+  void resetDocument();
+
+  ViewCellsManager *mViewCellsManager;
+  float mViewCellHeight;
+
+  VertexIndexContainer mCurrentVertexIndices;
+
+  // Handlers for X3D
+  void
+  StartIndexedFaceSet(
+		      AttributeList&  attributes);
+  
+  void
+  EndShape();
+
+  void
+  StartCoordinate(
+		  AttributeList&  attributes);
+
+  void
+  StartMaterial(
+		AttributeList&  attributes);
+  
+  
+  // -----------------------------------------------------------------------
+  //  Handlers for the SAX ErrorHandler interface
+  // -----------------------------------------------------------------------
+  void warning(const SAXParseException& exc);
+  void error(const SAXParseException& exc);
+  void fatalError(const SAXParseException& exc);
+  
+  
+private:
+  // -----------------------------------------------------------------------
+  //  Private data members
+  //
+  //  fAttrCount
+  //  fCharacterCount
+  //  fElementCount
+  //  fSpaceCount
+  //      These are just counters that are run upwards based on the input
+  //      from the document handlers.
+  // -----------------------------------------------------------------------
+  unsigned int    mAttrCount;
+  unsigned int    mCharacterCount;
+  unsigned int    mElementCount;
+  unsigned int    mSpaceCount;
+};
+
+
+// ---------------------------------------------------------------------------
+//  This is a simple class that lets us do easy (though not terribly efficient)
+//  trancoding of XMLCh data to local code page for display.
+// ---------------------------------------------------------------------------
+class StrX
+{
+public :
+  // -----------------------------------------------------------------------
+  //  Constructors and Destructor
+  // -----------------------------------------------------------------------
+  StrX(const XMLCh* const toTranscode)
+  {
+    // Call the private transcoding method
+    mLocalForm = XMLString::transcode(toTranscode);
+  }
+  
+  ~StrX()
+  {
+    XMLString::release(&mLocalForm);
+  }
+  
+  // -----------------------------------------------------------------------
+  //  Getter methods
+  // -----------------------------------------------------------------------
+  const char* LocalForm() const
+  {
+    return mLocalForm;
+  }
+  
+private :
+  // -----------------------------------------------------------------------
+  //  Private data members
+  //
+  //  fLocalForm
+  //      This is the local code page form of the string.
+  // -----------------------------------------------------------------------
+  char*   mLocalForm;
+};
+
+inline XERCES_STD_QUALIFIER ostream&
+operator<<(XERCES_STD_QUALIFIER ostream& target, const StrX& toDump)
+{
+  target << toDump.LocalForm();
+  return target;
+}
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/MeshKdTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/MeshKdTree.cpp	(revision 469)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/MeshKdTree.cpp	(revision 469)
@@ -0,0 +1,462 @@
+#include <stack>
+#include <algorithm>
+#include <queue>
+#include "Environment.h"
+#include "Mesh.h"
+#include "MeshKdTree.h"
+
+float MeshKdTree::mSplitBorder;
+int MeshKdTree::mTermMaxDepth;
+int MeshKdTree::mTermMinCost;
+float MeshKdTree::mMaxCostRatio;
+float MeshKdTree::mCt_div_ci;
+int MeshKdTree::mSplitMethod;
+
+MeshKdTree::MeshKdTree(Mesh *mesh):mMesh(mesh)
+{
+  mRoot = new MeshKdLeaf;
+  mSplitCandidates = NULL;
+}
+
+void
+MeshKdTree::ParseEnvironment()
+{
+  environment->GetIntValue("MeshKdTree.Termination.maxDepth", mTermMaxDepth);
+  environment->GetIntValue("MeshKdTree.Termination.minCost", mTermMinCost);
+  environment->GetFloatValue("MeshKdTree.Termination.maxCostRatio", mMaxCostRatio);
+  environment->GetFloatValue("MeshKdTree.Termination.ct_div_ci", mCt_div_ci);
+  environment->GetFloatValue("MeshKdTree.splitBorder", mSplitBorder);
+  
+  char splitType[64];
+  environment->GetStringValue("MeshKdTree.splitMethod", splitType);
+  
+  mSplitMethod = SPLIT_SPATIAL_MEDIAN;
+  if (strcmp(splitType, "spatialMedian") == 0)
+    mSplitMethod = SPLIT_SPATIAL_MEDIAN;
+  else
+    if (strcmp(splitType, "objectMedian") == 0)
+      mSplitMethod = SPLIT_OBJECT_MEDIAN;
+    else
+      if (strcmp(splitType, "SAH") == 0)
+	mSplitMethod = SPLIT_SAH;
+      else {
+	cerr<<"Wrong kd split type "<<splitType<<endl;
+	exit(1);
+      }
+}
+
+
+
+int
+MeshKdTree::SelectPlane(MeshKdLeaf *leaf,
+			const AxisAlignedBox3 &box,
+			float &position
+			)
+{
+  int axis = -1;
+  
+  switch (mSplitMethod)
+    {
+    case SPLIT_SPATIAL_MEDIAN: {
+      axis = box.Size().DrivingAxis();
+      position = (box.Min()[axis] + box.Max()[axis])*0.5f;
+      break;
+    }
+    case SPLIT_SAH: {
+      int objectsBack, objectsFront;
+      float costRatio;
+      bool mOnlyDrivingAxis = false;
+      if (mOnlyDrivingAxis) {
+	axis = box.Size().DrivingAxis();
+	costRatio = BestCostRatio(leaf,
+				  box,
+				  axis,
+				  position,
+				  objectsBack,
+				  objectsFront);
+      } else {
+	costRatio = MAX_FLOAT;
+	for (int i=0; i < 3; i++) {
+	  float p;
+	  float r = BestCostRatio(leaf,
+				  box,
+				  i,
+				  p,
+				  objectsBack,
+				  objectsFront);
+	  if (r < costRatio) {
+	    costRatio = r;
+	    axis = i;
+	    position = p;
+	  }
+	}
+      }
+      
+      if (costRatio > mMaxCostRatio) {
+	//	cout<<"Too big cost ratio "<<costRatio<<endl;
+	axis = -1;
+      }
+      break;
+    }
+    
+    }
+  return axis;
+}
+
+MeshKdNode *
+MeshKdTree::SubdivideNode(
+			  MeshKdLeaf *leaf,
+			  MeshKdInterior *parent,
+			  const AxisAlignedBox3 &box,
+			  const int depth,
+			  AxisAlignedBox3 &backBBox,
+			  AxisAlignedBox3 &frontBBox
+			  )
+{
+  
+  if (TerminationCriteriaMet(leaf, depth))
+    return leaf;
+  
+  float position;
+  // select subdivision axis
+  int axis = SelectPlane( leaf, box, position );
+  
+  if (axis == -1) {
+    return leaf;
+  }
+  
+  // add the new nodes to the tree
+  MeshKdInterior *node = new MeshKdInterior;
+  
+  node->mAxis = axis;
+  node->mPosition = position;
+  
+  backBBox = box;
+  frontBBox = box;
+  
+  // first count ray sides
+  
+  backBBox.SetMax(axis, position);
+  frontBBox.SetMin(axis, position);
+
+  vector<int>::const_iterator fi;
+  vector<int> objectsFront, objectsBack;
+  
+  for ( fi = leaf->mFaces.begin();
+	fi != leaf->mFaces.end();
+	fi++) {
+    // determine the side of this ray with respect to the plane
+    AxisAlignedBox3 box = mMesh->GetFaceBox(*fi);
+
+    if (box.Max(axis) > position ) 
+      objectsFront.push_back(*fi);
+    
+    if (box.Min(axis) < position )
+      objectsBack.push_back(*fi);
+  }
+  
+  MeshKdLeaf *back = new MeshKdLeaf(objectsBack);
+  MeshKdLeaf *front = new MeshKdLeaf(objectsFront);
+
+  // replace a link from node's parent
+  if (  parent )
+    parent->ReplaceChildLink(leaf, node);
+  
+  // and setup child links
+  node->SetupChildLinks(back, front);
+  
+  delete leaf;
+  return node;
+}
+
+
+
+
+void
+MeshKdTree::SortSplitCandidates(
+			    MeshKdLeaf *node,
+			    const int axis
+			    )
+{
+  mSplitCandidates->clear();
+  
+  int requestedSize = 2*(int)node->mFaces.size();
+  // creates a sorted split candidates array
+  if (mSplitCandidates->capacity() > 500000 &&
+      requestedSize < (int)(mSplitCandidates->capacity()/10) ) {
+    delete mSplitCandidates;
+    mSplitCandidates = new vector<SortableEntry>;
+  }
+  
+  mSplitCandidates->reserve(requestedSize);
+  
+  vector<int>::const_iterator fi;
+  // insert all queries 
+  for(fi = node->mFaces.begin();
+      fi < node->mFaces.end();
+      fi++) {
+    
+    AxisAlignedBox3 box = mMesh->GetFaceBox(*fi);
+    
+    mSplitCandidates->push_back(SortableEntry(SortableEntry::FACE_MIN,
+					     box.Min(axis),
+					     *fi)
+			       );
+    
+    
+    mSplitCandidates->push_back(SortableEntry(SortableEntry::FACE_MAX,
+					     box.Max(axis),
+					     *fi)
+			       );
+  }
+  
+  stable_sort(mSplitCandidates->begin(), mSplitCandidates->end());
+}
+
+
+float
+MeshKdTree::BestCostRatio(
+			  MeshKdLeaf *node,
+			  const AxisAlignedBox3 &box,
+			  const int axis,
+			  float &position,
+			  int &objectsBack,
+			  int &objectsFront
+			  )
+{
+
+  SortSplitCandidates(node, axis);
+  
+  // go through the lists, count the number of objects left and right
+  // and evaluate the following cost funcion:
+  // C = ct_div_ci  + (ol + or)/queries
+
+  int objectsLeft = 0, objectsRight = (int)node->mFaces.size();
+  
+  float minBox = box.Min(axis);
+  float maxBox = box.Max(axis);
+  float boxArea = box.SurfaceArea();
+  
+  float minBand = minBox + mSplitBorder*(maxBox - minBox);
+  float maxBand = minBox + (1.0f - mSplitBorder)*(maxBox - minBox);
+  
+  float minSum = 1e20f;
+  vector<SortableEntry>::const_iterator ci;
+
+  for(ci = mSplitCandidates->begin();
+      ci != mSplitCandidates->end();
+      ci++) {
+    switch ((*ci).type) {
+    case SortableEntry::FACE_MIN:
+      objectsLeft++;
+      break;
+    case SortableEntry::FACE_MAX:
+      objectsRight--;
+      break;
+    }
+    
+    if ((*ci).value > minBand && (*ci).value < maxBand) {
+      AxisAlignedBox3 lbox = box;
+      AxisAlignedBox3 rbox = box;
+      lbox.SetMax(axis, (*ci).value);
+      rbox.SetMin(axis, (*ci).value);
+
+      float sum = objectsLeft*lbox.SurfaceArea() + objectsRight*rbox.SurfaceArea();
+      
+      //      cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl;
+      //      cout<<"cost= "<<sum<<endl;
+      
+      if (sum < minSum) {
+	minSum = sum;
+	position = (*ci).value;
+	
+	objectsBack = objectsLeft;
+	objectsFront = objectsRight;
+      }
+    }
+  }
+  
+  float oldCost = (float)node->mFaces.size();
+  float newCost = mCt_div_ci + minSum/boxArea;
+  float ratio = newCost/oldCost;
+
+#if 0
+  cout<<"===================="<<endl;
+  cout<<"costRatio="<<ratio<<" pos="<<position<<" t="<<(position - minBox)/(maxBox - minBox)
+      <<"\t o=("<<objectsBack<<","<<objectsFront<<")"<<endl;
+#endif
+  return ratio;
+}
+
+int
+MeshKdTree::CastRay(
+										Ray &ray,
+										MeshInstance *instance
+										)
+{
+  int hits = 0;
+  
+  stack<RayTraversalData> tStack;
+  
+  float maxt = 1e6;
+  float mint = 0;
+  
+  AxisAlignedBox3 box = GetBox();
+  if (!box.GetMinMaxT(ray, &mint, &maxt))
+    return 0;
+
+  if (mint < 0)
+    mint = 0;
+
+
+	if (ray.GetType() == Ray::LOCAL_RAY &&
+			ray.intersections.size() && ray.intersections[0].mT < mint) {
+		return 0;
+	}
+
+  maxt += Limits::Threshold;
+  
+  Vector3 entp = ray.Extrap(mint);
+  Vector3 extp = ray.Extrap(maxt);
+  
+  MeshKdNode *node = mRoot;
+  MeshKdNode *farChild;
+  float position;
+  int axis;
+  
+  while (1) {
+    if (!node->IsLeaf()) {
+      MeshKdInterior *in = (MeshKdInterior *) node;
+      position = in->mPosition;
+      axis = in->mAxis;
+			
+      if (entp[axis] <= position) {
+				if (extp[axis] <= position) {
+					node = in->mBack;
+					// cases N1,N2,N3,P5,Z2,Z3
+					continue;
+				} else {
+					// case N4
+					node = in->mBack;
+					farChild = in->mFront;
+				}
+      }
+      else {
+				if (position <= extp[axis]) {
+					node = in->mFront;
+					// cases P1,P2,P3,N5,Z1
+					continue;
+				} else {
+					node = in->mFront;
+					farChild = in->mBack;
+					// case P4
+				}
+      }
+      // $$ modification 3.5.2004 - hints from Kamil Ghais
+      // case N4 or P4
+      float tdist = (position - ray.GetLoc(axis)) / ray.GetDir(axis);
+      tStack.push(RayTraversalData(farChild, extp, maxt));
+      extp = ray.GetLoc() + ray.GetDir()*tdist;
+      maxt = tdist;
+    } else {
+      // compute intersection with all objects in this leaf
+      MeshKdLeaf *leaf = (MeshKdLeaf *) node;
+      //      cout<<"leaf mfaces size="<<leaf->mFaces.size()<<endl<<flush;
+      hits += instance->CastRay(ray, leaf->mFaces);
+      
+      if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
+				if (ray.intersections[0].mT <= maxt) {
+					break;
+				}
+      
+      // get the next node from the stack
+      if (tStack.empty())
+				break;
+      
+      entp = extp;
+      mint = maxt;
+
+      if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f)
+				break;
+			
+      RayTraversalData &s  = tStack.top();
+      node = s.mNode;
+      extp = s.mExitPoint;
+      maxt = s.mMaxT;
+      tStack.pop();
+    }
+  }
+  
+  
+  return hits;
+}
+
+bool
+MeshKdTree::TerminationCriteriaMet(const MeshKdLeaf *leaf, const int depth)
+{
+  //  cerr<<"\n OBJECTS="<<leaf->mObjects.size()<<endl;
+  return
+    (leaf->mFaces.size() <= mTermMinCost) ||
+    (depth >= mTermMaxDepth);
+  
+}
+
+bool
+MeshKdTree::Construct()
+{
+  if (!mSplitCandidates)
+    mSplitCandidates = new vector<SortableEntry>;
+  
+  // first construct a leaf that will get subdivide
+  MeshKdLeaf *leaf = (MeshKdLeaf *) mRoot;
+
+  mRoot = Subdivide(TraversalData(leaf, NULL, GetBox(), 0));
+  
+  // remove the allocated array
+  delete mSplitCandidates;
+  mSplitCandidates = NULL;
+  
+  return true;
+}
+
+
+MeshKdNode *
+MeshKdTree::Subdivide(const TraversalData &tdata)
+{
+  MeshKdNode *result = NULL;
+  
+  priority_queue<TraversalData> tStack;
+  //  stack<STraversalData> tStack;
+  
+  tStack.push(tdata);
+  AxisAlignedBox3 backBox, frontBox;
+
+  
+  while (!tStack.empty()) {
+
+    TraversalData data = tStack.top();
+    tStack.pop();
+    
+    MeshKdNode *node = SubdivideNode((MeshKdLeaf *) data.mNode,
+				     data.mParent,
+				     data.mBox,
+				     data.mDepth,
+				     backBox,
+				     frontBox
+				     );
+    if (result == NULL)
+      result = node;
+    
+    if (!node->IsLeaf()) {
+
+      MeshKdInterior *interior = (MeshKdInterior *) node;
+      // push the children on the stack
+      tStack.push(TraversalData(interior->mBack, interior, backBox, data.mDepth+1));
+      tStack.push(TraversalData(interior->mFront, interior, frontBox, data.mDepth+1));
+      
+    }
+  }
+  
+  return result;
+
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.cpp	(revision 534)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.cpp	(revision 534)
@@ -0,0 +1,462 @@
+#include "Ray.h"
+#include "Mesh.h"
+#include "MeshKdTree.h"
+#include "Triangle3.h"
+
+int Intersectable::sMailId = 21843194198;
+int Intersectable::sReservedMailboxes = 1;
+
+void
+Mesh::Preprocess()
+{
+	Cleanup();
+	
+	mBox.Initialize();
+  VertexContainer::const_iterator vi = mVertices.begin();
+  for (; vi != mVertices.end(); vi++) {
+    mBox.Include(*vi);
+  }
+  
+  /** true if it is a watertight convex mesh */
+  mIsConvex = false;
+  
+  if (mFaces.size() > MeshKdTree::mTermMinCost) {
+    mKdTree = new MeshKdTree(this);
+    MeshKdLeaf *root = (MeshKdLeaf *)mKdTree->GetRoot();
+    for (int i = 0; i < mFaces.size(); i++)
+      root->mFaces.push_back(i);
+    cout<<"KD";
+    mKdTree->Construct();
+
+    if (mKdTree->GetRoot()->IsLeaf()) {
+      cout<<"d";
+      delete mKdTree;
+			mKdTree = NULL;
+    }
+  }
+}
+
+AxisAlignedBox3
+Mesh::GetFaceBox(const int faceIndex)
+{
+  Face *face = mFaces[faceIndex];
+  AxisAlignedBox3 box;
+  box.SetMin( mVertices[face->mVertexIndices[0]] );
+  box.SetMax(box.Min());
+  for (int i = 1; i < face->mVertexIndices.size(); i++) {
+    box.Include(mVertices[face->mVertexIndices[i]]);
+  }
+  return box;
+}
+
+int
+Mesh::CastRayToFace(
+										const int faceIndex,
+										Ray &ray,
+										float &nearestT,
+										int &nearestFace,
+										Intersectable *instance
+										)
+{
+  float t;
+  int hit = 0;
+  if (RayFaceIntersection(faceIndex, ray, t, nearestT) == Ray::INTERSECTION) {
+    switch (ray.GetType()) {
+    case Ray::GLOBAL_RAY:
+      ray.intersections.push_back(Ray::Intersection(t, instance, faceIndex));
+      hit++;
+      break;
+    case Ray::LOCAL_RAY:
+      nearestT = t;
+      nearestFace = faceIndex;
+      hit++;
+      break;
+    case Ray::LINE_SEGMENT:
+      if (t <= 1.0f) {
+				ray.intersections.push_back(Ray::Intersection(t, instance, faceIndex));
+				hit++;
+      }
+      break;
+    }
+  }
+  return hit;
+}
+
+int
+Mesh::CastRay(
+			  Ray &ray,
+			  MeshInstance *instance
+			  )
+{
+  if (mKdTree) {
+    return mKdTree->CastRay(ray, instance);
+  }
+  
+  int faceIndex = 0;
+  int hits = 0;
+  float nearestT = MAX_FLOAT;
+  int nearestFace = -1;
+  
+  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
+    nearestT = ray.intersections[0].mT;
+
+	
+  for ( ;
+		faceIndex < mFaces.size();
+		faceIndex++) {
+    hits += CastRayToFace(faceIndex, ray, nearestT, nearestFace, instance);
+    if (mIsConvex && nearestFace != -1)
+      break;
+  }
+  
+  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
+    if (ray.intersections.size())
+      ray.intersections[0] = Ray::Intersection(nearestT, instance, nearestFace);
+    else
+      ray.intersections.push_back(Ray::Intersection(nearestT, instance, nearestFace));
+  }
+  
+  return hits;
+}
+
+int
+Mesh::CastRayToSelectedFaces(
+							 Ray &ray,
+							 const vector<int> &faces,
+							 Intersectable *instance
+							 )
+{
+  vector<int>::const_iterator fi;
+  int faceIndex = 0;
+  int hits = 0;
+  float nearestT = MAX_FLOAT;
+  int nearestFace = -1;
+
+  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
+    nearestT = ray.intersections[0].mT;
+
+  for ( fi = faces.begin();
+				fi != faces.end();
+				fi++) {
+    hits += CastRayToFace(*fi, ray, nearestT, nearestFace, instance);
+    if (mIsConvex && nearestFace != -1)
+      break;
+  }
+  
+  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
+    if (ray.intersections.size())
+      ray.intersections[0] = Ray::Intersection(nearestT, instance, nearestFace);
+    else
+      ray.intersections.push_back(Ray::Intersection(nearestT, instance, nearestFace));
+  }
+  
+  return hits;
+}
+
+
+// int_lineseg returns 1 if the given line segment intersects a 2D
+// ray travelling in the positive X direction.	This is used in the
+// Jordan curve computation for polygon intersection.
+inline int
+int_lineseg(float px,
+			float py,
+			float u1,
+			float v1,
+			float u2,
+			float v2)
+{
+  float ydiff;
+
+  u1 -= px; u2 -= px; 	  // translate line
+  v1 -= py; v2 -= py;
+
+  if ((v1 > 0 && v2 > 0) ||
+      (v1 < 0 && v2 < 0) ||
+      (u1 < 0 && u2 < 0))
+    return 0;
+
+  if (u1 > 0 && u2 > 0)
+    return 1;
+
+  ydiff = v2 - v1;
+  if (fabs(ydiff) < Limits::Small) {	  // denominator near 0
+    if (((fabs(v1) > Limits::Small) ||
+		 (u1 > 0) || (u2 > 0)))
+      return 0;
+    return 1;
+  }
+  
+  double t = -v1 / ydiff;		  // Compute parameter
+
+  double thresh;
+  if (ydiff < 0.0f)
+	thresh = -1e20;
+  else
+	thresh = 1e20;
+
+  
+  return (u1 + t * (u2 - u1)) > thresh; //-Limits::Small;
+}
+
+
+
+// intersection with the polygonal face of the mesh
+int
+Mesh::RayFaceIntersection(const int faceIndex,
+						  const Ray &ray,
+						  float &t,
+						  const float nearestT
+						  )
+{
+  Face *face  = mFaces[faceIndex];
+
+  Plane3 plane = GetFacePlane(faceIndex);
+  float dot = DotProd(plane.mNormal, ray.GetDir());
+  
+  // Watch for near-zero denominator
+  // ONLY single sided polygons!!!!!
+  if (ray.mFlags & Ray::CULL_BACKFACES) {
+	if (dot > -Limits::Small)
+	  //  if (fabs(dot) < Limits::Small)
+	  return Ray::NO_INTERSECTION;
+  } else {
+	if (fabs(dot) < Limits::Small)
+	  return Ray::NO_INTERSECTION;
+  }
+  
+  t = (-plane.mD - DotProd(plane.mNormal, ray.GetLoc())) / dot;
+  
+  if (t <= Limits::Small)
+    return Ray::INTERSECTION_OUT_OF_LIMITS;
+  
+  if (t >= nearestT) {
+    return Ray::INTERSECTION_OUT_OF_LIMITS; // no intersection was found
+  }
+  
+  int count = 0;
+  float u, v, u1, v1, u2, v2;
+  int i;
+
+  int paxis = plane.mNormal.DrivingAxis();
+
+  // Project the intersection point onto the coordinate plane
+  // specified by which.
+  ray.Extrap(t).ExtractVerts(&u, &v, paxis);
+
+
+  int size = (int)face->mVertexIndices.size();
+
+  mVertices[face->mVertexIndices[size - 1]].
+    ExtractVerts(&u1, &v1, paxis );
+  
+  if (0 && size <= 4) {
+    // assume a convex face
+    for (i = 0; i < size; i++) {
+      mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
+      // line u1, v1, u2, v2
+      if ((v1 - v2)*(u - u1) + (u2 - u1)*(v - v1) > 0)
+		return Ray::NO_INTERSECTION;
+      u1 = u2;
+      v1 = v2;
+    }
+    
+    return Ray::INTERSECTION;
+  }
+  
+  // We're stuck with the Jordan curve computation.  Count number
+  // of intersections between the line segments the polygon comprises
+  // with a ray originating at the point of intersection and
+  // travelling in the positive X direction.
+  for (i = 0; i < size; i++) {
+    mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
+    count += (int_lineseg(u, v, u1, v1, u2, v2) != 0);
+    u1 = u2;
+    v1 = v2;
+  }
+
+  // We hit polygon if number of intersections is odd.
+  return (count & 1) ? Ray::INTERSECTION : Ray::NO_INTERSECTION;
+}
+
+int
+Mesh::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
+{
+  int faceIndex = (int)RandomValue(0, (Real)((int)mFaces.size()-1));
+  
+  // assume the face is convex and generate a convex combination
+  //
+  Face *face = mFaces[faceIndex];
+  point = Vector3(0,0,0);
+  float sum = 0.0f;
+  for (int i = 0; i < face->mVertexIndices.size(); i++) {
+    float r = RandomValue(0,1);
+    sum += r;
+    point += mVertices[face->mVertexIndices[i]]*r;
+  }
+  point *= 1.0f/sum;
+	
+	normal = GetFacePlane(faceIndex).mNormal;
+
+	return faceIndex;
+}
+
+int
+Mesh::GetRandomVisibleSurfacePoint(Vector3 &point,
+																	 Vector3 &normal,
+																	 const Vector3 &viewpoint,
+																	 const int maxTries
+																	 )
+{
+  Plane3 plane;
+  int faceIndex = (int)RandomValue(0, (Real)((int)mFaces.size()-1));
+	int tries;
+  for (tries = 0; tries < maxTries; tries++) {
+    Face *face = mFaces[faceIndex];
+    plane = GetFacePlane(faceIndex);
+    
+    if (plane.Side(viewpoint) > 0) {
+      point = Vector3(0,0,0);
+      float sum = 0.0f;
+      // pickup a point inside this triangle
+      for (int i = 0; i < face->mVertexIndices.size(); i++) {
+				float r = RandomValue(0,1);
+				sum += r;
+				point += mVertices[face->mVertexIndices[i]]*r;
+      }
+      point *= 1.0f/sum;
+      break;
+    }
+  }
+  
+  normal = plane.mNormal;
+  return (tries < maxTries) ? faceIndex + 1 : 0;
+}
+
+
+int
+MeshInstance::CastRay(
+					  Ray &ray
+					  )
+{
+  int res = mMesh->CastRay(ray, this);
+  return res;
+}
+
+int
+MeshInstance::CastRay(
+					  Ray &ray,
+					  const vector<int> &faces
+					  )
+{
+  return mMesh->CastRayToSelectedFaces(ray, faces, this);
+}
+
+
+
+int
+MeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
+{
+  return mMesh->GetRandomSurfacePoint(point, normal);
+}
+
+int
+MeshInstance::GetRandomVisibleSurfacePoint(Vector3 &point,
+																					 Vector3 &normal,
+																					 const Vector3 &viewpoint,
+																					 const int maxTries
+																					 )
+{
+	return mMesh->GetRandomVisibleSurfacePoint(point, normal, viewpoint, maxTries);
+}
+
+
+int
+TransformedMeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
+{
+  int index = mMesh->GetRandomSurfacePoint(point, normal);
+  point = mWorldTransform*point;
+  normal = TransformNormal(mWorldTransform, normal);
+  return index;
+}
+
+Plane3
+Mesh::GetFacePlane(const int faceIndex)
+{
+  Face *face = mFaces[faceIndex];
+	return Plane3(mVertices[face->mVertexIndices[0]],
+								mVertices[face->mVertexIndices[1]],
+								mVertices[face->mVertexIndices[2]]);
+}
+
+bool
+Mesh::ValidateFace(const int i)
+{
+	Face *face = mFaces[i];
+
+	Plane3 plane = Plane3(mVertices[face->mVertexIndices[0]],
+												mVertices[face->mVertexIndices[1]],
+												mVertices[face->mVertexIndices[2]]);
+	
+	if (!eq(Magnitude(plane.mNormal), 1.0f))
+		return false;
+
+	return true;
+}
+
+void
+Mesh::Cleanup()
+{
+	int toRemove = 0;
+	FaceContainer newFaces;
+	for (int i=0; i < mFaces.size(); i++)
+		if (ValidateFace(i)) {
+			newFaces.push_back(mFaces[i]);
+		} else {
+			cout<<"d";
+			delete mFaces[i];
+			toRemove++;
+		}
+	
+	if (toRemove) {
+		mFaces = newFaces;
+	}
+	
+	// cleanup vertices??
+}
+
+int
+TransformedMeshInstance::CastRay(
+								 Ray &ray
+								 )
+{
+  ray.ApplyTransform(Invert(mWorldTransform));
+  int res = mMesh->CastRay(ray, this);
+  ray.ApplyTransform(mWorldTransform);
+  
+  return res;
+}
+
+
+void
+Mesh::AddTriangle(const Triangle3 &triangle)
+{
+  int index = (int)mVertices.size();
+
+  for (int i=0; i < 3; i++) {
+    mVertices.push_back(triangle.mVertices[i]);
+  }
+  
+  AddFace(new Face(index + 0, index + 1, index + 2) );
+}
+
+void
+Mesh::AddRectangle(const Rectangle3 &rect)
+{
+  int index = (int)mVertices.size();
+
+  for (int i=0; i < 4; i++) {
+    mVertices.push_back(rect.mVertices[i]);
+  }
+  
+  AddFace(new Face(index + 0, index + 1, index + 2, index + 3) );
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/gzstream.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/gzstream.cpp	(revision 372)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/gzstream.cpp	(revision 372)
@@ -0,0 +1,175 @@
+// ============================================================================
+// gzstream, C++ iostream classes wrapping the zlib compression library.
+// Copyright (C) 2001  Deepak Bandyopadhyay, Lutz Kettner
+//
+// 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, or (at your option) any later version.
+//
+// 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
+// ============================================================================
+//
+// File          : gzstream.C
+// Revision      : $Revision: 1.1 $
+// Revision_date : $Date: 2004/02/16 14:46:00 $
+// Author(s)     : Deepak Bandyopadhyay, Lutz Kettner
+// 
+// Standard streambuf implementation following Nicolai Josuttis, "The 
+// Standard C++ Library".
+// ============================================================================
+
+#include "gzstream.h"
+#include <string.h>  // for memcpy
+
+#ifdef GZSTREAM_NAMESPACE
+namespace GZSTREAM_NAMESPACE {
+#endif
+
+// ----------------------------------------------------------------------------
+// Internal classes to implement gzstream. See header file for user classes.
+// ----------------------------------------------------------------------------
+
+// --------------------------------------
+// class gzstreambuf:
+// --------------------------------------
+
+gzstreambuf*
+gzstreambuf::open( const char* name, int open_mode) {
+  if ( is_open() )
+    return (gzstreambuf*)0;
+  mode = open_mode;
+  // no append nor read/write mode
+  if ((mode & std::ios::ate) || (mode & std::ios::app)
+      || ((mode & std::ios::in) && (mode & std::ios::out)))
+    return (gzstreambuf*)0;
+  char fmode[10];
+  char* fmodeptr = fmode;
+  if ( mode & std::ios::in)
+    *fmodeptr++ = 'r';
+  else
+    if ( mode & std::ios::out)
+      *fmodeptr++ = 'w';
+  *fmodeptr++ = 'b';
+  *fmodeptr = '\0';
+  file = gzopen( name, fmode);
+  if (file == 0)
+    return (gzstreambuf*)0;
+  opened = 1;
+  return this;
+}
+  
+gzstreambuf *
+gzstreambuf::close() {
+  if ( is_open()) {
+    sync();
+    opened = 0;
+    if ( gzclose( file) == Z_OK)
+      return this;
+  }
+  return (gzstreambuf*)0;
+}
+  
+int
+gzstreambuf::underflow() { // used for input buffer only
+  if ( gptr() && ( gptr() < egptr()))
+    return * reinterpret_cast<unsigned char *>( gptr());
+  
+  if ( ! (mode & std::ios::in) || ! opened)
+    return EOF;
+  // Josuttis' implementation of inbuf
+  int n_putback = gptr() - eback();
+  if ( n_putback > 4)
+    n_putback = 4;
+  memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
+  
+  int num = gzread( file, buffer+4, gzbufferSize-4);
+  if (num <= 0) // ERROR or EOF
+    return EOF;
+  
+  // reset buffer pointers
+  setg( buffer + (4 - n_putback),   // beginning of putback area
+	buffer + 4,                 // read position
+	buffer + 4 + num);          // end of buffer
+  
+  // return next character
+  return * reinterpret_cast<unsigned char *>( gptr());    
+}
+  
+int
+gzstreambuf::flush_buffer() {
+  // Separate the writing of the buffer from overflow() and
+  // sync() operation.
+  int w = pptr() - pbase();
+  if ( gzwrite( file, pbase(), w) != w)
+    return EOF;
+  pbump( -w);
+  return w;
+}
+  
+int
+gzstreambuf::overflow( int c) { // used for output buffer only
+  if ( ! ( mode & std::ios::out) || ! opened)
+    return EOF;
+  if (c != EOF) {
+    *pptr() = c;
+    pbump(1);
+  }
+  if ( flush_buffer() == EOF)
+    return EOF;
+  return c;
+}
+  
+int
+gzstreambuf::sync() {
+  // Changed to use flush_buffer() instead of overflow( EOF)
+  // which caused improper behavior with std::endl and flush(),
+  // bug reported by Vincent Ricard.
+  if ( pptr() && pptr() > pbase()) {
+    if ( flush_buffer() == EOF)
+      return -1;
+  }
+  return 0;
+}
+  
+  
+  // --------------------------------------
+  // class gzstreambase:
+// --------------------------------------
+
+gzstreambase::gzstreambase( const char* name, int mode)
+{
+  init( &buf);
+  open( name, mode);
+}
+  
+  gzstreambase::~gzstreambase()
+  {
+    buf.close();
+  }
+  
+  void
+  gzstreambase::open( const char* name, int open_mode) {
+    if ( ! buf.open( name, open_mode))
+      clear( rdstate() | std::ios::badbit);
+}
+
+void gzstreambase::close() {
+    if ( buf.is_open())
+        if ( ! buf.close())
+            clear( rdstate() | std::ios::badbit);
+}
+
+#ifdef GZSTREAM_NAMESPACE
+} // namespace GZSTREAM_NAMESPACE
+#endif
+
+// ============================================================================
+// EOF //
Index: GTP/trunk/Lib/Vis/Preprocessing/src/common.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/common.h	(revision 582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/common.h	(revision 582)
@@ -0,0 +1,487 @@
+// ================================================================
+// $Id: common.h,v 1.1 2004/02/16 14:46:00 bittner Exp $
+// ****************************************************************
+// 
+/** \file common.h
+Common defines for the ERS system.
+
+This file contains various macros, templates and constants for the ERS system.
+
+@author Jiri Bittner
+*/
+
+#ifndef __COMMON_H
+#define __COMMON_H
+
+
+#include <math.h>
+#include <stdlib.h>
+#include <iostream>
+#include <fstream>
+using namespace std;
+
+#include <limits.h>
+
+
+// This constant should be used for the length of the array char for filenames
+// etc., for example: char filename[MaxStringLength]
+const int MaxStringLength = 256;
+
+#if defined(_MSC_VER)
+#pragma warning(disable:4018)
+#pragma warning(disable:4800)
+//#pragma warning(disable:4244)
+
+typedef unsigned int uint;
+typedef unsigned short ushort;
+typedef unsigned char uchar;
+typedef unsigned long ulong;
+#endif
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+#define DIRCAT '.'
+#endif
+
+#if !defined(__WATCOMC__) && !defined(__CYGWIN32__) && !defined(_MSC_VER)
+#include <values.h>
+#else // __WATCOMC__
+#define M_PI        3.14159265358979323846
+#define MAXFLOAT    3.40282347e+38F
+#endif // __WATCOMC__
+
+// some compilers do not define the bool yet, but it was declared by ANSI
+#if !defined(__WATCOMC__) && !defined(_MSC_VER)
+#if defined (__GNUC__) || (_BOOL)
+//#error "HAS BOOL defined"
+#define HAS_BOOL
+#endif
+#else // __WATCOMC__
+#if  (__WATCOMC__ > 1060)
+//#error "Watcom HAS BOOL defined"
+#define HAS_BOOL
+#endif
+#endif // __WATCOMC__
+
+
+#if defined(__WATCOMC__) || defined(_MSC_VER)
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+#endif // __WATCOMC__
+
+#ifdef sgi
+#define OUT_BIN_MODE ios::out
+#define IN_BIN_MODE ios::in
+#else // sgi
+#if defined(__WATCOMC__) || defined(_MSC_VER)
+#define OUT_BIN_MODE ios::out | ios::binary
+#define IN_BIN_MODE ios::in | ios::binary
+#else
+#define OUT_BIN_MODE ios::out | ios::bin
+#define IN_BIN_MODE ios::in | ios::bin
+#endif // __WATCOMC_
+#endif // sgi
+
+
+//  #ifndef HAS_BOOL
+//  //enum bool {
+//  //  false = 0,
+//  //  true
+//  //};
+//  #define bool int
+//  #define false 0
+//  #define true  1
+//  #endif // HAS_BOOL
+
+typedef unsigned long dword;
+
+#ifndef NULL
+#define NULL (void *)0
+#endif // NULL
+
+//ostream& operator<<(ostream &s,const BaseC &c);
+
+typedef float Real;
+typedef unsigned char byte;
+
+//#ifndef FALSE
+//#define FALSE 0
+//#define TRUE !0
+//#endif
+
+#ifndef __GNUG__
+// typedef int bool;
+#endif
+
+#ifndef getch
+#define getch() getchar()
+#endif
+
+
+#define TRASH 1.0e-5
+
+#ifndef PI
+#define PI    3.14159265358979323846f
+#endif
+
+#define MIN_FLOAT -1e30f
+#define MAX_FLOAT  1e30f
+
+
+// tolerance value for polygon area
+#define AREA_LIMIT 0.0001f
+
+#ifndef DEL_PTR
+#define DEL_PTR(ptr) do {if (ptr) {        \
+                           delete (ptr);   \
+						   (ptr) = 0;}}    \
+                     while (0)
+#endif
+// Clears a container (i.e., a vector of pointers) and deletes the pointers
+#if 0
+#ifndef CLEAR_CONTAINER
+#define CLEAR_CONTAINER(co) do { while (!(co).empty()) {   \
+						           DEL_PTR((co).back());     \
+								   (co).pop_back();}}      \
+							while (0)
+#endif
+
+#else
+
+#ifndef CLEAR_CONTAINER
+#define CLEAR_CONTAINER(co) do { for (int _i = 0; _i < (int)(co).size(); ++ _i) { \
+	DEL_PTR((co)[_i]);} \
+	(co).clear(); } \
+while (0)
+#endif
+
+#endif
+
+
+inline
+int signum(const Real a, const Real thresh = TRASH)
+{
+  if (a>thresh)
+    return 1; 
+  else
+    if (a<-thresh)
+      return -1; 
+  return 0;
+}
+
+inline double Absd(const double a)
+{
+  return (a >= 0.0) ? a : -a;
+}
+
+inline float Abs(const float a)
+{
+  return (a >= 0.0f) ? a : -a;
+}
+
+// =======================================================
+// Comparing things
+//struct Limits {
+//  const Real thresh=TRASH;
+//  const Real small=0.1;
+//};
+
+template <class T>
+bool
+ClipValue(T &v, const T m, const T M)
+{
+  if (v<m) {
+    v = m;
+    return true;
+  }
+  if (v>M) {
+    v = M;
+    return true;
+  }
+
+  return false;
+}
+
+
+inline int eq(Real a, Real b, Real t=TRASH)
+{
+  return Abs(a-b)<t;
+}
+
+inline int leq(Real a,Real b,Real t=TRASH)
+{
+  return a - b < t;
+}
+
+inline int geq(Real a,Real b,Real t=TRASH)
+{
+  return t > b - a;
+}
+
+inline int le(Real a,Real b,Real t=TRASH)
+{
+  return !geq(a,b,t);
+}
+
+inline int ge(Real a,Real b,Real t=TRASH)
+{
+  return !leq(a,b,t);
+}
+
+// ========================================================
+
+// -------------------------------------------------------------------
+// Indents to a given stream by the number of spaces specified.
+// This routine is located in main.cpp, for lack of a better place.
+// -------------------------------------------------------------------
+void indent(ostream &app, int ind);
+
+// ---------------------------------------------------------
+// RandomValue
+//	Returns a random Realing-point value between the two 
+//	values.  Range is inclusive; the function should 
+//	occasionally return exactly a or b.
+// ---------------------------------------------------------
+inline Real
+RandomValue(Real a, Real b)
+{
+  Real range = (Real) Abs(a - b);
+  return ((Real)rand() / RAND_MAX) * range + ((a < b) ? a : b);
+}
+
+
+
+
+inline Real sqr(Real a)
+{
+  return a*a;
+}
+
+template <class T>
+void Swap(T &a,T &b)
+{
+  T c;                 
+  c = b;
+  b = a;
+  a = c;
+}
+
+template <class T>
+int eq(T &a, T &b, T &c, T &d) {
+  return a == b && c==d && b==c;
+}
+
+template <class T>
+T Min(T a,T b)
+{
+  return a<b ? a : b;
+}
+
+template <class T>
+T Max(T a,T b)
+{
+  return a>b ? a : b;
+}
+
+
+Real Random(Real max);
+int  Random(int max);
+void Randomize();
+void
+Randomize(const unsigned int seed);
+
+
+void GetKey(char *s=NULL);
+
+inline Real Deg2Rad(const Real a)
+{
+   return a*(PI/180.0f);
+}
+
+inline Real Rad2Deg(const Real a) {
+  return a*(180.0f/PI);
+}
+  
+void InitTiming();
+long GetTime();
+long GetRealTime();
+Real TimeDiff(long t1,long t2);
+char *TimeString();
+
+
+// manipulator
+inline ostream &DEBUGINFO( ostream &s ) {
+  return s<<"FILE "<<__FILE__<<",LINE "<<__LINE__<<endl;
+}
+
+#define DINFO __FILE__<<":"<<__LINE__
+
+
+class CGlobals {
+public:
+
+  static int Special;
+
+};
+
+// -------------------------------------------------------------------
+// Limits.
+//  This class encapsulates all the concessions to Realing-point
+//  error made by ray tracers.
+// -------------------------------------------------------------------
+
+class Limits {
+public:
+  // This is the number used to reject too-close intersections.
+  // The default value is 1.0.
+  static Real Threshold;
+
+  // This is a "small" number.  Less than this number is assumed to
+  // be 0, when such things matter.
+  // The default value is 0.1.
+  static Real Small;
+
+  // This is an impractically "large" number, used for intersection
+  // parameters out to infinity (e.g. the span resulting from an
+  // FindAllIntersections operation on a plane).
+  // The default value is 100000.
+  static Real Infinity;
+};
+
+// ---------------------------------------------------------
+// EpsilonEqual(x,y)
+//   Returns if two values are equal or not (by epsilon)
+// ---------------------------------------------------------
+inline int
+EpsilonEqual(const Real &x, const Real &y)
+{
+  return fabs(x-y) < Limits::Small;
+}
+
+// ---------------------------------------------------------
+// EpsilonEqual(x)
+//   Returns if a value is zero (+/- epsilon)
+// ---------------------------------------------------------
+inline int
+EpsilonEqual(const Real &x)
+{
+  return fabs(x) < Limits::Small;
+}
+
+// ---------------------------------------------------------
+// EpsilonEqual(x,y,epsilon)
+//   Returns if two values are equal or not by a given epsilon
+// ---------------------------------------------------------
+inline int
+EpsilonEqual(const Real &x, const Real &y, const Real &epsilon)
+{
+  return fabs(x-y) < epsilon;
+}
+
+// ---------------------------------------------------------
+// InRange
+//	Returns nonzero if min <= candidate <= max.
+// ---------------------------------------------------------
+template<class T>
+inline int 
+InRange(T min, T max, T candidate)
+{
+  return (candidate >= min) && (candidate <= max);
+}
+
+// --------------------------------------------------------------
+// string function with new operator
+
+inline char*
+StrDup(char *src) {
+  char *p;
+  for (p = src; *p++; );
+  char *dest = new char[p-src];
+  for ( p = dest;(*p++ = *src++) != 0; );
+  return dest;
+}
+
+
+inline char *
+StrToLower(char *src) {
+  char *p;
+  for (p = src; *p; p++)
+    *p = tolower(*p);
+  return src;
+}
+
+// return l = log2(a) if a is a power of two else -ceillog2(a)
+inline int
+GetLog2(int a)
+{
+  int i, x;
+  i = 0;
+  x = 1;
+
+  while (x < a) {
+    i++;
+    x <<= 1;
+  }
+
+  return (x==a) ? i: -i;
+}
+
+
+// return ceil(log2(a)) even if a is not a power of two
+// Example:
+// GetCeilLog2(15) = 4
+// GetCeilLog2(16) = 4
+// GetCeilLog2(17) = 5
+inline int
+GetCeilLog2(int a)
+{
+  int i, x;
+  if (a < 0)
+    return -1;
+
+  i = 0;
+  x = 1;
+
+  while (x < a) {
+    i++;
+    x <<= 1;
+  }
+
+  return i;
+}
+
+
+char *
+GetAbsPath(char *path);
+
+char *
+strdup(char *a);
+
+bool
+FileExists(char *filename);
+
+#define DEBUG_LEVEL 5
+//#define DEBUG_LEVEL 1000
+//#define DEBUG_LEVEL 50000
+  
+// debug stream
+extern ofstream Debug;
+
+
+bool
+CreateDir(char *dir);
+
+char *
+GetPath(const char *s);
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
