Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.h	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.h	(revision 176)
@@ -47,5 +47,5 @@
   // create the rotation matrix that rotates 'vecFrom' to 'vecTo'
   friend Matrix4x4 RotationVectorsMatrix(const Vector3 &vecFrom,
-					const Vector3 &vecTo);
+					 const Vector3 &vecTo);
   
   friend Matrix4x4 ScaleMatrix(float X, float Y, float Z);
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.cpp	(revision 170)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.cpp	(revision 176)
@@ -27,6 +27,4 @@
 #include "Mesh.h"
 #include "SceneGraph.h"
-
-
 
 // ---------------------------------------------------------------------------
@@ -62,10 +60,10 @@
 // ---------------------------------------------------------------------------
 X3dParseHandlers::X3dParseHandlers(SceneGraphNode *root) :
-  fElementCount(0)
-  , fAttrCount(0)
-  , fCharacterCount(0)
-  , fSpaceCount(0)
-{
-  currentNode = root;
+  mElementCount(0)
+  , mAttrCount(0)
+  , mCharacterCount(0)
+  , mSpaceCount(0)
+{
+  mCurrentNode = root;
 }
 
@@ -81,5 +79,5 @@
 {
   StrX lname(name);
-  string element(lname.localForm());
+  string element(lname.LocalForm());
   if (element == "Shape")
     EndShape();
@@ -89,9 +87,14 @@
 X3dParseHandlers::EndShape()
 {
-  currentMesh->Preprocess();
-  // make an instance of this mesh
-  MeshInstance *mi = new MeshInstance(currentMesh);
-  currentNode->mGeometry.push_back(mi); 
-  currentMesh = NULL;
+  if (mCurrentMesh->mFaces.size()) {
+    mCurrentMesh->Preprocess();
+    // make an instance of this mesh
+    MeshInstance *mi = new MeshInstance(mCurrentMesh);
+    mCurrentNode->mGeometry.push_back(mi);
+  } else {
+    cout<<"X";
+    delete mCurrentMesh;
+  }
+  mCurrentMesh = NULL;
 }
 
@@ -105,10 +108,10 @@
   
   for (i=0; i < len; i++) {
-    string attrName(StrX(attributes.getName(i)).localForm());
+    string attrName(StrX(attributes.getName(i)).LocalForm());
     if (attrName == "coordIndex") {
       StrX attrValue(attributes.getValue(i));
       // handle coordIndex
       vertices.clear();
-      const char *ptr = attrValue.localForm();
+      const char *ptr = attrValue.LocalForm();
       char *endptr;
       while(1) {
@@ -117,5 +120,5 @@
 	  if (vertices.size() > 2) {
 	    Face *face = new Face(vertices);
-	    currentMesh->mFaces.push_back(face);
+	    mCurrentMesh->mFaces.push_back(face);
 	  }
 	  vertices.clear();
@@ -137,14 +140,14 @@
   int len = attributes.getLength();
   int i;
-  if (!currentMesh->mMaterial)
-    currentMesh->mMaterial = new Material;
+  if (!mCurrentMesh->mMaterial)
+    mCurrentMesh->mMaterial = new Material;
   for (i=0; i < len; i++) {
-    string attrName(StrX(attributes.getName(i)).localForm());
+    string attrName(StrX(attributes.getName(i)).LocalForm());
     StrX attrValue(attributes.getValue(i));
-    const char *ptr = attrValue.localForm();
+    const char *ptr = attrValue.LocalForm();
     if (attrName == "diffuseColor") {
       float r, g, b;
       if (sscanf(ptr, "%f %f %f", &r, &g, &b) == 3)
-	currentMesh->mMaterial->mDiffuseColor = RgbColor(r, g, b);
+	mCurrentMesh->mMaterial->mDiffuseColor = RgbColor(r, g, b);
     }
   }
@@ -159,8 +162,8 @@
   VertexContainer vertices;
   for (i=0; i < len; i++) {
-    string attrName(StrX(attributes.getName(i)).localForm());
+    string attrName(StrX(attributes.getName(i)).LocalForm());
     if (attrName == "point") {
       StrX attrValue(attributes.getValue(i));
-      const char *ptr = attrValue.localForm();
+      const char *ptr = attrValue.LocalForm();
       char *endptr;
       while(1) {
@@ -182,5 +185,5 @@
 	vertices.push_back(v);
       }
-      currentMesh->mVertices = vertices;
+      mCurrentMesh->mVertices = vertices;
     }
   }
@@ -193,5 +196,5 @@
 {
   StrX lname(name);
-  string element(lname.localForm());
+  string element(lname.LocalForm());
   
   if (element == "IndexedFaceSet") {
@@ -202,9 +205,9 @@
   if (element == "Shape") {
     cout<<"+";
-    currentMesh = new Mesh;
+    mCurrentMesh = new Mesh;
   }
   
   if (element == "Coordinate") {
-    if (currentMesh)
+    if (mCurrentMesh)
       StartCoordinate(attributes);
   }
@@ -214,6 +217,6 @@
   }
 
-  fElementCount++;
-  fAttrCount += attributes.getLength();
+  mElementCount++;
+  mAttrCount += attributes.getLength();
 }
 
@@ -222,5 +225,5 @@
 			     const unsigned int length)
 {
-  fCharacterCount += length;
+  mCharacterCount += length;
 }
 
@@ -229,5 +232,5 @@
 				      const unsigned int length)
 {
-  fSpaceCount += length;
+  mSpaceCount += length;
 }
 
@@ -235,8 +238,8 @@
 X3dParseHandlers::resetDocument()
 {
-  fAttrCount = 0;
-  fCharacterCount = 0;
-  fElementCount = 0;
-  fSpaceCount = 0;
+  mAttrCount = 0;
+  mCharacterCount = 0;
+  mElementCount = 0;
+  mSpaceCount = 0;
 }
 
@@ -345,12 +348,13 @@
 	return false;
       }
+
     
     // Print out the stats that we collected and time taken
     if (!errorCount) {
       XERCES_STD_QUALIFIER cout << filename << ": " << duration << " ms ("
-				<< handler.getElementCount() << " elems, "
-				<< handler.getAttrCount() << " attrs, "
-				<< handler.getSpaceCount() << " spaces, "
-				<< handler.getCharacterCount() << " chars)" << XERCES_STD_QUALIFIER endl;
+				<< handler.GetElementCount() << " elems, "
+				<< handler.GetAttrCount() << " attrs, "
+				<< handler.GetSpaceCount() << " spaces, "
+				<< handler.GetCharacterCount() << " chars)" << XERCES_STD_QUALIFIER endl;
     }
   }
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.h	(revision 170)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.h	(revision 176)
@@ -13,4 +13,5 @@
 class KdLeaf;
 class KdInterior;
+class Intersectable;
 
 
@@ -156,5 +157,5 @@
 
   /** pointers to occluders contained in this node */
-  MeshContainer mObjects;
+  ObjectContainer mObjects;
   
   /** pointers to viewcells contained in this node */
@@ -220,13 +221,4 @@
   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 */
@@ -266,4 +258,7 @@
   }
 
