Index: trunk/VUT/GtpVisibilityPreprocessor/src/UnigraphicsParser.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/UnigraphicsParser.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/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: trunk/VUT/GtpVisibilityPreprocessor/src/Material.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Material.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Material.h	(revision 162)
@@ -0,0 +1,42 @@
+#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)
+  {
+  }
+  
+};
+
+
+class Material 
+{
+public:
+  RgbColor mDiffuseColor;
+  RgbColor mSpecularColor;
+  RgbColor mAmbientColor;
+  
+  Material() 
+  {
+  }
+  
+  friend Material RandomMaterial();
+  
+};
+
+
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/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: trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.h	(revision 162)
@@ -0,0 +1,85 @@
+#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);
+  
+
+  // 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
+  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: trunk/VUT/GtpVisibilityPreprocessor/src/Environment.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Environment.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Environment.h	(revision 162)
@@ -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,
+		      const 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,
+			 const 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, const 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, const 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: trunk/VUT/GtpVisibilityPreprocessor/src/ExactPreprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ExactPreprocessor.cpp	(revision 65)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ExactPreprocessor.cpp	(revision 162)
@@ -1,13 +1,10 @@
 #include "ExactPreprocessor.h"
 
-namespace GtpVisibilityPreprocessor {
   
-  bool
-  ExactPreprocessor::ComputeVisibility()
-  {
-
-    return true;
-  };
+bool
+ExactPreprocessor::ComputeVisibility()
+{
   
+  return true;
 };
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.cpp	(revision 162)
@@ -0,0 +1,128 @@
+
+#include "X3dParser.h"
+
+
+bool
+X3dParser::ParseFile(const string filename,
+		     SceneGraphNode **root)
+{
+  
+  
+  
+}
+
+  
+namespace X3DTK {
+namespace MESH {
+
+MyStructureComputer::MyStructureComputer()
+{
+  setGraphTraversal(new DFSGraphTraversal());
+	setComponentVisitor(new MyStructureComputerCoreVisitor());
+      }
+      
+      MyStructureComputer::~MyStructureComputer()
+      {
+	Singleton<MyStructureComputerStateVariables>::removeInstance();
+      }
+      
+      MySimpleMesh *MyStructureComputer::compute(SFNode N)
+      {
+	Singleton<MyStructureComputerStateVariables>::getInstance()->init();
+	traverse(N);
+	Singleton<MyStructureComputerStateVariables>::getInstance()->finish();
+	
+	return Singleton<MyStructureComputerStateVariables>::getInstance()->getMesh();
+      }
+      
+      
+      MyStructureComputerCoreVisitor::MyStructureComputerCoreVisitor()
+      {
+	// Enter functions.
+	define(Recorder<Mesh>::getEnterFunction(&MyStructureComputerCoreVisitor::enterMesh));
+	define(Recorder<Transform>::getEnterFunction(&MyStructureComputerCoreVisitor::enterTransform));
+	// Leave function.
+	define(Recorder<X3DGroupingNode>::getLeaveFunction(&MyStructureComputerCoreVisitor::leaveX3DGroupingNode));
+      }
+      
+      void MyStructureComputerCoreVisitor::enterMesh(Mesh *M)
+      {
+	// StateVariables assignation.
+	MyStructureComputerStateVariables *stateVariables = Singleton<MyStructureComputerStateVariables>::getInstance();
+	
+	SFMatrix34f T = stateVariables->getMatrix();
+
+  // Beginning a new Mesh by memorizing the current vertex index.
+  stateVariables->beginNewMesh();
+
+  // filling the vertices.
+  for (Mesh::MFVertex::const_iterator v = M->getVertices().begin(); v != M->getVertices().end(); ++v)
+  {
+    SFPoint3f P = T*(*v)->data().getPoint();
+    stateVariables->addVertex(P.x, P.y, P.z);
+  }
+  
+  // filling the faces.
+  for (Mesh::MFFace::const_iterator
+	 f = M->getFaces().begin(); f != M->getFaces().end(); ++f)
+  {
+    const SFFace::MFEdge &edges = (*f)->getEdges();
+    list<unsigned int> indexList;
+    for (SFFace::MFEdge::const_iterator e = edges.begin(); e != edges.end(); ++e)
+      indexList.push_back((*e)->getFromVertex()->getIndex());
+    
+    stateVariables->addFace(indexList);
+  }
+}
+
+void MyStructureComputerCoreVisitor::enterTransform(Transform *T)
+{
+  Singleton<MyStructureComputerStateVariables>::getInstance()->pushMatrix(T->getTransform());
+}
+
+void MyStructureComputerCoreVisitor::leaveX3DGroupingNode(X3DGroupingNode *)
+{
+  Singleton<MyStructureComputerStateVariables>::getInstance()->popMatrix();
+}
+
+: StateVariables(), _mesh(0), _decal(0)
+{
+}
+
+void MyStructureComputerStateVariables::init()
+{
+  _mesh = new MySimpleMesh();
+  _matrixStack.push_front(SFMatrix34f::identity);
+}
+
+void MyStructureComputerStateVariables::finish()
+{
+  _matrixStack.clear();
+}
+
+void MyStructureComputerStateVariables::beginNewMesh()
+{
+  _decal = _mesh->getVertexArray().size();
+}
+
+void MyStructureComputerStateVariables::addFace(const Face &face)
+{
+  //  MyFace decalFace = face;
+  //  for (MyFace::iterator it = decalFace.begin(); it != decalFace.end(); ++it)
+  //    *it = _decal + *it;
+    
+  //  _mesh->addFace(decalFace);
+};
+
+void MyStructureComputerStateVariables::pushMatrix(const SFMatrix34f &transformation)
+{
+  _matrixStack.push_front(_matrixStack.front()*transformation);
+}
+
+void MyStructureComputerStateVariables::popMatrix()
+{
+  _matrixStack.pop_front();
+}
+
+}
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.h	(revision 162)
@@ -0,0 +1,465 @@
+#ifndef _KdTree_H__
+#define _KdTree_H__
+
+#include <functional>
+using namespace std;
+
+#include "Containers.h"
+#include "AxisAlignedBox3.h"
+#include "Ray.h"
+
+  
+class KdNode;
+class KdLeaf;
+class KdInterior;
+
+
+// --------------------------------------------------------------
+// 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:
+  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) {
+    mObjects.reserve(objects);
+  }
+
+  
+  /** \sa KdNode::IsLeaf() */
+  virtual bool IsLeaf() const { return true; }
+
+  /** pointers to occluders contained in this node */
+  MeshContainer mObjects;
+  
+  /** pointers to viewcells contained in this node */
+  //  ViewCellContainer mViewCells;
+};
+  
+  
+
+/** 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 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);
+  }
+
+  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
+	  );
+
+  const KdTreeStatistics &GetStatistics() const {
+    return mStat;
+  }
+
+    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;
+  }
+
+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 {
+      MESH_MIN,
+      MESH_MAX
+    };
+    
+    int type;
+    float value;
+    void *data;
+    
+    SortableEntry() {}
+    SortableEntry(const int t, const float v, void *d):type(t),
+						       value(v),
+						       data(d) {}
+    
+    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;
+
+  /// root of the tree
+  KdNode *mRoot;
+  /// bounding box of the tree root
+  AxisAlignedBox3 mBox;
+  KdTreeStatistics mStat;
+
+};
+  
+
+
+
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.h	(revision 162)
@@ -0,0 +1,38 @@
+#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:
+  
+  
+  MeshContainer mGeometry;
+  SceneGraphNodeContainer mChildren;
+  AxisAlignedBox3 mBox;
+};
+
+
+/** Scene graph class */
+class SceneGraph {
+
+public:
+  SceneGraphNode *mRoot;
+  bool Export(const string filename);
+  
+  int CollectMeshInstaces(MeshContainer *instances);
+  
+protected:
+};
+
+
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBSP.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBSP.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBSP.h	(revision 162)
@@ -0,0 +1,80 @@
+#ifndef _ViewCellBsp_H__
+#define _ViewCellBsp_H__
+
+#include "Plane3.h"
+
+
+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 {
+    return parent == NULL;
+  }
+protected:
+  /// parent of this node
+  BSPInterior *parent;
+};
+
+/** BSP interior node implementation */
+class BSPInterior : public BSPNode {
+    
+  /** @return false since it is an interior node */
+  virtual bool IsLeaf() const { return false; }
+
+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):mViewCell(viewCell) {}
+  /** @return true since it is an interior node */
+  virtual bool IsLeaf() const { return true; }
+
+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:
+  /** Constructor takes a pointer to the cell corresponding to the whole
+      viewspace */
+  BSPTree(ViewCell *cell) {
+    mRootCell = cell;
+    mRoot = new BSPLeaf(mRootCell);
+  }
+    
+    
+protected:
+  /// Pointer to the root of the tree
+  BSPNode *mRoot;
+  /// Pointer to the root cell of the viewspace */
+  ViewCell *mRootCell;
+};
+  
+
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp	(revision 162)
@@ -0,0 +1,43 @@
+#include "SamplingPreprocessor.h"
+#include "ExactPreprocessor.h"
+#include "Parser.h"
+#include "UnigraphicsParser.h"
+#include "Environment.h"
+#include "Camera.h"
+
+#define USE_EXE_PATH false
+
+
+int
+main(int argc, const char **argv)
+{
+  Debug.open("debug.log");
+  environment = new Environment;
+  environment->Parse(argc, argv, USE_EXE_PATH);
+  
+  Preprocessor *p =
+    new SamplingPreprocessor();
+
+  p->LoadScene("soda.dat");
+  p->BuildKdTree();
+  p->KdTreeStatistics(cout);
+
+  //  p->mSceneGraph->Export("soda.x3d");
+  p->Export("soda.x3d", true, false);
+  p->Export("soda-kdtree.x3d", false, true);
+
+  //  p->LoadViewcells("viewcells.wrl");
+  p->ComputeVisibility();
+  p->ExportPreprocessedData("scene.vis");
+
+  Camera camera;
+  camera.LookAtBox(p->mKdTree->GetBox());
+  camera.SnapImage("camera.png", p->mKdTree);
+
+  camera.LookInBox(p->mKdTree->GetBox());
+  camera.SetPosition(camera.mPosition - Vector3(0,100,0));
+  camera.SnapImage("camera2.png", p->mKdTree);
+  
+  return 0;
+}
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h	(revision 162)
@@ -0,0 +1,16 @@
+#ifndef _SamplingPreprocessor_H__
+#define _SamplingPreprocessor_H__
+
+#include "Preprocessor.h"
+
+
+/** Sampling based visibility preprocessing. The implementation is based on heuristical
+    sampling of view space */
+class SamplingPreprocessor : public Preprocessor {
+public:
+  virtual bool ComputeVisibility();
+};
+
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 162)
@@ -0,0 +1,211 @@
+#include <stack>
+#include "common.h"
+#include "SceneGraph.h"
+#include "X3dExporter.h"
+#include "Mesh.h"
+#include "KdTree.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)
+{
+  vector<Ray>::const_iterator ri = rays.begin();
+  stream<<"<Shape>"<<endl;
+  stream<<"<IndexedLineSet ccw=\"TRUE\" 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 = (*ri).GetLoc() + length*(*ri).GetDir();
+    
+    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);
+  
+  
+  MeshContainer::const_iterator mi = node->mGeometry.begin();
+  for (; mi != node->mGeometry.end(); mi++) {
+    // export the transform...
+    ExportMesh((*mi)->GetMesh());
+  }
+  
+  stream<<"</Group>"<<endl;
+
+}
+
+void
+X3dExporter::ExportMesh(Mesh *mesh)
+{
+
+  stream<<"<Shape>"<<endl;
+  stream<<"<Appearance>"<<endl;
+
+  // $$ tmp -> random material
+  
+  float r, g, b;
+
+  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 (wireframe)
+    stream<<"<IndexedLineSet ccw=\"TRUE\" coordIndex=\""<<endl;
+  else
+    stream<<"<IndexedFaceSet ccw=\"TRUE\" 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<<" ";
+    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 (wireframe)
+    stream<<"</IndexedLineSet>"<<endl;
+  else
+    stream<<"</IndexedFaceSet>"<<endl;
+  
+  stream<<"</Shape>"<<endl;
+
+}
+
+bool
+X3dExporter::ExportBox(const AxisAlignedBox3 &box)
+{
+  Mesh *mesh = new Mesh;
+  // add 6 vertices of the box
+  int index = 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::ExportKdTree(const KdTree &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 = 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;
+}
+
+
+void
+X3dExporter::ExportMeshInstance(MeshInstance *mi)
+{
+  ExportMesh(mi->GetMesh());
+}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/common.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/common.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/common.cpp	(revision 162)
@@ -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 = 1e20f;
+
+
+
+
+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: trunk/VUT/GtpVisibilityPreprocessor/src/Intersectable.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Intersectable.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Intersectable.h	(revision 162)
@@ -0,0 +1,11 @@
+#ifndef __INTERSECTABLE_H
+#define __INTERSECTABLE_H
+
+
+class Intersectable {
+  
+  
+};
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/UnigraphicsParser.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/UnigraphicsParser.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/UnigraphicsParser.cpp	(revision 162)
@@ -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 = 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: trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h	(revision 162)
@@ -0,0 +1,434 @@
+#ifndef _AxisAlignedBox3_H__
+#define _AxisAlignedBox3_H__
+
+
+#include "Matrix4x4.h"
+#include "Vector3.h"
+#include "Plane3.h"
+
+class Plane3;
+class Ray;
+
+
+// --------------------------------------------------------
+// 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.5 * (mMin[axis] + mMax[axis]);
+  }
+
+  float Min(const int axis) const {
+    return mMin[axis];
+  }
+
+  float Max(const int axis) const {
+    return  mMax[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(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 AxisAlignedBox3 &bbox);
+  // Expand the axis-aligned box to include given values in particular axis
+  void Include(const int &axis, const float &newBound);
+
+  
+
+  // 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
+  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;
+  
+  // 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};
+  
+  // 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(int N, Vector3 &vertex) const;
+  
+  // Returns 1, if the box includes on arbitrary face a given box
+  int IsPiercedByBox(const AxisAlignedBox3 &box, int &axis) 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;
+
+
+#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: trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.h	(revision 162)
@@ -0,0 +1,463 @@
+#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);
+};
+
+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;
+}
+
+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: trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h	(revision 162)
@@ -0,0 +1,100 @@
+#ifndef _Preprocessor_H__
+#define _Preprocessor_H__
+
+#include <string>
+using namespace std;
+#include "Containers.h"
+#include "Mesh.h"
+#include "KdTree.h"
+#include "ViewCellBsp.h"
+//#include "SceneGraph.h"
+
+class SceneGraph;
+
+/** 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:
+  /** Load the input scene. 
+      @param filename file to load
+	@return true on success
+  */
+  virtual bool LoadScene(const string filename);
+  
+  /** 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 LoadViewcells(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;
+  
+  
+  bool
+  Export( const string filename,
+	  const bool scene,
+	  const bool kdtree
+	  );
+  
+  
+  virtual void KdTreeStatistics(ostream &s);
+  
+  /// 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: trunk/VUT/GtpVisibilityPreprocessor/src/Camera.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Camera.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Camera.h	(revision 162)
@@ -0,0 +1,67 @@
+#ifndef __CAMERA_H
+#define __CAMERA_H
+
+#include "Vector3.h"
+#include "AxisAlignedBox3.h"
+
+class KdTree;
+
+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 = 640;
+    mHeight = 480;
+    mFovy = 60*M_PI/180;
+  }
+  
+  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 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);
+
+  void SetupRay(Ray &ray, const int x, const int y);
+
+};
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Material.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Material.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Material.cpp	(revision 162)
@@ -0,0 +1,19 @@
+#include "common.h"
+#include "Material.h"
+
+
+Material
+RandomMaterial()
+{
+  float a = 0.1f;
+  float b = 0.9f;
+
+  Material m;
+  m.mDiffuseColor =
+    RgbColor(a + Random(b),
+	     a + Random(b),
+	     a + Random(b));
+
+  return m;
+}
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h	(revision 162)
@@ -0,0 +1,233 @@
+#ifndef __RAY_H__
+#define __RAY_H__
+
+#include <vector>
+#include "Matrix4x4.h"
+#include "Vector3.h"
+
+// forward declarations
+class Plane3;
+class Intersectable;
+class KdLeaf;
+class MeshInstance;
+
+
+// -------------------------------------------------------------------
+// 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 };
+
+  enum { NO_INTERSECTION=0, INTERSECTION_OUT_OF_LIMITS, INTERSECTION };
+
+  struct RayIntersection {
+    // the point of intersection
+    float mT;
+    // can be either mesh or a viewcell
+    Intersectable *mObject;
+    // the face of the intersectable
+    int mFace;
+    RayIntersection(const float t,
+		    Intersectable *object,
+		    const int face):mT(t), mObject(object), mFace(face) {}
+    RayIntersection() {}
+
+    bool operator<(
+		   const RayIntersection &b) const {
+      return 
+	mT
+	<
+	b.mT;
+    }
+
+
+    
+  };
+  
+  vector<RayIntersection> intersections;
+  vector<KdLeaf *> leaves;
+  vector<MeshInstance *> meshes;
+
+  // constructors
+  Ray(const Vector3 &wherefrom,
+      const Vector3 &whichdir,
+      const int _type,
+      const void *_originCell = NULL) {
+    loc = wherefrom;
+    dir = Normalize(whichdir);
+    mType = _type;
+    origin = _originCell;
+    termination = NULL;
+    depth = 0;
+    Init();
+  }
+  // dummy constructor
+  Ray() {}
+
+  
+  // Inititalize the ray again when already constructed
+  void Init(const Vector3 &wherefrom, const Vector3 &whichdir,
+	    const int _type, const void *_originCell = NULL,
+	    bool dirNormalized = false) {
+    loc = wherefrom;
+    dir = (dirNormalized) ? whichdir: Normalize(whichdir) ;
+    mType = _type;
+    origin = _originCell;
+    termination = NULL;
+    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 cell in the ASDS, where ray starts from
+  void SetOrigin(const void *c) {origin = c;}
+  const void *GetOrigin() const  { return origin; }
+
+  // the cell in the ASDS, where ray finishes the walk
+  void SetTermination(const void *c) {termination = c; }
+  const void* GetTermination() const { return termination;}
+
+  // the object on which the ray starts at
+  const RayIntersection* GetStartObject() const { return &intersections[0]; }
+  const RayIntersection* 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;}
+  
+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;
+ 
+  // I should have some abstract cell data type !!! here
+  // corresponds to the spatial elementary cell
+  const void *origin;
+  const void *termination;
+  
+  // 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 Plane;
+
+  // 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);
+};
+
+
+
+
+#endif 
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/gzstream.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/gzstream.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/gzstream.h	(revision 162)
@@ -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: trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.h	(revision 162)
@@ -0,0 +1,170 @@
+#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"
+
+
+class MeshInstance;
+
+/// 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) {}
+  
+  /// Constructor with container preallocation
+  Mesh(const int vertices,
+       const int faces):mVertices(),
+			mFaces(),
+			mMaterial(NULL)
+  {
+    mVertices.reserve(vertices);
+    mFaces.reserve(faces);
+  }
+
+  ~Mesh() {
+    for (int i=0; i < mFaces.size(); i++)
+      delete mFaces[i];
+  }
+  
+  void AddFace(Face *face) 
+  {
+    mFaces.push_back(face);
+  }
+
+  void Preprocess();
+
+  /** Axis aligned bounding box of the mesh */
+  AxisAlignedBox3 mBoundingBox;
+  
+  /** 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;
+  
+  int
+  CastRay(
+	  Ray &ray,
+	  MeshInstance *instance
+	  );
+
+
+  int
+  RayFaceIntersection(const int faceIndex,
+		      const Ray &ray,
+		      float &t,
+		      const float nearestT
+		      );
+
+  Plane3 GetFacePlane(const int faceIndex);
+
+};
+
+class MeshInstance : public Intersectable {
+protected:
+  static int mailID;
+  int mailbox;
+  float mVisibility;
+  Mesh *mMesh;
+  
+public:
+  MeshInstance(Mesh *mesh):mMesh(mesh), mVisibility(1.0f), mailbox(0)
+  {
+  }
+  
+  void Mail() { mailbox = mailID; }
+  static void NewMail() { mailID++; }
+  bool Mailed() const { return mailbox == mailID; }
+  
+
+  Mesh *GetMesh() { return mMesh; }
+
+  virtual AxisAlignedBox3 GetBox() {
+    return mMesh->mBoundingBox;
+  }
+
+  virtual int
+  CastRay(
+	  Ray &ray
+	  );
+  
+
+};
+
+
+class MeshTransformedInstance : public MeshInstance
+{
+public:
+  MeshTransformedInstance(Mesh *mesh):MeshInstance(mesh)
+  {
+    mWorldTransform = IdentityMatrix();
+  }
+  
+  virtual AxisAlignedBox3 GetBox() {
+    return Transform(mMesh->mBoundingBox,
+		     mWorldTransform);
+  }
+
+  virtual int
+  CastRay(
+	  Ray &ray
+	  );
+
+private:
+  Matrix4x4 mWorldTransform;
+  
+};
+
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Parser.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Parser.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Parser.h	(revision 162)
@@ -0,0 +1,20 @@
+#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) = 0;
+  
+};
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VisibilityVector3.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VisibilityVector3.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VisibilityVector3.h	(revision 162)
@@ -0,0 +1,13 @@
+#ifndef _VisibilityVector3_H__
+#define _VisibilityVector3_H__
+
+#include "OgreVector3.h"
+
+namespace GtpVisibility {
+  /** Vector3 class currently uses the native Ogre vector when compiled with the Ogre platform */
+  typedef Ogre::Vector3 Vector3;
+}
+
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 162)
@@ -0,0 +1,1197 @@
+// ================================================================
+// $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,
+			     const 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,
+				const char *argv[],
+				const char *optParams)
+{
+  int i;
+
+  // Make sure we are called for the first time
+  if (optionalParams != NULL)
+    return;
+
+  numParams = 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 = strtod(options[i].value, NULL);
+  } else {
+    // option was not read, so use the default
+    value = 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,
+			   const 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 = 200;
+
+  
+// 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("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("IFS.loadKDtree", optBool, NULL, "true");
+  RegisterOption("IFS.kdtree", optBool, NULL, "true");
+  RegisterOption("IFS.KDTree.minCost", optFloat, NULL, "20");
+  RegisterOption("IFS.KDTree.maxDepth", optInt, NULL, "12");
+  RegisterOption("IFS.KDTree.ct_div_ci", optFloat, NULL, "1");
+  RegisterOption("IFS.KDTree.tries", optFloat, NULL, "3");
+  RegisterOption("IFS.KDTree.minCostImprovement", optFloat, NULL, "1.0");
+  
+  RegisterOption("IFS.KDTree.buildCostCoef", optFloat, NULL, "2");
+
+  RegisterOption("IFS.optimizeBuffers", optBool, NULL, "true");
+  RegisterOption("IFS.strips", optBool, NULL, "false");
+  RegisterOption("IFS.stripsRemap", optBool, NULL, "false");
+  RegisterOption("IFS.loadStrips", optBool,
+		 "loadStrips", "true");
+
+  RegisterOption("World.loadTextures", optBool,
+		 "loadTextures",
+		 "true" );
+
+  RegisterOption("World.loadTransparentTextures", optBool,
+		 "loadTransparentTextures",
+		 "true" );
+
+  RegisterOption("World.loadLightmaps", optBool,
+		 "loadLightmaps",
+		 "true" );
+
+  RegisterOption("World.loadImages", optBool,
+		 "loadImages",
+		 "true" );
+  
+}
+
+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, const 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: trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.cpp	(revision 162)
@@ -0,0 +1,598 @@
+#include "Matrix4x4.h"
+#include "Vector3.h"
+
+// standard headers
+#include <iomanip>
+using namespace std;
+
+
+
+// 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: trunk/VUT/GtpVisibilityPreprocessor/src/Containers.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Containers.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Containers.h	(revision 162)
@@ -0,0 +1,31 @@
+#ifndef _Container_H__
+#define _Container_H__
+
+#include <vector>
+using namespace std;
+
+class Mesh;
+class MeshInstance;
+class ViewCell;
+class HierarchyNode;
+class SceneGraphNode;
+
+/** Container for Mesh pointers primarily for the use within the kDTree and
+    BSP hierarchies */
+typedef vector<MeshInstance *> 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;
+
+typedef vector<SceneGraphNode *> SceneGraphNodeContainer;
+
+
+
+#endif // _Container_H__
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h	(revision 162)
@@ -0,0 +1,50 @@
+#ifndef __EXPORTER_H
+#define __EXPORTER_H
+
+#include <string>
+#include <vector>
+using namespace std;
+
+class KdTree;
+class SceneGraphNode;
+class Ray;
+class AxisAlignedBox3;
+class MeshInstance;
+
+class Exporter
+{
+protected:
+  string mFilename;
+  bool wireframe;
+
+public:
+  
+  Exporter(const string filename):mFilename(filename),wireframe(false)
+  {
+  }
+  
+  virtual bool ExportScene(SceneGraphNode *node) = 0;
+
+  virtual bool
+  ExportBox(const AxisAlignedBox3 &box) = 0;
+
+  virtual bool
+  ExportKdTree(const KdTree &tree) = 0;
+
+  virtual bool
+  ExportRays(const vector<Ray> &rays, const float length=1000) = 0;
+
+  virtual void
+  ExportMeshInstance(MeshInstance *mesh) = 0;
+  
+  SetWireframe() { wireframe = true; }
+  SetFilled() { wireframe = false; }
+
+  static Exporter *
+  GetExporter(const string filename);
+
+};
+ 
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.cpp	(revision 65)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.cpp	(revision 162)
@@ -1,11 +1,586 @@
+#include <stack>
+#include <algorithm>
+#include <queue>
+#include "Environment.h"
+#include "Mesh.h"
 #include "KdTree.h"
 