+  void
+  CollectObjects(KdNode *n, ObjectContainer &objects);
+  
     AxisAlignedBox3 GetBox(const KdNode *node) const {
     KdInterior *parent = node->mParent;
@@ -383,16 +378,16 @@
   {
     enum {
-      MESH_MIN,
-      MESH_MAX
+      BOX_MIN,
+      BOX_MAX
     };
     
     int type;
     float value;
-    void *data;
+    Intersectable *intersectable;
     
     SortableEntry() {}
-    SortableEntry(const int t, const float v, void *d):type(t),
-						       value(v),
-						       data(d) {}
+    SortableEntry(const int t, const float v, Intersectable *i):type(t),
+								value(v),
+								intersectable(i) {}
     
     bool operator<(const SortableEntry &b) const {
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.h	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.h	(revision 176)
@@ -13,7 +13,5 @@
 class SceneGraphNode {
 public:
-  
-  
-  MeshContainer mGeometry;
+  ObjectContainer mGeometry;
   SceneGraphNodeContainer mChildren;
   AxisAlignedBox3 mBox;
@@ -28,5 +26,5 @@
   bool Export(const string filename);
   
-  int CollectMeshInstaces(MeshContainer *instances);
+  int CollectObjects(ObjectContainer *instances);
   
 protected:
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp	(revision 170)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp	(revision 176)
@@ -31,5 +31,5 @@
 
   //  p->mSceneGraph->Export("soda.x3d");
-  if (1) {
+  if (0) {
     p->Export(filename + "-out.x3d", true, false);
     p->Export(filename + "-kdtree.x3d", false, true);
@@ -37,8 +37,10 @@
   
   //  p->LoadViewcells("viewcells.wrl");
-  p->ComputeVisibility();
-  p->ExportPreprocessedData("scene.vis");
+  if (1) {
+    p->ComputeVisibility();
+    p->ExportPreprocessedData("scene.vis");
+  }
   
-  if (1) {
+  if (0) {
     Camera camera;
     camera.LookAtBox(p->mKdTree->GetBox());
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h	(revision 176)
@@ -9,5 +9,21 @@
 class SamplingPreprocessor : public Preprocessor {
 public:
+  int mSamplesPerPass;
+  int mTotalSamples;
+  int mKdPvsDepth;
+  
+  SamplingPreprocessor();
+
   virtual bool ComputeVisibility();
+
+  void
+  SetupRay(Ray &ray, const Vector3 &point, const Vector3 &direction);
+
+  KdNode *
+  GetNodeForPvs(KdLeaf *leaf);
+
+  int
+  AddNodeSamples(Intersectable *object, const Ray &ray);
+
 };
 
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 176)
@@ -23,9 +23,17 @@
 }
 
+
 bool
-X3dExporter::ExportRays(const vector<Ray> &rays, const float length)
+X3dExporter::ExportRays(const vector<Ray> &rays,
+			const float length,
+			const RgbColor &color)
 {
   vector<Ray>::const_iterator ri = rays.begin();
   stream<<"<Shape>"<<endl;
+  stream<<"<Appearance>"<<endl;
+  stream<<"<Material ambientColor=\""<<color.r<<" "<<color.g<<" "<<color.b<<
+    "\" />"<<endl;
+  stream<<"</Appearance>"<<endl;
+  
   stream<<"<IndexedLineSet ccw=\"TRUE\" coordIndex=\""<<endl;
 
@@ -43,5 +51,13 @@
   for (; ri != rays.end(); ri++) {
     Vector3 a = (*ri).GetLoc();
-    Vector3 b = (*ri).GetLoc() + length*(*ri).GetDir();
+    
+    Vector3 b;
+    if (length < 0)
+      b = (*ri).GetLoc() - length*(*ri).GetDir();
+    else
+      if ((*ri).intersections.size()==0)
+	b = (*ri).GetLoc() + length*(*ri).GetDir();
+      else
+	b = (*ri).Extrap((*ri).intersections[0].mT);
     
     stream<<a.x<<" "<<a.y<<" "<<a.z<<" ,";
@@ -66,12 +82,34 @@
   
   
-  MeshContainer::const_iterator mi = node->mGeometry.begin();
+  ObjectContainer::const_iterator mi = node->mGeometry.begin();
   for (; mi != node->mGeometry.end(); mi++) {
     // export the transform...
-    ExportMesh((*mi)->GetMesh());
+    ExportIntersectable(*mi);
   }
   
   stream<<"</Group>"<<endl;
 
+}
+void
+X3dExporter::ExportIntersectable(Intersectable *object)
+{
+  switch (object->Type()) {
+  case Intersectable::MESH_INSTANCE:
+  case Intersectable::TRANSFORMED_MESH_INSTANCE:
+    ExportMeshInstance((MeshInstance *)object);
+    break;
+  default:
+    cerr<<"Sorry the export for object not yet defined"<<endl;
+    break;
+  }
+}
+
+void
+X3dExporter::ExportMeshInstance(MeshInstance *object)
+{
+  // $$JB$$
+  // in the future check whether the mesh was not already exportet
+  // and use a reference to the that mesh instead
+  ExportMesh(object->GetMesh());
 }
 
@@ -82,18 +120,24 @@
   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);
-  }
+  if (mUseForcedMaterial) {
+    r = mForcedMaterial.mDiffuseColor.r;
+    g = mForcedMaterial.mDiffuseColor.g;
+    b = mForcedMaterial.mDiffuseColor.b;
+    
+  } else
+    if (mesh->mMaterial) {
+      r = mesh->mMaterial->mDiffuseColor.r;
+      g = mesh->mMaterial->mDiffuseColor.g;
+      b = mesh->mMaterial->mDiffuseColor.b;
+    } else {
+      r = RandomValue(0.5, 1.0);
+      g = RandomValue(0.5, 1.0);
+      b = RandomValue(0.5, 1.0);
+    }
   stream<<"<Material diffuseColor=\""<<r<<" "<<g<<" "<<b<<
     "\" specularColor=\"0.0 0.0 0.0\"/>"<<endl;
@@ -205,7 +249,2 @@
 
 
-void
-X3dExporter::ExportMeshInstance(MeshInstance *mi)
-{
-  ExportMesh(mi->GetMesh());
-}
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Intersectable.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Intersectable.h	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Intersectable.h	(revision 176)
@@ -2,8 +2,35 @@
 #define __INTERSECTABLE_H
 
+#include "AxisAlignedBox3.h"
+#include "Pvs.h"
+
 
 class Intersectable {
+public:
+  static int mailID;
+  int mailbox;
+
+  KdPvs mKdPvs;
   
+  enum { MESH_INSTANCE, TRANSFORMED_MESH_INSTANCE, SPHERE };
   
+  Intersectable():mailbox(0) {}
+  
+  void Mail() { mailbox = mailID; }
+  static void NewMail() { mailID++; }
+  bool Mailed() const { return mailbox == mailID; }
+  
+  virtual AxisAlignedBox3 GetBox() = 0;
+  
+  virtual int CastRay(Ray &ray) = 0;
+  
+  virtual bool IsConvex() = 0;
+  virtual bool IsWatertight() = 0;
+  virtual float IntersectionComplexity() = 0;
+  
+  virtual int Type() const = 0;
+
+  virtual void GetRandomSurfacePoint(Vector3 &point, Vector3 &normal) = 0;
+
 };
 
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/default.env
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/default.env	(revision 170)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/default.env	(revision 176)
@@ -6,4 +6,6 @@
 Scene {
 
+#	filename glasgow1.x3d
+#	filename vienna.x3d
 #	filename atlanta2.x3d
 	filename soda.dat
@@ -19,5 +21,5 @@
 
 Unigraphics {
-		meshGrouping 1000
+		meshGrouping 1
 }
 
@@ -48,2 +50,8 @@
 	splitBorder 0.01
 }
+
+
+SamplingPreprocessor {
+
+
+}
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.h	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.h	(revision 176)
@@ -226,4 +226,6 @@
   friend inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2, float thr);
   friend inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2);
+
+  friend Vector3 UniformRandomVector(const Vector3 &normal);
 };
 
@@ -411,6 +413,6 @@
 {
   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);
+		 A.z * B.x - A.x * B.z,
+		 A.x * B.y - A.y * B.x);
 }
 
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h	(revision 176)
@@ -84,7 +84,7 @@
   
   /// list of all loaded occluders
-  MeshContainer mOccluders;
+  ObjectContainer mOccluders;
   /// list of all loaded occludees
-  MeshContainer mOccludees;
+  ObjectContainer mOccludees;
   /// list of all loaded/generated viewcells
   ViewCellContainer mViewcells;
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h	(revision 176)
@@ -28,11 +28,15 @@
     // 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() {}
 
@@ -44,8 +48,11 @@
 	b.mT;
     }
-
-
     
   };
+  
+  // I should have some abstract cell data type !!! here
+  // corresponds to the spatial elementary cell
+  /** intersection with the source object if any */
+  RayIntersection sourceObject;
   
   vector<RayIntersection> intersections;
@@ -61,6 +68,4 @@
     dir = Normalize(whichdir);
     mType = _type;
-    origin = _originCell;
-    termination = NULL;
     depth = 0;
     Init();
@@ -72,11 +77,9 @@
   // Inititalize the ray again when already constructed
   void Init(const Vector3 &wherefrom, const Vector3 &whichdir,
-	    const int _type, const void *_originCell = NULL,
+	    const int _type, 
 	    bool dirNormalized = false) {
     loc = wherefrom;
     dir = (dirNormalized) ? whichdir: Normalize(whichdir) ;
     mType = _type;
-    origin = _originCell;
-    termination = NULL;
     depth = 0;
     Init();
@@ -146,11 +149,4 @@
   }
 