-namespace GtpVisibilityPreprocessor {
-  
-  bool
-  KdTree::Subdivide(KdNode *subtree)
-  {
-    return true;
-  }
-
-}
+
+
+
+KdNode::KdNode(KdInterior *parent):mParent(parent)
+{
+  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);
+
+  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 = new vector<SortableEntry>;
+}
+
+bool
+KdTree::Construct()
+{
+  // first construct a leaf that will get subdivide
+  KdLeaf *leaf = (KdLeaf *) mRoot;
+
+  mStat.nodes = 1;
+
+  mBox.Initialize();
+  
+  MeshContainer::const_iterator mi;
+  for ( mi = leaf->mObjects.begin();
+	mi != leaf->mObjects.end();
+	mi++) {
+    mBox.Include((*mi)->GetBox());
+  }
+
+  cout <<"box:"<< mBox<<endl;
+
+  
+  mRoot = Subdivide(TraversalData(leaf, mBox, 0));
+
+  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);
+
+  MeshContainer::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 -= leaf->mObjects.size();
+    mStat.objectRefs += objectsBack + objectsFront;
+  }
+  
+  delete leaf;
+  return node;
+}
+
+
+
+void
+KdTreeStatistics::Print(ostream &app) const
+{
+  app << "===== KdTree statistics ===============\n";
+
+  app << "#N_RAYS Number of rays )\n"
+      << rays <<endl;
+  app << "#N_DOMAINS  ( Number of query domains )\n"
+      << queryDomains <<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_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 = leaf->mObjects.size();
+  
+}
+
+
+
+void
+KdTree::SortSplitCandidates(
+			    KdLeaf *node,
+			    const int axis
+			    )
+{
+  splitCandidates->clear();
+  
+  int requestedSize = 2*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(MeshContainer::const_iterator mi = node->mObjects.begin();
+      mi < node->mObjects.end();
+      mi++) {
+    AxisAlignedBox3 box = (*mi)->GetBox();
+
+    splitCandidates->push_back(SortableEntry(SortableEntry::MESH_MIN,
+					     box.Min(axis),
+					     (void *)*mi)
+			       );
+    
+    
+    splitCandidates->push_back(SortableEntry(SortableEntry::MESH_MAX,
+					     box.Max(axis),
+					     (void *)*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
+
+  int ol = 0, or = 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 = 1e20;
+  
+  for(vector<SortableEntry>::const_iterator ci = splitCandidates->begin();
+      ci < splitCandidates->end();
+      ci++) {
+    
+    switch ((*ci).type) {
+    case SortableEntry::MESH_MIN:
+      ol++;
+      break;
+    case SortableEntry::MESH_MAX:
+      or--;
+      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 = ol*lbox.SurfaceArea() + or*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 = ol;
+	objectsFront = or;
+      }
+    }
+  }
+  
+  float oldCost = 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;
+
+  
+  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;
+      ray.leaves.push_back(leaf);
+      
+      MeshContainer::const_iterator mi;
+      for ( mi = leaf->mObjects.begin();
+	    mi != leaf->mObjects.end();
+	    mi++) {
+	MeshInstance *mesh = *mi;
+	if (!mesh->Mailed() ) {
+	  mesh->Mail();
+	  //ray.meshes.push_back(mesh);
+	  hits += mesh->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;
+      RayTraversalData &s  = tStack.top();
+      node = s.mNode;
+      extp = s.mExitPoint;
+      maxt = s.mMaxT;
+      tStack.pop();
+    }
+  }
+  
+  
+  return hits;
+}
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.cpp	(revision 162)
@@ -0,0 +1,53 @@
+//#include <boost/algorithm/string.hpp>
+
+#include <stack>
+#include "SceneGraph.h"
+#include "X3dExporter.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::CollectMeshInstaces(MeshContainer *instances)
+{
+  int number = 0;
+  stack<SceneGraphNode *> nodeStack;
+
+  nodeStack.push(mRoot);
+  
+  while (!nodeStack.empty()) {
+    SceneGraphNode *node = nodeStack.top();
+    nodeStack.pop();
+
+    MeshContainer::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;
+}
+
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ExactPreprocessor.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ExactPreprocessor.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ExactPreprocessor.h	(revision 162)
@@ -0,0 +1,15 @@
+#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: trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.h	(revision 162)
@@ -0,0 +1,83 @@
+#ifndef __X3DPARSER_H
+#define __X3DPARSER_H
+
+#include "parser.h"
+#include "mesh.h"
+
+#include <X3DTK/MESH/scenegraph.h>
+#include <X3DTK/kernel.h>
+#include <X3DTK/MESH/scenegraph.h>
+
+class X3dParser : public Parser
+{
+public:
+  X3dParser():Parser() {}
+  
+  
+  bool ParseFile(const string filename, SceneGraphNode **root);
+  
+};
+
+};
+
+
+namespace X3DTK {
+namespace MESH {
+
+class MyStructureComputerStateVariables : public StateVariables
+{
+public:
+  MyStructureComputerStateVariables();
+  
+  void init();
+  void finish();
+  
+  void beginNewMesh();
+  inline void addVertex(float x, float y, float z) {
+    //_mesh->addVertex(x, y, z);
+  };
+
+  void addFace(const Face &face);
+
+  void pushMatrix(const SFMatrix34f &transformation);  
+  void popMatrix();
+  
+inline Mesh *getMesh() const {return _mesh;};  
+  SFMatrix34f getMatrix() const {return _matrixStack.front();};
+  
+private: 
+  Mesh *_mesh;
+  unsigned int _decal;
+  std::list<SFMatrix34f> _matrixStack;
+};
+  
+  // MyStructureComputer processor.
+  
+  class MyStructureComputer : public X3DOnePassProcessor
+  {
+public:
+    MyStructureComputer();
+    virtual ~MyStructureComputer();
+    
+    virtual Mesh *compute(SFNode N);
+  };
+
+  class X3DGroupingNode;
+  class Transform;
+  
+  /// Visitor for the Core component of the MyStructureComputer module.
+  
+  class MyStructureComputerCoreVisitor : public CoreVisitor
+  {
+  public:
+    MyStructureComputerCoreVisitor();
+    
+    static void enterMesh(Mesh *M);
+    static void enterTransform(Transform *T);
+    static void leaveX3DGroupingNode(X3DGroupingNode *N);
+  };
+  
+}
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp	(revision 65)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp	(revision 162)
@@ -1,13 +1,10 @@
 #include "SamplingPreprocessor.h"
 
-namespace GtpVisibilityPreprocessor {
+
   
-  bool
-  SamplingPreprocessor::ComputeVisibility()
-  {
-
-    return true;
-  };
-  
+bool
+SamplingPreprocessor::ComputeVisibility()
+{
+  return true;
 };
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp	(revision 162)
@@ -0,0 +1,1509 @@
+
+// GOLEM library
+#include <assert.h>
+#include <iostream>
+using namespace std;
+#include "AxisAlignedBox3.h"
+#include "Ray.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 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;
+  }
+}
+
+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
+{
+  register float minx, maxx;
+  ray.ComputeInvertedDir();
+  
+  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.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) < 0.001) {
+    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) < 0.001) {
+    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(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.0 * (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.0 + 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.0 - 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.0)) - atan22(b*c/sqrt(b*b + c*c + 1.0))
+      - atan22(d*a/sqrt(a*a + d*d + 1.0)) + atan22(a*c/sqrt(a*a + c*c + 1.0));
+  }
+
+#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;
+
+
+}
+
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.cpp	(revision 162)
@@ -0,0 +1,189 @@
+#include "Vector3.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;  
+}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 65)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 162)
@@ -1,54 +1,86 @@
+#include "SceneGraph.h"
+#include "Exporter.h"
+#include "UnigraphicsParser.h"
 #include "Preprocessor.h"