-  // 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
@@ -183,5 +179,4 @@
   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();
@@ -191,11 +186,8 @@
   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
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.h	(revision 170)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.h	(revision 176)
@@ -50,5 +50,4 @@
 class Mesh {
 
-
 public:
 
@@ -58,7 +57,11 @@
   /// Constructor with container preallocation
   Mesh(const int vertices,
-       const int faces):mVertices(),
-			mFaces(),
-			mMaterial(NULL)
+       const int faces):
+    mFaces(),
+    mMaterial(NULL),
+    mKdTree(NULL),
+    mVertices(),
+    mIsConvex(false),
+    mIsWatertight(false)
   {
     mVertices.reserve(vertices);
@@ -78,6 +81,6 @@
   void Preprocess();
 
-  /** Axis aligned bounding box of the mesh */
-  AxisAlignedBox3 mBoundingBox;
+  /** Axis aligned bounding box of the mesh in local mesh coordinates */
+  AxisAlignedBox3 mBox;
   
   /** Vertices forming the mesh */
@@ -92,4 +95,7 @@
   /** true if the mesh is a convex mesh */
   bool mIsConvex;
+
+  /** true if the mesh is a convex mesh */
+  bool mIsWatertight;
 
   MeshKdTree *mKdTree;
@@ -128,28 +134,25 @@
 
   AxisAlignedBox3 GetFaceBox(const int faceIndex);
-  
+
+  void GetRandomSurfacePoint(Vector3 &point, Vector3 &normal);
+
 };
 
 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; }
-  
+  MeshInstance(Mesh *mesh):Intersectable(), mMesh(mesh)
+  {
+  }
+
+  void GetRandomSurfacePoint(Vector3 &point, Vector3 &normal);
+
 
   Mesh *GetMesh() { return mMesh; }
 
   virtual AxisAlignedBox3 GetBox() {
-    return mMesh->mBoundingBox;
+    return mMesh->mBox;
   }
 
@@ -158,5 +161,11 @@
 	  Ray &ray
 	  );