-#include "SamplingPreprocessor.h"
-#include "ExactPreprocessor.h"
 
-namespace GtpVisibilityPreprocessor {
 
-  bool
-  Preprocessor::LoadViewcells(const string filename)
-  {
 
+  
+bool
+Preprocessor::LoadViewcells(const string filename)
+{
+  
+  return true;
+}
+
+bool
+Preprocessor::GenerateViewcells()
+{
+  
+  return true;
+}
+
+bool
+Preprocessor::LoadScene(const string filename)
+{
+  // use leaf nodes of the original spatial hiearrchy as occludees
+
+  mSceneGraph = new SceneGraph;
+  Parser *parser = new UnigraphicsParser;
+  bool result = parser->ParseFile(filename, &mSceneGraph->mRoot);
+  
+  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->CollectMeshInstaces(&root->mObjects);
+  
+  mKdTree->Construct();
+  return true;
+}
+
+
+void
+Preprocessor::KdTreeStatistics(ostream &s)
+{
+  s<<mKdTree->GetStatistics();
+}
+
+
+bool
+Preprocessor::Export( const string filename,
+		      const bool scene,
+		      const bool kdtree
+		      )
+{
+  Exporter *exporter = Exporter::GetExporter(filename);
+
+  if (exporter) {
+    if (scene)
+      exporter->ExportScene(mSceneGraph->mRoot);
+
+    if (kdtree) {
+      exporter->SetWireframe();
+      exporter->ExportKdTree(*mKdTree);
+    }
+
+    delete exporter;
     return true;
   }
 
-  bool
-  Preprocessor::GenerateViewcells()
-  {
-    
-    return true;
-  }
-    
-  bool
-  Preprocessor::LoadScene(const string filename)
-  {
-    // use leaf nodes of the original spatial hiearrchy as occludees
-    
-    return true;
-  }
+  return false;
+}
 
-  bool
-  Preprocessor::ExportPreprocessedData(const string filename)
-  {
-    return false;
-  }
-  
-  bool
-  Preprocessor::BuildKdTree()
-  {
-    mKdTree = new KdTree;
-    mKdTree->Subdivide(mKdTree->GetRoot());
-    return true;
-  }
-  
-};
 
-int
-main(int argc, char **argv)
-{
-  GtpVisibilityPreprocessor::Preprocessor *p = new GtpVisibilityPreprocessor::SamplingPreprocessor();
-  p->LoadScene("scene.wrl");
-  p->LoadViewcells("viewcells.wrl");
-  p->ComputeVisibility();
-  p->ExportPreprocessedData("scene.vis");
-  return 0;
-}
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h	(revision 162)
@@ -0,0 +1,35 @@
+#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);
+
+  }
+
+  friend ostream &operator<<(ostream &s, const Plane3 p) {
+    s<<p.mNormal<<" "<<p.mD;
+    return s;
+  }
+
+};
+  
+
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Camera.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Camera.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Camera.cpp	(revision 162)
@@ -0,0 +1,99 @@
+#include <algorithm>
+#include <qstring.h>
+#include <qimage.h>
+#include "Camera.h"
+#include "Ray.h"
+#include "KdTree.h"
+#include "Mesh.h"
+#include "Exporter.h"
+
+bool
+Camera::SnapImage(string filename,
+		  KdTree *tree
+		  )
+{
+  int x;
+  int y;
+
+  bool exportRays = true;
+
+  
+  
+  QImage image(mWidth, mHeight, 32);
+  vector<Ray> rays;
+
+  long t1 = GetTime();
+
+  Ray ray;
+  for (y = 0; y < mHeight; y++) {
+    cout<<"+";
+    for (x = 0; x < mWidth; x++) {
+      SetupRay(ray, x, y);
+      MeshInstance::NewMail();
+      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;
+	  image.setPixel(x, y, qRgb(color.r*255,
+				    color.g*255,
+				    color.b*255
+				    ));
+	}
+      
+      if (exportRays && (x==222) && (y==97))
+	rays.push_back(ray);
+    }
+  }
+  
+  long t2 = GetTime();
+  cout<<"#RAY_CAST_TIME"<<endl<<TimeDiff(t1, t2)<<endl;
+
+  cerr<<"Saving image"<<endl;
+  image.save(filename, "PNG");
+
+  Exporter *exporter = NULL;
+  if (exportRays) {
+    exporter = Exporter::GetExporter(filename + "-rays" + ".x3d");
+    exporter->SetWireframe();
+    exporter->ExportKdTree(*tree);
+    exporter->ExportRays(rays, 10000);
+    exporter->SetFilled();
+    int k =0;
+    for (int j=0; j < rays.size(); j++)
+      if (rays[j].leaves.size()) {
+	Ray *ray = &(rays[j]);
+	int i;
+	if (1)
+	for (i= 0; i < ray->leaves.size(); i++)
+	  exporter->ExportBox(tree->GetBox(ray->leaves[i]));
+	if (0)
+	for (i= 0; i < ray->meshes.size(); i++)
+	  exporter->ExportMeshInstance(ray->meshes[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.intersections.clear();
+  ray.leaves.clear();
+  ray.meshes.clear();
+  
+  ray.Init(mPosition, target, Ray::LOCAL_RAY);
+  
+}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Ray.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Ray.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Ray.cpp	(revision 162)
@@ -0,0 +1,122 @@
+#include "Ray.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-6;
+
+  // 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-6;
+  const float invEps = 1e6;
+  
+  // 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.0 / dir.x;
+  
+  if (fabs(dir.y) < eps) {
+    if (dir.y < 0.0)
+      invDir.y = -invEps;
+    else
+      invDir.y = invEps;
+  }
+  else
+    invDir.y = 1.0 / dir.y;
+  
+  if (fabs(dir.z) < eps) {
+    if (dir.z < 0.0)
+      invDir.z = -invEps;
+    else
+      invDir.z = invEps;
+  }
+  else
+    invDir.z = 1.0 / dir.z;
+
+  return;
+}
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.cpp	(revision 162)
@@ -0,0 +1,207 @@
+#include "ray.h"
+#include "Mesh.h"
+
+int MeshInstance::mailID = 21843194198;
+
+void
+Mesh::Preprocess()
+{
+  mBoundingBox.Initialize();
+
+  VertexContainer::const_iterator vi = mVertices.begin();
+  for (; vi != mVertices.end(); vi++) {
+    mBoundingBox.Include(*vi);
+  }
+  
+  mIsConvex = false;
+}
+
+
+int
+Mesh::CastRay(
+	      Ray &ray,
+	      MeshInstance *instance
+	      )
+{
+  FaceContainer::const_iterator fi;
+  int faceIndex = 0;
+  int hits = 0;
+  float nearestT = MAX_FLOAT;
+  float nearestFace;
+
+  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
+    nearestT = ray.intersections[0].mT;
+
+  
+  for ( ;
+	faceIndex < mFaces.size();
+	faceIndex++) {
+    float t;
+    if (RayFaceIntersection(faceIndex, ray, t, nearestT) == Ray::INTERSECTION) {
+      switch (ray.GetType()) {
+      case Ray::GLOBAL_RAY:
+	ray.intersections.push_back(Ray::RayIntersection(t, instance, faceIndex));
+	hits++;
+	break;
+      case Ray::LOCAL_RAY:
+	hits++;
+	nearestT = t;
+	nearestFace = faceIndex;
+	break;
+      }
+    }
+  }
+  
+  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
+    if (ray.intersections.size())
+      ray.intersections[0] = Ray::RayIntersection(nearestT, instance, nearestFace);
+    else
+      ray.intersections.push_back(Ray::RayIntersection(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 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;
+}
+
+
+
+// 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 (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);
+
+
+  mVertices[face->mVertexIndices[face->mVertexIndices.size() - 1]].
+    ExtractVerts(&u1, &v1, paxis );
+
+  if (mIsConvex) {
+    // assume a convex face
+    for (i = 0; i < face->mVertexIndices.size(); i++) {
+      mVertices[face->mVertexIndices[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 < face->mVertexIndices.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
+MeshInstance::CastRay(
+		      Ray &ray
+		      )
+{
+  int res = mMesh->CastRay(ray, this);
+  return res;
+}
+
+
+Plane3
+Mesh::GetFacePlane(const int faceIndex)
+{
+  Face *face = mFaces[faceIndex];
+  return Plane3(mVertices[face->mVertexIndices[0]],
+		mVertices[face->mVertexIndices[1]],
+		mVertices[face->mVertexIndices[2]]);
+}
+
+int
+MeshTransformedInstance::CastRay(
+				 Ray &ray
+				 )
+{
+  ray.ApplyTransform(Invert(mWorldTransform));
+  int res = mMesh->CastRay(ray, this);
+  ray.ApplyTransform(mWorldTransform);
+  
+  return res;
+}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h	(revision 162)
@@ -0,0 +1,60 @@
+#ifndef __X3DEXPORTER_H
+#define __X3DEXPORTER_H
+
+#include <string>
+using std::string;
+
+#include <iostream>
+#include <fstream>
+
+#include "Exporter.h"
+
+class SceneGraphNode;
+class Mesh;
+
+
+
+class X3dExporter : public Exporter
+{
+  std::ofstream stream;
+
+public:
+
+  X3dExporter(const string filename);
+
+  ~X3dExporter();
+
+
+  bool
+  ExportRays(const vector<Ray> &rays, const float length=1000);
+
+  bool
+  ExportKdTree(const KdTree &tree);
+  
+  bool
+  ExportScene(SceneGraphNode *root) 
+  {
+    ExportSceneNode(root);
+    return true;
+  }
+  
+  bool
+  ExportBox(const AxisAlignedBox3 &box);
+
+  virtual void
+  ExportMeshInstance(MeshInstance *mi);
+
+  void
+  ExportMesh(Mesh *mesh);
+
+protected:
+  void
+  ExportSceneNode(SceneGraphNode *node);
+  
+
+  
+};
+ 
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/gzstream.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/gzstream.cpp	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/gzstream.cpp	(revision 162)
@@ -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: trunk/VUT/GtpVisibilityPreprocessor/src/common.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/common.h	(revision 162)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/common.h	(revision 162)
@@ -0,0 +1,455 @@
+// ================================================================
+// $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
+
+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
+
+
+
+
+
+
+
+
+
+
+