-  
+
+  virtual bool IsConvex() { return mMesh->mIsConvex; }
+  virtual bool IsWatertight() { return mMesh->mIsWatertight; }
+  virtual float IntersectionComplexity() {  return mMesh->mFaces.size(); }
+
+  virtual int Type() const { return MESH_INSTANCE; }
+
   virtual int
   CastRay(
@@ -169,8 +178,8 @@
 
 
-class MeshTransformedInstance : public MeshInstance
+class TransformedMeshInstance : public MeshInstance
 {
 public:
-  MeshTransformedInstance(Mesh *mesh):MeshInstance(mesh)
+  TransformedMeshInstance(Mesh *mesh):MeshInstance(mesh)
   {
     mWorldTransform = IdentityMatrix();
@@ -178,12 +187,16 @@
   
   virtual AxisAlignedBox3 GetBox() {
-    return Transform(mMesh->mBoundingBox,
+    return Transform(mMesh->mBox,
 		     mWorldTransform);
   }
-
+  
   virtual int
   CastRay(
 	  Ray &ray
 	  );
+
+  virtual int Type() const { return TRANSFORMED_MESH_INSTANCE; }
+
+  void GetRandomSurfacePoint(Vector3 &point, Vector3 &normal);
 
 private:
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/preprocessor.pro
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/preprocessor.pro	(revision 170)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/preprocessor.pro	(revision 176)
@@ -31,5 +31,5 @@
 UnigraphicsParser.cpp X3dExporter.cpp SceneGraph.cpp Material.cpp \
 Matrix4x4.cpp Vector3.cpp AxisAlignedBox3.cpp Ray.cpp main.cpp Mesh.cpp \
-Exporter.cpp Camera.cpp X3dParser.cpp MeshKdTree.cpp
+Exporter.cpp Camera.cpp X3dParser.cpp MeshKdTree.cpp Pvs.cpp
 
 
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.cpp	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.cpp	(revision 176)
@@ -300,5 +300,5 @@
 {
   Vector3 vec = CrossProd(vecStart, vecTo);
-
+  
   if (Magnitude(vec) > Limits::Small) {
     // vector exist, compute angle
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Containers.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Containers.h	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Containers.h	(revision 176)
@@ -5,13 +5,12 @@
 using namespace std;
 
-class Mesh;
-class MeshInstance;
 class ViewCell;
 class HierarchyNode;
 class SceneGraphNode;
+class Intersectable;
 
 /** Container for Mesh pointers primarily for the use within the kDTree and
     BSP hierarchies */
-typedef vector<MeshInstance *> MeshContainer;
+typedef vector<Intersectable *> ObjectContainer;
 
 /** Container for ViewCell pointers primarily for the use within the kDTree and
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h	(revision 170)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h	(revision 176)
@@ -6,9 +6,11 @@
 using namespace std;
 
+#include "Material.h"
+
 class KdTree;
 class SceneGraphNode;
 class Ray;
 class AxisAlignedBox3;
-class MeshInstance;
+class Intersectable;
 
 class Exporter
@@ -17,8 +19,12 @@
   string mFilename;
   bool wireframe;
+  bool mUseForcedMaterial;
+  Material mForcedMaterial;
 
 public:
   
-  Exporter(const string filename):mFilename(filename),wireframe(false)
+  Exporter(const string filename):mFilename(filename),
+				  wireframe(false),
+				  mUseForcedMaterial(false)
   {
   }
@@ -34,12 +40,24 @@
 
   virtual bool
-  ExportRays(const vector<Ray> &rays, const float length=1000) = 0;
+  ExportRays(const vector<Ray> &rays,
+	     const float length=1000,
+	     const RgbColor &color = RgbColor(1,1,1)
+	     ) = 0;
+  
 
   virtual void
-  ExportMeshInstance(MeshInstance *mesh) = 0;
-  
+  ExportIntersectable(Intersectable *object) = 0;
+
   void SetWireframe() { wireframe = true; }
   void SetFilled() { wireframe = false; }
 
+  void SetForcedMaterial(const Material &m) {
+    mForcedMaterial = m;
+    mUseForcedMaterial = true;
+  }
+  void ResetForcedMaterial() {
+    mUseForcedMaterial = false;
+  }
+    
   static Exporter *
   GetExporter(const string filename);
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.cpp	(revision 170)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.cpp	(revision 176)
@@ -60,5 +60,5 @@
   mBox.Initialize();
   
-  MeshContainer::const_iterator mi;
+  ObjectContainer::const_iterator mi;
   for ( mi = leaf->mObjects.begin();
 	mi != leaf->mObjects.end();
@@ -239,5 +239,5 @@
   frontBBox.SetMin(axis, position);
 
-  MeshContainer::const_iterator mi;
+  ObjectContainer::const_iterator mi;
 
   for ( mi = leaf->mObjects.begin();
@@ -391,18 +391,18 @@
   
   // insert all queries 
-  for(MeshContainer::const_iterator mi = node->mObjects.begin();
-      mi < node->mObjects.end();
+  for(ObjectContainer::const_iterator mi = node->mObjects.begin();
+      mi != node->mObjects.end();
       mi++) {
     AxisAlignedBox3 box = (*mi)->GetBox();
 
-    splitCandidates->push_back(SortableEntry(SortableEntry::MESH_MIN,
+    splitCandidates->push_back(SortableEntry(SortableEntry::BOX_MIN,
 					     box.Min(axis),
-					     (void *)*mi)
+					     *mi)
 			       );
     
     
-    splitCandidates->push_back(SortableEntry(SortableEntry::MESH_MAX,
+    splitCandidates->push_back(SortableEntry(SortableEntry::BOX_MAX,
 					     box.Max(axis),
-					     (void *)*mi)
+					     *mi)
 			       );
   }
@@ -429,5 +429,5 @@
   // C = ct_div_ci  + (ol + or)/queries
 
-  int totalFaces = 0;
+  float totalIntersections = 0.0f;
   vector<SortableEntry>::const_iterator ci;
 
@@ -435,11 +435,10 @@
       ci < splitCandidates->end();
       ci++) 
-    if ((*ci).type == SortableEntry::MESH_MIN) {
-      Mesh *mesh = ((MeshInstance *)(*ci).data)->GetMesh();
-      totalFaces += mesh->mFaces.size();
-    }
-
-  int facesLeft = 0;
-  int facesRight = totalFaces;
+    if ((*ci).type == SortableEntry::BOX_MIN) {
+      totalIntersections += (*ci).intersectable->IntersectionComplexity();
+    }
+
+  float intersectionsLeft = 0;
+  float intersectionsRight = totalIntersections;
 
   int objectsLeft = 0, objectsRight = node->mObjects.size();
@@ -457,13 +456,12 @@
       ci < splitCandidates->end();
       ci++) {
-    Mesh *mesh = ((MeshInstance *)(*ci).data)->GetMesh();
     switch ((*ci).type) {
-    case SortableEntry::MESH_MIN:
+    case SortableEntry::BOX_MIN:
       objectsLeft++;
-      facesLeft += mesh->mFaces.size();
+      intersectionsLeft += (*ci).intersectable->IntersectionComplexity();
       break;
-    case SortableEntry::MESH_MAX:
+    case SortableEntry::BOX_MAX:
       objectsRight--;
-      facesRight -= mesh->mFaces.size();
+      intersectionsRight -= (*ci).intersectable->IntersectionComplexity();
       break;
     }
@@ -477,5 +475,5 @@
       float sum;
       if (mSahUseFaces)
-	sum = facesLeft*lbox.SurfaceArea() + facesRight*rbox.SurfaceArea();
+	sum = intersectionsLeft*lbox.SurfaceArea() + intersectionsRight*rbox.SurfaceArea();
       else
 	sum = objectsLeft*lbox.SurfaceArea() + objectsRight*rbox.SurfaceArea();
@@ -494,5 +492,5 @@
   }
   
-  float oldCost = mSahUseFaces ? totalFaces : node->mObjects.size();
+  float oldCost = mSahUseFaces ? totalIntersections : node->mObjects.size();
   float newCost = mCt_div_ci + minSum/boxArea;
   float ratio = newCost/oldCost;
@@ -518,5 +516,6 @@
   float mint = 0;
 
-  
+  Intersectable::NewMail();
+
   if (!mBox.GetMinMaxT(ray, &mint, &maxt))
     return 0;
@@ -574,13 +573,13 @@
       ray.leaves.push_back(leaf);
       
-      MeshContainer::const_iterator mi;
+      ObjectContainer::const_iterator mi;
       for ( mi = leaf->mObjects.begin();
 	    mi != leaf->mObjects.end();
 	    mi++) {
-	MeshInstance *mesh = *mi;
-	if (!mesh->Mailed() ) {
-	  mesh->Mail();
+	Intersectable *object = *mi;
+	if (!object->Mailed() ) {
+	  object->Mail();
 	  //ray.meshes.push_back(mesh);
-	  hits += mesh->CastRay(ray);
+	  hits += object->CastRay(ray);
 	}
       }
@@ -608,2 +607,28 @@
 }
 
+void
+KdTree::CollectObjects(KdNode *n, ObjectContainer &objects)
+{
+  stack<KdNode *> nodeStack;
+
+  nodeStack.push(n);
+
+  while (!nodeStack.empty()) {
+    KdNode *node = nodeStack.top();
+    nodeStack.pop();
+    if (node->IsLeaf()) {
+      KdLeaf *leaf = (KdLeaf *)node;
+      for (int j=0; j < leaf->mObjects.size(); j++) {
+	Intersectable *object = leaf->mObjects[j];
+	if (!object->Mailed()) {
+	  object->Mail();
+	  objects.push_back(object);
+	}
+      }
+    } else {
+      KdInterior *interior = (KdInterior *)node;
+      nodeStack.push(interior->mFront);
+      nodeStack.push(interior->mBack);
+    }
+  }
+}
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.cpp	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.cpp	(revision 176)
@@ -26,9 +26,9 @@
 
 int
-SceneGraph::CollectMeshInstaces(MeshContainer *instances)
+SceneGraph::CollectObjects(ObjectContainer *instances)
 {
   int number = 0;
   stack<SceneGraphNode *> nodeStack;
-
+  
   nodeStack.push(mRoot);
   
@@ -37,5 +37,5 @@
     nodeStack.pop();
 
-    MeshContainer::const_iterator mi = node->mGeometry.begin();
+    ObjectContainer::const_iterator mi = node->mGeometry.begin();
     for (; mi != node->mGeometry.end(); mi++)
       instances->push_back(*mi);
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp	(revision 176)
@@ -1,11 +1,176 @@
+#include "SceneGraph.h"
+#include "KdTree.h"
 #include "SamplingPreprocessor.h"
+#include "X3dExporter.h"
 
+SamplingPreprocessor::SamplingPreprocessor()
+{
+  // this should increase coherence of the samples
+  mSamplesPerPass = 1;
+  mTotalSamples = 1e8;
+  mKdPvsDepth = 10;
 
+}
+
+void
+SamplingPreprocessor::SetupRay(Ray &ray, const Vector3 &point, const Vector3 &direction)
+{
+  ray.intersections.clear();
+  ray.leaves.clear();
+  ray.meshes.clear();
+  //  cout<<point<<" "<<direction<<endl;
+  ray.Init(point, direction, Ray::LOCAL_RAY);
+}
+
+KdNode *
+SamplingPreprocessor::GetNodeForPvs(KdLeaf *leaf)
+{
+  KdNode *node = leaf;
+  while (node->mParent && node->mDepth > mKdPvsDepth)
+    node = node->mParent;
+  return node;
+}
+
+int
+SamplingPreprocessor::AddNodeSamples(Intersectable *object, const Ray &ray)
+{
+  int contributingSamples = 0;
+
+  for (int j=0; j < ray.leaves.size(); j++) {
+    KdNode *node = GetNodeForPvs( ray.leaves[j] );
+    contributingSamples += object->mKdPvs.AddNodeSample(node);
+  }
   
+  return contributingSamples;
+}
+
 bool
 SamplingPreprocessor::ComputeVisibility()
 {
-  return true;
-};
+
+  // pickup an object
+  ObjectContainer objects;
+  
+  mSceneGraph->CollectObjects(&objects);
+
+  Vector3 point, normal, direction;
+  Ray ray;
+
+  long startTime = GetTime();
+  
+  int i;
+  int pass = 0;
+  int totalSamples = 0;
 
 
+  int pvsOut = Min((int)objects.size(), 10);
+  
+  vector<Ray> rays[10];
+  
+  while (totalSamples < mTotalSamples) {
+
+    int passContributingSamples = 0;
+    int passSampleContributions = 0;
+    int passSamples = 0;
+    
+    for (i =0; i < objects.size(); i++) {
+      for (int k=0; k < mSamplesPerPass; k++) {
+	Intersectable *object = objects[i];
+	object->GetRandomSurfacePoint(point, normal);
+	direction = UniformRandomVector(normal);
+	// construct a ray
+	SetupRay(ray, point, direction);
+	mKdTree->CastRay(ray);
+
+	if (i < pvsOut)
+	  rays[i].push_back(ray);
+	
+	int sampleContributions = 0;
+	
+	if (ray.leaves.size()) {
+	  sampleContributions += AddNodeSamples(object, ray);
+	  
+	  if (ray.intersections.size()) {
+	    sampleContributions += AddNodeSamples(ray.intersections[0].mObject, ray);
+	    // check whether we can add this to the rays
+	    for (int j = 0; j < pvsOut; j++) {
+	      if (objects[j] == ray.intersections[0].mObject) {
+		rays[j].push_back(ray);
+	      }
+	    }
+	  }
+	  passSamples++;
+	  if (sampleContributions) {
+	    passContributingSamples++;
+	    passSampleContributions += sampleContributions;
+	  }
+	}
+      }
+    }
+    totalSamples += passSamples;
+    pass++;
+    
+    int pvsSize = 0;
+    for (i=0; i < objects.size(); i++) {
+      Intersectable *object = objects[i];
+      pvsSize += object->mKdPvs.mEntries.size();
+    }
+    
+    cout<<"pass "<<pass<<" : t = "<<TimeDiff(startTime, GetTime())*1e-3<<"s"<<endl;
+    cout<<"#totalSamples="<<totalSamples/1000<<
+      "k   #sampleContributions="<<passSampleContributions<<
+      " ("<<100*passContributingSamples/passSamples<<"%)"<<
+      " avgPVS="<<pvsSize/(float)objects.size()<<endl;
+  }
+  bool exportRays = false;
+  if (exportRays) {
+    Exporter *exporter = NULL;
+    exporter = Exporter::GetExporter("sample-rays.x3d");
+    exporter->SetWireframe();
+    exporter->ExportKdTree(*mKdTree);
+    for (i=0; i < pvsOut; i++) 
+      exporter->ExportRays(rays[i], 1000, RgbColor(1, 0, 0));
+    exporter->SetFilled();
+    delete exporter;
+  }
+
+  if (1) {
+    for (int k=0; k < pvsOut; k++) {
+      Intersectable *object = objects[k];
+      char s[64];
+      sprintf(s, "sample-pvs%04d.x3d", k);
+      Exporter *exporter = Exporter::GetExporter(s);
+      exporter->SetWireframe();
+      KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
+      Intersectable::NewMail();
+	// avoid adding the object to the list
+      object->Mail();
+      ObjectContainer visibleObjects;
+      for (; i != object->mKdPvs.mEntries.end(); i++) {
+	KdNode *node = (*i).first;
+	exporter->ExportBox(mKdTree->GetBox(node));
+	mKdTree->CollectObjects(node, visibleObjects);
+      }
+      
+      exporter->ExportRays(rays[k], 1000, RgbColor(0, 1, 0));
+      exporter->SetFilled();
+
+      for (int j = 0; j < visibleObjects.size(); j++)
+	exporter->ExportIntersectable(visibleObjects[j]);
+	
+      Material m;
+      m.mDiffuseColor = RgbColor(1, 0, 0);
+      exporter->SetForcedMaterial(m);
+      exporter->ExportIntersectable(object);
+      
+      delete exporter;
+    }
+    
+  }
+  
+  return true;
+}
+
+  
+
+    
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.cpp	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.cpp	(revision 176)
@@ -1,2 +1,3 @@
+#include "Matrix4x4.h"
 #include "Vector3.h"
 
@@ -188,2 +189,37 @@
   return;  
 }
+
+Vector3
+UniformRandomVector(const Vector3 &normal)
+{
+  float r1 = RandomValue(0.0f, 1.0f);
+  float r2 = RandomValue(0.0f, 1.0f);
+  float cosTheta = 1.0f - r1;
+  float sinTheta = sqrt(1 - sqr(cosTheta));
+  float fi = 2.0f*M_PI*r2;
+  
+  Vector3 dir(sinTheta*sin(fi),
+	      cosTheta,
+	      sinTheta*cos(fi));
+
+  
+  //  return Normalize(dir);
+
+  Matrix4x4 m = RotationVectorsMatrix(
+				      normal,
+				      Vector3(0,1,0));
+  Matrix4x4 mi = Invert(m);
+  m = m*RotationVectorsMatrix(
+			      Vector3(0,1,0),
+			      Normalize(dir))*mi;
+  
+  return TransformNormal(m, normal);
+  
+//    return TransformNormal(
+//  			 RotationVectorsMatrix(
+//  					       Vector3(0,1,0),
+//  					       Normalize(dir)
+//  					       ),
+//  			 normal
+//  			 );
+}
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 170)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 176)
@@ -54,5 +54,5 @@
   // add mesh instances of the scene graph to the root of the tree
   KdLeaf *root = (KdLeaf *)mKdTree->GetRoot();
-  mSceneGraph->CollectMeshInstaces(&root->mObjects);
+  mSceneGraph->CollectObjects(&root->mObjects);
   
   mKdTree->Construct();
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Camera.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Camera.cpp	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Camera.cpp	(revision 176)
@@ -30,5 +30,4 @@
     for (x = 0; x < mWidth; x++) {
       SetupRay(ray, x, y);
-      MeshInstance::NewMail();
       if (tree->CastRay(ray))
 	if (ray.intersections.size()) {
@@ -50,8 +49,9 @@
   
   long t2 = GetTime();
-  cout<<"#RAY_CAST_TIME"<<endl<<TimeDiff(t1, t2)<<endl;
-
-  cerr<<"Saving image"<<endl;
-  image.save(filename, "PNG");
+  cout<<"#RAY_CAST_TIME\n";
+  cout<<TimeDiff(t1, t2)<<"\n";
+  
+  cout<<"Saving image"<<endl;
+  image.save(filename.c_str(), "PNG");
 
   Exporter *exporter = NULL;
@@ -72,5 +72,5 @@
 	if (0)
 	for (i= 0; i < ray->meshes.size(); i++)
-	  exporter->ExportMeshInstance(ray->meshes[i]);
+	  exporter->ExportIntersectable(ray->meshes[i]);
 
       }
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.cpp	(revision 170)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.cpp	(revision 176)
@@ -8,14 +8,15 @@
 Mesh::Preprocess()
 {
-  mBoundingBox.Initialize();
+  mBox.Initialize();
 
   VertexContainer::const_iterator vi = mVertices.begin();
   for (; vi != mVertices.end(); vi++) {
-    mBoundingBox.Include(*vi);
-  }
-  
+    mBox.Include(*vi);
+  }
+  
+  /** true if it is a watertight convex mesh */
   mIsConvex = false;
-
-  if (mFaces.size() > 2*MeshKdTree::mTermMinCost) {
+  
+  if (mFaces.size() > MeshKdTree::mTermMinCost) {
     mKdTree = new MeshKdTree(this);
     MeshKdLeaf *root = (MeshKdLeaf *)mKdTree->GetRoot();
@@ -24,4 +25,9 @@
     cout<<"KD";
     mKdTree->Construct();
+
+    if (mKdTree->GetRoot()->IsLeaf()) {
+      cout<<"d";
+      delete mKdTree;
+    }
   }
 }
@@ -252,4 +258,24 @@
 
 
+void
+Mesh::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
+{
+  int faceIndex = RandomValue(0, mFaces.size()-1);
+  
+  // assume the face is convex and generate a convex combination
+  //
+  Face *face = mFaces[faceIndex];
+  point = Vector3(0,0,0);
+  float sum = 0.0f;
+  for (int i = 0; i < face->mVertexIndices.size(); i++) {
+    float r = RandomValue(0,1);
+    sum += r;
+    point += mVertices[face->mVertexIndices[i]]*r;
+  }
+  point *= 1.0f/sum;
+  normal = GetFacePlane(faceIndex).mNormal;
+}
+
+
 int
 MeshInstance::CastRay(
@@ -271,4 +297,19 @@
 
 
+
+void
+MeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
+{
+  mMesh->GetRandomSurfacePoint(point, normal);
+}
+
+void
+TransformedMeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
+{
+  mMesh->GetRandomSurfacePoint(point, normal);
+  point = mWorldTransform*point;
+  normal = TransformNormal(mWorldTransform, normal);
+}
+
 Plane3
 Mesh::GetFacePlane(const int faceIndex)
@@ -281,5 +322,5 @@
 
 int
-MeshTransformedInstance::CastRay(
+TransformedMeshInstance::CastRay(
 				 Ray &ray
 				 )
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h	(revision 176)
@@ -12,6 +12,6 @@
 class SceneGraphNode;
 class Mesh;
-
-
+class Intersectable;
+class MeshInstance;
 
 class X3dExporter : public Exporter
@@ -27,5 +27,7 @@
 
   bool
-  ExportRays(const vector<Ray> &rays, const float length=1000);
+  ExportRays(const vector<Ray> &rays,
+	     const float length=1000,
+	     const RgbColor &color = RgbColor(1,1,1));
 
   bool
@@ -39,5 +41,5 @@
   }
   
-  bool
+  virtual bool
   ExportBox(const AxisAlignedBox3 &box);
 
@@ -45,9 +47,13 @@
   ExportMeshInstance(MeshInstance *mi);
 
-  void
+  virtual void
+  ExportIntersectable(Intersectable *object);
+
+  virtual void
   ExportMesh(Mesh *mesh);
 
+
 protected:
-  void
+  virtual void
   ExportSceneNode(SceneGraphNode *node);
   
