Index: GTP/trunk/Lib/Vis/Preprocessing/src/IntelRayCaster.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/IntelRayCaster.h	(revision 2176)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/IntelRayCaster.h	(revision 2582)
@@ -38,4 +38,14 @@
 	}
 
+        // Using packet of 4 rays supposing that these are coherent
+        // We give a box to which each ray is clipped to before the
+        // ray shooting is computed !
+  virtual void CastRaysPacket4(const Vector3 &minBox,
+							   const Vector3 &maxBox,
+							   const Vector3 origin4[],
+							   const Vector3 direction4[],
+							   int result4[],
+							   float dist4[]);
+  
 	virtual int CastRay(const SimpleRay &simpleRay,
 						VssRayContainer &vssRays,
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Mutation.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Mutation.cpp	(revision 2574)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Mutation.cpp	(revision 2582)
@@ -27,5 +27,6 @@
   //#define Q_SEARCH_STEPS 3
 
-#define SORT_RAY_ENTRIES 1
+  // VH - commened out !!!!! 8/1/2008
+  // #define SORT_RAY_ENTRIES 1
 
 // use avg ray contribution as importance
@@ -367,4 +368,5 @@
   static Vector3 dirs[packetSize];
   static Vector3 shifts[packetSize];
+  static Vector3 origs[packetSize];
   // now find the silhouette along the line
   int i;
@@ -378,18 +380,20 @@
 	  shifts[i] = r*line;
 	  dirs[i] = Normalize(newPivot + shifts[i] - termination );
-	  mlrtaStoreRayASEye4(&termination.x,
-						  &dirs[i].x,
-						  i);
-	}
-	
-	mlrtaTraverseGroupASEye4(&box.Min().x,
-							 &box.Max().x,
-							 hit_triangles,
-							 dist);
+	  origs[i] = termination;
+	  // mlrtaStoreRayASEye4(&termination.x, &dirs[i].x, i);
+	}
+
+	// mlrtaTraverseGroupASEye4(&box.Min().x, &box.Max().x, hit_triangles, dist);
+	assert(preprocessor->mRayCaster);
+	preprocessor->mRayCaster->CastRaysPacket4(box.Min(),
+											  box.Max(),
+											  origs, dirs,
+											  hit_triangles,
+											  dist);       
 	
 	for (i=0; i < packetSize; i++) {
 	  if (hit_triangles[i] == -1) {
-		// break on first passing ray
-		break;
+	    // break on first passing ray
+	    break;
 	  }
 	}
@@ -473,4 +477,5 @@
   static Vector3 dirs[packetSize];
   static Vector3 shifts[packetSize];
+  static Vector3 origs[packetSize];
   // mutate the 
   float alpha = RandomValue(0.0f, Real(2.0*M_PI));
@@ -491,13 +496,12 @@
 	  shifts[i] = r*line;
 	  dirs[i] = Normalize(ray.mTermination + shifts[i] - origin );
-	  mlrtaStoreRayASEye4(&origin.x,
-						  &dirs[i].x,
-						  i);
-	}
-	
-	mlrtaTraverseGroupASEye4(&box.Min().x,
-							 &box.Max().x,
-							 hit_triangles,
-							 dist);
+	  origs[i] = origin;
+	  //mlrtaStoreRayASEye4(&origin.x, &dirs[i].x, i);
+	}
+	
+	// mlrtaTraverseGroupASEye4(&box.Min().x, &box.Max().x, hit_triangles, dist);
+	assert(preprocessor->mRayCaster);
+	preprocessor->mRayCaster->CastRaysPacket4(box.Min(), box.Max(),
+						  origs, dirs, hit_triangles, dist);       
 	
 	for (i=0; i < packetSize; i++) {
Index: GTP/trunk/Lib/Vis/Preprocessing/src/run_test2
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/run_test2	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/run_test2	(revision 2582)
@@ -29,10 +29,10 @@
 #VIEWCELLS=../data/test1/test-viewcells.xml
 
-SCENE=../data/Arena/arena-high-lods.obj
-VIEWCELLS=../data/Arena/viewcells-5000.xml.gz
+#SCENE=../data/Arena/arena-high-lods.obj
+#VIEWCELLS=../data/Arena/viewcells-5000.xml.gz
 
 
-#SCENE=../data/vienna/vienna_cropped.obj
-#VIEWCELLS=../data/vienna/vienna_cropped-gradient-viewcells.xml.gz
+SCENE=../data/vienna/vienna_cropped.obj
+VIEWCELLS=../data/vienna/vienna_cropped-gradient-viewcells.xml.gz
 #VIEWCELLS=../data/vienna/vienna-sequential-30000-single-viewcell.xml
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Vector3.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Vector3.h	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Vector3.h	(revision 2582)
@@ -41,5 +41,5 @@
 
   // Functions to get at the std::vector components
-  float& operator[] (int inx) {
+  float& operator[] (const int inx) {
 #ifndef __VECTOR_HACK
     if (inx == 0)
@@ -60,5 +60,5 @@
 #endif
 
-  const float& operator[] (int inx) const {
+  const float &operator[] (const int inx) const {
 #ifndef __VECTOR_HACK
     if (inx == 0)
@@ -66,7 +66,7 @@
     else
       if (inx == 1)
-	return y;
+		return y;
       else
-	return z;
+		return z;
 #else
     return *(&x+inx);
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.h	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.h	(revision 2582)
@@ -67,4 +67,20 @@
 			const bool pruneInvalidRays = true);
 
+  // Using packet of 4 rays supposing that these are coherent
+  virtual void CastRaysPacket4(Vector3 origin4[],
+			       Vector3 direction4[],
+			       int     result4[],
+			       float   dist4[]) {  }
+
+  // Using packet of 4 rays supposing that these are coherent
+  // We give a box to which each ray is clipped to before the
+  // ray shooting is computed !
+  virtual void CastRaysPacket4(const Vector3 &minBox,
+							   const Vector3 &maxBox,
+							   const Vector3 origin4[],
+							   const Vector3 direction4[],
+							   int result4[],
+							   float dist4[]) {  }
+  
   // Just for testing concept
   virtual void CastRaysPacket2x2(RayPacket2x2 &raysPack,
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 2582)
@@ -2978,5 +2978,5 @@
 	result = false;
   }
-  delete envFilename;
+  delete [] envFilename;
 
   // Parse the command line; options given on the command line subsume
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.cpp	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.cpp	(revision 2582)
@@ -1,5 +1,4 @@
 #include "Intersectable.h"
 #include "SimpleRay.h"
-//#include "ktbconf.h"
 
 using namespace std;
@@ -8,5 +7,10 @@
 #define ALIGN16 __declspec(align(16))
 #else
-ALIGN16 GALIGN16
+#ifdef USE_HAVRAN_RAYCASTER 
+#include "ktbconf.h"
+#define ALIGN16 GALIGN16
+#else
+#define ALIGN16
+#endif
 #endif
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 2580)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 2582)
@@ -589,4 +589,5 @@
 
   mKdTree->Construct();
+  sceneBox = mKdTree->GetBox();
 
   cout << "finished kd tree construction in " << TimeDiff(startTime, GetTime()) * 1e-3 
@@ -1103,5 +1104,5 @@
 
 bool Preprocessor::InitRayCast(const string &externKdTree, 
-							   const string &internKdTree)
+			       const string &internKdTree)
 {
 	// always try to load the kd tree
@@ -1220,9 +1221,11 @@
 
 	const long t1 = GetTime();
-	
-	if (rays.size() > 10000)
-	{
-
-		mRayCaster->SortRays(rays);
+
+	// !!!!!!!!!!!!!!!! VH no sorting
+	if (0 &&
+	    rays.size() > 10000)
+	{
+
+	  mRayCaster->SortRays(rays);
 		cout<<"Rays sorted in "<<TimeDiff(t1, GetTime())<<" ms."<<endl;
 	}
@@ -1260,5 +1263,5 @@
 #endif
 	}
-	cerr<<"Deternmining PVS objects"<<endl;
+	// cerr<<"Determining PVS objects"<<endl;
 	DeterminePvsObjects(vssRays);
 }
Index: GTP/trunk/Lib/Vis/Preprocessing/src/FilterBasedDistribution.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/FilterBasedDistribution.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/FilterBasedDistribution.h	(revision 2582)
@@ -0,0 +1,34 @@
+#ifndef __FILTER_BASED_DISTRIBUTION
+#define __FILTER_BASED_DISTRIBUTION
+
+#include "SamplingStrategy.h"
+#include "ObjectPvs.h"
+
+namespace GtpVisibilityPreprocessor {
+
+class FilterBasedDistribution: public SamplingStrategy
+{
+public:
+
+  FilterBasedDistribution(Preprocessor &preprocessor)
+	: SamplingStrategy(preprocessor)
+  {
+	mType = FILTER_BASED_DISTRIBUTION;
+	mViewCell = NULL;
+  }
+  
+private:
+  
+  virtual bool GenerateSample(SimpleRay &ray);
+
+  // cached values
+  ViewCell *mViewCell;
+  ObjectPvs mFilteredPvs;
+  int samplesToGenerate;
+  int samplesGenerated;
+  
+  static HaltonSequence sHalton;
+};
+}
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/default.env
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/default.env	(revision 2574)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/default.env	(revision 2582)
@@ -52,5 +52,5 @@
 	useGlRenderer true
 	useGlDebugger false
-# 0 = INTERNAL 		1 = MLRT
+# 0 = INTERNAL 	1 = MLRT 2 = HAVRAN
 	rayCastMethod 1
 	
@@ -280,5 +280,5 @@
 
 #	filename ../data/Arena/viewcells-5000.xml
-filename ../data/Arena/viewcells-20000.xml
+#   filename ../data/Arena/viewcells-20000.xml
 
 #	filename ../data/atlanta/atlanta_viewcells_large.x3d
@@ -511,2 +511,17 @@
 }
 
+# settings for havran ray caster
+TestDoubleRays	true
+
+BSP {
+  termCrit	  auto
+  #termCrit	  auto2
+  #termCrit	  adhoc
+  # For Arena
+  #maxDepthAllowed 15
+  #maxListLength    8
+  # For Vienna
+  #maxDepthAllowed 22
+  #maxListLength    6
+}
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h	(revision 2580)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h	(revision 2582)
@@ -208,4 +208,5 @@
 	/// kD-tree organizing the scene graph (occluders + occludees) + viewcells
 	KdTree *mKdTree;
+        AxisAlignedBox3 sceneBox;
 	/// View space partition bsp tree
 	VspBspTree *mVspBspTree;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 2582)
@@ -376,6 +376,6 @@
 	Vector3 up(0,1,0);
 
-	if (abs(DotProd(mViewDirection, up)) > 0.99f)
-		up = Vector3(1, 0, 0);
+	if (fabs(DotProd(mViewDirection, up)) > 0.99f)
+	  up = Vector3(1, 0, 0);
 
 	glLoadIdentity();
Index: GTP/trunk/Lib/Vis/Preprocessing/src/common.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/common.h	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/common.h	(revision 2582)
@@ -22,5 +22,7 @@
 
 // use perftimer
-#define PERFTIMER
+// #define PERFTIMER
+
+#define USE_HAVRAN_RAYCASTER
 
 namespace GtpVisibilityPreprocessor {
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HavranRayCaster.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HavranRayCaster.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HavranRayCaster.cpp	(revision 2582)
@@ -0,0 +1,447 @@
+
+// Written by Vlastimil Havran, December 2007
+
+// This macro allows to use the ray shooting written by
+// Vlastimil Havran, 2007-2008
+
+
+#include "HavranRayCaster.h"
+#include "VssRay.h"
+#include "KdTree.h"
+#include "Preprocessor.h"
+#include "IntersectableWrapper.h"
+
+#ifdef USE_HAVRAN_RAYCASTER
+#include "timer.h"
+#include "ktball.h"
+#include "ktb.h"
+#include "raypack.h"
+#endif // USE_HAVRAN_RAYCASTER
+
+#define DEBUG_RAYCAST 0
+
+namespace GtpVisibilityPreprocessor {
+
+
+#ifdef USE_HAVRAN_RAYCASTER 
+// static rays
+RayPacket2x2
+HavranRayCaster::raypack;
+#endif // USE_HAVRAN_RAYCASTER
+  
+HavranRayCaster::HavranRayCaster(const Preprocessor &preprocessor):
+  RayCaster(preprocessor), mKtbtree(0)
+{
+#ifdef USE_HAVRAN_RAYCASTER 
+  mKtbtree = new CKTB();
+#endif  
+}
+  
+
+HavranRayCaster::~HavranRayCaster()
+{
+#ifdef USE_HAVRAN_RAYCASTER 
+  delete mKtbtree;
+  mKtbtree = 0;
+#endif // USE_HAVRAN_RAYCASTER
+}
+
+void
+HavranRayCaster::Build(ObjectContainer &objlist)
+{
+#ifdef USE_HAVRAN_RAYCASTER 
+
+  CTimer timer;
+
+  cout << "\nBuilding up kd-tree for Havran ray caster ..."<<endl<<flush;
+
+  timer.Start();
+  mKtbtree->BuildUp(objlist);
+  timer.Stop();
+  cout << "\nBuilding up kd-tree is finished, user time = "
+       << timer.UserTime() << " real time = " << timer.RealTime() <<
+	endl <<flush;
+#endif
+}
+
+
+// Using packet of 4 rays supposing that these are coherent
+// We give a box to which each ray is clipped to before the
+// ray shooting is computed !
+void HavranRayCaster::CastRaysPacket4(Vector3 &boxmax,
+				      Vector3 &boxmin,
+				      Vector3 origin4[],
+				      Vector3 direction4[],
+				      int     result4[],
+				      float   dist4[])
+{
+#ifdef USE_HAVRAN_RAYCASTER 
+  for (int i = 0; i < 4; i++) {
+    result4[i] = -1;
+    raypack.SetLoc(i, origin4[i]);
+    raypack.SetDir(i, direction4[i]);
+  }  
+
+  // The same operations for packets of rays, if implemented by
+  // a particular ASDS, otherwise it is emulated by decomposition
+  // of a packet to individual rays and traced individually.
+  mKtbtree->FindNearestI(raypack, boxmin, boxmax);
+
+  for (int i = 0; i < 4; i++) {
+    // if ray intersects an object, we set the pointer to
+    // this object
+    Intersectable* intersectable;
+    if ( (intersectable = raypack.GetObject(i)) )
+      result4[i] = (int)intersectable;
+  }
+    
+  return;
+#endif
+}
+
+int HavranRayCaster::CastRay(const SimpleRay &simpleRay,
+			     VssRayContainer &vssRays,
+			     const AxisAlignedBox3 &box,
+			     const bool castDoubleRay,
+			     const bool pruneInvalidRays)
+{
+#ifdef USE_HAVRAN_RAYCASTER 
+
+  int hits = 0;
+  Intersection hitA(simpleRay.mOrigin), hitB(simpleRay.mOrigin);
+  
+  // inside test for bounding box
+  // enlarge box slightly so the view point fits for sure
+  //  AxisAlignedBox3 sbox = box;
+  //  sbox.Enlarge(Vector3(-Limits::Small));
+  // $$ JB moved here from Validate routine
+
+//   if (!box.IsInside(simpleRay.mOrigin)) {
+// 	cout<<"out of box "<<simpleRay.mOrigin<<" "<<box<<endl;
+// 	return 0;
+//   }
+  
+  // ray.mFlags &= ~Ray::CULL_BACKFACES;
+
+  if (mKtbtree->FindNearestI(simpleRay))  {
+    hitA.mObject = SimpleRay::IntersectionRes[0].intersectable;
+    float tdist = SimpleRay::IntersectionRes[0].tdist;
+    hitA.mPoint = simpleRay.Extrap(tdist);
+    hitA.mNormal = SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
+    //hitA.mNormal = (dynamic_cast< TriangleIntersectable *>
+    //		    (hitA.mObject))->GetNormal(0);
+  }
+  
+  
+  if (castDoubleRay) {
+    Vector3 *v = (Vector3*)(&simpleRay.mDirection);
+    *v = -(*v);
+    // ray.mFlags &= ~Ray::CULL_BACKFACES;
+    if (mKtbtree->FindNearestI(simpleRay))  {
+      hitB.mObject = SimpleRay::IntersectionRes[0].intersectable;
+      float tdist = SimpleRay::IntersectionRes[0].tdist;
+      hitB.mPoint = simpleRay.Extrap(tdist);
+      hitB.mNormal = SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
+      //hitB.mNormal = (dynamic_cast< TriangleIntersectable *>
+      //	      (hitB.mObject))->GetNormal(0);
+    }
+    // restore the direction to the original
+    *v = -simpleRay.mDirection;
+  }
+
+  // This code is also in IntelRayCaster.cpp
+  return ProcessRay(
+		    simpleRay,
+		    hitA,
+		    hitB,
+		    vssRays,
+		    box,
+		    castDoubleRay,
+		    pruneInvalidRays
+		    );
+#else // USE_HAVRAN_RAYCASTER 
+  return 0;
+#endif
+}
+
+void HavranRayCaster::CastRays16(SimpleRayContainer &rays,
+				 VssRayContainer &vssRays,
+				 const AxisAlignedBox3 &sbox,
+				 const bool castDoubleRay,
+				 const bool pruneInvalidRays)
+{
+  CastRays16(rays, 0, vssRays, sbox, castDoubleRay, pruneInvalidRays);
+}
+
+
+void HavranRayCaster::CastRays16(SimpleRayContainer &rays,
+				 int offset,
+				 VssRayContainer &vssRays,
+				 const AxisAlignedBox3 &sbox,
+				 const bool castDoubleRays,
+				 const bool pruneInvalidRays)
+{
+#ifdef USE_HAVRAN_RAYCASTER
+  
+#if DEBUG_RAYCAST
+  Debug << "C16 " << flush;
+#endif
+
+#if 0
+  SimpleRayContainer::const_iterator sit, sit_end = rays.end();
+
+  // no acceleration for ray bundles implemented right now
+  for (sit = rays.begin(); sit != sit_end; ++ sit) 
+  {
+    CastRay(*sit, vssRays, sbox, castDoubleRays, pruneInvalidRays);
+  }
+#else
+  if (castDoubleRays) {
+#if 0
+    // Special routine to cast double sided rays
+    mKtbtree->SetOffset(0);
+    mKtbtree->FindNearestI_16twoDir(rays);
+#else
+    // Here we decompose shooting into two phases
+#if 1    
+    // Here we shoot first forward rays and then backward ones
+    mKtbtree->SetOffset(0);
+    mKtbtree->FindNearestI_16oneDir(rays, offset);
+    SimpleRayContainer::iterator sit = rays.begin() + offset; 
+    SimpleRayContainer::const_iterator sit_end = rays.begin() + offset + 16;
+    for (; sit != sit_end; ++ sit) 
+    {
+      (*sit).mDirection = - (*sit).mDirection;
+    }
+    // We store the results at different place
+    mKtbtree->SetOffset(16);
+    mKtbtree->FindNearestI_16oneDir(rays, offset);
+    sit = rays.begin() + offset; 
+    for ( ; sit != sit_end; ++ sit) 
+    {
+      (*sit).mDirection = - (*sit).mDirection;
+    }
+#else
+    // Here we shoot first backward rays and forward ones
+    SimpleRayContainer::iterator sit = rays.begin() + offset; 
+    SimpleRayContainer::const_iterator sit_end = rays.begin() + offset + 16;
+    for ( ; sit != sit_end; ++ sit) 
+    {
+      (*sit).mDirection = - (*sit).mDirection;
+    }
+    // backward rays to be shot
+    mKtbtree->SetOffset(16);
+    mKtbtree->FindNearestI_16oneDir(rays, offset);
+    sit = rays.begin() + offset; 
+    for ( ; sit != sit_end; ++ sit) 
+    {
+      (*sit).mDirection = - (*sit).mDirection;
+    }
+    // forward rays to be shot
+    mKtbtree->SetOffset(0);
+    mKtbtree->FindNearestI_16oneDir(rays, offset);
+#endif    
+#endif    
+  }
+  else {
+    // Shoot all 16 rays  at the same time using a special algorithm
+    mKtbtree->SetOffset(0);
+    mKtbtree->FindNearestI_16oneDir(rays, offset);    
+  }
+#endif
+
+  
+  for (int i=0, k=offset; i < 16; i++, k++) 
+  {
+    Intersection hitA(rays[k].mOrigin), hitB(rays[k].mOrigin);
+
+#if DEBUG_RAYCAST
+    Debug<<"FH\n"<<flush;
+#endif
+
+    Intersectable *intersect = SimpleRay::IntersectionRes[i].intersectable;
+
+    if (intersect)
+    {
+      hitA.mObject = intersect;
+      // Get the normal of that face
+      hitA.mNormal = intersect->GetNormal(0);
+      
+      //-rays[index+i].mDirection; // $$ temporary
+      float tdist = SimpleRay::IntersectionRes[i].tdist;
+      hitA.mPoint = rays[k].Extrap(tdist);
+    }
+    
+#if DEBUG_RAYCAST
+    Debug<<"BH\n"<<flush;
+#endif
+
+    if (castDoubleRays) 
+    {
+      Intersectable *intersect =
+	SimpleRay::IntersectionRes[i+16].intersectable;
+
+      if (intersect)
+      { 
+	hitB.mObject = intersect;
+	hitB.mNormal = intersect->GetNormal(0);;
+	float tdist = SimpleRay::IntersectionRes[i].tdist;
+	hitB.mPoint = rays[k].Extrap(-tdist);
+      }
+    }
+    
+#if DEBUG_RAYCAST
+    Debug<<"PR\n"<<flush;
+#endif
+
+#if 1
+    ProcessRay(rays[k],
+	       hitA,
+	       hitB,
+	       vssRays,
+	       sbox,
+	       castDoubleRays,
+	       pruneInvalidRays
+	       );
+#endif
+  } // for
+
+  
+#if DEBUG_RAYCAST
+  Debug<<"C16F\n"<<flush;
+#endif
+
+#endif // USE_HAVRAN_RAYCASTER 
+}
+
+
+
+void
+HavranRayCaster::CastSimpleForwardRays(
+				       SimpleRayContainer &rays,
+				       const AxisAlignedBox3 &sbox
+				      )
+{
+  int hit_triangles[16];
+  float dist[16];
+  Vector3 normals[16];
+  Vector3 min = sbox.Min();
+  Vector3 max = sbox.Max();
+  
+  int packets = rays.size() / 16;
+  
+  int i, j, k = 0;
+  Vector3 dir;
+  
+  // By groups of rays
+  for (i=0; i < packets; i++) {
+    int offset = i * 16;
+    mKtbtree->FindNearestI_16oneDir(rays, offset);
+    // ??? What to do with the results ? These are
+    // not used at the moment also in IntelRayCaster.cpp
+  } // for
+
+
+  for (; k < rays.size(); k++) {
+    double normal[3];
+    mKtbtree->FindNearestI(rays[k]);
+    // ??? What to do with the results ? These are
+    // not used at the moment also in IntelRayCaster.cpp
+  }
+
+
+  return;
+}
+
+void HavranRayCaster::CastRays(
+			       SimpleRayContainer &rays,
+			       VssRayContainer &vssRays,
+			       const AxisAlignedBox3 &sbox,
+			       const bool castDoubleRay,
+			       const bool pruneInvalidRays )
+{
+  int buckets = rays.size()/16;
+  int offset = 0;
+
+#if 0
+  int time = GetTime();
+  CastSimpleForwardRays(rays, sbox);
+  cout<<1e-3*2*rays.size()/TimeDiff(time, GetTime())<<" Mrays/sec"<<endl;
+#endif
+  
+  for (int i=0; i < buckets; i++, offset+=16) {
+    CastRays16(rays, offset, vssRays, sbox,
+	       castDoubleRay, pruneInvalidRays);
+
+    if ((int)rays.size() > 100000 && i % (100000/16) == 0)
+      cout<<"\r"<<offset<<"/"<<(int)rays.size()<<"\r";
+  }
+
+  for (; offset < (int)rays.size(); offset++)
+    CastRay(rays[offset], vssRays, sbox, castDoubleRay, pruneInvalidRays);
+}
+
+#if 0
+// BUG1 41579  196948 1064111
+// BUG2 254    1672   10869
+  
+// Just for testing concept
+void
+HavranRayCaster::CastRaysPacket2x2(RayPacket2x2 &raysPack,
+								   bool castDoubleRay,
+								   const bool pruneInvalidRays)
+{
+#ifdef USE_HAVRAN_RAYCASTER 
+
+  if (castDoubleRay) {
+    // cast forward rays
+    mKtbtree->FindNearestI(raysPack);
+    for (int i = 0; i < 4; i++)
+      raysPack.SetDir(i, -raysPack.GetDir(i));
+    // cast backward rays
+    mKtbtree->FindNearestI(raysPack);
+    // reverse the rays back
+    for (int i = 0; i < 4; i++)
+      raysPack.SetDir(i, -raysPack.GetDir(i));
+  }
+  else {
+    // only rays forwards
+    mKtbtree->FindNearestI(raysPack);
+#if 0
+    // Only verification of correctness by casting single rays
+    static int cntBugs = 0;
+    SimpleRay ray;
+    int cntErrors = 0, cntDistErrors = 0;
+    bool newBug = false;
+    for (int i = 0; i < 4; i++) {
+      ray.mOrigin = raysPack.GetLoc(i);
+      ray.mDirection = raysPack.GetDir(i);
+      mKtbtree->FindNearestI(ray);
+      if (raysPack.GetObject(i) != SimpleRay::IntersectionRes[0].intersectable) {
+	float dist = (raysPack.GetT(i) - SimpleRay::IntersectionRes[0].tdist);
+	if (fabs(dist) > 0.001f) {
+	  cntErrors++; newBug = true;
+	  cntBugs++;
+	  cout << " BUG1 d= " << dist;
+	}
+      }
+      else {
+	float dist = 0.f;
+	if (raysPack.GetObject(i) && SimpleRay::IntersectionRes[0].intersectable)
+	  if (fabs((dist=(fabs (raysPack.GetT(i) - SimpleRay::IntersectionRes[0].tdist)))) > 1.f) {
+	    cntDistErrors++; newBug = true; cntBugs++;
+	    cout << " BUG2 distdf= " << dist ;	    
+	  }
+      }
+    } // for
+    if (newBug) cout << " CB= " << cntBugs << "\n";
+#endif
+  }
+
+  return;
+#endif // USE_HAVRAN_RAYCASTER 
+}
+#endif
+
+
+} // the namespace
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 2570)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 2582)
@@ -5,246 +5,16 @@
 #include "common.h"
 #include <math.h>
+//#include "PvsBB.h"
 #include "PvsBase.h"
-
+#include "ObjectPvs.h"
 
 
 namespace GtpVisibilityPreprocessor {
 
-
-/** Iterator over the pvs.
-*/
-template<typename T, typename S>
-class PvsIterator
-{
-public:
-	PvsIterator<T, S>(){}
-	PvsIterator<T, S>(const typename vector<PvsEntry<T, S> >::const_iterator &itCurrent,
-					  const typename vector<PvsEntry<T, S> >::const_iterator &itEnd):
-	mItCurrent(itCurrent), mItEnd(itEnd)
-	{
-	}
-
-	inline bool HasMoreEntries() const { return (mItCurrent != mItEnd);	}
-
-	inline T Next(S &pdf) {
-		pdf = (*mItCurrent).mData;
-		return (*(mItCurrent ++)).mObject;
-	}
-
-	inline T Next() { return (*(mItCurrent ++)).mObject; }
-
-
-private:
-	
-	typename vector<PvsEntry<T, S> >::const_iterator mItCurrent;
-	typename vector<PvsEntry<T, S> >::const_iterator mItEnd;
-};
-
-
-struct VerbosePvsStats
-{
-	VerbosePvsStats(): mDistanceWeightedTriangles(0), mDistanceWeightedPvs(0), mWeightedTriangles(0)
-	{}
-
-	float mDistanceWeightedTriangles;
-	float mDistanceWeightedPvs;
-	float mWeightedTriangles;
-};
-
-
-/** Template class representing the Potentially Visible Set (PVS) 
-	mainly from a view cell, but also e.g., from objects.
-*/
-template<typename T, typename S>
-class VerbosePvs
-{
-	template<typename T, typename S> friend class PvsIterator;
-
-public:
-
-	VerbosePvs(): mSamples(0), mEntries(), mLastSorted(0), mQueriesSinceSort(0) 
-	{}
-
-	/** creates pvs and initializes it with the given entries. 
-		Assumes that entries are sorted.
-	*/
-	VerbosePvs(const vector<PvsEntry<T, S> > &samples);
-	virtual ~VerbosePvs() {};
-
-	/** Compresses PVS lossless or lossy.
-	*/
-	int Compress() { return 0; }
-	
-	inline int GetSize() const { return (int)mEntries.size(); }
-	
-	inline bool Empty() const { return mEntries.empty(); }
-
-	inline void Reserve(const int n) { mEntries.reserve(n); }
-	/** Normalize the visibility of entries in order to get 
-		comparable results.
-	*/
-	void NormalizeMaximum();
-	/** Merges pvs of a into this pvs.
-		Warning: very slow!
-	*/
-	void MergeInPlace(const VerbosePvs<T, S> &a);
-	/** Difference of pvs to pvs b.
-	@returns number of different entries.
-	*/
-	int Diff(const VerbosePvs<T, S> &b);
-	/** Finds sample in PVS.
-		@param checkDirty if dirty part of the pvs should be checked for entry 
-		(warning: linear runtime in dirty part)
-		@returns iterator on the sample if found, else the place where 
-		it would be added in the sorted vector.
-	*/
-	bool Find(T sample,
-			  typename vector<PvsEntry<T, S> >::iterator &it,
-			  const bool checkDirty = true);
-
-	bool GetSampleContribution(T sample, const float pdf, float &contribution);
-	/** Adds sample to PVS.
-		@returns contribution of sample (0 or 1)
-	*/
-	float AddSample(T sample, const float pdf);
-	/** Adds sample to PVS without checking for presence of the sample
-		warning: pvs remains unsorted!
-	*/
-	void AddSampleDirty(T sample, const float pdf);
-	/** Adds sample dirty (on the end of the vector) but
-		first checks if sample is already in clean part of the pvs.
-	*/
-	bool AddSampleDirtyCheck(T sample, const float pdf);
-	/** Sort pvs entries. This should always be called after a
-		sequence of AddSampleDirty calls 
-	*/
-	void Sort();
-	/** Sort pvs entries assume that the pvs contains unique entries
-	*/
-	void SimpleSort();
-	/** Adds sample to PVS.
-		@returns PvsData
-	*/
-	typename std::vector<PvsEntry<T, S> >::iterator 
-		AddSample2(T sample, const float pdf);
-	/** Subtracts one pvs from another one.
-		WARNING: could contains bugs
-		@returns new pvs size
-	*/
-	int SubtractPvs(const VerbosePvs<T, S> &pvs);
-
-	/** Returns PVS data, i.e., how often it was seen from the view cell, 
-		and the object itsef.
-	*/
-	void GetData(const int index, T &entry, S &data);
-
-	/** Collects the PVS entries and returns them in the vector.
-	*/
-	void CollectEntries(std::vector<T> &entries);
-
-	/** Removes sample from PVS if reference count is zero.
-	@param visibleSamples number of references to be removed
-	*/
-	bool RemoveSample(T sample, const float pdf);
-
-	/** Compute continuous PVS difference 
-	*/
-	void ComputeContinuousPvsDifference(VerbosePvs<T, S> &pvs, 
-										float &pvsReduction,
-										float &pvsEnlargement);
-
-	/** Clears the pvs.
-	*/
-	void Clear(const bool trim = true);
-	/** Trim the vector containing the pvs.
-	*/
-	void Trim();
-
-	static int GetEntrySizeByte(); 
-	static float GetEntrySize();
-
-	/** Compute continuous PVS difference 
-	*/
-	float GetPvsHomogenity(VerbosePvs<T, S> &pvs);
-
-	static void Merge(VerbosePvs<T, S> &mergedPvs, 
-					  const VerbosePvs<T, S> &a, 
-					  const VerbosePvs<T, S> &b);
-
-	inline int GetSamples() const {	return mSamples; }
-
-	/** If there is an unsorted part in the pvs.
-	*/
-	bool IsDirty() const { return mLastSorted < mEntries.size(); }
-
-	/** If this pvs requires a resort to stay efficient.
-	*/
-	bool RequiresResort() const
-	{
-		// the last part should not be more than log of the sorted part. this
-		// way we can achieve logarithmic behaviour for insertion and find
-		const int n = mEntries.size();
-		const int dirtySize = n - mLastSorted;
-
-		const double LOG2E = 1.442695040f;
-
-		const float logN = log((float)max(1, n))/LOG2E;
-		const float logS = log((float)max(1, mLastSorted))/LOG2E;
-		const float logD = log((float)max(1, dirtySize))/LOG2E;
-
-		if (8*(n + 2*dirtySize*logD) <
-			mQueriesSinceSort*((mLastSorted*logS + dirtySize*dirtySize/2)/n - logN)) 
-		{
-			// cout<<"Q="<<mQueriesSinceSort<<" N="<<n<<" D="<<dirtySize<<endl;
-			return true;
-		}
-		
-		return false;
-	}
-
-	/** If this pvs requires a resort to stay efficient.
-	*/
-	bool RequiresResortLog() const
-	{
-		// the last part should not be more than log of the sorted part. this
-		// way we can achieve logarithmic behaviour for insertion and find
-		const int dirtySize = (int)mEntries.size() - mLastSorted;
-		return dirtySize > 4 * (int)(log((double)mEntries.size()) / log(2.0));
-	}
-
-	inline int GetLastSorted() const { return mLastSorted; }
-
-	typename PvsIterator<T, S> GetIterator() const;
-
-	VerbosePvsStats mStats;
-
-protected:
-
-	/** Merge pvs 1 from begin iterator to end iterator with
-		pvs 2 from begin iterator to end iterator.
-	*/
-	static void Merge(VerbosePvs<T, S> &mergedPvs, 
-					  const typename std::vector<PvsEntry<T, S> >::const_iterator &aBegin,
-					  const typename std::vector<PvsEntry<T, S> >::const_iterator &aEnd,
-					  const typename std::vector<PvsEntry<T, S> >::const_iterator &bBegin,
-					  const typename std::vector<PvsEntry<T, S> >::const_iterator &bEnd,
-					  const int aSamples, 
-					  const int bSamples);
-
-
-	//////////////////////////////
-
-	/// vector of PVS entries
-	vector<PvsEntry<T, S> > mEntries; 
-
-	/// Number of samples used to create the PVS
-	int mSamples;
-
-	/// Last sorted entry in the pvs (important for find and merge)
-	int mLastSorted;
-
-	int mQueriesSinceSort;
-};
-
+inline int operator< (PvsEntry<Intersectable*, PvsData> const &a,
+                      PvsEntry<Intersectable*, PvsData> const &b)
+{
+  return a.mObject < b.mObject;
+} 
 
 template <typename T, typename S>
@@ -261,9 +31,9 @@
 void VerbosePvs<T, S>::Sort()
 {
-	vector<PvsEntry<T, S> >::iterator it = mEntries.begin() + mLastSorted;
-	vector<PvsEntry<T, S> >::iterator it_end = mEntries.end();
+	typename vector<PvsEntry<T, S> >::iterator it = mEntries.begin() + mLastSorted;
+	typename vector<PvsEntry<T, S> >::iterator it_end = mEntries.end();
 
 	// throw out double entries
-	std::vector<PvsEntry<T, S> >::iterator newEnd = unique(it, it_end);
+	typename std::vector<PvsEntry<T, S> >::iterator newEnd = unique(it, it_end);
 	sort(it, newEnd);
 	
@@ -287,5 +57,5 @@
 {
 	//  sort(mEntries.begin(), mEntries.end());
-	vector<PvsEntry<T, S> >::iterator it = mEntries.begin() + mLastSorted;
+        typename vector<PvsEntry<T, S> >::iterator it = mEntries.begin() + mLastSorted;
 
 	sort(it, mEntries.end());
@@ -312,5 +82,5 @@
 
 	// Uses sum of log differences, which corresponds to entropy
-	vector<PvsEntry<T, S> >::iterator it;
+	typename vector<PvsEntry<T, S> >::iterator it;
 
 	for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it) 
@@ -319,5 +89,5 @@
 		float aSumPdf = 0.0f;
 
-		vector<PvsEntry<T, S> >::iterator oit;
+		typename vector<PvsEntry<T, S> >::iterator oit;
 		const bool entryFound = Find((*it).mObject, oit);		
 
@@ -361,5 +131,5 @@
 		else 
 		{
-			vector<PvsEntry<T, S> >::iterator oit;
+		        typename vector<PvsEntry<T, S> >::iterator oit;
 		
 			const bool entryFound = b.Find((*it).mObject, oit);
@@ -391,9 +161,9 @@
 	int dif = 0;
 
-	std::vector<PvsEntry<T, S> >::const_iterator it;
+	typename std::vector<PvsEntry<T, S> >::const_iterator it;
 
 	for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
 	{
-		vector<PvsEntry<T, S> >::iterator bit;
+	        typename vector<PvsEntry<T, S> >::iterator bit;
 		const bool entryFound = Find((*it).first, bit);
 
@@ -436,7 +206,7 @@
 							 const VerbosePvs<T, S> &b)
 {
-	std::vector<PvsEntry<T, S> >::const_iterator ait = 
+        typename std::vector<PvsEntry<T, S> >::const_iterator ait = 
 		a.mEntries.begin(), ait_end = a.mEntries.end();
-	std::vector<PvsEntry<T, S> >::const_iterator bit = 
+	typename std::vector<PvsEntry<T, S> >::const_iterator bit = 
 		b.mEntries.begin(), bit_end = b.mEntries.end();
 	
@@ -458,6 +228,6 @@
 					  const int bSamples)
 {
-	std::vector<PvsEntry<T, S> >::const_iterator ait = aBegin;
-	std::vector<PvsEntry<T, S> >::const_iterator bit = bBegin;
+        typename std::vector<PvsEntry<T, S> >::const_iterator ait = aBegin;
+	typename std::vector<PvsEntry<T, S> >::const_iterator bit = bBegin;
 	
 	for (; (ait != aEnd); ++ ait)
@@ -525,6 +295,6 @@
 template <typename T, typename S> 
 bool VerbosePvs<T, S>::Find(T sample,
-					 typename vector<PvsEntry<T, S> >::iterator &it,
-					 const bool checkDirty)
+			    typename vector<PvsEntry<T, S> >::iterator &it,
+			    const bool checkDirty)
 {
 	bool found = false;
@@ -533,5 +303,5 @@
 
 	// only check clean part
-	vector<PvsEntry<T, S> >::iterator sorted_end = mEntries.begin() + mLastSorted;
+	typename vector<PvsEntry<T, S> >::iterator sorted_end = mEntries.begin() + mLastSorted;
 	mQueriesSinceSort++;
 
@@ -545,5 +315,5 @@
 	if (!found && checkDirty) 
 	{
-		vector<PvsEntry<T, S> >::iterator dit, dit_end = mEntries.end();
+	    typename vector<PvsEntry<T, S> >::iterator dit, dit_end = mEntries.end();
 
         for (dit = sorted_end; (dit != dit_end) && ((*dit).mObject != sample); ++ dit);
@@ -563,5 +333,5 @@
 void VerbosePvs<T, S>::GetData(const int index, T &entry, S &data)
 {
-	std::vector<PvsEntry<T, S> >::iterator i = mEntries.begin();
+        typename std::vector<PvsEntry<T, S> >::iterator i = mEntries.begin();
 	for (int k = 0; k != index && i != mEntries.end(); ++ i, ++ k);
 
@@ -576,5 +346,5 @@
 	++ mSamples;
 	
-	vector<PvsEntry<T, S> >::iterator it;
+	typename vector<PvsEntry<T, S> >::iterator it;
 	const bool entryFound = Find(sample, it);		
 
@@ -609,5 +379,5 @@
 	++ mSamples;
 	
-	vector<PvsEntry<T, S> >::iterator it;
+	typename vector<PvsEntry<T, S> >::iterator it;
 	const bool entryFound = Find(sample, it);
 
@@ -633,5 +403,5 @@
 	++ mSamples;
 
-	vector<PvsEntry<T, S> >::iterator it;
+	typename vector<PvsEntry<T, S> >::iterator it;
 	const bool entryFound = Find(sample, it);
 
@@ -656,5 +426,5 @@
 									  float &contribution) 
 {
-	vector<PvsEntry<T, S> >::iterator it;
+        typename vector<PvsEntry<T, S> >::iterator it;
 	const bool entryFound = Find(sample, it);
 
@@ -678,5 +448,5 @@
 	-- mSamples;
 	
-	vector<PvsEntry<T, S> >::iterator it;
+	typename vector<PvsEntry<T, S> >::iterator it;
 	const bool entryFound = Find(sample, it);
 
@@ -703,6 +473,6 @@
 	const int samples = mSamples - pvs.mSamples;
 
-	std::vector<PvsEntry<T, S> >::
-		const_iterator it, it_end = pvs.mEntries.end();
+	typename std::vector<PvsEntry<T, S> >::
+	  const_iterator it, it_end = pvs.mEntries.end();
 
 	// output PVS of view cell
@@ -719,6 +489,6 @@
 void VerbosePvs<T, S>::CollectEntries(std::vector<T> &entries)
 {
-	std::vector<PvsEntry<T, S> >::
-		const_iterator it, it_end = mEntries.end();
+        typename std::vector<PvsEntry<T, S> >::
+	   const_iterator it, it_end = mEntries.end();
 
 	// output PVS of view cell
@@ -731,5 +501,5 @@
 void VerbosePvs<T, S>::NormalizeMaximum()
 {
-	std::vector<PvsEntry<T, S> >::
+	typename std::vector<PvsEntry<T, S> >::
 		const_iterator it, it_end = mEntries.end();
 
@@ -739,12 +509,12 @@
 	for (it = mEntries.begin(); it != it_end; ++ it) {
 		float sum = (*it)->second.sumPdf;
-		if (sum > maxSum)
-			maxSum = sum;
-	}
-
-	maxSum = 1.0f / maxSum;
+		if (sum > maxPdfSum)
+			maxPdfSum = sum;
+	}
+
+	maxPdfSum = 1.0f / maxPdfSum;
 
 	for (it = mEntries.begin(); it != it_end; ++ it) {
-		(*it)->second.sumPdf *= maxSum;
+		(*it)->second.sumPdf *= maxPdfSum;
 	}
 }
@@ -776,5 +546,5 @@
 
 template <typename T, typename S>
-typename PvsIterator<T, S> VerbosePvs<T, S>::GetIterator() const
+PvsIterator<T, S> VerbosePvs<T, S>::GetIterator() const
 {
 	PvsIterator<T, S> pit(mEntries.begin(), mEntries.end());
Index: GTP/trunk/Lib/Vis/Preprocessing/src/FilterBasedDistribution.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/FilterBasedDistribution.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/FilterBasedDistribution.cpp	(revision 2582)
@@ -0,0 +1,103 @@
+
+#include "Mesh.h"
+#include "FilterBasedDistribution.h"
+#include "Vector3.h"
+#include "Preprocessor.h"
+#include "ViewCellsManager.h"
+
+namespace GtpVisibilityPreprocessor {
+
+bool
+FilterBasedDistribution::GenerateSample(SimpleRay &ray)
+{
+  int tries = 0;
+  const int maxTries = 10;
+  
+  while (mViewCell == NULL || samplesGenerated >= samplesToGenerate
+		 ) {
+	// find a new viewcell to cast the sample from
+	if (tries++ > maxTries)
+	  return false;
+
+	Vector3 point; 
+
+	
+	float r[3];
+	r[0] = RandomValue(0.0f,1.0f);
+	r[1] = RandomValue(0.0f,1.0f);
+	r[2] = RandomValue(0.0f,1.0f);
+	//	static HaltonSequence sHalton;
+	//	sHalton.GetNext(3, r);
+	
+	mPreprocessor.mViewCellsManager->GetViewPoint(point, Vector3(r[0],
+																 r[1],
+																 r[2]));
+
+	
+	mViewCell = mPreprocessor.mViewCellsManager->GetViewCell(point);
+	
+	if (mViewCell && mViewCell->GetPvs().GetSize()) {
+
+	  //	  cout<<mViewCell<<endl;
+
+	  
+	  
+	  // apply spatial filter
+	  mFilteredPvs.Clear();
+	  PvsFilterStatistics fstat = mPreprocessor.mViewCellsManager->
+		ApplyFilter2(mViewCell,
+					 false,
+					 mPreprocessor.mViewCellsManager->GetFilterWidth(),
+					 mFilteredPvs,
+					 NULL,
+					 true);
+	  
+	  //	  cout<<mViewCell->GetPvs().GetSize()<<" "<<mFilteredPvs.GetSize()<<endl;
+
+	  if (mFilteredPvs.GetSize()) {
+		samplesGenerated = 0;
+		samplesToGenerate = Max(100, Min(1000, mFilteredPvs.GetSize()));
+	  } else
+		mViewCell = NULL; // try another viewcell
+	}
+  }
+
+  Vector3 origin, normal;
+  
+  mViewCell->GetRandomSurfacePoint(origin, normal);
+  
+  // pickup random object from the filtered pvs
+  int id = RandomValue(0, mFilteredPvs.GetSize()-1);
+  
+  ObjectPvsIterator pit = mFilteredPvs.GetIterator();
+
+  Intersectable *object;
+  
+  for (; id>=0; --id)
+	object = pit.Next();
+
+  
+  Vector3 point;
+  object->GetRandomSurfacePoint(point, normal);
+  Vector3 direction = point - origin;
+
+  const float c = Magnitude(direction);
+  
+  if (c <= Limits::Small) 
+	return false;
+  
+  direction *= 1.0f / c;
+
+  // $$ jb the pdf is yet not correct for all sampling methods!
+  const float pdf = 1.0f;
+  
+  ray = SimpleRay(origin, direction, FILTER_BASED_DISTRIBUTION, pdf);
+  
+  //cout << "ray: " << ray.mOrigin << " " << ray.mDirection << endl;
+  
+  samplesGenerated++;
+  
+  return true;
+}
+
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/IntelRayCaster.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/IntelRayCaster.cpp	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/IntelRayCaster.cpp	(revision 2582)
@@ -60,12 +60,30 @@
 }
 
-
-int IntelRayCaster::CastRay(
-			    const SimpleRay &simpleRay,
-			    VssRayContainer &vssRays,
-			    const AxisAlignedBox3 &box,
-			    const bool castDoubleRay,
-			    const bool pruneInvalidRays
-			    )
+// Using packet of 4 rays supposing that these are coherent
+// We give a box to which each ray is clipped to before the
+// ray shooting is computed !
+void IntelRayCaster::CastRaysPacket4(const Vector3 &minBox,
+									 const Vector3 &maxBox,
+									 const Vector3 origin4[],
+									 const Vector3 dirs4[],
+									 int     result4[],
+									 float   dist4[])
+{
+  for (int i = 0; i < 4; i++) {
+    mlrtaStoreRayASEye4(&origin4[i].x, &dirs4[i].x, i);
+  }
+  
+  mlrtaTraverseGroupASEye4(&minBox.x, &maxBox.x, result4, dist4);
+  return;
+}
+
+
+  
+int IntelRayCaster::CastRay(const SimpleRay &simpleRay,
+							VssRayContainer &vssRays,
+							const AxisAlignedBox3 &box,
+							const bool castDoubleRay,
+							const bool pruneInvalidRays
+							)
 {  
   //cout << "intel ray" << endl;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Makefile
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Makefile	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Makefile	(revision 2582)
@@ -1,5 +1,5 @@
 #############################################################################
 # Makefile for building: preprocessor
-# Generated by qmake (2.00a) (Qt 4.1.2) on: ?t 3. I 15:47:31 2008
+# Generated by qmake (2.00a) (Qt 4.1.2) on: st 9. I 11:11:49 2008
 # Project:  preprocessor.pro
 # Template: app
Index: GTP/trunk/Lib/Vis/Preprocessing/src/PvsBase.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/PvsBase.h	(revision 2530)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/PvsBase.h	(revision 2582)
@@ -6,11 +6,75 @@
 
 
-
 namespace GtpVisibilityPreprocessor {
-
 
 /** Information stored with a PVS entry. Consists of the number
 	the object was seen from the view cell.
 */
+struct PvsData 
+{
+public:
+	PvsData() {}
+	PvsData(const float sumPdf):
+	mSumPdf(sumPdf) {}
+	
+	// $$JB in order to return meaningfull values
+	// it assumes that the sum pdf has been normalized somehow!!!
+	inline float GetVisibility() { return mSumPdf; }
+
+	/// sum of probability density of visible sample rays
+	float mSumPdf;
+};
+
+
+class MailablePvsData 
+{
+public:
+	// sum of probability density of visible sample rays
+	float mSumPdf;
+	int mCounter;
+
+	MailablePvsData() {}
+	MailablePvsData(const float sumPdf):
+	mSumPdf(sumPdf) {}
+
+	// $$JB in order to return meaningfull values
+	// it assumes that the sum pdf has been normalized somehow!!!
+	inline float GetVisibility() { return mSumPdf; }
+
+
+	///////////////
+	//  Mailing stuff
+
+	// last mail id -> warning not thread safe!
+	// both mailId and mailbox should be unique for each thread!!!
+	static int sMailId;
+	static int sReservedMailboxes;
+
+	static void NewMail(const int reserve = 1) 
+	{
+		sMailId += sReservedMailboxes;
+		sReservedMailboxes = reserve;
+	}
+
+	void Mail() { mMailbox = sMailId; }
+	bool Mailed() const { return mMailbox == sMailId; }
+
+	void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
+	bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
+
+	int IncMail() { return ++ mMailbox - sMailId; }
+	
+	//////////////////////////////////////////
+
+protected:
+
+	int mMailbox;
+
+};
+
+
+/** Information stored with a PVS entry. Consists of the number
+	the object was seen from the view cell.
+*/
 template<typename T, typename S>
 struct PvsEntry 
@@ -25,8 +89,8 @@
 	S mData;
 
-	template<typename T, typename S>
-	friend int operator< (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b);
-	template<typename T, typename S>
-	friend int operator== (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b);
+  //template<typename T, typename S>
+  friend int operator< (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b);
+  //template<typename T, typename S>
+  friend int operator== (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b);
 };
 
@@ -60,68 +124,242 @@
 } 
 
-/** Information stored with a PVS entry. Consists of the number
-	the object was seen from the view cell.
+
+/** Iterator over the pvs.
 */
-struct PvsData 
-{
-public:
-	PvsData() {}
-	PvsData(const float sumPdf):
-	mSumPdf(sumPdf) {}
-	
-	// $$JB in order to return meaningfull values
-	// it assumes that the sum pdf has been normalized somehow!!!
-	inline float GetVisibility() { return mSumPdf; }
-
-	/// sum of probability density of visible sample rays
-	float mSumPdf;
-};
-
-
-class MailablePvsData 
-{
-public:
-	// sum of probability density of visible sample rays
-	float mSumPdf;
-	int mCounter;
-
-	MailablePvsData() {}
-	MailablePvsData(const float sumPdf):
-	mSumPdf(sumPdf) {}
-
-	// $$JB in order to return meaningfull values
-	// it assumes that the sum pdf has been normalized somehow!!!
-	inline float GetVisibility() { return mSumPdf; }
-
-
-	///////////////
-	//  Mailing stuff
-
-	// last mail id -> warning not thread safe!
-	// both mailId and mailbox should be unique for each thread!!!
-	static int sMailId;
-	static int sReservedMailboxes;
-
-	static void NewMail(const int reserve = 1) 
+template<typename T, typename S>
+class PvsIterator
+{
+public:
+	PvsIterator<T, S>(){}
+	PvsIterator<T, S>(const typename vector<PvsEntry<T, S> >::const_iterator &itCurrent,
+					  const typename vector<PvsEntry<T, S> >::const_iterator &itEnd):
+	mItCurrent(itCurrent), mItEnd(itEnd)
 	{
-		sMailId += sReservedMailboxes;
-		sReservedMailboxes = reserve;
-	}
-
-	void Mail() { mMailbox = sMailId; }
-	bool Mailed() const { return mMailbox == sMailId; }
-
-	void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
-	bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
-
-	int IncMail() { return ++ mMailbox - sMailId; }
-	
-	//////////////////////////////////////////
+	}
+  
+	inline bool HasMoreEntries() const { return (mItCurrent != mItEnd);	}
+
+	inline T Next(S &pdf) {
+		pdf = (*mItCurrent).mData;
+		return (*(mItCurrent ++)).mObject;
+	}
+
+	inline T Next() { return (*(mItCurrent ++)).mObject; }
+
+
+private:
+	
+	typename vector<PvsEntry<T, S> >::const_iterator mItCurrent;
+	typename vector<PvsEntry<T, S> >::const_iterator mItEnd;
+};
+
+
+
+
+struct VerbosePvsStats
+{
+	VerbosePvsStats(): mDistanceWeightedTriangles(0), mDistanceWeightedPvs(0), mWeightedTriangles(0)
+	{}
+
+	float mDistanceWeightedTriangles;
+	float mDistanceWeightedPvs;
+	float mWeightedTriangles;
+};
+
+
+/** Template class representing the Potentially Visible Set (PVS) 
+	mainly from a view cell, but also e.g., from objects.
+*/
+template<typename T, typename S>
+class VerbosePvs
+{
+  template<typename T1, typename S1> friend class PvsIterator;
+
+public:
+
+	VerbosePvs(): mSamples(0), mEntries(), mLastSorted(0), mQueriesSinceSort(0) 
+	{}
+
+	/** creates pvs and initializes it with the given entries. 
+		Assumes that entries are sorted.
+	*/
+	VerbosePvs(const vector<PvsEntry<T, S> > &samples);
+	virtual ~VerbosePvs() {};
+
+	/** Compresses PVS lossless or lossy.
+	*/
+	int Compress() { return 0; }
+	
+	inline int GetSize() const { return (int)mEntries.size(); }
+	
+	inline bool Empty() const { return mEntries.empty(); }
+
+	inline void Reserve(const int n) { mEntries.reserve(n); }
+	/** Normalize the visibility of entries in order to get 
+		comparable results.
+	*/
+	void NormalizeMaximum();
+	/** Merges pvs of a into this pvs.
+		Warning: very slow!
+	*/
+	void MergeInPlace(const VerbosePvs<T, S> &a);
+	/** Difference of pvs to pvs b.
+	@returns number of different entries.
+	*/
+	int Diff(const VerbosePvs<T, S> &b);
+	/** Finds sample in PVS.
+		@param checkDirty if dirty part of the pvs should be checked for entry 
+		(warning: linear runtime in dirty part)
+		@returns iterator on the sample if found, else the place where 
+		it would be added in the sorted vector.
+	*/
+	bool Find(T sample,
+			  typename vector<PvsEntry<T, S> >::iterator &it,
+			  const bool checkDirty = true);
+
+	bool GetSampleContribution(T sample, const float pdf, float &contribution);
+	/** Adds sample to PVS.
+		@returns contribution of sample (0 or 1)
+	*/
+	float AddSample(T sample, const float pdf);
+	/** Adds sample to PVS without checking for presence of the sample
+		warning: pvs remains unsorted!
+	*/
+	void AddSampleDirty(T sample, const float pdf);
+	/** Adds sample dirty (on the end of the vector) but
+		first checks if sample is already in clean part of the pvs.
+	*/
+	bool AddSampleDirtyCheck(T sample, const float pdf);
+	/** Sort pvs entries. This should always be called after a
+		sequence of AddSampleDirty calls 
+	*/
+	void Sort();
+	/** Sort pvs entries assume that the pvs contains unique entries
+	*/
+	void SimpleSort();
+	/** Adds sample to PVS.
+		@returns PvsData
+	*/
+	typename std::vector<PvsEntry<T, S> >::iterator 
+		AddSample2(T sample, const float pdf);
+	/** Subtracts one pvs from another one.
+		WARNING: could contains bugs
+		@returns new pvs size
+	*/
+	int SubtractPvs(const VerbosePvs<T, S> &pvs);
+
+	/** Returns PVS data, i.e., how often it was seen from the view cell, 
+		and the object itsef.
+	*/
+	void GetData(const int index, T &entry, S &data);
+
+	/** Collects the PVS entries and returns them in the vector.
+	*/
+	void CollectEntries(std::vector<T> &entries);
+
+	/** Removes sample from PVS if reference count is zero.
+	@param visibleSamples number of references to be removed
+	*/
+	bool RemoveSample(T sample, const float pdf);
+
+	/** Compute continuous PVS difference 
+	*/
+	void ComputeContinuousPvsDifference(VerbosePvs<T, S> &pvs, 
+										float &pvsReduction,
+										float &pvsEnlargement);
+
+	/** Clears the pvs.
+	*/
+	void Clear(const bool trim = true);
+	/** Trim the vector containing the pvs.
+	*/
+	void Trim();
+
+	static int GetEntrySizeByte(); 
+	static float GetEntrySize();
+
+	/** Compute continuous PVS difference 
+	*/
+	float GetPvsHomogenity(VerbosePvs<T, S> &pvs);
+
+	static void Merge(VerbosePvs<T, S> &mergedPvs, 
+					  const VerbosePvs<T, S> &a, 
+					  const VerbosePvs<T, S> &b);
+
+	inline int GetSamples() const {	return mSamples; }
+
+	/** If there is an unsorted part in the pvs.
+	*/
+	bool IsDirty() const { return mLastSorted < mEntries.size(); }
+
+	/** If this pvs requires a resort to stay efficient.
+	*/
+	bool RequiresResort() const
+	{
+		// the last part should not be more than log of the sorted part. this
+		// way we can achieve logarithmic behaviour for insertion and find
+		const int n = mEntries.size();
+		const int dirtySize = n - mLastSorted;
+
+		const double LOG2E = 1.442695040f;
+
+		const float logN = log((float) Max(1, n))/LOG2E;
+		const float logS = log((float) Max(1, mLastSorted))/LOG2E;
+		const float logD = log((float) Max(1, dirtySize))/LOG2E;
+
+		if (8*(n + 2*dirtySize*logD) <
+			mQueriesSinceSort*((mLastSorted*logS + dirtySize*dirtySize/2)/n - logN)) 
+		{
+			// cout<<"Q="<<mQueriesSinceSort<<" N="<<n<<" D="<<dirtySize<<endl;
+			return true;
+		}
+		
+		return false;
+	}
+
+	/** If this pvs requires a resort to stay efficient.
+	*/
+	bool RequiresResortLog() const
+	{
+		// the last part should not be more than log of the sorted part. this
+		// way we can achieve logarithmic behaviour for insertion and find
+		const int dirtySize = (int)mEntries.size() - mLastSorted;
+		return dirtySize > 4 * (int)(log((double)mEntries.size()) / log(2.0));
+	}
+
+	inline int GetLastSorted() const { return mLastSorted; }
+
+  PvsIterator<T, S> GetIterator() const;
+
+	VerbosePvsStats mStats;
 
 protected:
 
-	int mMailbox;
-
-};
+	/** Merge pvs 1 from begin iterator to end iterator with
+		pvs 2 from begin iterator to end iterator.
+	*/
+	static void Merge(VerbosePvs<T, S> &mergedPvs, 
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &aBegin,
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &aEnd,
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &bBegin,
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &bEnd,
+					  const int aSamples, 
+					  const int bSamples);
+
+
+	//////////////////////////////
+
+	/// vector of PVS entries
+	vector<PvsEntry<T, S> > mEntries; 
+
+	/// Number of samples used to create the PVS
+	int mSamples;
+
+	/// Last sorted entry in the pvs (important for find and merge)
+	int mLastSorted;
+
+	int mQueriesSinceSort;
+};
+
 
 }
Index: GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 2579)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 2582)
@@ -26,5 +26,5 @@
 #include "GlobalLinesRenderer.h"
 #include "RayCaster.h"
-//#include "testrt.h"
+//#include "vlastimil/testrt.h"
 
 #include "ViewCellsManager.h"
@@ -177,4 +177,7 @@
   //be ignored. Use it as you will!
   //note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() {
+
+//#define _CRT_SET
+
 #ifdef _CRT_SET
   _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
@@ -218,4 +221,5 @@
 	}
 
+	
 	//Debug << "using pvs type " << PVS_TYPE << endl;
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ReverseGvs.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ReverseGvs.cpp	(revision 2546)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ReverseGvs.cpp	(revision 2582)
@@ -361,4 +361,5 @@
   static float dist[packetSize];
   static Vector3 dirs[packetSize];
+  static Vector3 origs[packetSize];
   static Vector3 shifts[packetSize];
   // now find the silhouette along the line
@@ -373,13 +374,12 @@
 	  shifts[i] = r*line;
 	  dirs[i] = Normalize(newPivot + shifts[i] - termination );
-	  mlrtaStoreRayASEye4(&termination.x,
-						  &dirs[i].x,
-						  i);
-	}
-	
-	mlrtaTraverseGroupASEye4(&box.Min().x,
-							 &box.Max().x,
-							 hit_triangles,
-							 dist);
+	  origs[i] = termination;
+	  // mlrtaStoreRayASEye4(&termination.x, &dirs[i].x, i);
+	}
+	
+	// mlrtaTraverseGroupASEye4(&box.Min().x, &box.Max().x, hit_triangles, dist);
+	assert(preprocessor->mRayCaster);
+	preprocessor->mRayCaster->CastRaysPacket4(&box.Min(), &box.Max(), origs,
+						  dirs, hit_triangles, dist);
 	
 	for (i=0; i < packetSize; i++) {
@@ -467,4 +467,5 @@
   static float dist[packetSize];
   static Vector3 dirs[packetSize];
+  static Vector3 origs[packetSize];
   static Vector3 shifts[packetSize];
   // mutate the 
@@ -486,13 +487,12 @@
 	  shifts[i] = r*line;
 	  dirs[i] = Normalize(ray.mTermination + shifts[i] - origin );
-	  mlrtaStoreRayASEye4(&origin.x,
-						  &dirs[i].x,
-						  i);
-	}
-	
-	mlrtaTraverseGroupASEye4(&box.Min().x,
-							 &box.Max().x,
-							 hit_triangles,
-							 dist);
+	  // mlrtaStoreRayASEye4(&origin.x, &dirs[i].x, i);
+	  origs[i] = origin;
+	}
+	
+	// mlrtaTraverseGroupASEye4(&box.Min().x, &box.Max().x, hit_triangles, dist);	
+	assert(preprocessor->mRayCaster);
+	preprocessor->mRayCaster->CastRaysPacket4(box.Min(), box.Max(), origs,
+						  dirs, hit_triangles, dist);
 	
 	for (i=0; i < packetSize; i++) {
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbai.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbai.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbai.h	(revision 2582)
@@ -0,0 +1,647 @@
+// ============================================================================
+// $Id: $
+//
+// ktbai.h
+//     classes for building up the different KD-trees
+//
+// Class: CKTBBuildUp, CKTBBuildUp_new
+//
+// REPLACEMENT_STRING
+//
+// Initial coding by Vlasta Havran, February 2007
+
+#ifndef __KTBAI_H__
+#define __KTBAI_H__
+
+// GOLEM headers
+#include "configh.h"
+#include "ktbconf.h"
+#include "ktb.h"
+#include "ktb8b.h"
+#include "Containers.h"
+
+namespace GtpVisibilityPreprocessor {
+
+// forward declarations
+class SKTBNode;
+
+#ifndef _KTB8Bytes
+// Use 12 Bytes representation
+#define CKTBAllocManPredecessor CKTBAllocMan
+#undef  SKTBNodeT
+#define SKTBNodeT CKTBNodeAbstract::SKTBNode
+#else
+// Use 8 Bytes representation per node
+#define CKTBAllocManPredecessor CKTB8BAllocMan
+#undef  SKTBNodeT
+#define SKTBNodeT CKTB8BNodeAbstract::SKTBNode
+#endif
+
+#ifndef INFINITY
+#define INFINITY 10e10
+#endif
+
+// The base class for KD-tree with irregular change of axes, where
+// the splitting plane can be positioned.
+class CKTBABuildUp:
+  public CKTBAllocManPredecessor
+{
+public:
+  // The definition of flags
+  enum EBoundaryType {
+    EE_LeftBoundary = 1,
+    EE_InLeftList = 1,
+    EE_RightBoundary = 2,
+    EE_InRightList = 2,
+    EE_BothBoundaries = 3,
+    EE_ToBeRemoved = 4
+  };
+  
+  // the item in the list for all objects
+  struct SSolid
+  {
+    Intersectable *obj; // pointer to the object itself
+    unsigned int flags; // the flags to be set, they are common for all boundaries
+
+    // query functions
+    inline bool InFirstList() const { return (flags & EE_InLeftList); }
+    inline bool InSecondList() const { return (flags & EE_InRightList); }
+    inline bool InBothLists() const { return (flags == EE_BothBoundaries); }
+    inline bool ToBeRemoved() const { return (flags & EE_ToBeRemoved); }
+    inline bool ToBeRemovedOnly() const { return (flags == EE_ToBeRemoved); }
+    inline unsigned int Flags() const { return flags;}
+    // Setting functions
+    inline void SetInFirstList() { flags |= 1; }
+    inline void SetInSecondList() { flags |= 2; }
+    inline void SetToRemove() { flags |= 4; }
+    inline void SetToRemoveOnly() { flags = 4; }
+    
+    inline void ResetFlags() { flags = 0;}
+    SSolid() { ResetFlags(); }
+  };
+
+  // The container of the object entries
+  typedef vector<SSolid> SSolidVec;
+  
+  // the array of all objects in the scene
+  SSolidVec solidArray;
+
+  // the item of the boundary list - either left or right boundary
+  // of the axis-aligned bounding box of the object. This structure
+  // is intentionally of small size, namely 12 or 16 Bytes.
+
+  struct SItem
+  {
+    float pos;  // boundary values for all three axes
+    struct SSolid *obj; // the pointer to the object with flags
+
+    // The axis represented by the item (CKTBAxes::Axes)
+    uint1 axis; // = (X=0, Y=1, Z=2)
+    // the type of boundary (low, high)
+    uint1 typeLoHi;
+    // only allignment to 12 Bytes
+    //uint2 dummy;
+    // -------------------------------------------------
+    // some basic functions
+    SItem(float posN, SSolid *objN, int axisN, EBoundaryType LoHiN) {
+      pos = posN; obj = objN; axis = axisN; typeLoHi = (uint1)LoHiN;
+    }
+    // Simply constructor, just initializing flags
+    SItem() {obj = 0; axis = 255; typeLoHi = 0; }
+    //SItem& operator=(const SItem &src) {
+    //  this->pos = src.pos; this->obj = src.obj;
+    //  this->axis = src.axis; this->typeLoHi = src.typeLoHi;
+    //  return *this;
+    // }
+
+    // Simple query functions
+    inline bool IsLeftBoundary() const {
+      return (typeLoHi ==  EE_LeftBoundary);
+    }
+    inline bool IsRightBoundary() const {
+      return (typeLoHi == EE_RightBoundary);
+    }    
+    // Simple set functions
+    void SetLeftBoundary() { typeLoHi = EE_LeftBoundary; }
+    void SetRightBoundary() { typeLoHi = EE_RightBoundary; }
+    // For quicksort
+    friend bool operator<(const SItem &a, const SItem &b) {
+      if (a.pos < b.pos)
+	return -1;
+      else
+	if (a.pos > b.pos)
+	  return 1;
+	else
+	  // the coordinates are equal
+	  if ( (a.IsRightBoundary()) &&
+	       (b.IsLeftBoundary()) )
+	    return -1; // right_boundary < left_boundary
+	  else
+	    if ( (a.IsLeftBoundary()) &&
+		 (b.IsRightBoundary()) )
+	      return 1; // left_boundary > right_boundary
+      // coordinates are equal, the same value and type, order is correct
+      return 0; 
+    }
+  };
+
+  // Here is the extended element for RadixSort
+  struct SItemRadix:
+    public SItem
+  {
+    // the pointer needed to chain the data during sorting
+    SItemRadix *next;
+    // Basic operations
+    SItemRadix(): SItem() { next = 0;}
+    // This is necessary constructor
+    SItemRadix(const SItem &it) {
+      memcpy(this, &it, sizeof(SItem));
+      next = 0;
+    }
+    // This is necessary copy operator
+    SItemRadix& operator=(const SItem &it) {
+      memcpy(this, &it, sizeof(SItem));
+      next = 0;
+      return *this;
+    }
+  };
+  
+
+  // ---------------------------------------------------------
+  // The declaration of container with object boundaries
+  typedef vector<SItem> SItemVec;
+  typedef vector<SItemRadix> SItemVecRadix;
+
+  // ---------------------------------------------------------
+  // Sorting by QuickSort and RadixSort
+
+  // QuickSort
+  // compare function for SItem*
+  static int Compare(const SItem *p, const SItem *q);
+  // bounding box sorting by Quick Sort
+  void SortOneAxis(SItemVec &itemvec, int cnt, int * const stackQuickSort);
+
+  // -------------------------------------
+  // For Radix Sort
+  // Radix sort int 2^8=256 classes and three
+  // passes .. 4x8 bits=32 bits
+  bool _useRadixSort;
+  enum { RXBITS30 = 11 }; // the number of bits used for one phase of Radix Sort
+  enum { // the number of buckets for RadixSort
+         RXBUFS30 = 1 << RXBITS30,
+         RXBUFS30_2 = 1 << (RXBITS30-1)};
+  // This is one bucket of radix soft
+  struct SRadix {
+    SItemRadix *beg, *end;
+  };
+  // for 3-passes radix sort over the vectored data
+  void CopyToAuxArray(const SItemVec &bounds, SItemVecRadix &aux);
+  void RadixPassHoffset11(SItemVecRadix &bounds, int bit, SRadix *rb,
+			  float offset, SItemRadix **start);
+  void RadixPass11(SItemRadix **start, int cnt, int bit, SRadix *rb);
+  void RadixPassOffset10(SItemRadix **start, int cnt, int bit, SRadix *rb,
+			 float offset);
+  void CopyFromAuxArray(SItemRadix *aux, SItemVec &bounds);
+
+  // forward declaration
+  struct SInputData;
+  // sorts all three axes, cnt is the number of elems
+  void SortAxes(SInputData *data);
+  // initialization of the bounding box for a given object
+  void LoadBB(SBBox &bb, SSolid *obj);
+
+  // test if the lists are correctly sorted
+  void Check3List(SInputData *data);
+  void Check1List(SItemVec *vec, int axis, int countExpected);
+  void Check1List(SInputData *data, int axis, int countExpected);
+    
+  //----------------------------------------------------------------------
+  // Termination criteria and fixing the splitting plane orientation
+
+  // structure for prefered and required params for evaluation functions
+  // and the termination criteria
+  struct SReqPrefParams
+  {
+    //if any position on required axis is preferred for next subdivision step
+    float reqPosition; // then reqPosition>0
+    // if any axis is prefered for next step
+    bool  useReqAxis;
+    // the prescribed axis for the next subdivision
+    CKTBAxes::Axes reqAxis;
+
+    // -------------- AUTOMATIC TERMINATION CRITERIA ---------------------
+    // the ratio of improvement for the cost by subdivision and not-subdividing
+    // for the previous subdivision
+    float ratioLast;
+    // the ratio of improvement for the subdivision in the previous step
+    float ratioLastButOne;
+    // the number of subdivision from the root node, where the improvement
+    // in the cost failed
+    int   failedSubDivCount;
+    void Init() {
+      reqPosition = Limits::Infinity;
+      useReqAxis = false;
+      reqAxis = CKTBAxes::EE_Leaf;
+  
+      ratioLast = 1000.0;
+      ratioLastButOne = 1000.0;
+      failedSubDivCount = 0;      
+    }
+  };
+
+  // initialize required and preferenced parameters before first subdivision
+  void InitReqPref(SReqPrefParams *pars);
+
+  // ------------------------------------------------------
+  // A structure for a single step of subdivision
+  struct SInputData {
+    // the traversal bounding box of the scene (not necessarily tight)
+    SBBox box;
+    // the number of objects in the node (= number_of_boundaries/2)
+    int count;
+    // the number of reserved boundaries in the node (>=2*count)
+    int cntReserved;
+
+    // The list of x-boundaries, y-boundaries, z-boundaries
+    SItemVec *xvec;
+    SItemVec *yvec;
+    SItemVec *zvec;
+
+    // only for allignment, it can be used for different purpose
+    int algorithmBreakAx;
+
+    // ----------------------------
+    // The mode of subdivision
+    ESubdivMode modeSubDiv;
+
+    // Some prescribed parameters to be used
+    SReqPrefParams pars;
+
+    // ----------------------------------
+    // Axis to be used if prescribed
+    CKTBAxes::Axes axis;
+    // the position to be used for MakeOneCut
+    float position;
+    float position2;
+    // the number of objects to be duplicated
+    int cntThickness;
+    // the iterator to be used for splitting
+    SItemVec::iterator bestIterator;
+    // if 1 or 2 splits
+    int twoSplits;
+    // the best cost
+    float bestCost;
+
+    // if to make subdivision on the left node
+    int makeSubdivisionLeft;
+    // if to make subdivision on the right node
+    int makeSubdivisionRight;
+
+    // -----------------------------------
+    // When the min boxes was inserted as the first one
+    int lastDepthForMinBoxes;
+    // The surface area for the last minimum box inserted
+    float lastMinBoxSA2;
+    // The pointer to the last inserted minimum box
+    SKTBNodeT* lastMinBoxNode;
+  private:
+    void Init() {
+      box.Initialize();
+      algorithmBreakAx = 0;
+      count = 0; cntReserved = 0;
+      xvec = yvec = zvec = 0;
+      pars.Init();
+      cntThickness = 0;
+      makeSubdivisionLeft = makeSubdivisionRight = 1;
+      lastDepthForMinBoxes = 0;
+      lastMinBoxSA2 = INFINITY;
+      lastMinBoxNode = 0;
+    }
+  public:
+
+    // -----------------------------------
+    // Implicit constructor
+    SInputData() {
+      Init();
+    }
+    ~SInputData() {
+      Free();
+    }
+    
+    // Allocate at least for one object
+    void Alloc(int sizeN = 2) {
+      if (!xvec)
+	xvec = new GALIGN16 vector<SItem>;
+      assert(xvec);
+      if (!yvec)
+	yvec = new GALIGN16 vector<SItem>;
+      assert(yvec);
+      if (!zvec)
+	zvec = new GALIGN16 vector<SItem>;
+      assert(zvec);
+      cntReserved = sizeN;
+      // cout << "SizeN = " << sizeN << endl;
+      xvec->reserve(sizeN); xvec->resize(0); 
+      yvec->reserve(sizeN); yvec->resize(0); 
+      zvec->reserve(sizeN); zvec->resize(0);
+      count = 0;
+    } // Alloc
+    void Free() {
+      delete xvec; xvec = 0;
+      delete yvec; yvec = 0;
+      delete zvec; zvec = 0;
+      count = cntReserved = 0;
+    } // Free
+    void Reserve(int sizeN) {
+      assert(xvec);
+      assert(yvec);
+      assert(zvec);
+      if (sizeN > cntReserved) {
+	xvec->reserve(sizeN);
+	yvec->reserve(sizeN);
+	zvec->reserve(sizeN);
+	cntReserved = sizeN;
+      }
+    } // Reserve
+    void Resize(int sizeN) {
+      assert(sizeN >= 0);
+      assert(xvec);
+      assert(yvec);
+      assert(zvec);
+      xvec->resize(sizeN);
+      yvec->resize(sizeN);
+      zvec->resize(sizeN);
+      count = sizeN*2;
+    } // Reserve
+
+    // Return the item using the index
+    SItemVec* GetItemVec(int i) {
+      assert((i >= 0) && (i < 3));
+      return (&xvec)[i];
+    }
+    void CopyBasicData(SInputData *d) {
+      box = d->box;
+      count = 0;
+      algorithmBreakAx = d->algorithmBreakAx;
+      modeSubDiv = d->modeSubDiv;
+      pars = d->pars;
+      axis = d->axis;
+      position = d->position;
+      // added 12/2007 VH
+      position2 = d->position2;
+      cntThickness = d->cntThickness;
+      //
+      makeSubdivisionLeft = d->makeSubdivisionLeft;
+      makeSubdivisionRight = d->makeSubdivisionRight;      
+      // Intentionally, do not copy vectors of items
+      lastDepthForMinBoxes = d->lastDepthForMinBoxes;
+      lastMinBoxSA2 = d->lastMinBoxSA2;
+      lastMinBoxNode = d->lastMinBoxNode;
+    }
+  };
+
+  // Stack of data to be used
+  SInputData *stackID;
+  // current index
+  int         stackIndex;
+  // the maximum depth of tree
+  int         maxTreeDepth;
+  // the depth of the stack
+  int         stackDepth;
+  // Return the new data to be used
+  SInputData* AllocNewData() {
+    int i = stackIndex;
+    stackIndex++;
+    return &(stackID[i]);
+  }
+  SInputData* AllocNewData(int cnt) {
+    int i = stackIndex;
+    stackID[i].Alloc(cnt);
+    stackIndex++;
+    return &(stackID[i]);
+  }
+  // Free the last data allocated
+  void FreeLastData() { stackIndex--; }
+    
+  // ---------------------------------------------------------------------
+  // upper-level function for building up CKTB tree
+
+  // creates all the auxiliary structures for building up CKTB tree
+  SInputData* Init(ObjectContainer *objlist, const AxisAlignedBox3 &box);
+
+  void DeleteAuxiliaryData() {
+    for (int i = 0; i < stackDepth; i++) {
+      stackID[i].Free();
+    }
+  }
+  
+  // ---------------------------------------------------------------------
+  // Working with boundaries of objects
+  
+  // make the full leaf from current node
+  SKTBNodeT* MakeLeaf(SInputData *i);
+
+  // breaks the list into two list for a given axis and value
+  void BreakAx(SInputData *i, int axis,
+	       SInputData *right,
+	       int &cntL, int &cntR);
+  // breaks the list into two list for a given axis and value
+  void BreakAxPosition(SInputData *i, int axis,
+		       SInputData *right,
+		       int &cntL, int &cntR);
+
+  // split the list in the other than splitting axis into two lists
+  void DivideAx_I(SInputData *i, int axis,
+		  SInputData *right,
+		  int &cntL, int &cntR);
+  // also split and set the boundaries to be only in the first list
+  void DivideAx_II(SInputData *i, int axis,
+		   SInputData *right,
+		   int &cntL, int &cntR);
+  // split the list in the other than splitting axis into two lists
+  void DivideAx_I_opt(SInputData *i, int axis,
+		      SInputData *right,
+		      int cntL, int cntR);
+  // also split and set the boundaries to be only in the first list
+  void DivideAx_II_opt(SInputData *i, int axis,
+		       SInputData *right,
+		       int cntL, int cntR);
+  // reduce bounding boxes of objects split by the splitting plane
+  void ReduceBBoxes(SInputData *i, int axis,
+		    SInputData *right,
+		    const float &position);
+  // Remove the objects from the containter
+  void RemoveObjects(SItemVec *, int cntObjects);
+  void RemoveObjectsReset(SItemVec *, int cntObjects);
+
+  // Computes the tight bounding box and the number of changed planes
+  // when the tight box is used
+  int GetEBox(const SInputData &i, SBBox &tbox);
+
+  // returns a box enclosing all the objects in the node
+  void GetTightBox(const SInputData &i, SBBox &tbox);
+  
+  // creates one cut inside CKTB tree
+  SKTBNodeT* MakeOneCut(SInputData *i);
+  // recursive function for creation of CKTB tree
+  SKTBNodeT* SubDiv(SInputData *i);
+
+  // ------ Methods for building up CKTB tree ------------------
+  // returns 1 to supress to call the following criteria
+  struct SSplitState
+  {
+    // counts
+    int   cntAll;       // the number of all objects in the bounding box
+    int   cntLeft;      // the count of bounding boxes on the left
+    int   cntRight;     // the count of bounding boxes on the right
+    int   thickness;    // the count of bounding boxes straddling the splitting plane
+
+    CKTBAxes::Axes  axis;  // the axis, where the splitting is proposed
+    float sizeb[3]; // the size of the box for x, y, and z
+    SBBox box; // the box, that is subdivided
+    
+    // derived values from basic ones
+    float width;        // the size of bounding box along the axis
+    float frontw;       // the size of the bounding box in another axis (depth)
+    float topw;         // the size of the bounding box in next next axis (height)
+    float areaSplitPlane; // the area of the splitting plane
+    float areaSumLength; // the size of the bounding as sum of height and depth
+    float areaWholeSA2; // the half of the surface area of the whole box for this node
+
+    // The iterator valid for current position
+    SItemVec::iterator it;    
+    // The position for this splitting plane to be evaluated
+    float position; // the distance from the left boundary of the box for this node
+    // The position for the next position, makes sense only for free interval (thickness=0)
+    float position2; // the distance from the left boundary of the box for this node
+    
+    // The evaluation best cost until now
+    float bestCost;
+    // The position to be used
+    SItemVec::iterator bestIterator;
+    // The number of objects stradling the spliting plane for best position
+    int   bestThickness;
+    // Which mechanism to be used for splitting, either 0,1, or 2 splitting planes
+    int   bestTwoSplits;
+
+    // setting the evaluation for split cases that must not be done
+    float WorstEvaluation() const { return MAXFLOAT;}
+    
+    // The initialization for the first axis to be tested.
+    void InitXaxis(int cnt, const SBBox &box);
+    void InitYaxis(int cnt, const SBBox &box);
+    void InitZaxis(int cnt, const SBBox &box);
+    // This function can be called only if InitXaxis was called before
+    void ReinitYaxis(int cnt, const SBBox &box);
+    // This function can be called only if InitXaxis was called, and subsequently
+    // the function ReinitYaxis was called.
+    void ReinitZaxis(int cnt, const SBBox &box);
+    // Normalize the best cost by surface area of the box
+    void NormalizeCostBySA2() { bestCost /= areaWholeSA2;}
+  };
+
+  // splitting state for current search
+  SSplitState state;
+
+  // Evaluating the cost, given the state and the values of splitting
+  void EvaluateCost(SSplitState &state);
+
+  // Evaluating the cost, given the state and the values of splitting
+  // for free cuts
+  void EvaluateCostFreeCut(SSplitState &state);
+  
+  // ----- statistical data ---------
+  int cntDuplicate;     // count of duplicated objects until now
+  bool resetFlagsForBreakAx; 
+
+  // ------ debugging data ----------
+  // if to print out the tree during construction
+  bool _printCuts;
+  
+protected:
+
+  // ---------------------------------
+  // The selection of the axis
+  int _algorithmForAxisSelection;
+  
+  //  ---- termination criteria -----
+  int algorithmAutoTermination; // the algorithm for automatic termination criteria
+  int maxDepthAllowed; // maximal depth of CKTB tree
+  int maxListLength; // maximal list length of CKTB tree
+  int maxCountTrials; // maximum number of trials for automatic termination criteria
+  // the cutting off empty space in leaves
+  bool cutEmptySpace; // if to cut off empty space in leaves in postprocessing
+  int absMaxAllowedDepth; // maximal depth from the root - mut not be surpassed
+  // maximal depth allowed for cutting within the leaf .. cut off empty space
+  int maxEmptyCutDepth; // must be <0,1,2,3,4,5,6> since six planes are enough
+  // This is working variable, denoting the depth of the leaf to be created.
+  int startEmptyCutDepth;
+
+  // ---------- Special improvements on the kd-tree construction --------
+  // flag if to split bounding boxes during splitting
+  bool    splitClip;
+  // flag if to put minimum enclosing boxes sparsely during the construction
+  bool    makeMinBoxes;
+  // if we make tight boxes if we put min box !
+  bool    makeTightMinBoxes;
+  // parameters to drive the minboxes construction
+  int     minObjectsToCreateMinBox, minDepthDistanceBetweenMinBoxes;
+  float   minSA2ratioMinBoxes;
+  // Biasing the empty cuts (no objects are split). The cost is multiplied
+  // by the coefficient which is assumed to be 0.8-0.9
+  float  biasFreeCuts;
+  // Make min box here
+  bool   makeMinBoxHere;
+  
+  // two next axes are stored in oaxes for each axis
+  static const CKTBAxes::Axes oaxes[3][2];
+
+  // ------ data to create the tree --------------------
+  int         initcnt;      // initial number of objects
+  SBBox       wBbox; // the box of the world in float values
+  Vector3   boxSize;   // the size of world bounding box in float
+  float       wholeBoxArea; // the surface area of the scene bounding box
+  
+  // for some functions it is necessary to have determined the following costs
+  float       Ct; // traversal cost - going in given direction != decision
+  float       Ci; // intersection cost - average intersection cost with object
+
+  // just if to be verbose
+  bool verbose;
+  
+  // the main function of this class .. returns the best splitting plane
+  // in X axis, requires InitXaxis() to be called before or InitYaxis() or InitZaxis()
+  // optimized version
+  void GetSplitPlaneOpt(SItemVec *vec, int axisToTest);
+  void GetSplitPlaneOpt2(SItemVec *vec, int axisToTest);
+  void GetSplitPlaneOpt3(SItemVec *vec, int axisToTest);
+  void GetSplitPlaneOptUnroll4(SItemVec *vec, int axisToTest);
+public:
+  // setting the evaluation for split cases that must not be done
+  float WorstEvaluation() const { return MAXFLOAT;}
+
+  // update the best value for evaluation
+  int UpdateEvaluation(float &eval, const float &newEval);
+
+public:
+  // default constructor
+  CKTBABuildUp();
+
+  // default destructor
+  virtual ~CKTBABuildUp();
+
+  // provide info about construction method
+  virtual void ProvideID(ostream &app);  
+  
+  // constructs the KD-tree for given objectlist and given bounding box
+  // returns NULL in case of failure, in case of success returns
+  // the pointer to the root node of constructed KD-tree.
+  virtual SKTBNodeT* BuildUp(ObjectContainer &objlist,
+			     const AxisAlignedBox3 &box,
+			     bool verbose = true);
+};
+
+}
+
+#endif // __KTBAI_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/raypack.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/raypack.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/raypack.h	(revision 2582)
@@ -0,0 +1,444 @@
+// ============================================================================
+// $Id: raypack.h $
+//
+// raypack.h
+//	  CRayPacket class - core of the ray-packet traversal routines
+//
+// Class: CRayPacket2x2
+//
+// REPLACEMENT_STRING
+//
+// Initial coding by Vlastimil Havran, 2006. The data design is in fact
+// Jakko Biker layout as propose in the article on Intel Web Site in year 2005
+// http://www.intel.com/cd/ids/developer/asmo-na/eng/245711.htm?page=1
+
+#ifndef __RAYPACK_H__
+#define __RAYPACK_H__
+
+#include <cassert>
+
+namespace GtpVisibilityPreprocessor {
+
+#include "Vector3.h"
+  
+// $$JB __SSE__ macro not define in _WIN32
+//#ifdef __SSE__
+#if 1
+
+// System headers for SSE
+#ifdef __INTEL_COMPILER
+#include <xmmintrin.h>
+#else
+// We assume GNU GCC compiler 3.4 or higher
+#include <xmmintrin.h>
+#endif
+
+
+// forward declarations
+#define SSE_INTRINSIC
+#ifdef SSE_INTRINSIC
+#define ALIGN16             __declspec(align(16)) 
+
+#ifdef _MSC_VER
+#define NEW_ALIGN16(type,n)  ((type*)_aligned_malloc((n)*sizeof(type),16))
+#define FREE_ALIGN16(array)  if(array){_aligned_free(array);(array)=0;}
+#else
+#define NEW_ALIGN16(type,n)  ((type*)malloc((n)*sizeof(type)))
+#define FREE_ALIGN16(array)  if (array) { free(array);(array)=0;}
+#endif // _MSC_VC
+
+#define PAD_FOUR(h)           mulFour(h)
+union extract_m128
+{
+  __m128 m;
+  float f[4];
+};
+#else
+#define NEW_ALIGN16(type,n)  ((type*)malloc((n)*sizeof(type)))
+#define ALIGN16              
+#define FREE_ALIGN16(array)  if(array){free(array);(array)=0;}
+#define PAD_FOUR(h)           (h)
+#endif
+  
+// -------------------------------------------------------------------
+// RayPacket2x2 class.  A set of 4 ray is defined by a location and a
+// direction. The direction is always normalized (length == 1) during
+// use.
+// -------------------------------------------------------------------
+class RayPacket2x2
+{
+public:
+  enum {
+    // The number of rays in one packet
+    PACKSIZE = 4
+  };
+  
+  // constructor
+  RayPacket2x2(
+    // origin and the direction of rays
+    const Vector3 orf[],
+    const Vector3 dirf[],
+    // The same type for all four rays
+    const int _type,
+    // All the rays has to start at the same cell
+    const void *_originCell = NULL,
+    // All the rays has to start at the same object
+    const Intersectable *_startObject = NULL,
+    // and also for shadow rays finish at the same object
+    const Intersectable *_stopObject = NULL
+  )
+  {
+    // location
+    ox[0] = orf[0].x; ox[1] = orf[1].x; ox[2] = orf[2].x; ox[3] = orf[3].x;
+    oy[0] = orf[0].y; oy[1] = orf[1].y; oy[2] = orf[2].y; oy[3] = orf[3].y;
+    oz[0] = orf[0].z; oz[1] = orf[1].z; oz[2] = orf[2].z; oz[3] = orf[3].z;
+    // direction, we assume to be normalized
+    dx[0] = dirf[0].x; dx[1] = dirf[1].x; dx[2] = dirf[2].x; dx[3] = dirf[3].x;
+    dy[0] = dirf[0].y; dy[1] = dirf[1].y; dy[2] = dirf[2].y; dy[3] = dirf[3].y;
+    dz[0] = dirf[0].z; dz[1] = dirf[1].z; dz[2] = dirf[2].z; dz[3] = dirf[3].z;
+    // Other components
+    ttype = _type;
+    origin = _originCell;
+    termination = NULL;
+    startObject = _startObject;
+    stopObject = _stopObject;
+    Init();
+  }
+  // dummy constructor
+  RayPacket2x2() {}
+
+  // Inititalize the ray again when already constructed
+  void Init(
+    // origin and the direction of rays
+    const Vector3 orf[],
+    const Vector3 dirf[],
+    // The same type for all four rays
+    const int _type,
+    // All the rays has to start at the same cell
+    const void *_originCell = NULL,
+    // All the rays has to start at the same object
+    const Intersectable *_startObject = NULL,
+    // and also for shadow rays finish at the same object
+    const Intersectable *_stopObject = NULL,
+    // if the direction of rays is normalized or not
+    bool dirNormalized = false)
+  {
+    // location
+    ox[0] = orf[0].x; ox[1] = orf[1].x; ox[2] = orf[2].x; ox[3] = orf[3].x;
+    oy[0] = orf[0].y; oy[1] = orf[1].y; oy[2] = orf[2].y; oy[3] = orf[3].y;
+    oz[0] = orf[0].z; oz[1] = orf[1].z; oz[2] = orf[2].z; oz[3] = orf[3].z;
+    // direction
+    if (dirNormalized) {
+      // already normalized
+      dx[0] = dirf[0].x; dx[1] = dirf[1].x; dx[2] = dirf[2].x; dx[3] = dirf[3].x;
+      dy[0] = dirf[0].y; dy[1] = dirf[1].y; dy[2] = dirf[2].y; dy[3] = dirf[3].y;
+      dz[0] = dirf[0].z; dz[1] = dirf[1].z; dz[2] = dirf[2].z; dz[3] = dirf[3].z;
+    }
+    else {
+      dx[0] = dirf[0].x; dx[1] = dirf[1].x; dx[2] = dirf[2].x; dx[3] = dirf[3].x;
+      dy[0] = dirf[0].y; dy[1] = dirf[1].y; dy[2] = dirf[2].y; dy[3] = dirf[3].y;
+      dz[0] = dirf[0].z; dz[1] = dirf[1].z; dz[2] = dirf[2].z; dz[3] = dirf[3].z;
+      std::cerr << "Normalization not yet implemented" << std::endl;
+      abort();
+    }
+    // other components
+    ttype = _type;
+    origin = _originCell;
+    termination = NULL;
+    startObject = _startObject;
+    stopObject = _stopObject;
+    Init();
+  }
+
+  // Computes the inverted direction of the rays, used optionally by
+  // a ray traversal algorithm. This has to be reconsidered, if it
+  // is really valuable. !!!
+  void ComputeInvertedDir() const;
+
+  // Computes the sign of the rays and returns false if all the directions
+  // for all three axes are the same, but it could be different among axes,
+  // but for one axis all 4 rays must have the same direction
+  bool ComputeDirSign() const;
+  
+  // 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 Intersectable* GetStartObject() const { return startObject;}
+  const Intersectable* GetStopObject() const { return stopObject;}
+
+  void SetStartObject(const Intersectable *newStartObject) {
+    startObject = newStartObject;
+  }
+  void SetStopObject(const Intersectable *newStopObject) {
+    stopObject = newStopObject;
+  }
+  int GetType() const { return ttype; }
+
+  // Reading and Setting origin of the ray and direction
+  // Ray origin
+  inline void SetLoc(int i, const Vector3 &l);
+  Vector3  GetLoc(int i) const;
+  // Direction
+  void SetDir(int i, const Vector3 &ndir);
+  Vector3  GetDir(int i) const;
+
+  // Retuns an object that is intersected by i-th ray
+  Intersectable* GetObject(int i) const;
+  void SetObject(int i, Intersectable* obj);
+  // Retuns a signed distance that is intersected by i-th ray
+  float GetT(int i) const;
+  void SetT(int i, float t);
+  // Retuns maximum signed distance that is intersected by i-th ray
+  float GetMaxT(int i) const;
+  void SetMaxT(int i, float t);
+  
+  // make such operation to slightly change the ray direction
+  // in case any component of ray direction is zero. This is
+  // carried out for all the rays in a packet
+  void CorrectZeroComponents();
+
+  // Returns the sign of the direction if this was precomputed
+  const int &GetSign(int axis) const { return sign_dir[axis];}
+
+  // Reset the result of intersection
+  void ResetObjects() {
+    obj[0] = obj[1] = obj[2] = obj[3] = 0;
+  }
+  
+private:
+  // Here it is crucial the layout of the rays in memory
+  // The layout by Jakko Biker is used
+  typedef float real;
+  union
+  {
+    struct
+    {
+      // ox[N],oy[N],oz[N] - origin of the ray N
+      union { real ox[4]; __m128 ox4; };
+      union { real oy[4]; __m128 oy4; };
+      union { real oz[4]; __m128 oz4; };
+    };
+    __m128 orig[3];
+  };
+  union
+  {
+    struct
+    {
+      // dx[N],dy[N],dz[N] - direction of the ray N
+      union { real dx[4]; __m128 dx4; };
+      union { real dy[4]; __m128 dy4; };
+      union { real dz[4]; __m128 dz4; };
+    };
+    __m128 dir[3];
+  };
+
+#define _USE_INVDIR_RP
+#ifdef _USE_INVDIR_RP
+  union
+  {
+    struct
+    {
+      // idx[N],idy[N],idz[N] - direction of the ray N
+      // inverted dir - maybe an overkill for SSE
+      // to be checked !
+      union { real idx[4]; __m128 idx4; };
+      union { real idy[4]; __m128 idy4; };
+      union { real idz[4]; __m128 idz4; };
+    };
+    __m128 idir[3];
+  };
+#endif
+
+  // The auxiliary and result values for traversal
+      
+  // Here is the result - currently computed signed distance
+  union { real t[4]; __m128 t4; };
+  // and so far minimum signed distance computed. This is required
+  // for computing ray object intersections
+  union { real tmax[4]; __m128 tmax4; };
+  // Here are the pointers to the objects that correspond to tmax[4]
+  // above. They can be different for all the rays !
+  union { Intersectable* obj[4]; __m128 obj4; };
+
+  friend class CKTBTraversal;
+  
+  // Type of the ray: primary, shadow, dummy etc., see ERayType above
+  int ttype;
+
+  // The sign of direction to be used in some algorithms. The sign
+  // has to be the same for all the rays in all the components of the
+  // direction vector !!!!
+  mutable int      sign_dir[3];
+ 
+  // I should have some abstract cell data type !!! here
+  // corresponds to the spatial elementary cell
+  const void *origin;
+  const void *termination;
+  
+  // the object on which surface a ray starts from
+  const Intersectable *startObject;
+  // the object on which surface a ray ends, for computation
+  // of the visibility queries between two points
+  const Intersectable *stopObject;
+
+  /// Precompute some CRay parameters. Most of them used for ropes traversal.
+  inline void Init();
+
+  // Precompute some values that are necessary.
+  inline void Precompute();
+};
+
+// --------------------------------------------------------------------------
+//  RayPacket2x2::SetLoc()
+// --------------------------------------------------------------------------
+inline void
+RayPacket2x2::SetLoc(int i, const Vector3 &l)
+{
+  assert( (i>=0) && (i<4));
+  ox[i] = l.x;
+  oy[i] = l.y;
+  oz[i] = l.z;
+}
+
+inline void
+RayPacket2x2::SetDir(int i, const Vector3 &ndr)
+{
+  // We assume that the direction is normalized !!!
+  assert( (i>=0) && (i<4));
+  dx[i] = ndr.x;
+  dy[i] = ndr.y;
+  dz[i] = ndr.z;
+}
+
+inline Vector3
+RayPacket2x2::GetLoc(int i) const
+{
+  assert( (i>=0) && (i<4));
+  return Vector3(ox[i],oy[i],oz[i]);
+}
+
+inline Vector3
+RayPacket2x2::GetDir(int i) const
+{
+  assert( (i>=0) && (i<4));
+  return Vector3(dx[i],dy[i],dz[i]);
+}
+
+// --------------------------------------------------------------------------
+//  RayPacket2x2::Precompute()
+// --------------------------------------------------------------------------
+inline void
+RayPacket2x2::Precompute()
+{
+  // initialize inverted dir ?
+#ifdef _USE_INVDIR_RP
+  // inverted dir - maybe an overkill for SSE
+  // to be checked !
+  idx[0] = 1.0f / dx[0];
+  idx[1] = 1.0f / dx[1];
+  idx[2] = 1.0f / dx[2];
+  idx[3] = 1.0f / dx[3];
+  
+  idy[0] = 1.0f / dy[0];
+  idy[1] = 1.0f / dy[1];
+  idy[2] = 1.0f / dy[2];
+  idy[3] = 1.0f / dy[3];
+
+  idz[0] = 1.0f / dz[0];
+  idz[1] = 1.0f / dz[1];
+  idz[2] = 1.0f / dz[2];
+  idz[3] = 1.0f / dz[3];
+#endif
+}
+
+// --------------------------------------------------------------------------
+//  RayPacket2x2::Init()
+// --------------------------------------------------------------------------
+inline void
+RayPacket2x2::Init()
+{
+  // apply the standard precomputation
+  Precompute();
+}
+
+// Computes the sign of the rays and returns false if all the directions
+// for all three axes are the same, but it could be different among axes,
+// but for one axis all 4 rays must have the same direction
+inline bool
+RayPacket2x2::ComputeDirSign() const
+{
+  // Set the sign of the direction 1 when negative
+  sign_dir[0] = (dx[0] < 0.0f);
+  sign_dir[1] = (dy[0] < 0.0f);
+  sign_dir[2] = (dz[0] < 0.0f);
+  for (int i = 1; i < 4; i++) {
+    if (sign_dir[0] != (dx[i] < 0.0f))
+      return true; // different direction in x 
+    if (sign_dir[1] != (dy[i] < 0.0f))
+      return true; // different direction in y
+    if (sign_dir[2] != (dz[i] < 0.0f))
+      return true; // different direction in z
+  }// for
+
+  // Returns false if all 4 rays have the consistent direction
+  return false;
+}
+
+inline Intersectable*
+RayPacket2x2::GetObject(int i) const
+{
+  assert( (i>=0) && (i<4));
+  return obj[i];
+}
+
+inline void
+RayPacket2x2::SetObject(int i, Intersectable* object)
+{
+  assert( (i>=0) && (i<4));
+  obj[i] = object;
+}
+
+inline float
+RayPacket2x2::GetT(int i) const
+{
+  assert( (i>=0) && (i<4));
+  return t[i];
+}
+
+inline void
+RayPacket2x2::SetT(int i, float tnew)
+{
+  assert( (i>=0) && (i<4));
+  t[i] = tnew;
+}
+
+inline float
+RayPacket2x2::GetMaxT(int i) const
+{
+  assert( (i>=0) && (i<4));
+  return tmax[i];
+}
+
+inline void
+RayPacket2x2::SetMaxT(int i, float tmaxnew)
+{
+  assert( (i>=0) && (i<4));
+  tmax[i] = tmaxnew;
+}
+#else // __SSE__
+
+// ? What to do here
+//#error "AAA"
+
+#endif // __SSE__
+
+} // namespace
+
+#endif // __RAYPACK_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/allocgo2.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/allocgo2.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/allocgo2.cpp	(revision 2582)
@@ -0,0 +1,233 @@
+// ===================================================================
+// $Id: $
+//
+// allocgo2.cpp
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2006 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlastimil Havran, 2003
+
+// standard headers
+#include <cassert>
+#include <iostream>
+
+// GOLEM headers
+#include "allocgo2.h"
+
+namespace GtpVisibilityPreprocessor {
+
+using namespace std;
+
+// ************* size-equal item allocator with alligning in the cache ****
+
+CAllocContinuous::CAllocContinuous(int sizeOfEntryV,
+				   int numEntriesInBlockV,
+				   int maxItemsForAllocation,
+				   int allignEntrySizeV,
+				   int allignBlockSizeV)
+{
+  if ((sizeOfEntryV < ((int)sizeof(void*))) || (numEntriesInBlockV < 2)) {
+    cerr << "Error: The Spc size-equal allocator initialization wrong.\n";
+    abort();
+  }
+  // input variables
+  sizeOfEntry = sizeOfEntryV;
+  granularity = numEntriesInBlockV;
+  maxItemsAtOnce = maxItemsForAllocation;
+  // Increase the allignment to be at least of entry size
+  int ta =  allignEntrySizeV;
+  while (sizeOfEntryV > allignEntrySizeV) {
+    allignEntrySizeV += ta;
+  } // while
+  // Increase the allignment of the block to be at least the size of one entry
+  ta = allignBlockSizeV;
+  while (allignEntrySizeV > allignBlockSizeV) {
+    allignBlockSizeV += ta;
+  } // while
+
+  // The allignment of entry
+  allignEntrySize = allignEntrySizeV;
+
+  // The allingment of block
+  allignBlockSize = allignBlockSizeV;
+
+  // Compute the memory needed for one block
+  memoryForOneBlock = (sizeOfEntry * (granularity + 2*maxItemsAtOnce))/allignEntrySize;
+  memoryForOneBlock = (memoryForOneBlock + 1) * allignEntrySize;
+  // Now we want to make sure for the big allignment
+  memoryForOneBlock /= allignBlockSize;
+  memoryForOneBlock = (memoryForOneBlock+2) * allignBlockSize;
+  
+  // status variables
+  initMemBlock = 0;
+  mstor = &initMemBlock;
+  // Release the memory and prepare the variables
+  ReleaseMemory();
+
+#if 0
+  cout << "CAllocContinuous: item size " << sz << " alligned to size " << size
+	 <<" granularity " << gran << "\n";
+  cout << "     BigAlignment=" << bigAllignment << "\n";
+#endif
+}
+
+void
+CAllocContinuous::ReleaseMemory()
+{
+  // delete all allocated memory blocks
+  void *bk = mstor;
+  void *p;
+  while (bk != &initMemBlock) {
+    p = *(void**)bk;
+    //cout << "Release " << "  p = " << (void*)bk << endl;
+    delete [] (char*)bk;
+    bk = p;
+  } // while
+  remainItems = 0;
+  initMemBlock = 0;
+  mstor = &initMemBlock;
+  bytesAllocated = 0;
+  lastEntryInBlockAllocated = 0;
+  nextAllocp = 0;
+  lastValidAddress = 0;
+}
+
+void*
+CAllocContinuous::AllocNewBlock()
+{
+  int allocHere = 0;
+  allocHere++;
+  
+  nextAllocp = new char[memoryForOneBlock]; // append to chain
+  if (nextAllocp == NULL) {
+    cerr << "Memory exhausted in CAllocContinuous\n";
+    abort();
+  }
+  
+#ifdef _DEBUG
+  memset((void*)nextAllocp, 0xFF, memoryForOneBlock);
+#endif  
+  // Compute the last valid address to be used in the current block
+  lastValidAddress = (void*)
+    (nextAllocp + memoryForOneBlock - 1);
+  
+  //cout << "ALloc " << allocHere << "  p = " << (void*)nextAllocp << endl;
+  
+  // Link the block to the chain of block !
+  *((void**)nextAllocp) = (void*)mstor; // link the previous chain
+  mstor = (void**)nextAllocp; // link the currently allocated block
+
+  // set chain of blocks .. allign the starting address
+  nextAllocp = (char*)(allignBlockSize * (((unsigned long)nextAllocp +
+                     sizeof(void*) + allignBlockSize - 1) / allignBlockSize));
+#ifdef _DEBUG
+  if ((unsigned long)mstor > (unsigned long)nextAllocp) {
+    cerr << "Allignment of the block is wrong" << endl;
+    abort();
+  }
+#endif
+  // Compute Allignment
+  unsigned long allignmentTotal = 2 * maxItemsAtOnce * sizeOfEntry;
+      
+  char *maxAddressInBlock = ((char*)mstor + memoryForOneBlock);
+  // We have to put there the place for the last entry
+  maxAddressInBlock -= allignmentTotal;
+
+  // The maximum number of single items to be allocated, which then allows
+  // also to allocate a last entry by a special routine
+  remainItems = (unsigned long)( maxAddressInBlock - ((char*)nextAllocp) );
+  remainItems /= sizeOfEntry;
+  remainItems -= 2 * maxItemsAtOnce;
+
+#ifdef _DEBUG
+  if (remainItems<0) {
+    cerr << "CAllocContinuous::Alloc Error\n";
+    abort();
+  }
+#endif
+
+  // Update the statistics, the total number of bytes allocated
+  // by the instance of this allocator
+  bytesAllocated += memoryForOneBlock;
+  //cout << "The Alloc called\n" << flush;
+
+  // We will be left with the last entry to allocate
+  lastEntryInBlockAllocated = false;
+  
+  // Return the address to be allocated as the next one
+  return (void*)nextAllocp;
+}
+
+// alloc the memory of size "sizeItem*entriesCnt" alligned in the memory
+// started in the new block
+void*
+CAllocContinuous::NewEntryInNewBlock(int entriesCnt)
+{
+  // We require first to allocate a new block
+  AllocNewBlock();
+  return New(entriesCnt);
+}
+
+void*
+CAllocContinuous::New(int entriesCnt)
+{
+  // void *m;  // <JK> is unreferenced
+  assert(entriesCnt > 0);
+  assert(entriesCnt <= maxItemsAtOnce);
+
+  if (remainItems < entriesCnt) {
+    return (void*)0; // not enough space left
+  }
+
+  unsigned long tmp = (unsigned long)nextAllocp;
+  if ((tmp % allignEntrySize) == 0) {
+    remainItems -= entriesCnt;
+    nextAllocp = (char*)(tmp + entriesCnt * sizeOfEntry);
+    return (void*)tmp;
+  }
+  // We have to allign the address to the allignEntrySize
+  tmp /= allignEntrySize;
+  tmp = (tmp+1) * allignEntrySize;
+  remainItems -= (tmp - (unsigned long)nextAllocp) / entriesCnt;
+  nextAllocp = (char*)(tmp + entriesCnt * sizeOfEntry);
+  assert(nextAllocp < lastValidAddress);
+  
+  return (void*)tmp;
+}
+
+// alloc the memory of size "sizeItem*entriesCnt" alligned in the memory
+// it can be in the current block, which is definitely the last one in
+// the current block. This should be used only if function New() above
+// returns 0.
+void*
+CAllocContinuous::NewLastEntry(int entriesCnt)
+{
+  if (!lastEntryInBlockAllocated) {
+    // if the last entry in the current block was not yet allocated
+    void *tmp = nextAllocp;
+#ifdef _DEBUG
+    // check if we do not go behind the block
+    if ( (unsigned long)tmp + sizeOfEntry * entriesCnt >
+	 (unsigned long)lastValidAddress) {
+      cerr << "Problem with the allocator, using the memory" << endl;
+      abort();
+    }    
+#endif // _DEBUG
+    lastEntryInBlockAllocated = true; // do not allocate again
+    return nextAllocp;
+  } // if the last entry
+
+  return (void*)0; // the entry was already allocated
+}
+
+void
+CAllocContinuous::Report()
+{
+  cout << "Unused entries in the current block = " << remainItems << "\n";
+  cout << "Total consumed memory = " << bytesAllocated << "\n";
+}
+
+
+}
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/allocgo2.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/allocgo2.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/allocgo2.h	(revision 2582)
@@ -0,0 +1,100 @@
+// ===================================================================
+// $Id: allocgo2.h $
+//
+// allocgo2.h
+//     Header file for different type of allocators
+//
+// Class: CAllocator, CAllocSub
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2006 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlastimil Havran, November 2005
+
+#ifndef __ALLOCGO2_H__
+#define __ALLOCGO2_H__
+
+// GOLEM headers
+#include "configh.h"
+
+namespace GtpVisibilityPreprocessor {
+
+// ------------------------------------------------------------------------
+// ************* size-equal item allocator with alligning in the cache ****
+
+// size-equal item allocator for ordinary subtree representation with cache
+// line alligning, sizeItem is the size of the smallest allocated block,
+// count is the number of items to perform one skip in the allocator forward
+// -------------------------------------------------------------------------
+class CAllocContinuous
+{
+public:
+  // constructor .. the size of one allocated item in Bytes,  number of items
+  // allocated in one block, the allignment for one entry, the allignment
+  // for the first allocated variable in the new blcok.
+  CAllocContinuous(int sizeEntryV, int numEntriesInBlock,
+		   int maxItemsForAllocation = 1,
+		   int allignEntrySizeV = 1,
+		   int allignBlockSizeV = 1);
+  ~CAllocContinuous() { ReleaseMemory(); }
+
+  // alloc the memory of size "sizeItem*entriesCnt" alligned in the memory
+  // started in the new block
+  void* NewEntryInNewBlock(int entriesCnt = 1);
+  
+  // alloc the memory of size "sizeItem*entriesCnt" alligned in the memory
+  // it has to be in the current block
+  void* New(int entriesCnt = 1);
+
+  // alloc the memory of size "sizeItem*entriesCnt" alligned in the memory
+  // it can be in the current block, which is definitely the last one in
+  // the current block. This should be used only if function New() above
+  // returns 0.
+  void* NewLastEntry(int entriesCnt = 1);
+
+  // alloc next block of size = granularity and returns the address to
+  // the first entry to be allocated in the next allocation by New() functions
+  void* AllocNewBlock(); 
+  
+#if 0
+  // alloc the memory of size "sizeItem*entriesCnt" alligned in the memory
+  // it has to be in the current block, but it is alligned to the allignment
+  // specified as the parameter.
+  void* NewAlligned(it entriesCnt = 1, int allignment = 4);
+#endif
+    
+  void ReleaseMemory(); // releases all memory alloc. by Alloc
+
+  // Returns the allignment
+  unsigned long GetEntryAllignment() const { return allignEntrySize;}
+  unsigned long GetBlockAllignment() const { return allignBlockSize;}
+  unsigned long GetFreeEntryCnt() const { return remainItems; }
+  unsigned long GetBytesAllocated() const { return bytesAllocated;}
+  
+  void Report();
+private:
+  
+  // Input variables
+  int granularity; // num of basic items in one block
+  int sizeOfEntry;  // size of one item to be allocated
+  int maxItemsAtOnce; // the number of items to be allocated at once
+  int allignBlockSize; // the allignment of the first entry in the block
+  int allignEntrySize; // the allignment of the individual entry
+
+  // The memory required to allocate for a new block
+  unsigned long memoryForOneBlock; 
+
+  // The status variables
+  unsigned long bytesAllocated;  // the count of bytes allocated by this allocator
+  void *initMemBlock; // initial memory block
+  void *lastValidAddress; // the maximum address to be used in the current block
+  void **mstor; // where store allocated memory
+  char *nextAllocp; // next returned addr
+  bool lastEntryInBlockAllocated; // if we have allready used the last entry in the block
+  unsigned long remainItems; // items remains in the block
+};
+
+}
+
+#endif // __ALLOCGO2_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktball.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktball.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktball.cpp	(revision 2582)
@@ -0,0 +1,1073 @@
+// ===================================================================
+// $Id: $
+//
+// ktball.cpp
+//     Implementation of interface functions for CKTB trees
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlastimil Havran, February 2007
+
+// GOLEM library
+#include "ktb.h"
+#include "ktbai.h"
+#include "ktball.h"
+#include "ktbtrav.h"
+#include "Environment.h"
+#include "raypack.h"
+#include "Mesh.h"
+
+// standard headers
+#include <fstream>
+#include <iomanip>
+
+namespace GtpVisibilityPreprocessor {
+
+// Static data structures fo CKTBTraversal class
+GALIGN16 CKTBTraversal::SStackElem
+CKTBTraversal::stack[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
+
+CKTBTraversal::SStackElem2
+CKTBTraversal::stack2[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
+
+CKTBTraversal::SStackElem3
+CKTBTraversal::stack3[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
+
+CKTBTraversal::SStackElem4
+CKTBTraversal::stack4[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
+
+  
+// ------------------------------------------------------------------
+// CKTB class
+// 
+// Binary Space Partitioning Tree, that handles bounded objects only
+// during intersection computation other way
+
+// default constructor
+CKTB::CKTB():
+  builtUp(false),
+  buildClass(NULL), traversalClass(NULL), sizeBuffer(0),buffer(0),
+  indexRead(0), indexWrite(0)
+{
+
+}
+
+// only for creating building class of CKTB tree
+CKTBAllocManPredecessor*
+CKTB::AllocBuildClass()
+{
+  CKTBAllocManPredecessor *bc = 0;
+  bool useArray = true;
+  
+  // this should be already initialised, but we want to be sure
+  if (useArray) {
+    // the implementation based on arrays
+    bc = new CKTBABuildUp(); // file ktbai.cpp
+  }
+  else {
+    // the implementation based on lists
+    // bc = new CKTBBuildUp(); // file ktbi.cpp
+  }
+    
+  if (bc == NULL) {
+    cerr << "The building class for KTB cannot be allocated"<< endl;
+    exit(3);
+  }
+
+  return bc;
+}
+
+void
+CKTB::AllocTraversalClass()
+{
+  if (traversalClass != NULL)
+    delete traversalClass;
+
+  traversalClass = NULL;
+
+  // if we use min boxes idea in the tree
+
+  Environment::GetSingleton()->GetBoolValue("BSP.minBoxes.use",
+					    makeMinBoxes);
+  Environment::GetSingleton()->GetBoolValue("BSP.minBoxes.tight",
+					    makeTightMinBoxes);
+  // the number of cells along ray path
+  const int size1D = 150;
+
+  cerr<<"th1"<<endl;
+  // $$JB tmp
+  size2D = 1;
+  cerr<<"size2d="<<size2D<<endl;
+  // initial index
+  index2D = 0;
+  AllocBuffer(size2D, size1D);
+  cerr<<"th2"<<endl;
+
+#if 0  
+  // -------------------------------------------------------------------
+  if (makeMinBoxes) {
+    // This class uses information about the box
+    // inside from which the ray starts from
+    traversalClass = new CKTBMinBoxesTraversal(size1D);
+  }
+  else {
+    // normal traversal always from root
+    traversalClass = new CKTBTraversal; 
+  }
+#else
+  cerr<<"th3"<<endl;
+
+  traversalClass = new CKTBTraversal; 
+#endif
+
+  assert(traversalClass);
+
+  return;
+}
+
+// default destructor
+CKTB::~CKTB()
+{
+  // Print the statistics
+  PrintStats();
+  
+  Remove();
+}
+
+void
+CKTB::Remove()
+{
+  if (buildClass) {
+    // DEBUG << "Deleting build class from CKTB" << endl;
+    buildClass->Remove();
+    delete buildClass;
+    buildClass = NULL;
+  }
+
+  if (traversalClass) {
+    delete traversalClass;
+    traversalClass = NULL;
+  }
+
+  return;
+}
+
+void
+CKTB::ProvideID(ostream& app)
+{
+  app << "#CASDS = CKTB - KD-tree for only bounded objects\n";
+  //app << (int)GetID() << "\n";
+  
+  //app << "#ActMaxDepth (Dreach)\tActual maximal depth of the KD-tree"
+  //    << " reached\n";
+  //app << world->_statistics->actMaxDepth << "\n";
+
+  ProvidePars(app);
+}
+
+void
+CKTB::ProvidePars(ostream& app)
+{
+  app << "#NumberOfObjects\t\tNumber of objects inside kd-tree\n";
+  app << countObjects << "\n";
+  
+  app << "#BBox\t\t\tSize of axis-aligned box of the whole scene\n"
+      << bbox.Max().x - bbox.Min().x << ","
+      << bbox.Max().y - bbox.Min().y << ","
+      << bbox.Max().z - bbox.Min().z << "\n";
+
+#if 0  
+  bool tempvar;
+  Environment::GetSingleton()->GetBoolValue("BSP.pruning", tempvar);
+  if (tempvar) {
+    app << "#BSP.pruning \t\tPruning of CKTB disabled/enabled\n";
+    app << tempvar << "\n";
+  }
+  app << "#BSP.constrMethod \tBuilding up method for KD-tree\n";
+#endif  
+
+  if (buildClass)
+    buildClass->ProvideID(app);
+
+  return;
+}
+
+void
+CKTB::PrintStats()
+{
+  if (traversalClass)
+    traversalClass->PrintStatsTR(cout);
+}
+
+// builds up CKTB tree 
+void
+CKTB::BuildUp(const ObjectContainer &alist)
+{
+  cerr<<"KTB buildup\n";
+  Remove();
+
+  // Create the list of objects to be processed.
+  ObjectContainer *objlist = new ObjectContainer;
+
+  // The minimum size
+  bbox.Initialize();
+  
+  // Copy only finite (not invisible and bounded) objects from
+  // the original list to 'objlist'
+   
+  // copy the pointers to objects to the array
+  int i = 0;
+  AxisAlignedBox3 objbox;  
+  bool hasUnboundeds = false;
+  countObjects = 0;
+  for (ObjectContainer::iterator it = ((ObjectContainer*)&alist)->begin();
+       it != alist.end(); it++, i++) {
+    Intersectable* obj = *it;
+    objbox = (*it)->GetBox();
+    // invisible objects are not added - lights etc.
+    bbox.Include(objbox);
+    // This is a regular object, add it to the list
+    objlist->push_back(obj);
+  } // for
+    
+  // prepare building up for CKTB tree
+  //  BuildingUp(*objlist);
+  BuildingUp(*objlist, NULL, NULL, true);
+
+  cerr<<"KTB buildup3\n";
+
+  delete objlist;
+
+  return;
+}
+
+bool
+CKTB::CheckBoxes(ObjectContainer &objlist)
+{
+  // the minimum size of the box at any dimension
+  const float epsilon = Limits::Small * 5.0f;
+
+  for (ObjectContainer::iterator oi = objlist.begin();
+       oi != objlist.end(); oi++) {
+    AxisAlignedBox3 box = (*oi)->GetBox();
+    Vector3 diff = box.Diagonal();
+    for (int i = 0; i < 3; i++) {
+      float d = fabs(diff[i]);
+#if 0
+      if (d < epsilon) {
+	CObject3D &obj = **(oi);
+	cerr << "CKTB::CheckBoxes - the scene incorrectly prepared, "
+	      << " the size of the box = " << d << " in dimension "
+	      << i << " is" << " below threshold = " << epsilon << endl;
+	cerr << "object = " << (void*)(*oi) << " uniqueID = " <<
+	  (*oi)->GetUniqueID() << " description = " << endl;
+	obj.Describe(cout, 1);
+	cerr << "----------" << endl;
+	abort();
+	return true; // error
+      }
+#else
+      if (d < epsilon) {
+	int size = objlist.size();
+	*oi = objlist[size-1];
+	objlist.resize(size-1);
+	oi--; // check this object as well
+      }      
+#endif
+    } // for i    
+  } // for all objecs
+
+  return false;
+}
+
+// builds up CKTB tree without unbounded objects. The 'boxToInclude
+// is a box that can be optionally given and the kd-tree constructed
+// must contain such a box. The 'boxToBoundObjects' when given, is
+// a box to which the objects boxes are bounded. This is used for special
+// cases such a multilevel kd-trees.
+void
+CKTB::BuildingUp(ObjectContainer& objlist,
+		 const AxisAlignedBox3 *boxToInclude,
+		 const AxisAlignedBox3 *boxToBoundObjects,
+		 bool verbose)
+{
+  // the number of objects for statistics purposes - it can be different
+  // from objlist->size() since objlist need not be initialized at all!
+  countObjects = objlist.size();
+
+  // compute the estimate for the kd-tree constructed this way
+  _expectedIntersectionCost = log((float)countObjects) / log(2.0f) + 2.0;
+  
+#ifdef _DEBUG
+  // check the flatness of the boxes for all objects
+  if (CheckBoxes(objlist)) {
+    cerr << "Problem with the size of the box for some object" << endl;
+    return;
+  }
+#endif // _DEBUG
+
+  cerr<<"hh2"<<endl;
+  // possibly remove the old building class
+  // and allocate the class for CKTB building up
+  if (buildClass)
+    delete buildClass;  
+  buildClass = AllocBuildClass();
+
+  cerr<<"hh3"<<endl;
+
+  // and for traversal
+  AllocTraversalClass();
+  cerr<<"hh4"<<endl;
+
+  if (boxToBoundObjects) {
+    // maximum box of the scene is given in advance
+    bbox = Intersect(bbox, *boxToBoundObjects);
+  }
+
+  // we can additionally include the user box 
+  if (boxToInclude)
+    bbox.Include(*boxToInclude);  
+
+  cerr<<"hh5"<<endl;
+
+  // build up the CKTB tree and make setup for traversal
+  SKTBNodeT *rootNode =
+    buildClass->BuildUp(objlist, bbox, verbose);
+  cerr<<"hh6"<<endl;
+
+  traversalClass->Setup(bbox, rootNode);
+  cerr<<"hh7"<<endl;
+
+#ifdef _DEBUG
+  //traversalClass->AssignIDs();
+#endif
+  builtUp = true;
+
+#if 0  
+  // if to clean up the whole structure
+  bool pruning;
+  Environment::GetSingleton()->GetBoolValue("BSP.pruning", pruning);
+  if (pruning)
+    // only the objects whose surfaces intersects with the subdivision
+    PruneLeaves(); // cells are not pruned from the CKTB tree
+#endif
+}
+
+// functions that allows correctly traverse recursively allowing to have
+// the same traversal stack
+void
+CKTB::TraversalReset()
+{
+  assert(traversalClass);
+  traversalClass->ResetTraversalDepth();
+}
+
+// Allocate 2D buffer of pointers to the interior nodes
+void
+CKTB::AllocBuffer(int size2D, int size1Dv)
+{
+  int i, j;
+  
+  if (buffer) {
+    for (i=0; i < sizeBuffer; i++) {
+      delete [] buffer[i];
+    } // for
+    delete [] buffer;
+    buffer = 0;
+  }
+
+  sizeBuffer = size2D;
+  this->size1D = size1Dv;
+  buffer = new SKTBNodeT ** [sizeBuffer];
+  assert(buffer);
+  for (i=0; i < sizeBuffer; i++) {
+    buffer[i] = new SKTBNodeT* [size1D];
+    assert(buffer[i]);
+    // reset the array content
+    for (j = 0; j < size1D; j++) {
+      buffer[i][j] = 0;
+    }
+  } // for
+
+  return;
+}
+
+int
+CKTB::FindNearestI(const SimpleRay &ray)
+{
+  return traversalClass->FindNearestI(ray);      
+}
+
+#ifdef __SSE__
+// --------------------------------------------------------------
+// Ray packets
+void
+CKTB::FindNearestI(RayPacket2x2 &raypack)
+{
+  if (!makeMinBoxes)
+    raypack.SetOrigin(0); // min boxes are not used, we cannot use them here !
+  traversalClass->FindNearestI(raypack);
+}
+
+void
+CKTB::FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax)
+{
+  if (!makeMinBoxes)
+    raypack.SetOrigin(0); // min boxes are not used, we cannot use them here !
+  traversalClass->FindNearestI(raypack, boxmin, boxmax);
+}
+
+#endif // __SSE__
+  
+void
+CKTB::DeleteBuildClass()
+{
+  if (buildClass)
+    delete buildClass;
+  buildClass = NULL;
+}
+
+void
+CKTB::GatherStats(bool itself)
+{
+  // DEBUG << "CKTB::GatherStats called" << endl;
+  struct EDir {
+    SKTBNodeT *node;
+    int depth;
+    AxisAlignedBox3 bbox;
+  };
+  EDir stack[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
+  int stackTop = 0; // pointer to the stack
+  stack[stackTop].node = 0;
+  stack[stackTop].depth = 0;
+  stack[stackTop].bbox = bbox;
+  int tmpdir;
+#ifdef __TAGGED_KDR
+  int taggedLists = 0;
+#endif // __TAGGED_KDR
+  
+  /*
+  if (!BuiltUp) {
+    cerr << "Internal error: CASDS not built up. Giving up.\n" << flush;
+    abort();
+  }
+  */
+  
+  // average depth for all leaves
+  long avgLeafDepth = 0;
+  // for full leaves
+  long avgFullLeafDepth = 0;
+  // for empty leaves
+  long avgEmptyLeafDepth = 0;
+
+  // Surface areas  (divided by the area of the box)
+  // Surface area of leaves (empty + full)
+  double saLeaves = 0.f;
+  // Surface area of interior nodes
+  double saInteriorNodes = 0.f;
+  // Sum of surface area of (full) leaves multiplied by
+  // the number of objects in leaves
+  double sa_cntLeaves = 0.f;
+  // number of boxes enclosing tightly the objects
+  long int boxesMin = 0;
+  long int boxesMinX = 0;
+  long int boxesMinY = 0;
+  long int boxesMinZ = 0;
+  // the sum of depth of tight boxes
+  long int boxesMinDepth = 0;
+
+  // start from the root node
+  SKTBNodeT *curr = buildClass->GetRootNode();
+  // copy the box over the scene objects
+  AxisAlignedBox3 wbox = this->bbox;
+  int currDepth = 0;
+
+  if (buildClass->IsLeaf_(curr)) {
+    this->numElemCells++;
+    if (buildClass->IsEmptyLeaf_(curr)) {
+      this->numEmptyElemCells++;
+      AxisAlignedBox3 bwbox = this->bbox;
+      // Surface area for empty leaf
+      this->emptyVolume += bwbox.GetVolume();
+      saLeaves += bwbox.SurfaceArea();
+    }
+    else { // CKTB tree is single non-empty leaf
+      AxisAlignedBox3 bwbox = this->bbox;
+      this->nonEmptyVolume += bwbox.GetVolume();
+      ObjectContainer *olist = curr->objlist;
+      saLeaves += bwbox.SurfaceArea();
+      if (!olist) {
+	this->numSolidsInElemCells += olist->size();
+	this->actMaxListLen = olist->size();
+	// surface area for full leaf
+	sa_cntLeaves = bwbox.SurfaceArea() * (float)(olist->size());
+      }
+    }
+  }
+  else { // CKTB tree is not a single leaf
+    // now we access the interior node
+
+    // surface area for interior node
+    AxisAlignedBox3 bwbox = this->bbox;
+    // surface area for interior node
+    saInteriorNodes += bwbox.SurfaceArea();
+    this->numHierCells++;
+	
+    // traverse through whole CKTB tree
+    do {
+      CKTBAxes::Axes nodeType = buildClass->GetNodeType(curr);
+      if (nodeType == CKTBAxes::EE_Link) {
+	// just relink
+	curr = buildClass->GetLinkNode(curr);
+	// cout << "Link node was accessed" << endl;
+	continue;	
+      }
+      
+      if ( (nodeType == CKTBAxes::EE_X_axis)||
+	   (nodeType == CKTBAxes::EE_Y_axis)||
+	   (nodeType == CKTBAxes::EE_Z_axis)||
+	   (nodeType == CKTBAxes::EE_X_axisBox)||
+	   (nodeType == CKTBAxes::EE_Y_axisBox)||
+	   (nodeType == CKTBAxes::EE_Z_axisBox)
+	 ) {
+
+	// push onto the stack
+        AxisAlignedBox3 rightBox = bwbox;
+	float value = curr->splitPlane;
+	switch(nodeType) {
+	  case CKTBAxes:: EE_X_axisBox: {
+	    rightBox.SetMin(0, value);
+	    bwbox.SetMax(0, value);
+	    boxesMin++;
+	    boxesMinX++;
+	    boxesMinDepth += currDepth;
+	    break;	  
+	  }
+	  case CKTBAxes:: EE_X_axis: {
+	    rightBox.SetMin(0, value);
+	    bwbox.SetMax(0, value);
+	    break;	  
+	  }
+	  case CKTBAxes:: EE_Y_axisBox: {
+	    rightBox.SetMin(0, value);
+	    bwbox.SetMax(0, value);
+	    boxesMin++;
+	    boxesMinY++;
+	    boxesMinDepth += currDepth;
+	    break;	  
+	  }
+  	  case CKTBAxes:: EE_Y_axis: {
+	    rightBox.SetMin(1, value);
+	    bwbox.SetMax(1, value);
+	    break;	  
+	  }
+	  case CKTBAxes:: EE_Z_axisBox: {
+	    rightBox.SetMin(0, value);
+	    bwbox.SetMax(0, value);
+	    boxesMin++;
+	    boxesMinZ++;
+	    boxesMinDepth += currDepth;
+	    break;	  
+	  }
+	  case CKTBAxes:: EE_Z_axis: {
+	    rightBox.SetMin(2, value);
+	    bwbox.SetMax(2, value);
+	    break;	  
+	  }
+	} // switch
+      
+	stack[stackTop].node = buildClass->GetRight(curr);
+	stack[stackTop].depth = currDepth+1;
+	stack[stackTop].bbox = rightBox;
+	stackTop++;
+	// where to go
+	if ( (nodeType == CKTBAxes:: EE_X_axisBox)||
+	     (nodeType == CKTBAxes:: EE_Y_axisBox)||
+	     (nodeType == CKTBAxes:: EE_Z_axisBox) )
+	  curr = buildClass->GetLeftMinBox(curr);
+	else
+	  curr = buildClass->GetLeft(curr);
+	// the box was already set      
+	currDepth++;
+      
+	if (this->actMaxDepth < currDepth)
+	  this->actMaxDepth = currDepth;
+
+	// surface area for interior node
+	saInteriorNodes += bwbox.SurfaceArea();	
+	this->numHierCells++;
+
+	continue;
+      } // interior nodes
+
+      assert(nodeType == CKTBAxes::EE_Leaf);
+      
+      while ( (nodeType == CKTBAxes::EE_Leaf) && currDepth) {
+	this->numElemCells++;
+	avgLeafDepth += currDepth;
+
+	ObjectContainer *olist = buildClass->GetObjList(curr);
+	
+	// test to empty leaf
+	if (!olist) {
+	  this->numEmptyElemCells++;
+	  avgEmptyLeafDepth += currDepth;
+	  this->emptyVolume += bwbox.GetVolume();
+	  // Surface area for empty leaf
+	  saLeaves += bwbox.SurfaceArea();
+	}
+	else {
+	  // full leaf 
+	  this->nonEmptyVolume += bwbox.GetVolume();
+	  avgFullLeafDepth += currDepth;
+	  int length = olist->size();
+	  this->numSolidsInElemCells += length;
+	  // surface area for full leaf
+	  saLeaves += bwbox.SurfaceArea();
+	  sa_cntLeaves += bwbox.SurfaceArea() * (float)(olist->size());
+	  if (this->actMaxListLen < length)
+	    this->actMaxListLen = length;
+	}
+	
+	// traverse up the tree
+	stackTop--;
+	if (stackTop < 0)
+	  goto FINISH;
+	// pop the node from the stack
+	curr = stack[stackTop].node;
+	currDepth = stack[stackTop].depth;
+
+	nodeType = buildClass->GetNodeType(curr);
+	
+      } // while is a leaf
+    }
+    while (stackTop >= 0);
+  } // either single leaf or tree
+
+FINISH:
+
+  cout << "BBox " << this->bbox << "\n";
+  
+#ifdef __TAGGED_KDR
+  DEBUGW << "Tagged lists = " << taggedLists << "\n";
+#endif // __TAGGED_KDR
+
+  cout << "#CntLeaves = \n" << this->numElemCells << "\n";
+  cout << "#AverageLeafDepth = \n"
+       << (float)avgLeafDepth/(float)this->numElemCells << "\n";
+  cout << "#CntFullLeaves = \n" << (this->numElemCells-this->numEmptyElemCells)
+	<< "\n";
+  cout << "#AverageFullLeafDepth = \n"
+	<< (float)avgFullLeafDepth/
+            (float)(this->numElemCells - this->numEmptyElemCells) << "\n";
+  cout << "#AverageEmptyLeafDepth = \n";
+  if (this->numEmptyElemCells)
+    cout << (float)avgEmptyLeafDepth / (float)this->numEmptyElemCells<<"\n";
+  else
+    cout << "undefined\n";
+
+  // Normalized the surface area
+  this->sumSurfaceAreaLeaves = saLeaves / wbox.SurfaceArea();
+  this->sumSurfaceAreaMULcntLeaves = sa_cntLeaves / wbox.SurfaceArea();
+  this->sumSurfaceAreaInteriorNodes = saInteriorNodes / wbox.SurfaceArea();
+
+  cout << "#SumSurfaceLeafArea = \n" << saLeaves << "\n";
+  cout << "#SumSurfaceLeafAreaMulCNT = \n" << sa_cntLeaves << "\n";
+  cout << "#NormSurfaceLeafArea = \n" << this->sumSurfaceAreaLeaves << "\n";
+  cout << "#NormSurfaceLeafAreaMulCNT = \n" << this->sumSurfaceAreaMULcntLeaves << "\n";
+  cout << "#SurfaceAreaInteriorNodes = \n" << this->sumSurfaceAreaInteriorNodes<<"\n";  
+  cout << "#MinBoxesCount = \n" << boxesMin << "\n";
+  cout << "#MinBoxesXCount = \n" << boxesMinX << "\n";
+  cout << "#MinBoxesYCount = \n" << boxesMinY << "\n";
+  cout << "#MinBoxesZCount = \n" << boxesMinZ << "\n";
+  if (boxesMin)
+    cout << "#AverageMinBoxesDepth = \n"
+	  << (float)boxesMinDepth/(float)boxesMin << "\n";
+
+  long int memUsed = 0;
+#ifdef _KTB8Bytes
+  memUsed += this->numHierCells*8;
+  memUsed += (this->numElemCells-this->numEmptyElemCells)*8;
+#ifdef _SHORT_FORM_MINBOX
+  memUsed += boxesMin * (sizeof(SBBox) + 2*8);
+#else
+  memUsed += boxesMin * (5*8);
+#endif
+#else // _KTB8Bytes
+  memUsed += this->numHierCells*12;
+  memUsed += (this->numElemCells-this->numEmptyElemCells)*12;
+#ifdef _SHORT_FORM_MINBOX
+  memUsed += boxesMin * (sizeof(SBBox) + 2*12);
+#else
+  memUsed += boxesMin * (4*12);
+#endif
+#endif // _KTB8Bytes
+
+  // The references to objects
+  memUsed += this->numSolidsInElemCells * sizeof(Intersectable*);
+  memUsed += (this->numElemCells-this->numEmptyElemCells) *
+    sizeof(ObjectContainer);
+  cout << "#MemUsedKBB = \n" << memUsed << "\n";
+    
+  return;
+}
+
+
+void CKTB::ExportBinLeaf(OUT_STREAM &stream, SKTBNodeT *leaf)
+{
+#define TYPE_LEAF -3
+  int type = TYPE_LEAF;
+  if (leaf->objlist == 0) {
+    // empty leaf
+    int size = 0;
+    stream.write(reinterpret_cast<char *>(&type), sizeof(int));
+    stream.write(reinterpret_cast<char *>(&size), sizeof(int));    
+    return;
+  }
+  
+  ObjectContainer::const_iterator it, it_end = leaf->objlist->end();  
+  int size = (int)leaf->objlist->size();
+  
+  stream.write(reinterpret_cast<char *>(&type), sizeof(int));
+  stream.write(reinterpret_cast<char *>(&size), sizeof(int));
+  
+  for (it = leaf->objlist->begin(); it != it_end; ++ it)
+  {	
+    Intersectable *obj = *it;
+    int id = obj->mId;		
+      
+    //stream.write(reinterpret_cast<char *>(&origin), sizeof(Vector3));
+    stream.write(reinterpret_cast<char *>(&id), sizeof(int));
+  }
+}
+
+
+inline static bool ilt(Intersectable *obj1, Intersectable *obj2)
+{
+  return obj1->mId < obj2->mId;
+}
+
+  
+SKTBNodeT*
+CKTB::ImportBinLeaf(IN_STREAM &stream, 
+		    SKTBNodeT *parent,
+		    const ObjectContainer &objects)
+{
+  int leafId = TYPE_LEAF;
+  int objId = leafId;
+  int size;
+  
+  stream.read(reinterpret_cast<char *>(&size), sizeof(int));
+  if (size == 0) {
+    // alloc empty leaf -- ?????????? I am not sure if this works !!!
+    // since for 
+    SKTBNodeT* leaf = buildClass->AllocLeaf(0);
+    return leaf;
+  }
+  
+  MeshInstance dummyInst(NULL);
+  SKTBNodeT* leaf = buildClass->AllocLeaf(size);
+
+  ObjectContainer *newobjlist = new ObjectContainer;
+  
+  // read object ids
+  // note: this can also be done geometrically
+  for (int i = 0; i < size; ++ i)
+  {	
+    stream.read(reinterpret_cast<char *>(&objId), sizeof(int));
+    dummyInst.SetId(objId);
+      
+    ObjectContainer::const_iterator oit =
+      lower_bound(objects.begin(), objects.end(), (Intersectable *)&dummyInst, ilt);
+      
+    if ((oit != objects.end()) && ((*oit)->GetId() == objId))
+      newobjlist->push_back(*oit);
+    else
+      Debug << "error: object with id " << objId << " does not exist" << endl;
+  } // for
+
+  buildClass->SetFullLeaf(leaf, newobjlist);
+  
+  return leaf;
+}
+
+
+void CKTB::ExportBinInterior(OUT_STREAM &stream, SKTBNodeT *interior)
+{
+#define TYPE_INTERIOR -2
+  int interiorid = TYPE_INTERIOR;
+  stream.write(reinterpret_cast<char *>(&interiorid), sizeof(int));
+
+  int axis = (int)(buildClass->GetNodeType(interior));
+  float pos = buildClass->GetSplitValue(interior);
+
+  stream.write(reinterpret_cast<char *>(&axis), sizeof(int));
+  stream.write(reinterpret_cast<char *>(&pos), sizeof(float));
+}
+
+
+SKTBNodeT *
+CKTB::ImportBinInterior(IN_STREAM  &stream, SKTBNodeT *parent)
+{
+  int axis;
+  float pos;
+
+  stream.read(reinterpret_cast<char *>(&axis), sizeof(int));
+  stream.read(reinterpret_cast<char *>(&pos), sizeof(float));
+
+  SKTBNodeT *interiorNode =
+    buildClass->AllocInteriorNode(axis, pos, 0, 0);
+	
+  return interiorNode;
+}
+
+
+bool CKTB::ExportBinTree(const string &filename)
+{
+  OUT_STREAM stream(filename.c_str(), OUT_BIN_MODE);
+	
+  if (!stream.is_open()) return false;
+
+  // DEBUG << "CKTB::GatherStats called" << endl;
+  struct EDir {
+    SKTBNodeT *node;
+    int depth;
+    AxisAlignedBox3 bbox;
+  };
+  EDir stack[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
+  int stackTop = 0; // pointer to the stack
+  stack[stackTop].node = 0;
+  stack[stackTop].depth = 0;
+  stack[stackTop].bbox = bbox;
+  int tmpdir;
+  
+  // export binary version of mesh
+  queue<SKTBNodeT *> tStack;
+  // start from the root node
+  SKTBNodeT *currNode = buildClass->GetRootNode();
+
+  // copy the box over the scene objects
+  AxisAlignedBox3 bwbox = this->bbox;
+  int currDepth = 0;  
+
+  // traverse through whole CKTB tree
+  do {
+    CKTBAxes::Axes nodeType = buildClass->GetNodeType(currNode);
+    if (nodeType == CKTBAxes::EE_Link) {
+      // just relink
+      currNode = buildClass->GetLinkNode(currNode);
+      // cout << "Link node was accessed" << endl;
+      continue;	
+    }
+      
+    if ( (nodeType == CKTBAxes::EE_X_axis)||
+	 (nodeType == CKTBAxes::EE_Y_axis)||
+	 (nodeType == CKTBAxes::EE_Z_axis)||
+	 (nodeType == CKTBAxes::EE_X_axisBox)||
+	 (nodeType == CKTBAxes::EE_Y_axisBox)||
+	 (nodeType == CKTBAxes::EE_Z_axisBox)
+       ) {
+      
+      // push onto the stack
+      AxisAlignedBox3 rightBox = bwbox;
+      float value = currNode->splitPlane;
+      switch(nodeType) {
+        case CKTBAxes:: EE_X_axisBox: {
+	  rightBox.SetMin(0, value);
+	  bwbox.SetMax(0, value);
+	  break;	  
+	}
+        case CKTBAxes:: EE_X_axis: {
+	  rightBox.SetMin(0, value);
+	  bwbox.SetMax(0, value);
+	  break;	  
+	}
+        case CKTBAxes:: EE_Y_axisBox: {
+	  rightBox.SetMin(0, value);
+	  bwbox.SetMax(0, value);
+	  break;	  
+	}
+        case CKTBAxes:: EE_Y_axis: {
+	  rightBox.SetMin(1, value);
+	  bwbox.SetMax(1, value);
+	  break;	  
+	}
+        case CKTBAxes:: EE_Z_axisBox: {
+	  rightBox.SetMin(0, value);
+	  bwbox.SetMax(0, value);
+	  break;	  
+	}
+        case CKTBAxes:: EE_Z_axis: {
+	  rightBox.SetMin(2, value);
+	  bwbox.SetMax(2, value);
+	  break;	  
+	}
+      } // switch
+
+      // Exporting interior node
+      ExportBinInterior(stream, currNode);
+      
+      stack[stackTop].node = buildClass->GetRight(currNode);
+      stack[stackTop].depth = currDepth + 1;
+      stack[stackTop].bbox = rightBox;
+      stackTop++;
+      // where to go
+      if ( (nodeType == CKTBAxes:: EE_X_axisBox)||
+	   (nodeType == CKTBAxes:: EE_Y_axisBox)||
+	   (nodeType == CKTBAxes:: EE_Z_axisBox) )
+	currNode = buildClass->GetLeftMinBox(currNode);
+      else
+	currNode = buildClass->GetLeft(currNode);
+      // the box was already set
+      currDepth++;
+      
+      continue;
+    } // interior nodes
+
+    assert(nodeType == CKTBAxes::EE_Leaf);
+      
+    while ( (nodeType == CKTBAxes::EE_Leaf) && currDepth) {
+      ObjectContainer *olist = buildClass->GetObjList(currNode);
+      // Exporting leaf node
+      ExportBinLeaf(stream, static_cast<SKTBNodeT *>(currNode));
+	
+      // traverse up the tree
+      stackTop--;
+      if (stackTop < 0)
+	goto FINISH;
+      // pop the node from the stack
+      currNode = stack[stackTop].node;
+      currDepth = stack[stackTop].depth;
+      bwbox = stack[stackTop].bbox;
+      
+      nodeType = buildClass->GetNodeType(currNode);
+	
+    } // while is a leaf
+  }
+  while (stackTop >= 0);
+
+FINISH:
+  // close the stream
+  stream.close();
+  
+  return true;
+}
+
+#if 0
+KdNode *KdTree::ImportNextNode(IN_STREAM &stream, 
+			       KdInterior *parent,
+			       const ObjectContainer &objects)
+{
+	int nodeType;
+	stream.read(reinterpret_cast<char *>(&nodeType), sizeof(int));
+
+	if (nodeType == TYPE_LEAF)
+		return ImportBinLeaf(stream, static_cast<KdInterior *>(parent), objects);
+
+	if (nodeType == TYPE_INTERIOR)
+		return ImportBinInterior(stream, static_cast<KdInterior *>(parent));
+
+	Debug << "error! loading failed!" << endl;
+	return NULL;
+}
+
+
+bool KdTree::ImportBinTree(const string &filename, ObjectContainer &objects)
+{
+  // export binary version of mesh
+  queue<TraversalData> tStack;
+  IN_STREAM stream(filename.c_str(), IN_BIN_MODE);
+  
+  if (!stream.is_open()) return false;
+  
+  // sort objects by their id
+  //	if (!is_sorted(objects.begin(), objects.end(), ilt))
+  sort(objects.begin(), objects.end(), ilt);
+  
+  mBox.Initialize();
+  ObjectContainer::const_iterator oit, oit_end = objects.end();
+  
+  ///////////////////////////
+  //-- compute bounding box of object space
+  
+  for (oit = objects.begin(); oit != oit_end; ++ oit)
+  {
+    const AxisAlignedBox3 box = (*oit)->GetBox();
+    mBox.Include(box);
+  }
+  
+  // hack: we make a new root
+  DEL_PTR(mRoot);
+  
+  mRoot = ImportNextNode(stream, NULL, objects);
+  
+  tStack.push(TraversalData(mRoot, mBox, 0));
+  mStat.Reset();
+  mStat.nodes = 1;
+  
+  while(!tStack.empty())
+  {
+    TraversalData tData = tStack.front();
+    tStack.pop();
+    
+    KdNode *node = tData.mNode;
+    
+    if (!node->IsLeaf())
+    {
+      mStat.nodes += 2;
+      
+      //Debug << "i" ;
+      KdInterior *interior = static_cast<KdInterior *>(node);
+      interior->mBox = tData.mBox;
+      
+      KdNode *front = ImportNextNode(stream, interior, objects);
+      KdNode *back = ImportNextNode(stream, interior, objects);
+      
+      interior->SetupChildLinks(back, front);
+      
+      ++ mStat.splits[interior->mAxis];
+      
+      // compute new bounding box
+      AxisAlignedBox3 frontBox, backBox;
+      
+      tData.mBox.Split(interior->mAxis, 
+		       interior->mPosition, 
+		       frontBox, 
+		       backBox);
+      
+      tStack.push(TraversalData(front, frontBox, tData.mDepth + 1));			
+      tStack.push(TraversalData(back, backBox, tData.mDepth + 1));
+    }
+    else
+    {
+      EvaluateLeafStats(tData);
+      //cout << "l";
+    }
+  }
+
+  float area = GetBox().SurfaceArea()*mKdPvsArea;
+  
+  SetPvsTerminationNodes(area);
+  
+  Debug << mStat << endl;
+  
+  return true;
+}
+#endif
+
+
+void
+CKTB::GatherPostStats()
+{
+
+}
+
+void*
+CKTB::Locate(const Vector3 &loc)
+{
+  return (void*)(traversalClass->Locate(loc));
+}
+
+
+} // namespace
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb8b.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb8b.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb8b.cpp	(revision 2582)
@@ -0,0 +1,464 @@
+// ===================================================================
+// $Id: $
+//
+// ktb.cpp
+//
+//     KDB - trees for ray tracing, special version for SCCG 2006
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, 1998-2001.
+
+// GOLEM library
+#include "ktb8b.h"
+#include "Environment.h"
+
+// standard headers
+#include <algorithm>
+
+namespace GtpVisibilityPreprocessor {
+
+// default constructor
+CKTB8BNodeIterator::CKTB8BNodeIterator()
+{
+
+}
+  
+//-------------------------------------------------------------
+// class CKTB8BNodeIterator .. implementation
+
+// test all objects in the leaf for intersection with ray
+// and returns the pointer to closest one if exists
+// and passing through parameter returns in tmax
+int
+CKTB8BNodeIterator::TestFullLeaf(const SimpleRay &ray, const SKTBNode *p)
+{
+  ObjectContainer *list = GetObjList(p);  
+  if (!list) // no object 
+    return 0;
+  ObjectContainer::iterator sc_end = list->end();
+
+  int intersected = 0;
+  // iterate the whole list and find out the nearest intersection
+  for (ObjectContainer::iterator sc = list->begin(); sc != sc_end; sc++) {
+    // if the intersection realy lies in the node        
+    if ((*sc)->CastSimpleRay(ray)) {
+      intersected = 1;
+    }
+  } // for all objects
+
+  return intersected;
+}
+
+int
+CKTB8BNodeIterator::TestFullLeaf(const SimpleRay &ray, const SKTBNode *p,
+				 int indexRay)
+{
+  ObjectContainer *list = GetObjList(p);  
+  if (!list) // no object 
+    return 0;
+  ObjectContainer::iterator sc_end = list->end();
+
+  float tclosest = Limits::Infinity;
+  int intersected = 0;
+  // indexRay += rayOffset;
+  // iterate the whole list and find out the nearest intersection
+  for (ObjectContainer::iterator sc = list->begin(); sc != sc_end; sc++) {
+    // if the intersection realy lies in the node        
+    if ((*sc)->CastSimpleRay(ray, indexRay)) {
+      // update tclosest !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      // tclosest = ray.
+      intersected = 1;
+    }
+  } // for all objects
+
+  return intersected;
+}
+
+  
+// test all objects in the leaf for intersection with ray
+// and find any if exist .. returns this object, otherwise 0
+int
+CKTB8BNodeIterator::HitAnyObj(const SimpleRay &ray, const SKTBNode *p)
+{
+  ObjectContainer *list = GetObjList(p);  
+  if (!list) // no object 
+    return 0;
+  ObjectContainer::iterator sc_end = list->end();
+
+  float tclosest = Limits::Infinity;
+  int intersected = 0;
+  // iterate the whole list and find out the nearest intersection
+  for (ObjectContainer::iterator sc = list->begin(); sc != sc_end; sc++) {
+    Intersectable *is = (*sc);
+    // if the intersection realy lies in the node        
+    if (is->CastSimpleRay(ray)) {
+      // update tclosest !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      // tclosest = ray.
+      return 1; // intersected
+    }
+  } // for all objects
+
+  return 0;
+}
+
+const CKTB8BNodeAbstract::SKTBNode*
+CKTB8BNodeIterator::Locate(const Vector3 & /*position*/)
+{
+  cerr << "Locate vector - Not yet implemented" << endl;
+  return (CKTB8BNodeAbstract::SKTBNode*)0;
+}
+
+
+// ---------------------------------------------------------------------
+// Allocator for KTB tree
+
+// forget the content that is created by previous kd-tree construction
+// or just init for the first use.
+void
+CKTB8BAllocMan::InitForConstructor()
+{
+#ifdef _KTB_CONSTR_STATS
+  _stats_interiorCount = 0;
+  _stats_bboxCount = 0;
+  _stats_leafNodeCount = 0;
+  _stats_emptyLeftNodeCount = 0;
+  // Aggregate statistics
+  _sumLeafDepth = 0;
+  _sumFullLeafDepth = 0;
+  // The count of object references in leaves
+  _sumObjectRefCount = 0;
+  // The maximum number of object references in a leaf
+  _maxObjectRefInLeaf = 0;
+  // surface areas
+  _sumSurfaceAreaLeaves = 0.f;
+  _sumSurfaceAreaMULcntLeaves = 0.f;
+  _sumSurfaceAreaInteriorNodes = 0.f;
+#endif
+  
+  // This is the statistics
+  _currDepth = 0;
+  _maxDepth = -1;
+  InitPars();
+}
+
+// init the stack of auxiliary variables from min to max
+void
+CKTB8BAllocMan::InitAux(int /*min*/, int /*maxD*/, int maxItemsAtOnce)
+{
+  // The size of one entry
+  int sizeEntryV = sizeof(SKTBNode);
+  // The number of entries to be allocated at once in a block
+  // (=size of the block)
+  int numEntriesInBlock = 1024;
+  // the allignment
+  int allignEntrySizeV = sizeof(SKTBNode);
+  int allignBlockSizeV = 128;
+
+  // Create an allocator in DFS order
+  alloc2 = new CAllocContinuous(sizeEntryV, numEntriesInBlock,
+				maxItemsAtOnce,
+				allignEntrySizeV,
+			        allignBlockSizeV);
+  assert(alloc2);
+  // the first allocation is enabled by this command
+  alloc2->AllocNewBlock();
+  return;
+}
+
+// Read some basic parameters from the environment file
+void
+CKTB8BAllocMan::InitPars()
+{
+  Environment::GetSingleton()->GetIntValue("BSP.maxListLength",
+					   maxListLength);
+  Environment::GetSingleton()->GetIntValue("BSP.maxDepthAllowed",
+					   maxDepthAllowed);
+}
+
+void
+CKTB8BAllocMan::PostBuild()
+{
+  // Here it can be some postprocessing of the tree, such as branches
+  // collapsing for the same content of leaves etc.
+}
+
+void
+CKTB8BAllocMan::Remove()
+{
+  // Release the all memory by blocks, so all the interior nodes
+  // and leaves representations. This should be fast.
+  alloc2->ReleaseMemory();
+}
+
+
+// Create the representation of the interior node
+SKTBNodeT*
+CKTB8BAllocMan::AllocInteriorNode(int axis, float position,
+				  int cntLeft, int cntRight)
+{
+#ifdef _DEBUG
+  nodeToLink = 0;
+#endif
+
+#ifdef _KTB_CONSTR_STATS
+  _stats_interiorCount++;
+#endif
+  
+  // Just to satisfy the compiler
+  cntLeft = cntLeft;
+  cntRight = cntRight;
+  
+  // Alloc a single node
+  SKTBNodeT *n = (SKTBNodeT*)(alloc2->New(1));
+  nodeToLink = n;
+  if (n == 0) {
+    // we have to insert a special node that links only
+    nodeToLink = (SKTBNodeT*)alloc2->NewLastEntry(1);
+    assert(nodeToLink);
+    nodeToLink->offset = CKTBAxes::EE_Link;
+    n = (SKTBNodeT*)(alloc2->NewEntryInNewBlock(1));
+    // This is the link
+    nodeToLink->linkedNode = n;    
+  } // if n
+
+  assert(n);
+  assert(nodeToLink);
+
+  // Set the interior node
+  assert((axis >=0) && (axis < 3));
+  n->offset = axis;
+  n->splitPlane = position;
+
+#ifdef _DEBUG_ALLOCATION  
+  cout << "AllocInterior node adr = " << (void*)n << endl;
+#endif // _DEBUG_ALLOCATION
+  // Return the setupped node, but do not forget to
+  // use in the parent node to use nodeToLink !!!!
+  return n;
+}
+
+// Create the representation of the interior node with box
+SKTBNodeT*
+CKTB8BAllocMan::AllocInteriorNodeWithBox(int axis, float position,
+					 int cntLeft, int cntRight,
+					 const SBBox &tsbox, SKTBNodeT* prevMinBoxNode,
+					 int depthStore)
+{
+#ifdef _DEBUG
+  nodeToLink = 0;
+  if ( (position < tsbox.Min(axis)) ||
+    (position > tsbox.Max(axis)) ) {
+    cerr << "Something wrong with the tree axis = " << axis;
+    cerr << " Min(axis) = " << tsbox.Min(axis)
+	  << " splitValue = " << position
+	  << " Max(axis) = " << tsbox.Max(axis) << endl;
+    abort();;
+  }  
+#endif
+
+#ifdef _KTB_CONSTR_STATS
+  _stats_interiorCount++;
+  _stats_minbboxCount++;
+#endif
+  
+  // Just to satisfy the compiler
+  cntLeft = cntLeft;
+  cntRight = cntRight;
+
+#ifdef _SHORT_FORM_MINBOX  
+  // Alloc two nodes = 2*8 Bytes = 16 Bytes
+  SKTBNodeT *n = (SKTBNodeT*)(alloc2->New(2));
+  nodeToLink = n;
+  if (n == 0) {
+    // we have to insert a special node that links only
+    nodeToLink = (SKTBNodeT*)alloc2->NewLastEntry(1);
+    assert(nodeToLink);
+    nodeToLink->offset = CKTBAxes::EE_Link;
+    n = (SKTBNodeT*)(alloc2->NewEntryInNewBlock(2));
+    // This is the link
+    nodeToLink->linkedNode = n;    
+  } // if n
+
+  assert(n);
+  assert(nodeToLink);
+
+  // Set the interior node
+  assert((axis >=0) && (axis < 3));
+  n->offset = (int)CKTBAxes::EE_X_axisBox + axis;
+  n->splitPlane = position;
+
+  // Set the box
+  // and the address to the parent min box node
+  (n+1)->parentBoxNode = prevMinBoxNode;
+
+  // Here we simply allocate the box for the address
+  SBBox *badr = new SBBox; 
+  assert(badr);
+  (n+1)->pointer = (unsigned char *)badr;
+
+  // Note that we cannot store the depth here !
+  depthStore = depthStore; // to satisfy the compiler
+#else // _SHORT_FORM_MINBOX
+  // Alloc two single nodes (16 Bytes) + box (24 Bytes) = 40 Bytes
+  SKTBNodeT *n = (SKTBNodeT*)(alloc2->New(5));
+  nodeToLink = n;
+  if (n == 0) {
+    // we have to insert a special node that links only
+    nodeToLink = (SKTBNodeT*)alloc2->NewLastEntry(1);
+    assert(nodeToLink);
+    nodeToLink->offset = CKTBAxes::EE_Link;
+    n = (SKTBNodeT*)(alloc2->NewEntryInNewBlock(5));
+    // This is the link
+    nodeToLink->linkedNode = n;    
+  } // if n
+
+  assert(n);
+  assert(nodeToLink);
+
+  // Set the interior node
+  assert((axis >=0) && (axis < 3));
+  n->offset = (int)CKTBAxes::EE_X_axisBox + axis;
+  n->splitPlane = position;
+
+  // Set the box itself
+  // and the address to the parent min box node
+  (n+1)->parentBoxNode = prevMinBoxNode;
+  // here we set the depth of the node (suited for debugging)
+  (n+1)->depth = depthStore;
+  
+  // This is not very nice, we use the address in already allocated
+  //item, but this saves memory of 4 Bytes, which allows allingment to 32 Bytes
+  //for this entry
+  SBBox *badr = (SBBox*)(((char*)n)+16);  
+#endif // _SHORT_FORM_MINBOX
+
+  // and copy the box content from the function parameters
+  *(badr) = tsbox;
+  
+#ifdef _DEBUG_ALLOCATION  
+  cout << "AllocInterior node adr = " << (void*)n << endl;
+#endif // _DEBUG_ALLOCATION
+  // Return the setupped node, but do not forget to
+  // use in the parent node to use nodeToLink !!!!
+  return n;
+}
+  
+// Set the pointers to children for the interior node
+void
+CKTB8BAllocMan::SetInteriorNodeLinks(SKTBNodeT *node,
+				     SKTBNodeT *leftChild,
+				     SKTBNodeT *rightChild)
+{
+  leftChild = leftChild; // to satisfy the compiler
+
+  // Check on correctness of DFS order
+  assert( (node+1 == leftChild) || (node+2 == leftChild) || (node+5 == leftChild) );
+
+#ifdef _DEBUG_ALLOCATION  
+  cout << "SetInteriorNode adr = " << (void*)node
+       << " right = " << (void*)rightChild << endl;
+#endif
+  
+#ifdef _DEBUG
+  // Check if last 3 bits of the address are really zero
+  // and hence they can be used for different purposes
+  if ( ( ((unsigned int)rightChild) & CKTBAxes::EE_Mask) != 0) {
+    // The bug in implementation of DFS order allocator or so
+    // This should never happen.
+    cerr << "cerr error, node is not 8Bytes aligned, it cannot be linked in DFS" << endl;
+    abort();;
+  }
+#endif
+
+  // Bitwise OR should work correctly
+  assert(node->offset <= CKTBAxes::EE_Z_axisBox);
+  //assert(node->offset >= 0);
+  //(unsigned long)node->offset |= (unsigned long)rightChild;
+  node->offset = node->offset | (unsigned int)rightChild;
+#ifdef _DEBUG
+  // Compute right child
+  SKTBNodeT *p = GetRight(node);
+  if (p != rightChild) {
+    cerr << "Problem with implementation of setting right child" << endl;
+    abort();;
+  } 
+#endif
+
+  return;
+}
+
+// Create the representation of the leaf. Note that possibly there
+// can be special cases, such as 0, 1, 2, or 3 objects, or in general
+// N objects.
+SKTBNodeT*
+CKTB8BAllocMan::AllocLeaf(int cntObjects)
+{
+#ifdef _DEBUG
+  nodeToLink = 0;
+#endif
+
+#ifdef _KTB_CONSTR_STATS
+  _stats_leafNodeCount++;
+  _sumLeafDepth += _currDepth;
+  if (cntObjects) {
+    _sumFullLeafDepth += _currDepth;
+    // The count of object references in leaves
+    _sumObjectRefCount += cntObjects;
+    // The maximum number of object references in a leaf
+    if (cntObjects > _maxObjectRefInLeaf)
+      _maxObjectRefInLeaf = cntObjects;
+  }
+  else
+    _stats_emptyLeftNodeCount++;
+#endif
+  
+  // Alloc a single node
+  SKTBNodeT *n = (SKTBNodeT*)(alloc2->New(1));
+  nodeToLink = n;
+  if (n == 0) {
+    // we have to insert a special node that links only
+    n = nodeToLink = (SKTBNodeT*)alloc2->NewLastEntry(1);
+    assert(nodeToLink);
+    // Allocate a new block for the next allocation
+    alloc2->AllocNewBlock();
+  } // if n
+
+  n->offset = CKTBAxes::EE_Leaf;
+  n->objlist = 0;
+
+#ifdef _DEBUG_ALLOCATION  
+  cout << "AllocLeaf adr = " << (void*)n << endl;
+#endif
+  
+  // Return the node
+  return n;
+}
+
+// if active node is empty, then is replaced by full leaf with
+// the object list. In success returns 0, for failure returns 1.
+// The object list is used as it is .. it is not copied !!
+int
+CKTB8BAllocMan::SetFullLeaf(SKTBNodeT *node, const ObjectContainer *objlist)
+{
+  assert(node);
+  assert(IsLeaf_(node));
+
+#ifdef _DEBUG_ALLOCATION  
+  cout << "SetFullLeaf adr = " << (void*)node << endl;
+#endif
+  
+  if ( (objlist == NULL) ||
+       (objlist->size() == 0) ) {
+    node->objlist = 0;
+  }
+  else {
+    // Set the pointer to the list of objects
+    node->objlist = (ObjectContainer *) objlist;
+  }
+
+  return 0;
+}
+
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/sbbox.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/sbbox.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/sbbox.cpp	(revision 2582)
@@ -0,0 +1,446 @@
+// ===================================================================
+// $Id: sbbox.cpp $
+//
+// ssbbox.cpp
+//      Simply bounding box for ray tracing only, 24 Bytes in size.
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, December 2005
+
+// GOLEM headers
+#include "sbbox.h"
+
+#undef INLINE
+#define INLINE 
+//#define INLINE INLINE
+
+namespace GtpVisibilityPreprocessor {
+
+
+void
+Describe(const SBBox &b, ostream &app, int ind)
+{
+  indent(app, ind);
+  app << "SBBox: min at(" << b.Min() << "), max at(" << b.Max() << ")\n";
+}
+
+// Function describing the box
+void
+DescribeXYZ(const SBBox &b, ostream &app, int ind)
+{
+  indent(app, ind);
+  app << " box = ( "
+      << b.Min().x << " , " << b.Max().x << " )( "
+      << b.Min().y << " , " << b.Max().y << " )( "
+      << b.Min().z << " , " << b.Max().z << " )\n";
+}
+
+
+bool
+SBBox::Includes(const SBBox &b) const
+{
+  if (b.pp[0].x >= pp[0].x &&
+      b.pp[0].y >= pp[0].y &&
+      b.pp[0].z >= pp[0].z &&
+      b.pp[1].x <= pp[1].x &&
+      b.pp[1].y <= pp[1].y &&
+      b.pp[1].z <= pp[1].z)
+    return true;
+  return false;
+}
+
+bool
+SBBox::Includes(const SBBox &b, float eps) const
+{
+  if  (b.pp[0].x >= pp[0].x - eps &&
+       b.pp[0].y >= pp[0].y - eps &&
+       b.pp[0].z >= pp[0].z - eps &&
+       b.pp[1].x <= pp[1].x + eps &&
+       b.pp[1].y <= pp[1].y + eps &&
+       b.pp[1].z <= pp[1].z + eps)
+    return true;
+  return false;  
+}
+
+#if 0
+// The implementation I, the first version implemented by Vlastimil
+// Havran, without looking into the literature
+INLINE bool
+SBBox::RayIntersect(const CRay &ray,
+		    float &tmin, float &tmax) const
+{
+   float interval_min = tmin;
+   float interval_max = tmax;
+
+   const CVector3D &rayLoc = ray.GetLoc();
+   const CVector3D &rayinvDir = ray.GetInvertedDir();
+   
+   float t0, t1;
+   if (rayinvDir.x > 0) {
+     t0 = (pp[0].x - rayLoc.x) * rayinvDir.x;
+     t1 = (pp[1].x - rayLoc.x) * rayinvDir.x;
+   }
+   else {
+     t0 = (pp[1].x - rayLoc.x) * rayinvDir.x;
+     t1 = (pp[0].x - rayLoc.x) * rayinvDir.x;
+   }
+   assert(t0 <= t1);     
+   if (t0 > interval_min)
+     interval_min = t0;
+   if (t1 < interval_max)
+     interval_max = t1;
+   if (interval_min > interval_max)
+     return false;
+
+   if (rayinvDir.y > 0) {
+     t0 = (pp[0].y - rayLoc.y) * rayinvDir.y;
+     t1 = (pp[1].y - rayLoc.y) * rayinvDir.y;
+   }
+   else {
+     t0 = (pp[1].y - rayLoc.y) * rayinvDir.y;
+     t1 = (pp[0].y - rayLoc.y) * rayinvDir.y;
+   }
+   assert(t0 <= t1);     
+   if (t0 > interval_min)
+     interval_min = t0;
+   if (t1 < interval_max)
+     interval_max = t1;
+   if (interval_min > interval_max)
+     return false;
+
+   if (rayinvDir.z > 0) {
+     t0 = (pp[0].z - rayLoc.z) * rayinvDir.z;
+     t1 = (pp[1].z - rayLoc.z) * rayinvDir.z;
+   }
+   else {
+     t0 = (pp[1].z - rayLoc.z) * rayinvDir.z;
+     t1 = (pp[0].z - rayLoc.z) * rayinvDir.z;
+   }
+   assert(t0 <= t1);     
+   if (t0 > interval_min)
+     interval_min = t0;
+   if (t1 < interval_max)
+     interval_max = t1;
+
+   // return true if the box is intersected
+   // return false if not intersected by ray
+   if ( (interval_max > 0.0f) &&
+	(interval_min <= interval_max) ) {
+     // yes, intersected, update tmin and tmax for current node
+     tmin = interval_min;
+     tmax = interval_max;
+     return true;
+   }
+   return false; // not intersected
+}
+#endif
+
+// -------------------------------------------------------------
+#if 0
+// The implementation II
+// The code follows the article by Mueller/Geimer 2003 paper
+
+INLINE
+float minf(const float a, const float b) { return (a < b) ? a : b;}
+INLINE
+float maxf(const float a, const float b) { return (a > b) ? a : b;}
+
+INLINE bool
+SBBox::RayIntersect(const CRay &ray,
+		    float &tmin,
+		    float &tmax) const
+{
+   //assert(tmin <= tmax);
+   const CVector3D &rayLoc = ray.GetLoc();
+   const CVector3D &rayinvDir = ray.GetInvertedDir();
+
+   register float t0, t1;
+   // coordinate x
+   t0 = (pp[0].x - rayLoc.x) * rayinvDir.x;
+   t1 = (pp[1].x - rayLoc.x) * rayinvDir.x;
+   register float ttmin = maxf(minf(t0, t1), tmin);
+   register float ttmax = minf(maxf(t0, t1), tmax);
+   // coordinate y
+   t0 = (pp[0].y - rayLoc.y) * rayinvDir.y;
+   t1 = (pp[1].y - rayLoc.y) * rayinvDir.y;
+   ttmin = maxf(minf(t0, t1), ttmin);
+   ttmax = minf(maxf(t0, t1), ttmax);
+   // coordinate z
+   t0 = (pp[0].z - rayLoc.z) * rayinvDir.z;
+   t1 = (pp[1].z - rayLoc.z) * rayinvDir.z;
+   ttmin = maxf(minf(t0, t1), ttmin);
+   ttmax = minf(maxf(t0, t1), ttmax);
+
+   // return true if the box is intersected
+   // return false if not intersected by ray
+   if ( (ttmax > 0.f) &&
+	(ttmin <= ttmax)) {
+     // yes, intersected, update tmin and tmax for current node
+     tmin = ttmin;
+     tmax = ttmax;
+     return true; 
+   }
+   return false; // not intersected
+}
+#endif
+
+// -------------------------------------------------------------
+#if 0
+// The implementation III
+// The code follows the article by Mueller/Geimer 2003 paper
+// - improved possibly by earlier termination.
+INLINE
+float minf(const float a, const float b) { return (a < b) ? a : b;}
+INLINE
+float maxf(const float a, const float b) { return (a > b) ? a : b;}
+
+INLINE bool
+SBBox::RayIntersect(const CRay &ray,
+		    float &tmin,
+		    float &tmax) const
+{
+   //assert(tmin <= tmax);
+   const CVector3D &rayLoc = ray.GetLoc();
+   const CVector3D &rayinvDir = ray.GetInvertedDir();
+   
+   register float t0, t1;
+   // coordinate x
+   t0 = (pp[0].x - rayLoc.x) * rayinvDir.x;
+   t1 = (pp[1].x - rayLoc.x) * rayinvDir.x;
+   register float ttmin = maxf(minf(t0, t1), tmin);
+   register float ttmax = minf(maxf(t0, t1), tmax);
+   if (ttmin > ttmax)
+     return false;
+
+   // coordinate y
+   t0 = (pp[0].y - rayLoc.y) * rayinvDir.y;
+   t1 = (pp[1].y - rayLoc.y) * rayinvDir.y;
+   ttmin = maxf(minf(t0, t1), ttmin);
+   ttmax = minf(maxf(t0, t1), ttmax);
+   if (ttmin > ttmax)
+     return false;
+
+   // coordinate z
+   t0 = (pp[0].z - rayLoc.z) * rayinvDir.z;
+   t1 = (pp[1].z - rayLoc.z) * rayinvDir.z;
+   ttmin = maxf(minf(t0, t1), ttmin);
+   ttmax = minf(maxf(t0, t1), ttmax);
+
+   // return true if the box is intersected
+   // return false if not intersected by ray
+   if ( (ttmax > 0.f) &&
+	(ttmin <= ttmax)) {
+     // yes, intersected, update tmin and tmax for current node
+     tmin = ttmin;
+     tmax = ttmax;
+     return true; 
+   }
+   return false; // not intersected
+}
+#endif
+
+#if 0
+// The implementation IV
+// - improved implementation I - it does not work for shadow rays ?
+INLINE
+float minf(const float a, const float b) { return (a < b) ? a : b;}
+INLINE
+float maxf(const float a, const float b) { return (a > b) ? a : b;}
+
+INLINE bool
+SBBox::RayIntersect(const CRay &ray,
+		    float &tmin,
+		    float &tmax) const
+{
+   register float interval_min = tmin;
+   register float interval_max = tmax;
+
+   const CVector3D &rayLoc = ray.GetLoc();
+   const CVector3D &rayinvDir = ray.GetInvertedDir();
+   
+   register float t0, t1;
+   if (rayinvDir.x > 0) {
+     t0 = (pp[0].x - rayLoc.x) * rayinvDir.x;
+     t1 = (pp[1].x - rayLoc.x) * rayinvDir.x;
+   }
+   else {
+     t0 = (pp[1].x - rayLoc.x) * rayinvDir.x;
+     t1 = (pp[0].x - rayLoc.x) * rayinvDir.x;
+   }
+   assert(t0 <= t1);     
+   interval_min = maxf(t0, interval_min);
+   interval_max = minf(t1, interval_min);
+   if (interval_min > interval_max)
+     return false;
+
+   if (rayinvDir.y > 0) {
+     t0 = (pp[0].y - rayLoc.y) * rayinvDir.y;
+     t1 = (pp[1].y - rayLoc.y) * rayinvDir.y;
+   }
+   else {
+     t0 = (pp[1].y - rayLoc.y) * rayinvDir.y;
+     t1 = (pp[0].y - rayLoc.y) * rayinvDir.y;
+   }
+   assert(t0 <= t1);     
+   interval_min = maxf(t0, interval_min);
+   interval_max = minf(t1, interval_min);
+   if (interval_min > interval_max)
+     return false;
+
+   if (rayinvDir.z > 0) {
+     t0 = (pp[0].z - rayLoc.z) * rayinvDir.z;
+     t1 = (pp[1].z - rayLoc.z) * rayinvDir.z;
+   }
+   else {
+     t0 = (pp[1].z - rayLoc.z) * rayinvDir.z;
+     t1 = (pp[0].z - rayLoc.z) * rayinvDir.z;
+   }
+   assert(t0 <= t1);     
+   interval_min = maxf(t0, interval_min);
+   interval_max = minf(t1, interval_min);
+
+   // return true if the box is intersected
+   // return false if not intersected by ray
+   if ( (interval_max > 0.f) &&
+	(interval_min <= interval_max)) {
+     // yes, intersected, update tmin and tmax for current node
+     tmin = interval_min;
+     tmax = interval_max;
+     return true; 
+   }
+   return false; // not intersected
+}
+#endif
+
+// -------------------------------------------------------------
+#if 0
+// The implementation V
+// The code follows the article by Mueller/Geimer 2003 paper
+// - changed. - it does not work for shadow rays ?
+INLINE bool
+SBBox::RayIntersect(const CRay &ray,
+		    float &tmin,
+		    float &tmax) const
+{
+   //assert(tmin <= tmax);
+   const CVector3D &rayLoc = ray.GetLoc();
+   const CVector3D &rayinvDir = ray.GetInvertedDir();
+
+   register float tt_min = tmin;
+   register float tt_max = tmax;
+   
+   register float t0, t1;
+   // coordinate x
+   t0 = (pp[0].x - rayLoc.x) * rayinvDir.x;
+   t1 = (pp[1].x - rayLoc.x) * rayinvDir.x;
+   register float rmin, rmax;
+   if (t1 < t0) {
+     rmin = t1;  // min
+     rmax = t0; // max
+   }
+   else {
+     rmin = t0; // min
+     rmax = t1; // max     
+   }
+   assert(rmin <= rmax);
+   if (tt_min < rmin)
+     tt_min = rmin; // take maximum
+   if (tt_max > rmax)
+     tt_max = rmax; // take minimum
+   if (tt_min > tt_max)
+     return false;
+
+   // coordinate y
+   t0 = (pp[0].y - rayLoc.y) * rayinvDir.y;
+   t1 = (pp[1].y - rayLoc.y) * rayinvDir.y;
+   if (t1 < t0) {
+     rmin = t1;  // min
+     rmax = t0; // max
+   }
+   else {
+     rmin = t0; // min
+     rmax = t1; // max     
+   }
+   assert(rmin <= rmax);
+   if (tt_min < rmin)
+     tt_min = rmin; // take maximum
+   if (tt_max > rmax)
+     tt_max = rmax; // take minimum
+   if (tt_min > tt_max)
+     return false;
+
+   // coordinate z
+   t0 = (pp[0].z - rayLoc.z) * rayinvDir.z;
+   t1 = (pp[1].z - rayLoc.z) * rayinvDir.z;
+   if (t1 < t0) {
+     rmin = t1;  // min
+     rmax = t0; // max
+   }
+   else {
+     rmin = t0; // min
+     rmax = t1; // max     
+   }
+   assert(rmin <= rmax);
+   if (tt_min < rmin)
+     tt_min = rmin; // take maximum
+   if (tt_max > rmax)
+     tt_max = rmax; // take minimum
+   if ((tt_min > tt_max) ||
+       (tt_max < 0.f) )		  
+     return false; // not intersected
+
+   // yes, intersected, update tmin and tmax for current node
+   tmin = tt_min;
+   tmax = tt_max;
+   return true; 
+}
+#endif
+
+// -------------------------------------------------------------
+#if 0
+// The implementation VI
+// The code follows the article in SIGGRAPH 2005 course notes,
+// page 59, likely by Peter Shirley and Boulos Solomon.
+
+INLINE
+float minf(const float a, const float b) { return (a < b) ? a : b;}
+INLINE
+float maxf(const float a, const float b) { return (a > b) ? a : b;}
+
+INLINE bool
+SBBox::RayIntersect(const CRay &ray,
+		    float &t0,
+		    float &t1) const
+{
+   //assert(tmin <= tmax);
+   const CVector3D &rayLoc = ray.GetLoc();
+   const CVector3D &rayinvDir = ray.GetInvertedDir();
+
+   // coordinate x
+   float tmin = (pp[ray.GetSign(0)].x - rayLoc.x) * rayinvDir.x;
+   float tmax = (pp[1-ray.GetSign(0)].x - rayLoc.x) * rayinvDir.x;
+   float tymin = (pp[ray.GetSign(1)].y - rayLoc.y) * rayinvDir.y;
+   float tymax = (pp[1-ray.GetSign(1)].y - rayLoc.y) * rayinvDir.y;
+   if ( (tmin > tymax) || (tymin > tmax) )
+     return false;
+   if (tymin > tmin)
+     tmin = tymin;
+   if (tymax < tmax)
+     tmax = tymax;
+   float tzmin = (pp[ray.GetSign(2)].z - rayLoc.z) * rayinvDir.z;
+   float tzmax = (pp[1-ray.GetSign(2)].z - rayLoc.y) * rayinvDir.z;
+   if ( (tmin > tzmax) || (tzmin > tmax) )
+     return false;
+   if (tzmin > tmin)
+     tmin = tzmin;
+   if (tzmax < tmax)
+     tmax = tzmax;
+   return ( (tmin < t1) && (tmax >= 0.f) );
+}
+#endif
+// End of ray-box intersections
+
+// ----------------------------------------------------------
+
+} // namespace
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbtrav.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbtrav.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbtrav.cpp	(revision 2582)
@@ -0,0 +1,1008 @@
+// ===================================================================
+// $Id: $
+//
+// ktbtrav.cpp
+//
+// class: CKTBTraversal
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, February 2007 (copy from kdrtrav.cpp)
+
+// GOLEM headers
+#include "ktbtrav.h"
+#include "Intersectable.h"
+
+namespace GtpVisibilityPreprocessor {
+  
+//------------------------------------------------------------------
+// Robust statistically optimized algorithm for CKTB ray-traversal
+// original version 025. This algorithm was published at Journal of
+// Graphics Tools, 1997, Havran et al.
+
+// the depth of traversal when kd-trees are nested. The global (the highest
+// level) kd-tree is at the depth 0.
+int
+CKTBTraversal::traversalDepth = 0;
+
+// sets the stack pointers that are used for the traversal.
+void
+CKTBTraversal::GetStackPointers(struct SStackElem *&entryPointer,
+				struct SStackElem *&exitPointer)
+{
+  assert(traversalDepth < MAX_NESTING);
+  
+  int index = traversalDepth * MAX_HEIGHT;
+  entryPointer = &(stack[index]);
+  exitPointer = &(stack[index + 1]);
+
+  traversalDepth++;  
+  return;
+}
+
+// sets the stack pointers that are used for the traversal.
+void
+CKTBTraversal::RestoreStackPointers()
+{
+  assert(traversalDepth >= 0);
+  traversalDepth--;  
+  return;
+}
+
+
+// default constructor
+CKTBTraversal::CKTBTraversal()
+{
+  bbox = AxisAlignedBox3(Vector3(MAXFLOAT),
+			 Vector3(-MAXFLOAT));
+  root = 0;
+  epsilon = 0;
+
+#ifdef __TRAVERSAL_STATISTICS
+  _allNodesTraversed = 0L;
+  _fullLeavesTraversed = 0L;
+  _emptyLeavesTraversed = 0L;
+#endif
+}
+
+// Here we find the node (preferably minbox node) containing
+// the point
+const SKTBNodeT*
+CKTBTraversal::Locate(const Vector3 &position)
+{
+  const SKTBNodeT *current, *next = root;
+  const SKTBNodeT *returnNode = 0;
+
+  do {
+    current = next;
+    switch (GetNodeType(current)) {
+      // -------------------------------------------------
+      case CKTBAxes::EE_X_axis: {
+	if (position[CKTBAxes::EE_X_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	break;
+      }
+      case CKTBAxes::EE_Y_axis: {
+	if (position[CKTBAxes::EE_Y_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	break;
+      }
+      case CKTBAxes::EE_Z_axis: {
+	if (position[CKTBAxes::EE_Z_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	break;
+      }
+      case CKTBAxes::EE_X_axisBox: {
+	if (position[CKTBAxes::EE_X_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	returnNode = current;
+	break;
+      }
+      case CKTBAxes::EE_Y_axisBox: {
+	if (position[CKTBAxes::EE_Y_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	returnNode = current;
+	break;
+      }
+      case CKTBAxes::EE_Z_axisBox: {
+	if (position[CKTBAxes::EE_Z_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	returnNode = current;
+	break;
+      }
+      case CKTBAxes::EE_Leaf: {
+	next = 0; // finishing
+	break;
+      }
+      case CKTBAxes::EE_Link:{
+	next = GetLinkNode(current);
+	// cout << "Link node was accessed" << endl;
+	break;
+      }
+    } // switch
+  }
+  while (next != NULL);
+
+  if (returnNode)
+    return returnNode;
+
+  // return the last (leaf node) visited on the path
+  return current;
+}
+
+#ifdef TRV000
+int
+CKTBTraversal::FindNearestI(const SimpleRay &ray) 
+{
+  // passing through parameters
+  float tmin, tmax;
+  
+  // test if the whole CKTB tree is missed by the input ray
+  if ( (!root) ||
+       (!bbox.ComputeMinMaxT(ray.mOrigin, ray.mDirection, &tmin, &tmax)) ||       
+       (tmin >= tmax) ||
+       (tmax < 0.f)
+     ) {
+    SimpleRay::IntersectionRes[0].intersectable = 0;
+    return 0; // no object can be intersected
+  }
+
+//#define _DEBUGKTB
+#ifdef _DEBUGKTB
+  int ib = 0;
+  int depth = 0; 
+#endif
+  
+#ifdef __TRAVERSAL_STATISTICS
+  int allNodesTraversed = 0L;
+  int fullLeavesTraversed = 0L;
+  int emptyLeavesTraversed = 0L;
+#endif // __TRAVERSAL_STATISTICS
+
+#ifdef _COMPUTE_INVERTED_DIR_KTB  
+  Vector3 invertedDir;
+  invertedDir.x = 1.0f / ray.mDirection.x;
+  invertedDir.y = 1.0f / ray.mDirection.y;
+  invertedDir.z = 1.0f / ray.mDirection.z;
+#endif // _COMPUTE_INVERTED_DIR_KTB  
+
+  // start from the root node
+  SKTBNodeT *currNode = root;
+
+  struct SStackElem *entp, *extp;
+  GetStackPointers(entp, extp);
+  //struct SStackElem *entp = &(stack[0]);
+  //struct SStackElem *extp = &(stack[1]);
+
+  // exit point setting for the box and the ray
+  extp->x = ray.mOrigin.x + ray.mDirection.x * tmax;
+  extp->y = ray.mOrigin.y + ray.mDirection.y * tmax;
+  extp->z = ray.mOrigin.z + ray.mDirection.z * tmax;
+  extp->nodep = NULL;
+  extp->prev = NULL;
+  extp->t = tmax;
+
+  // entry point setting for the box and the ray
+  entp->nodep = NULL;
+  entp->prev = NULL;
+  if (tmin > 0.0) { // external node
+    entp->x = ray.mOrigin.x + ray.mDirection.x * tmin;
+    entp->y = ray.mOrigin.y + ray.mDirection.y * tmin;
+    entp->z = ray.mOrigin.z + ray.mDirection.z * tmin;
+    entp->t = tmin;
+  }
+  else { // internal node
+    entp->x = ray.mOrigin.x;
+    entp->y = ray.mOrigin.y;
+    entp->z = ray.mOrigin.z;
+    entp->t = 0.0;
+  }
+  SKTBNodeT *farChild;
+
+  // DEBUG << "A: c= " << currNode << "\n" << flush ;
+ 
+  // traverse through whole CKTB tree
+  for (;;) {
+#ifndef _ALLOC_EMPTY_LEAVES
+    for (;;) {
+    // label for continuing the traversal
+#else
+    // we have to check the node
+    // current node is not the leaf, empty leaves are NULL pointers
+    while (currNode) {
+#endif
+
+#ifdef _DEBUGKTB
+      cout << "i = " << ib << " node = " << (void*)currNode
+	   << " depth=" << depth << endl;
+      ib++;
+#endif      
+      
+#ifdef __TRAVERSAL_STATISTICS
+      allNodesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+      // the position of the splitting plane
+      float splitVal = GetSplitValue(currNode);
+      // decision based on the axis given by splitting plane
+      switch (GetNodeType(currNode) & 0x7) {
+	// -------------------------------------------------
+	case CKTBAxes::EE_X_axis: {
+#ifdef _DEBUGKTB
+	  cout << "X-axis v=" << splitVal << endl;
+	  depth++;
+#endif
+	  if (entp->x <= splitVal) {
+	    if (extp->x <= splitVal) {
+	      currNode = GetLeft(currNode);
+	      // cases N1,N2,N3,P5,Z2,Z3
+	      continue;
+	    }
+	    // case N4
+	    farChild = GetRight(currNode);
+	    currNode = GetLeft(currNode);
+	  }
+          else {
+	    if (splitVal <= extp->x) {
+	      currNode = GetRight(currNode);
+	      continue; // cases P1,P2,P3,N5,Z1
+	    }
+	    farChild = GetLeft(currNode); // case P4
+	    currNode = GetRight(currNode);
+	  }
+#ifdef _DEBUGKTB
+	  cout << "X-Push right node = " << farChild << endl;
+#endif	  
+          // case N4 or P4
+#ifdef _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.x) * invertedDir.x;
+#else  // _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.x) / ray.mDirection.x;
+#endif // _COMPUTE_INVERTED_DIR_KTB
+	  
+	  struct SStackElem *tmp = extp;
+	  if (++extp == entp)
+	    extp++;
+#if defined(_KTBEXTSTACK) && defined(_DEBUGKTB)
+	  extp->dummy = depth+1;
+#endif
+	  extp->prev = tmp;
+	  extp->nodep = farChild;
+	  extp->t = tdist;
+	  extp->x = splitVal;
+	  extp->y = ray.mOrigin.y +  tdist * ray.mDirection.y;
+	  extp->z = ray.mOrigin.z +  tdist * ray.mDirection.z;
+	  continue;
+        }
+	// -------------------------------------------------
+	case CKTBAxes::EE_Y_axis: {
+#ifdef _DEBUGKTB
+	  cout << "Y-axis v=" << splitVal << endl;
+	  depth++;
+#endif
+	  if (entp->y <= splitVal) {
+	    if (extp->y <= splitVal) {
+	      currNode = GetLeft(currNode); 
+	      //case N1,N2,N3,P5,Z2,Z3
+	      continue;
+	    }
+	    // case N4
+	    farChild = GetRight(currNode);
+	    currNode = GetLeft(currNode);
+	  }
+          else {
+	    if (splitVal <= extp->y) {
+	      currNode = GetRight(currNode);
+	      continue; // case P1,P2,P3,N5
+	    }
+	    farChild = GetLeft(currNode); // case P4
+	    currNode = GetRight(currNode);
+	  }
+#ifdef _DEBUGKTB
+	  cout << "Y-Push right node = " << farChild << endl;
+#endif	  
+          // case N4 or P4
+#ifdef _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.y) * invertedDir.y;
+#else  // _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.y) / ray.mDirection.y;
+#endif // _COMPUTE_INVERTED_DIR_KTB
+
+	  struct SStackElem *tmp = extp;
+	  if (++extp == entp)
+	    extp++;
+#if defined(_KTBEXTSTACK) && defined(_DEBUGKTB)
+	  extp->dummy = depth+1;
+#endif	  	  
+	  extp->prev = tmp;
+	  extp->nodep = farChild;
+	  extp->t = tdist;
+	  extp->x = ray.mOrigin.x + tdist * ray.mDirection.x;
+	  extp->y = splitVal;
+	  extp->z = ray.mOrigin.z + tdist * ray.mDirection.z;
+	  continue;
+        }
+	// -------------------------------------------------
+	case CKTBAxes::EE_Z_axis: {
+#ifdef _DEBUGKTB
+	  cout << "Z-axis v=" << splitVal << endl;
+	  depth++;
+#endif
+	  if (entp->z <= splitVal) {
+	    if (extp->z <= splitVal) {
+	      currNode = GetLeft(currNode);
+	      //case N1,N2,N3,P5,Z2,Z3
+	      continue;
+	    }
+	    // case N4
+	    farChild = GetRight(currNode);
+	    currNode = GetLeft(currNode);
+  	  }
+          else {
+	    if (splitVal <= extp->z) {
+	      currNode = GetRight(currNode);
+	      continue; // case P1,P2,P3,N5
+	    }
+	    farChild = GetLeft(currNode); // case P4
+	    currNode = GetRight(currNode);
+          }
+#ifdef _DEBUGKTB
+	  cout << "Z-Push right node = " << farChild << endl;
+#endif	  
+          // case N4 or P4
+#ifdef _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.z) * invertedDir.z;
+#else  // _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.z) / ray.mDirection.z;
+#endif // _COMPUTE_INVERTED_DIR_KTB
+
+	  struct SStackElem *tmp = extp;
+          if (++extp == entp)
+	    extp++;
+#if defined(_KTBEXTSTACK) && defined(_DEBUGKTB)
+	  extp->dummy = depth+1;
+#endif	  
+	  
+	  extp->prev = tmp;
+	  extp->nodep = farChild;
+	  extp->t = tdist;
+	  extp->x = ray.mOrigin.x + tdist * ray.mDirection.x;
+	  extp->y = ray.mOrigin.y + tdist * ray.mDirection.y;
+	  extp->z = splitVal;
+	  continue;
+        }	  
+        case CKTBAxes::EE_Leaf:
+	{ // test objects for intersection
+#ifdef _DEBUGKTB
+	  cout << "Leaf " << endl;
+	  depth++;
+#endif
+	  goto TEST_OBJECTS;
+	}
+        case CKTBAxes::EE_Link:{
+#ifdef _DEBUGKTB
+	  cout << "Link " << endl;
+#endif 	  
+	  currNode = GetLinkNode(currNode);
+	  // cout << "Link node was accessed" << endl;
+	  continue;
+        }
+	case CKTBAxes::EE_X_axisBox: {
+#ifdef _DEBUGKTB
+	  cout << "X-axis Box v=" << splitVal << endl;
+	  depth++;
+#endif
+	  if (entp->x <= splitVal) {
+	    if (extp->x <= splitVal) {
+	      currNode = GetLeftMinBox(currNode);
+	      // cases N1,N2,N3,P5,Z2,Z3
+	      continue;
+	    }
+	    // case N4
+	    farChild = GetRight(currNode);
+	    currNode = GetLeftMinBox(currNode);
+	  }
+          else {
+	    if (splitVal <= extp->x) {
+	      currNode = GetRight(currNode);
+	      continue; // cases P1,P2,P3,N5,Z1
+	    }
+	    farChild = GetLeftMinBox(currNode); // case P4
+	    currNode = GetRight(currNode);
+	  }
+#ifdef _DEBUGKTB
+	  cout << "X-Push (Box) right node = " << farChild << endl;
+#endif	  
+          // case N4 or P4
+#ifdef _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.x) * invertedDir.x;
+#else  // _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.x) / ray.mDirection.x;
+#endif // _COMPUTE_INVERTED_DIR_KTB
+	  
+	  struct SStackElem *tmp = extp;
+	  if (++extp == entp)
+	    extp++;
+#if defined(_KTBEXTSTACK) && defined(_DEBUGKTB)
+	  extp->dummy = depth+1;
+#endif
+	  extp->prev = tmp;
+	  extp->nodep = farChild;
+	  extp->t = tdist;
+	  extp->x = splitVal;
+	  extp->y = ray.mOrigin.y +  tdist * ray.mDirection.y;
+	  extp->z = ray.mOrigin.z +  tdist * ray.mDirection.z;
+	  continue;
+        }
+	// -------------------------------------------------
+	case CKTBAxes::EE_Y_axisBox: {
+#ifdef _DEBUGKTB
+	  cout << "Y-axis Box v=" << splitVal << endl;
+	  depth++;
+#endif
+	  if (entp->y <= splitVal) {
+	    if (extp->y <= splitVal) {
+	      currNode = GetLeftMinBox(currNode); 
+	      //case N1,N2,N3,P5,Z2,Z3
+	      continue;
+	    }
+	    // case N4
+	    farChild = GetRight(currNode);
+	    currNode = GetLeftMinBox(currNode);
+	  }
+          else {
+	    if (splitVal <= extp->y) {
+	      currNode = GetRight(currNode);
+	      continue; // case P1,P2,P3,N5
+	    }
+	    farChild = GetLeftMinBox(currNode); // case P4
+	    currNode = GetRight(currNode);
+	  }
+#ifdef _DEBUGKTB
+	  cout << "Y-Push (Box) right node = " << farChild << endl;
+#endif	  
+          // case N4 or P4
+#ifdef _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.y) * invertedDir.y;
+#else  // _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.y) / ray.mDirection.y;
+#endif // _COMPUTE_INVERTED_DIR_KTB
+
+	  struct SStackElem *tmp = extp;
+	  if (++extp == entp)
+	    extp++;
+#if defined(_KTBEXTSTACK) && defined(_DEBUGKTB)
+	  extp->dummy = depth+1;
+#endif	  	  
+	  extp->prev = tmp;
+	  extp->nodep = farChild;
+	  extp->t = tdist;
+	  extp->x = ray.mOrigin.x + tdist * ray.mDirection.x;
+	  extp->y = splitVal;
+	  extp->z = ray.mOrigin.z + tdist * ray.mDirection.z;
+	  continue;
+        }
+	// -------------------------------------------------
+	case CKTBAxes::EE_Z_axisBox: {
+#ifdef _DEBUGKTB
+	  cout << "Z-axis Box v=" << splitVal << endl;
+	  depth++;
+#endif
+	  if (entp->z <= splitVal) {
+	    if (extp->z <= splitVal) {
+	      currNode = GetLeftMinBox(currNode);
+	      //case N1,N2,N3,P5,Z2,Z3
+	      continue;
+	    }
+	    // case N4
+	    farChild = GetRight(currNode);
+	    currNode = GetLeftMinBox(currNode);
+  	  }
+          else {
+	    if (splitVal <= extp->z) {
+	      currNode = GetRight(currNode);
+	      continue; // case P1,P2,P3,N5
+	    }
+	    farChild = GetLeftMinBox(currNode); // case P4
+	    currNode = GetRight(currNode);
+          }
+#ifdef _DEBUGKTB
+	  cout << "Z-Push (Box) right node = " << farChild << endl;
+#endif	  
+          // case N4 or P4
+#ifdef _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.z) * invertedDir.z;
+#else  // _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.z) / ray.mDirection.z;
+#endif // _COMPUTE_INVERTED_DIR_KTB
+
+	  struct SStackElem *tmp = extp;
+          if (++extp == entp)
+	    extp++;
+#if defined(_KTBEXTSTACK) && defined(_DEBUGKTB)
+	  extp->dummy = depth+1;
+#endif	  
+	  
+	  extp->prev = tmp;
+	  extp->nodep = farChild;
+	  extp->t = tdist;
+	  extp->x = ray.mOrigin.x + tdist * ray.mDirection.x;
+	  extp->y = ray.mOrigin.y + tdist * ray.mDirection.y;
+	  extp->z = splitVal;
+	  continue;
+        }	  
+      } // switch
+    } // while current node is not the leaf
+
+    // leaf can be empty or full at this point
+TEST_OBJECTS:
+
+#ifdef _DEBUGKTB
+    DEBUG << "currNode = " << currNode << " entp.t = " << entp->t
+	  << " extp.t = " << extp->t << endl;
+#endif
+    
+    if (!IsEmptyLeaf_(currNode)) {
+#ifdef _DEBUGKTB
+      cout << "Full leaf at depth= " << depth << endl; 
+#endif      
+
+#ifdef __TRAVERSAL_STATISTICS
+      fullLeavesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+      // test the objects in the full leaf against the ray
+      
+      SimpleRay::IntersectionRes[0].maxt = extp->t;
+      if (TestFullLeaf(ray, currNode)) {
+#ifdef _DEBUGKTB
+	cout << "Full leaf HIT " << endl; 
+#endif 	
+
+#ifdef __TRAVERSAL_STATISTICS
+	_allNodesTraversed += allNodesTraversed;
+	_fullLeavesTraversed += fullLeavesTraversed;
+	_emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+	
+	// signed distance should be already set in TestFullLeaf
+	// the first object intersected was found	
+	RestoreStackPointers();
+	return 1;
+      }
+    }
+#ifdef __TRAVERSAL_STATISTICS
+    else {
+#ifdef _DEBUGKTB
+      cout << "Empty leaf at depth= " << depth << endl; 
+#endif      
+      emptyLeavesTraversed++;
+    }
+#endif // __TRAVERSAL_STATISTICS
+
+
+#ifdef _DEBUGKTB
+    cout << "Pop the node" << endl;
+#endif      
+    
+    // pop farChild from the stack
+    // restore the current values
+    entp = extp;
+    currNode = entp->nodep;
+#ifdef _DEBUGKTB
+#ifdef _KTBEXTSTACK
+    depth = entp->dummy;
+    cout << "Popped node at depth = " << depth << endl;
+#endif	  
+#endif
+
+    // DEBUG << "Pop c= " << currNode << "\n" << flush ;
+    if (currNode == NULL) {
+#ifdef _DEBUGKTB
+	cout << "NO HIT - EXIT " << endl; 
+#endif 	
+
+#ifdef __TRAVERSAL_STATISTICS
+	_allNodesTraversed += allNodesTraversed;
+	_fullLeavesTraversed += fullLeavesTraversed;
+	_emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+
+      // no objects found along the ray path
+      RestoreStackPointers();
+      return 0;
+    }
+    extp = extp->prev;
+  } // for(;;)
+} // FindNearestI
+#endif // TRV000
+
+#ifdef TRV001
+int
+CKTBTraversal::FindNearestI(const SimpleRay &ray)
+{
+  // passing through parameters
+  float tmin, tmax;
+  
+  // test if the whole CKTB tree is missed by the input ray
+  if ( (!root) ||
+       (!bbox.ComputeMinMaxT(ray.mOrigin, ray.mDirection, &tmin, &tmax)) ||
+       (tmin >= tmax) ||
+       (tmax <= 0.f)
+     ) {
+    SimpleRay::IntersectionRes[0].intersectable = 0;
+    return 0; // no object can be intersected
+  }
+
+//#define _DEBUGKTB
+#ifdef _DEBUGKTB
+  int ib = 0;
+  int depth = 0; 
+#endif
+  
+#ifdef __TRAVERSAL_STATISTICS
+  int allNodesTraversed = 0L;
+  int fullLeavesTraversed = 0L;
+  int emptyLeavesTraversed = 0L;
+#endif // __TRAVERSAL_STATISTICS
+
+#ifdef _COMPUTE_INVERTED_DIR_KTB  
+  Vector3 invertedDir;
+  invertedDir.x = 1.0f / ray.mDirection.x;
+  invertedDir.y = 1.0f / ray.mDirection.y;
+  invertedDir.z = 1.0f / ray.mDirection.z;
+#endif // _COMPUTE_INVERTED_DIR_KTB  
+
+  // start from the root node
+  SKTBNodeT *currNode = root;
+
+  struct SStackElem *entp, *extp;
+  GetStackPointers(entp, extp);
+  //struct SStackElem *entp = &(stack[0]);
+  //struct SStackElem *extp = &(stack[1]);
+
+  // exit point setting for the box and the ray
+  extp->x = ray.mOrigin.x + ray.mDirection.x * tmax;
+  extp->y = ray.mOrigin.y + ray.mDirection.y * tmax;
+  extp->z = ray.mOrigin.z + ray.mDirection.z * tmax;
+  extp->nodep = NULL;
+  extp->prev = NULL;
+  extp->t = tmax;
+
+  // entry point setting for the box and the ray
+  entp->nodep = NULL;
+  entp->prev = NULL;
+  if (tmin > 0.0) { // external node
+    entp->x = ray.mOrigin.x + ray.mDirection.x * tmin;
+    entp->y = ray.mOrigin.y + ray.mDirection.y * tmin;
+    entp->z = ray.mOrigin.z + ray.mDirection.z * tmin;
+    entp->t = tmin;
+  }
+  else { // internal node
+    entp->x = ray.mOrigin.x;
+    entp->y = ray.mOrigin.y;
+    entp->z = ray.mOrigin.z;
+    entp->t = 0.0;
+  }
+  SKTBNodeT *farChild;
+
+  // DEBUG << "A: c= " << currNode << "\n" << flush ;
+ 
+  // traverse through whole CKTB tree
+  for (;;) {
+#ifndef _ALLOC_EMPTY_LEAVES
+    for (;;) {
+    // label for continuing the traversal
+#else
+    // we have to check the node
+    // current node is not the leaf, empty leaves are NULL pointers
+    while (currNode) {
+#endif
+
+#ifdef _DEBUGKTB
+      cout << "i = " << ib << " node = " << (void*)currNode
+	   << " depth=" << depth << endl;
+      ib++;
+#endif      
+      
+#ifdef __TRAVERSAL_STATISTICS
+      allNodesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+      // the position of the splitting plane
+      float splitVal = GetSplitValue(currNode);
+      // decision based on the axis given by splitting plane
+      switch (GetNodeType(currNode) & 0x07) {
+	// -------------------------------------------------
+	case CKTBAxes::EE_X_axis: {
+#ifdef _DEBUGKTB
+	  cout << "X-axis v=" << splitVal << endl;
+	  depth++;
+#endif
+	  if (entp->x <= splitVal) {
+	    if (extp->x <= splitVal) {
+	      currNode = GetLeft(currNode);
+	      // cases N1,N2,N3,P5,Z2,Z3
+	      continue;
+	    }
+	    // case N4
+	    farChild = GetRight(currNode);
+	    currNode = GetLeft(currNode);
+	  }
+          else {
+	    if (splitVal <= extp->x) {
+	      currNode = GetRight(currNode);
+	      continue; // cases P1,P2,P3,N5,Z1
+	    }
+	    farChild = GetLeft(currNode); // case P4
+	    currNode = GetRight(currNode);
+	  }
+#ifdef _DEBUGKTB
+	  cout << "X-Push right node = " << farChild << endl;
+#endif	  
+          // case N4 or P4
+#ifdef _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.x) * invertedDir.x;
+#else  // _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.x) / ray.mDirection.x;
+#endif // _COMPUTE_INVERTED_DIR_KTB
+	  
+	  struct SStackElem *tmp = extp;
+	  if (++extp == entp)
+	    extp++;
+#if defined(_KTBEXTSTACK) && defined(_DEBUGKTB)
+	  extp->dummy = depth+1;
+#endif
+	  extp->prev = tmp;
+	  extp->nodep = farChild;
+	  extp->t = tdist;
+	  extp->x = splitVal;
+	  extp->y = ray.mOrigin.y +  tdist * ray.mDirection.y;
+	  extp->z = ray.mOrigin.z +  tdist * ray.mDirection.z;
+	  continue;
+        }
+	// -------------------------------------------------
+	case CKTBAxes::EE_Y_axis: {
+#ifdef _DEBUGKTB
+	  cout << "Y-axis v=" << splitVal << endl;
+	  depth++;
+#endif
+	  if (entp->y <= splitVal) {
+	    if (extp->y <= splitVal) {
+	      currNode = GetLeft(currNode); 
+	      //case N1,N2,N3,P5,Z2,Z3
+	      continue;
+	    }
+	    // case N4
+	    farChild = GetRight(currNode);
+	    currNode = GetLeft(currNode);
+	  }
+          else {
+	    if (splitVal <= extp->y) {
+	      currNode = GetRight(currNode);
+	      continue; // case P1,P2,P3,N5
+	    }
+	    farChild = GetLeft(currNode); // case P4
+	    currNode = GetRight(currNode);
+	  }
+#ifdef _DEBUGKTB
+	  cout << "Y-Push right node = " << farChild << endl;
+#endif	  
+          // case N4 or P4
+#ifdef _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.y) * invertedDir.y;
+#else  // _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.y) / ray.mDirection.y;
+#endif // _COMPUTE_INVERTED_DIR_KTB
+
+	  struct SStackElem *tmp = extp;
+	  if (++extp == entp)
+	    extp++;
+#if defined(_KTBEXTSTACK) && defined(_DEBUGKTB)
+	  extp->dummy = depth+1;
+#endif	  	  
+	  extp->prev = tmp;
+	  extp->nodep = farChild;
+	  extp->t = tdist;
+	  extp->x = ray.mOrigin.x + tdist * ray.mDirection.x;
+	  extp->y = splitVal;
+	  extp->z = ray.mOrigin.z + tdist * ray.mDirection.z;
+	  continue;
+        }
+	// -------------------------------------------------
+	case CKTBAxes::EE_Z_axis: {
+#ifdef _DEBUGKTB
+	  cout << "Z-axis v=" << splitVal << endl;
+	  depth++;
+#endif
+	  if (entp->z <= splitVal) {
+	    if (extp->z <= splitVal) {
+	      currNode = GetLeft(currNode);
+	      //case N1,N2,N3,P5,Z2,Z3
+	      continue;
+	    }
+	    // case N4
+	    farChild = GetRight(currNode);
+	    currNode = GetLeft(currNode);
+  	  }
+          else {
+	    if (splitVal <= extp->z) {
+	      currNode = GetRight(currNode);
+	      continue; // case P1,P2,P3,N5
+	    }
+	    farChild = GetLeft(currNode); // case P4
+	    currNode = GetRight(currNode);
+          }
+#ifdef _DEBUGKTB
+	  cout << "Z-Push right node = " << farChild << endl;
+#endif	  
+          // case N4 or P4
+#ifdef _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.z) * invertedDir.z;
+#else  // _COMPUTE_INVERTED_DIR_KTB
+	  float tdist = (splitVal - ray.mOrigin.z) / ray.mDirection.z;
+#endif // _COMPUTE_INVERTED_DIR_KTB
+
+	  struct SStackElem *tmp = extp;
+          if (++extp == entp)
+	    extp++;
+#if defined(_KTBEXTSTACK) && defined(_DEBUGKTB)
+	  extp->dummy = depth+1;
+#endif	  
+	  
+	  extp->prev = tmp;
+	  extp->nodep = farChild;
+	  extp->t = tdist;
+	  extp->x = ray.mOrigin.x + tdist * ray.mDirection.x;
+	  extp->y = ray.mOrigin.y + tdist * ray.mDirection.y;
+	  extp->z = splitVal;
+	  continue;
+        }	  
+        case CKTBAxes::EE_Leaf:
+	{ // test objects for intersection
+#ifdef _DEBUGKTB
+	  cout << "Leaf " << endl;
+	  depth++;
+#endif
+	  goto TEST_OBJECTS;
+	}
+        case CKTBAxes::EE_Link:{
+#ifdef _DEBUGKTB
+	  cout << "Link " << endl;
+#endif 	  
+	  currNode = GetLinkNode(currNode);
+	  // cout << "Link node was accessed" << endl;
+	  continue;
+        }
+      } // switch
+    } // while current node is not the leaf
+
+    // leaf can be empty or full at this point
+TEST_OBJECTS:
+
+#ifdef _DEBUGKTB
+    DEBUG << "currNode = " << currNode << " entp.t = " << entp->t
+	  << " extp.t = " << extp->t << endl;
+#endif
+    
+    if (!IsEmptyLeaf_(currNode)) {
+#ifdef _DEBUGKTB
+      cout << "Full leaf at depth= " << depth << endl; 
+#endif      
+
+#ifdef __TRAVERSAL_STATISTICS
+      fullLeavesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+      // test the objects in the full leaf against the ray
+      
+      SimpleRay::IntersectionRes[0].maxt = extp->t;
+      if (TestFullLeaf(ray, currNode)) {
+#ifdef _DEBUGKTB
+	cout << "Full leaf HIT " << endl; 
+#endif 	
+
+#ifdef __TRAVERSAL_STATISTICS
+	_allNodesTraversed += allNodesTraversed;
+	_fullLeavesTraversed += fullLeavesTraversed;
+	_emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+	
+	// signed distance should be already set in TestFullLeaf
+	// the first object intersected was found	
+	RestoreStackPointers();
+	return 1;
+      }
+    }
+#ifdef __TRAVERSAL_STATISTICS
+    else {
+#ifdef _DEBUGKTB
+      cout << "Empty leaf at depth= " << depth << endl; 
+#endif      
+      emptyLeavesTraversed++;
+    }
+#endif // __TRAVERSAL_STATISTICS
+
+
+#ifdef _DEBUGKTB
+    cout << "Pop the node" << endl;
+#endif      
+    
+    // pop farChild from the stack
+    // restore the current values
+    entp = extp;
+    currNode = entp->nodep;
+#ifdef _DEBUGKTB
+#ifdef _KTBEXTSTACK
+    depth = entp->dummy;
+    cout << "Popped node at depth = " << depth << endl;
+#endif	  
+#endif
+
+    // DEBUG << "Pop c= " << currNode << "\n" << flush ;
+    if (currNode == NULL) {
+#ifdef _DEBUGKTB
+	cout << "NO HIT - EXIT " << endl; 
+#endif 	
+
+#ifdef __TRAVERSAL_STATISTICS
+	_allNodesTraversed += allNodesTraversed;
+	_fullLeavesTraversed += fullLeavesTraversed;
+	_emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+
+      // no objects found along the ray path
+      RestoreStackPointers();
+      return 0;
+    }
+    extp = extp->prev;
+  } // for(;;)
+} // FindNearestI
+
+#endif // TRV001
+
+#if defined(TRV000)||defined(TRV001)||defined(TRV002)||defined(TRV003)||defined(TRV004)||defined(TRV007)
+int
+CKTBTraversal::FindNearestI_16oneDir(SimpleRayContainer &rays)
+{
+  assert("NYI");
+}
+#endif
+
+#if defined(TRV000)||defined(TRV001)||defined(TRV002)||defined(TRV003)||defined(TRV004)||defined(TRV006)||defined(TRV007)||defined(TRV00F)
+int
+CKTBTraversal::FindNearestI_16twoDir(SimpleRayContainer &rays)
+{
+  assert("NYI");
+  return 0;
+}
+#endif
+
+#ifdef __SSE__
+#if defined(TRV000)||defined(TRV001)||defined(TRV002)||defined(TRV003)||defined(TRV004)||defined(TRV005)
+// The same operations for packets of rays, if implemented by
+// a particular ASDS, otherwise it is emulated by decomposition
+// of a packet to individual rays and traced individually.
+void
+CKTBTraversal::FindNearestI(RayPacket2x2 &raypack)
+{
+  for (int i = 0; i < 4; i++) {
+    cout << " orig = " << raypack.GetLoc(i) << " dir = "
+	 << raypack.GetDir(i) << endl;
+  }
+  // cout << "Not yet implemented" << endl;
+}
+#endif
+#endif // __SSE__
+ 
+} // namespace
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/subdivm.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/subdivm.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/subdivm.h	(revision 2582)
@@ -0,0 +1,36 @@
+// ===================================================================
+// $Id: subdivm.h $
+//
+// subdvim.h
+//      definition of subdivision modes for KD-trees
+//
+// Class:
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, 1999
+
+#ifndef __SUBDIVM_H__
+#define __SUBDIVM_H__
+
+// GOLEM headers
+#include "configh.h"
+
+namespace GtpVisibilityPreprocessor {
+
+// ------------------------------------------------------------------
+// The enumeration of subdivision modes for termination criteria
+// when the KD-tree construction should be stopped
+enum ESubdivMode
+{
+  // the termination criteria used at present
+  EE_SUBDIVADHOC = 0, // ad-hoc termination criteria are used, maximum height
+                      // and the number of objects in leaves
+  EE_SUBDIVCUTEMPTY = 1, // late cutting off empty space in leaves is performed
+  EE_SUBDIVAUTOMATIC = 2, // automatic termination criteria are used
+};
+
+}
+
+#endif //  __SUBDIVM_H__
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktball.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktball.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktball.h	(revision 2582)
@@ -0,0 +1,217 @@
+// ===================================================================
+// $Id: $
+//
+// ktball.h
+//      CKTB accelerating data structure for ray-shooting
+//
+// Class: CKTB
+//
+// REPLACEMENT_STRING
+//
+// Initial coding by Vlasta Havran
+
+#ifndef __KTBALL_H__
+#define __KTBALL_H__
+
+// GOLEM headers
+#include "configh.h"
+//#include "ktbi.h"
+#include "ktbai.h"
+#include "ktbtrav.h"
+#include "gzstream.h"
+
+namespace GtpVisibilityPreprocessor {
+
+// forward declarations
+class CKTBAllocMan;
+class RayPacket2x2;
+
+// ----------------------------------------------------------
+// ----------------------------------------------------------
+// ----------------------------------------------------------
+// the CASDS describing CKTB itself, the interface object to
+// the other objects for CKTB tree building up and traversing
+class CKTB
+//  : public CASDS_BB
+{
+protected:
+  // True if the data structure is built up
+  bool builtUp;
+  
+  // the box bounding the whole scene
+  AxisAlignedBox3 bbox;
+  
+  // the number of objects in the case the object list is
+  // not copied to this->objlist
+  int countObjects;
+
+  // precomputed cost for intersection of kd-tree with arbitrary ray
+  float _expectedIntersectionCost;
+  
+  // the class which serves as builder of CKTB tree
+  CKTBAllocManPredecessor *buildClass;
+
+  // the class that provides traversing through CKTB tree
+  CKTBNodeIteratorPredecessor *traversalClass;
+
+  // if we use min boxes enhancement
+  bool makeMinBoxes;
+  // if we want to make boxing with only tight boxes
+  bool makeTightMinBoxes;
+
+  // the size of 2D buffer
+  int size2D;
+  int index2D;
+  // the indices in the buffer
+  int indexRead, indexWrite;
+  // the distance between two rays, where a new buffer of box nodes is written
+  int distSLCTS;
+
+  // Whether we use SLCTS boxes for FindNearest
+  bool useSLCTS;
+  
+  // construct traversal class for CKTB Trees
+  void AllocTraversalClass();
+
+  // provide the parameters for construction of CKTB tree to stream
+  void ProvidePars(ostream &app);
+
+  // builds up CKTB tree without unbounded objects. The 'boxToInclude
+  // is a box that can be optionally given and the kd-tree constructed
+  // must contain such a box. The 'boxToBoundObjects' when given, is
+  // a box to which the objects boxes are bounded. This is used for special
+  // cases such a multilevel kd-trees.
+  void BuildingUp(ObjectContainer& objlist,
+		  const AxisAlignedBox3 *boxToInclude = 0,
+		  const AxisAlignedBox3 *boxToBoundObjects = 0,
+		  bool verbose = true);
+
+  // create the array of pointers to objects addressable by object uniqueID
+  void CreatePointerArray(ObjectContainer &arrobjlist,
+			  int objCounterOffset);
+
+  // checks the boxes of all objects if they are not flat somehow
+  bool CheckBoxes(ObjectContainer& objlist);  
+
+protected:
+  // statistics
+  int numElemCells;
+  int numEmptyElemCells;
+  float emptyVolume;
+  float nonEmptyVolume;
+  int numSolidsInElemCells;
+  int actMaxListLen;
+  int numHierCells;
+  int actMaxDepth;
+  float sumSurfaceAreaLeaves;
+  float sumSurfaceAreaMULcntLeaves;
+  float sumSurfaceAreaInteriorNodes;
+  
+public:
+  // default constructor
+  CKTB();
+
+  // default destructor
+  ~CKTB();
+
+  void BuildUp(const ObjectContainer &objlist);
+
+  // functions that allows correctly traverse recursively allowing to have
+  // the same traversal stack
+  void TraversalReset();
+
+  void StatsReset() {
+    if (traversalClass)
+      traversalClass->DynamicStatsReset();
+  }
+  
+  bool HandleUnboundeds() const { return true;}
+  
+  void GetBBox(AxisAlignedBox3 &box) { box = bbox;}
+    
+  void PrintStats();
+
+  // Delete all the data structures
+  void Remove();
+  
+  void ProvideID(ostream &app);
+  
+  float ExpectecteRayIntersectionCost() const {
+    return _expectedIntersectionCost;
+  }
+  
+  // describe the toplogy of CKTB to a given stream
+  void DescribeTopology(const string &filename,
+			int objCounterOffset,
+			int format) { }
+  
+  // Not yet implemented
+  bool RestoreTopology(const string &filename,
+		       long int streamOffset,
+		       const ObjectContainer &objects,
+		       int objCounterOffset,
+		       int format) { return true; }
+  
+  // allocate new build class and return it
+  static CKTBAllocManPredecessor* AllocBuildClass();
+  
+  CKTBNodeIteratorPredecessor* GetTraversalClass() {
+    return traversalClass;
+  }
+  
+  CKTBAllocManPredecessor* GetBuildClass() {
+    return buildClass;
+  }
+  void SetBuildClass(CKTBAllocManPredecessor *build) {
+    buildClass = build;
+  }
+  void DeleteBuildClass();
+  
+  // Here are the functions required from CASDS interface
+  void GatherStats(bool itself = false);
+  void GatherPostStats();
+  void* Locate(const Vector3 &loc);
+  
+  int FindNearestI(const SimpleRay &ray);
+  void SetOffset(int offset) { traversalClass->SetOffset(offset); }
+  int FindNearestI_16oneDir(SimpleRayContainer &rays) {
+    return traversalClass->FindNearestI_16oneDir(rays);
+  }
+  int FindNearestI_16oneDir(SimpleRayContainer &rays, int offset) {
+    return traversalClass->FindNearestI_16oneDir(rays, offset);
+  }
+  int FindNearestI_16twoDir(SimpleRayContainer &rays) {
+    return traversalClass->FindNearestI_16twoDir(rays);
+  }
+  
+#ifdef __SSE__
+  // The same operations for packets of rays, if implemented by
+  // a particular ASDS, otherwise it is emulated by decomposition
+  // of a packet to individual rays and traced individually.
+  void FindNearestI(RayPacket2x2 &raypack);
+  void FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax);
+#else
+  void FindNearestI(RayPacket2x2 &raypack) { }
+  void FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax) { }
+#endif // __SSE__
+
+  // Loading and saving
+  void ExportBinLeaf(OUT_STREAM &stream, SKTBNodeT *leaf);
+  SKTBNodeT* ImportBinLeaf(IN_STREAM &stream, 
+			   SKTBNodeT *parent,
+			   const ObjectContainer &objects);
+  void ExportBinInterior(OUT_STREAM &stream, SKTBNodeT *interior);
+  SKTBNodeT* ImportBinInterior(IN_STREAM  &stream,
+			       SKTBNodeT *parent);  
+  bool ExportBinTree(const string &filename);
+  
+protected:  
+  // The 2D array of pointers to the interior nodes with boxes.
+  SKTBNodeT ***buffer;
+  int sizeBuffer, size1D;
+  void AllocBuffer(int size2D, int size1Dv);
+};
+
+}
+
+#endif // __KTBALL_H__
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb8b.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb8b.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb8b.h	(revision 2582)
@@ -0,0 +1,372 @@
+// ===================================================================
+// $Id: $
+//
+// ktb.h
+//      definition of classes for CKTB tree building up and traversal
+//
+// Class: CKTBNodeAbstract, SKTBNode, CKTBAllocMan, CKTBNodeIterator
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, February 2007
+
+#ifndef __KTB8B_H__
+#define __KTB8B_H__
+
+// GOLEM headers
+#include "configh.h"
+#include "AxisAlignedBox3.h"
+#include "Intersectable.h"
+#include "Containers.h"
+#include "allocgo2.h"
+#include "ktbconf.h"
+#include "sbbox.h"
+#include "Ray.h"
+
+// standard headers
+#include <vector>
+
+
+namespace GtpVisibilityPreprocessor {
+
+// Forward declarations
+
+// Use 8 Bytes representation
+#undef  SKTBNodeT
+#define SKTBNodeT CKTB8BNodeAbstract::SKTBNode
+
+//===============================================
+// Representation of one node of CKTB
+class CKTB8BNodeAbstract
+{
+public:
+  // maximal height of the CKTB tree
+  enum { MAX_HEIGHT = 32, MaskForOffset = 0xFFFFFFF8 };
+
+  // the basic element of CKTB tree .. node of tree
+  // it must be accessible by more classes
+
+  // but must be declared because of compilation
+  struct SKTBNode {
+    // SKTBNode *left; // pointer to the left child is implict in DFS order
+    union {
+      // here is the compressed version of the axis
+      unsigned char *pointer;
+      unsigned int offset;
+      int depth;
+    };
+    union {
+      float splitPlane; // the position of splitting plane
+      ObjectContainer *objlist; // object list for a leaf or tagged interior node
+      Intersectable *object; // the pointer to the object, if only one object
+      SBBox     *encbox; // enclosing bounding box for this node
+      SBBox     *minbox; // minimum bounding box for this node
+      SKTBNodeT *linkedNode; // the linked node
+      SKTBNodeT *parentBoxNode; // the pointer to the same node type
+    };
+
+    bool IsLeaf() const {
+      return ( CKTBAxes::Axes(offset & CKTBAxes::EE_Mask) == CKTBAxes::EE_Leaf);
+    }
+    bool IsEmptyLeaf() const {
+      return (this == 0);
+    }
+  }; // struct SKTBNode
+
+public:
+
+  // It was _KTB_R2
+  // default constructor
+  CKTB8BNodeAbstract() { }
+  // default destructor
+  ~CKTB8BNodeAbstract() {}
+
+  bool IsEmptyLeaf_(const SKTBNodeT *p) const {
+    assert(( CKTBAxes::Axes(p->offset & CKTBAxes::EE_Mask) == CKTBAxes::EE_Leaf));
+    return (p->objlist == NULL);
+  }
+
+  bool IsFullLeaf_(const SKTBNodeT *p) const {
+    return (( CKTBAxes::Axes(p->offset & CKTBAxes::EE_Mask) == CKTBAxes::EE_Leaf) &&
+	    (p->objlist != NULL));
+  }
+  
+  bool IsLeaf_(const SKTBNodeT *p) const
+  { return ( CKTBAxes::Axes(p->offset & CKTBAxes::EE_Mask) == CKTBAxes::EE_Leaf); }
+  
+  bool HasMinBox_(const SKTBNodeT *p) const
+  { return (CKTBAxes::Axes(p->offset & CKTBAxes::EE_Mask) >= CKTBAxes::EE_X_axisBox); }
+
+  // ------------------------------------------------------
+  // Common functions for iterator and allocator
+
+  float GetSplitValue(const SKTBNodeT *nodep) const {
+    return nodep->splitPlane;
+  }
+  
+  CKTBAxes::Axes GetNodeType(const SKTBNodeT *nodep) const {
+    return (CKTBAxes::Axes)(nodep->offset & 0x7);
+  }
+  SKTBNodeT* GetLeft(const SKTBNode *nodep) const {
+    return (SKTBNodeT*)(nodep+1); // We assume linking in DFS order
+  }
+  SKTBNodeT* GetRight(const SKTBNodeT *nodep) const {
+    // We assume 8-Bytes aligned nodes in memory in 32-Bits environment
+    // This has to be checked during node linking.
+    return (SKTBNodeT*)(nodep->offset & MaskForOffset);
+  }
+
+  SKTBNodeT* GetLinkNode(const SKTBNodeT *nodep) const {
+    // We assume 8-Bytes aligned nodes in memory in 32-Bits environment
+    // This has to be checked during node linking.
+    return (SKTBNodeT*)(nodep->linkedNode);
+  }
+  // We assume linking in DFS order, this is for EncBox
+  SKTBNodeT* GetLeftLong(const SKTBNodeT *nodep) const {
+    return (SKTBNodeT*)(((char*)nodep) + 4*sizeof(SKTBNode)); 
+  }
+  SKTBNode* GetParentBoxNode(const SKTBNode *nodep) const {
+    return (SKTBNode*)(nodep+1)->parentBoxNode;
+  }
+  
+#ifdef _SHORT_FORM_MINBOX
+  SKTBNode* GetLeftMinBox(const SKTBNode *nodep) const {
+    return (SKTBNode*)(nodep+2);
+  }
+  int GetDepth(const SKTBNode * /*nodep*/) const {
+    return 0; // depth was not stored
+  }
+#else
+  SKTBNode* GetLeftMinBox(const SKTBNode *nodep) const {
+    return (SKTBNode*)(((char*)nodep) + 5*sizeof(SKTBNode)); 
+  }  
+  int GetDepth(const SKTBNode *nodep) const {
+    return (int)((nodep+1)->depth);
+  }
+#endif // _SHORT_FORM_MINBOX
+  
+}; // CKTBNodeAbstract
+
+//----------------------------------------------------------------
+// this class should be used as the base class for allocating
+// and connecting the nodes in the CKTB tree and for
+// for manipulating the nodes during building up
+class CKTB8BAllocMan:
+  public CKTB8BNodeAbstract
+{
+protected:
+#ifdef LEAVES_ARRAYS
+  CObjectArray arrayAlloc;
+#endif
+  
+  // init the stack of auxiliary variables from min to max
+  void InitAux(int min, int max, int maxItemsAtOnce);
+
+  // the direction of traversal through CKTB tree
+  enum EDirection { LEFT = 0, RIGHT = 1, NOWHERE = 2 };
+
+  //#ifdef _KTB_R2
+  SKTBNodeT* _AllocEmptyLeaf() {
+#ifdef _KTB_CONSTR_STATS
+    _stats_emptyLeftNodeCount++;
+#endif
+    return (SKTBNodeT*)0;
+  }
+protected:
+  // data required as the input parameter for construction of CKTB tree
+  int maxDepthAllowed; // maximal depth of CKTB tree
+  int maxListLength; // maximal list length of CKTB tree  
+public:
+  // default constructor
+  CKTB8BAllocMan() { InitForConstructor(); }
+
+  // default destructor
+  ~CKTB8BAllocMan() { }
+
+  // forget the content that is created by previous kd-tree construction
+  // or just init for the first use.
+  void InitForConstructor();
+
+  // the function, which reads the parameters from envinroment/commandline
+  void InitPars();
+
+  // -------------------------------------------------------
+  // allocate and free functions for SKTBNode
+  CAllocContinuous *alloc2; // the allocator saving space
+  SKTBNodeT *root; // this is the root node of the whole tree
+
+  // This is the node to return from the allocation functions
+  // Here it can be implemented some linking when DFS order allocation,
+  // so the node can be different than the representation of the real
+  // node with the information
+  SKTBNodeT *nodeToLink;
+
+  // Create the representation of the interior node
+  SKTBNodeT* AllocInteriorNode(int axis, float position,
+			       int cntLeft, int cntRight);
+
+  // Create the representation of the interior node with box, where box
+  // can be used during the traversal
+  SKTBNodeT* AllocInteriorNodeWithBox(int axis, float position,
+				      int cntLeft, int cntRight,
+				      const SBBox &tsbox, SKTBNodeT* prevMinBoxNode,
+				      int depthStore);
+  
+  // Create the representation of the node with the bounding box
+  SKTBNodeT* AllocEncBoxNode(const SBBox &sbox);
+
+  // Create the representation of the leaf. Note that possibly there
+  // can be special cases, such as 0, 1, 2, or 3 objects, or in general
+  // N objects.
+  SKTBNodeT* AllocLeaf(int cntObjects);
+
+  ObjectContainer* GetObjList(const SKTBNodeT *nodep) const {
+    return nodep->objlist;
+  }
+
+  // -------------------------------------------------------
+  // linking and setting functions for CKTB tree
+
+  // Set the pointers to children for the interior node
+  void SetInteriorNodeLinks(SKTBNodeT *node,
+			    SKTBNodeT *leftChild,
+			    SKTBNodeT *rightChild);
+
+  // Set the objects list to the leaf. The object list is used as it is
+  // ... it is not copied !!
+  int SetFullLeaf(SKTBNodeT *node, const ObjectContainer *objlist);
+
+  // -------------------------------------------------------
+  // inquiry functions for CKTB tree nodes for current node
+
+  // returns the pointer to the root node of tree
+  SKTBNodeT* GetRootNode() { return root;}
+
+  // postprocessing of CKTB tree after its initial construction
+  virtual void PostBuild();
+
+  // provides the information on the method used for CKTB tree
+  // and some setting parameters to given stream
+  virtual void ProvideID(ostream &app) = 0;
+  
+  // ---- Get Statistical Data ---------------------------------
+  void GetKTBTreeStats(int &nodes, int &leaves, int &emptyLeaves)
+  {
+#ifdef _KTB_CONSTR_STATS
+    nodes = _stats_interiorCount + _stats_bboxCount + _stats_minbboxCount +
+      + _stats_leafNodeCount + _stats_emptyLeftNodeCount;
+    leaves = _stats_leafNodeCount + _stats_emptyLeftNodeCount;
+    emptyLeaves = _stats_emptyLeftNodeCount;
+#endif
+  }
+
+  // constructs the CKTB tree for given objectlist and given bounding box
+  virtual SKTBNodeT* BuildUp(ObjectContainer &objlist,
+			     const AxisAlignedBox3 &box,
+			     bool verbose = true) = 0;
+
+  // deletes all the structure starting from the root node
+  virtual void Remove();
+
+  // The current depth in the tree
+  inline int GetDepth() const {return _currDepth;}
+  void IncDepth() {_currDepth++;}
+  void DecDepth() {_currDepth--;}
+
+  // --------------------------------------------------------------
+  // Statistics
+public:
+#ifdef _KTB_CONSTR_STATS
+  int _stats_interiorCount;
+  int _stats_bboxCount;
+  int _stats_minbboxCount;
+  int _stats_leafNodeCount;
+  int _stats_emptyLeftNodeCount;
+
+  // maximal depth of the currently built path during building up
+  int _maxDepth;  
+  // Sum of depths of leaf nodes (empty + full)
+  unsigned long int _sumLeafDepth;
+  // Sum of depths of empty leaves
+  unsigned long int _sumFullLeafDepth;
+  // The count of object references in leaves
+  unsigned long int _sumObjectRefCount;
+  // The maximum number of object references in a leaf
+  unsigned long int _maxObjectRefInLeaf;
+  // Surface area of leaves and interior nodes
+  float _sumSurfaceAreaLeaves;
+  float _sumSurfaceAreaMULcntLeaves;
+  float _sumSurfaceAreaInteriorNodes;
+#endif
+
+  // General statistics on the depth of current node
+  // the depth of the currently accessed node during building up
+  int _currDepth;
+};
+
+//------------------------------------------------------
+// class which enables to use some functions with direct
+// access to the members of the tree
+// traversal classes should be derived from this class
+class CKTB8BNodeIterator:
+  public CKTB8BNodeAbstract
+{
+protected:
+  int rayOffset;  
+public:
+  // default constructor
+  CKTB8BNodeIterator();
+  // default destructor
+  ~CKTB8BNodeIterator() { }
+
+  float GetSplitValue(const SKTBNodeT *nodep) const {
+    return nodep->splitPlane;
+  }
+    
+  ObjectContainer* GetObjList(const SKTBNodeT *nodep) const {
+    return nodep->objlist;
+  }
+  SBBox* GetEncBox(const SKTBNodeT *nodep) const {
+    // Here is the overlapping to save some memory !!! 
+    return (SBBox*)(((char*)nodep)+8);
+  }
+
+#ifdef _SHORT_FORM_MINBOX
+  SBBox* GetMinBox(const SKTBNodeT *nodep) const {
+    return (SBBox*)((nodep+1)->pointer);
+  }  
+#else // _SHORT_FORM_MINBOX
+  SBBox* GetMinBox(const SKTBNodeT *nodep) const {
+    // Here is the overlapping to save some memory !!! 
+    return (SBBox*)(((char*)nodep)+16);
+  }
+#endif // _SHORT_FORM_MINBOX
+  
+  // test the objects in the full leaf p and if finds the closest intersection
+  // with object so tmin<= t <= tmax, returns the pointer to that
+  // object, t is returned in tmax
+  int TestFullLeaf(const SimpleRay &ray, const SKTBNodeT *p);
+  int TestFullLeaf(const SimpleRay &ray, const SKTBNode *p, int rayIndex);
+
+  // test the objects in the full leaf and finds out any intersection
+  // in this case returns the pointer to the object, otherwise NULL
+  int HitAnyObj(const SimpleRay &ray, const SKTBNodeT *p);
+
+  // ------------------------------------------------------------------------
+  // Only abstract functions to simplify the interface
+
+  // this resets the nesting to start from the zero depth (root)
+  virtual void ResetTraversalDepth() = 0;
+
+  // sets the bbox and the root node for this traversal class
+  virtual void Setup(const AxisAlignedBox3 &box, SKTBNodeT *Nroot) = 0;
+
+  // Find a leaf or the minimum box containg a point.
+  virtual const SKTBNode* Locate(const Vector3& /*position*/);
+}; // class CKTBNodeIterator
+
+}
+
+#endif // __KTB8B_H__ 
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/timer.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/timer.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/timer.cpp	(revision 2582)
@@ -0,0 +1,228 @@
+// ===================================================================
+// $Id: timer.cpp,v $
+//
+// timer.cpp
+//     Timing for running process
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Windows time measuring added by Jaroslav Krivanek, October 2003.
+
+// GOLEM headers
+#include "timer.h"
+
+// ------------------------------------------------------
+// Use ftime instead of time, see > man ftime
+#define _USE_FTIME_CALL
+
+// standard headers
+#include <ctime>
+#ifdef __UNIX__
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#ifdef _USE_FTIME_CALL
+#include  <sys/timeb.h>
+#endif // _USE_FTIME_CALL
+
+#endif // __UNIX__
+#ifdef _MSC_VER
+#include <windows.h>
+#include <sys/types.h> 
+#include <sys/timeb.h>
+#endif // _MSC_VER
+
+namespace GtpVisibilityPreprocessor {
+
+
+// Staic variable
+bool
+CTimer::initTimingCalled = false;
+
+// The following are not static's in the CTimer class to prevent
+// #including <windows.h> into the "timer.h" header.
+#ifdef  _MSC_VER
+/// true if the performance timer works under windows
+static BOOL hasHRTimer;
+/// frequency of the performance timer under windows
+static LARGE_INTEGER hrFreq;
+#endif // MSC_VER
+
+void 
+CTimer::_initTiming()
+{
+#ifdef  _MSC_VER
+  hasHRTimer = QueryPerformanceFrequency(&hrFreq);
+#endif
+  initTimingCalled = true;
+}
+
+void
+CTimer::Reset()
+{
+  // Real times in seconds
+#ifdef _USE_FTIME_CALL
+  timeb beg;
+  ftime(&beg);
+  lastRealTime = (double)(beg.time + 0.001 * beg.millitm);  
+#else //  _USE_FTIME_CALL
+  time_t beg;
+  time(&beg);
+  lastRealTime = (double)beg;
+#endif // _USE_FTIME_CALL
+  
+  lastUserTime   = 0.0;
+  lastSystemTime = 0.0;
+
+  realTime   = 0.0;
+  userTime   = 0.0;
+  systemTime = 0.0;
+
+  countStop = 0;
+  running = false;
+
+#ifdef __UNIX__
+  // Timing in OS UNIX
+  begrusage.ru_utime.tv_usec = begrusage.ru_utime.tv_sec =
+  begrusage.ru_stime.tv_usec = begrusage.ru_stime.tv_sec = 0L;
+  endrusage = begrusage;
+#endif // __UNIX__
+}
+
+void
+CTimer::_start() const
+{
+  if (running)
+    return; // timer is already running
+
+  // Measure the real time
+#ifdef _USE_FTIME_CALL
+  timeb beg;
+  ftime(&beg);
+  lastRealTime = (double)(beg.time + 0.001 * beg.millitm);  
+#else //  _USE_FTIME_CALL
+  time_t beg;
+  time(&beg);
+  lastRealTime = (double)beg;
+#endif //  _USE_FTIME_CALL
+
+  // Measure the real and system time
+#ifdef __UNIX__
+  // Measure under UNIX
+  struct rusage begrusage;
+  getrusage(RUSAGE_SELF, &begrusage);
+
+  lastUserTime = (double)begrusage.ru_utime.tv_sec +
+	             1e-6 * begrusage.ru_utime.tv_usec;
+
+  lastSystemTime = (double)begrusage.ru_stime.tv_sec +
+		           1e-6 * begrusage.ru_stime.tv_usec;
+#endif // __UNIX__
+
+#ifdef  _MSC_VER
+  // Mesure under Windows
+  if (hasHRTimer) {
+    LARGE_INTEGER counter;
+    QueryPerformanceCounter(&counter);
+    lastUserTime = (double)counter.QuadPart / (double)hrFreq.QuadPart;
+    lastSystemTime = 0;	  
+  } 
+  else {
+    static struct _timeb mtime;
+    _ftime(&mtime);
+    lastUserTime   = (double)mtime.time + 1e-3 * mtime.millitm;
+    lastSystemTime = 0;
+  }
+#endif
+  // Begin trace.
+  running = true;
+}
+
+void
+CTimer::_stop() const
+{
+  if (!running)
+    return; // timer is not running
+  
+  // Begin trace.
+#ifdef _USE_FTIME_CALL
+  timeb end;
+  ftime(&end);
+  realTime += (double)(end.time + 0.001 * end.millitm) - lastRealTime;  
+#else //  _USE_FTIME_CALL
+  time_t end;
+  time(&end);
+  realTime += (double)end - lastRealTime;
+#endif //  _USE_FTIME_CALL
+
+#ifdef __UNIX__
+  // timing in unix OS
+  getrusage(RUSAGE_SELF, &endrusage);
+
+  userTime += (double)endrusage.ru_utime.tv_sec +
+	  1e-6 * endrusage.ru_utime.tv_usec -
+	  lastUserTime;
+
+  systemTime += (double)endrusage.ru_stime.tv_sec +
+	  1e-6 * endrusage.ru_stime.tv_usec -
+	  lastSystemTime;
+#endif // __UNIX__
+
+#ifdef  _MSC_VER
+  // Mesure under Windows
+  if (hasHRTimer) {
+    LARGE_INTEGER counter;
+    QueryPerformanceCounter(&counter);
+    userTime += (double)counter.QuadPart / (double)hrFreq.QuadPart - 
+      lastUserTime;
+    systemTime = 0;
+   } 
+  else {
+    static struct _timeb mtime;
+    _ftime(&mtime);
+    userTime   += (double)mtime.time + 1e-3 * mtime.millitm -
+      lastUserTime;
+    systemTime = 0;
+  }
+#endif
+
+  running = false;
+  countStop++;
+}
+
+// returns the real time measured by timer in seconds
+double
+CTimer::RealTime() const
+{
+  if (running) {
+    _stop();
+    _start();
+  }
+  return realTime;
+}
+
+// returns the user time measured by timer in seconds
+double
+CTimer::UserTime() const
+{
+  if (running) {
+    _stop();
+    _start();
+  }
+  return userTime;
+}
+
+// returns the user+system time measured by timer in seconds
+double
+CTimer::SystemTime() const
+{
+  if (running) {
+    _stop();
+    _start();
+  }
+  return systemTime;
+}
+
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb.cpp	(revision 2582)
@@ -0,0 +1,419 @@
+// ===================================================================
+// $Id: $
+//
+// ktb.cpp
+//
+//  Implementation of basic functions to create kd-trees
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2006 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, 1998-2001.
+
+// GOLEM library
+#include "ktb.h"
+#include "Environment.h"
+
+// standard headers
+#include <algorithm>
+
+namespace GtpVisibilityPreprocessor {
+
+
+//-------------------------------------------------------------
+// class CKTBNodeIterator .. implementation
+
+// test all objects in the leaf for intersection with ray
+// and returns the pointer to closest one if exists
+// and passing through parameter returns in tmax
+int
+CKTBNodeIterator::TestFullLeaf(const SimpleRay &ray, const SKTBNode *p)
+{
+  ObjectContainer *list = GetObjList(p);  
+  if (!list) // no object 
+    return 0;
+  ObjectContainer::iterator sc_end = list->end();
+
+  float tclosest = Limits::Infinity;
+  int intersected = 0;
+  // iterate the whole list and find out the nearest intersection
+  for (ObjectContainer::iterator sc = list->begin(); sc != sc_end; sc++) {
+    // if the intersection realy lies in the node        
+    if ((*sc)->CastSimpleRay(ray) == Ray::INTERSECTION) {
+      // update tclosest !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      // tclosest = ray.
+      intersected = 1;
+    }
+  } // for all objects
+
+  return intersected;
+}
+
+int
+CKTBNodeIterator::TestFullLeaf(const SimpleRay &ray, const SKTBNode *p,
+			       int rayIndex)
+{
+  ObjectContainer *list = GetObjList(p);  
+  if (!list) // no object 
+    return 0;
+  ObjectContainer::iterator sc_end = list->end();
+
+  float tclosest = Limits::Infinity;
+  int intersected = 0;
+  // iterate the whole list and find out the nearest intersection
+  for (ObjectContainer::iterator sc = list->begin(); sc != sc_end; sc++) {
+    // if the intersection realy lies in the node        
+    if ((*sc)->CastSimpleRay(ray, rayIndex)) {
+      // update tclosest !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      // tclosest = ray.
+      intersected = 1;
+    }
+  } // for all objects
+
+  return intersected;
+}
+
+  
+// test all objects in the leaf for intersection with ray
+// and find any if exist .. returns this object, otherwise 0
+int
+CKTBNodeIterator::HitAnyObj(const SimpleRay &ray, const SKTBNode *p)
+{
+  ObjectContainer *list = GetObjList(p);  
+  if (!list) // no object 
+    return 0;
+  ObjectContainer::iterator sc_end = list->end();
+
+  float tclosest = Limits::Infinity;
+  int intersected = 0;
+  // iterate the whole list and find out the nearest intersection
+  for (ObjectContainer::iterator sc = list->begin(); sc != sc_end; sc++) {
+    Intersectable *is = (*sc);
+    // if the intersection realy lies in the node        
+    if (is->CastSimpleRay(ray)) {
+      // update tclosest !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      // tclosest = ray.
+      return 1; // intersected
+    }
+  } // for all objects
+
+  return 0;
+}
+
+const CKTBNodeAbstract::SKTBNode*
+CKTBNodeIterator::Locate(const Vector3 & /*position*/)
+{
+  cerr << "Locate vector - Not yet implemented" << endl;
+  return (SKTBNode*)0;
+}
+
+// ---------------------------------------------------------------------
+// Allocator for KTB tree
+
+// forget the content that is created by previous kd-tree construction
+// or just init for the first use.
+void
+CKTBAllocMan::InitForConstructor()
+{
+#ifdef _KTB_CONSTR_STATS
+  _stats_interiorCount = 0;
+  _stats_bboxCount = 0;
+  _stats_minbboxCount = 0;
+  _stats_leafNodeCount = 0;
+  _stats_emptyLeftNodeCount = 0;
+  // Aggregate statistics
+  _sumLeafDepth = 0;
+  _sumFullLeafDepth = 0;
+  // The count of object references in leaves
+  _sumObjectRefCount = 0;
+  // The maximum number of object references in a leaf
+  _maxObjectRefInLeaf = 0;
+  // surface areas
+  _sumSurfaceAreaLeaves = 0.f;
+  _sumSurfaceAreaMULcntLeaves = 0.f;
+  _sumSurfaceAreaInteriorNodes = 0.f;
+#endif
+  
+  // This is the statistics
+  _currDepth = 0;
+  _maxDepth = -1;
+  InitPars();
+}
+
+// init the stack of auxiliary variables from min to max
+void
+CKTBAllocMan::InitAux(int /*min*/, int /*maxD*/, int maxItemsAtOnce)
+{
+  // The size of one entry
+  int sizeEntryV = sizeof(SKTBNode);
+  // The number of entries to be allocated at once in a block
+  // (=size of the block)
+  int numEntriesInBlock = 1024;
+  // the allignment
+  int allignEntrySizeV = sizeof(SKTBNode);
+  int allignBlockSizeV = 128;
+
+  // Create an allocator in DFS order
+  alloc2 = new CAllocContinuous(sizeEntryV, numEntriesInBlock,
+				maxItemsAtOnce,
+				allignEntrySizeV,
+			        allignBlockSizeV);
+  assert(alloc2);
+  // the first allocation is enabled by this command
+  alloc2->AllocNewBlock();
+  return;
+}
+
+// Read some basic parameters from the environment file
+void
+CKTBAllocMan::InitPars()
+{
+  Environment::GetSingleton()->GetIntValue("BSP.maxDepthAllowed",
+					   maxDepthAllowed);
+  Environment::GetSingleton()->GetIntValue("BSP.maxListLength",
+					   maxListLength);
+}
+
+void
+CKTBAllocMan::PostBuild()
+{
+  // Here it can be some postprocessing of the tree, such as branches
+  // collapsing for the same content of leaves etc.
+}
+
+void
+CKTBAllocMan::Remove()
+{
+  // Release the all memory by blocks, so all the interior nodes
+  // and leaves representations. This should be fast.
+  alloc2->ReleaseMemory();
+}
+
+
+// Create the representation of the interior node
+SKTBNodeT*
+CKTBAllocMan::AllocInteriorNode(int axis, float position,
+				int cntLeft, int cntRight)
+{
+#ifdef _DEBUG
+  nodeToLink = 0;
+#endif
+
+#ifdef _KTB_CONSTR_STATS
+  _stats_interiorCount++;
+#endif
+  
+  // Just to satisfy the compiler
+  cntLeft = cntLeft;
+  cntRight = cntRight;
+  
+  // Alloc a single node
+  SKTBNodeT *n = (SKTBNodeT*)(alloc2->New(1));
+  nodeToLink = n;
+  if (n == 0) {
+    // we have to insert a special node that links only
+    nodeToLink = (SKTBNodeT*)alloc2->NewLastEntry(1);
+    assert(nodeToLink);
+    nodeToLink->nodeType = CKTBAxes::EE_Link;
+    n = (SKTBNodeT*)(alloc2->NewEntryInNewBlock(1));
+    // This is the link
+    nodeToLink->right = n;    
+  } // if n
+
+  assert(n);
+  assert(nodeToLink);
+
+  // Set the interior node
+  assert((axis >=0) && (axis < 3));
+  n->nodeType = (CKTBAxes::Axes)axis;
+  n->splitPlane = position;
+
+  // Return the setupped node, but do not forget to
+  // use in the parent node to use nodeToLink !!!!
+  return n;
+}
+
+// Create the representation of the interior node
+SKTBNodeT*
+CKTBAllocMan::AllocInteriorNodeWithBox(int axis, float position,
+				       int cntLeft, int cntRight,
+				       const SBBox &tsbox,
+				       SKTBNodeT* prevMinBoxNode,
+				       int depthStore)
+{
+#ifdef _DEBUG
+  nodeToLink = 0;
+  if ( (position < tsbox.Min(axis)) ||
+    (position > tsbox.Max(axis)) ) {
+    cerr << "Something wrong with the tree axis = " << axis;
+    cerr << " Min(axis) = " << tsbox.Min(axis)
+	  << " splitValue = " << position
+	  << " Max(axis) = " << tsbox.Max(axis) << endl;
+    abort();
+  }
+#endif
+
+#ifdef _KTB_CONSTR_STATS
+  _stats_interiorCount++;
+#endif
+  
+  // Just to satisfy the compiler
+  cntLeft = cntLeft;
+  cntRight = cntRight;
+
+#ifdef _SHORT_FORM_MINBOX
+  // Alloc a single node + node to store the pointer to box, in total 24 Bytes
+  SKTBNodeT *n = (SKTBNodeT*)(alloc2->New(2));
+  nodeToLink = n;
+  if (n == 0) {
+    // we have to insert a special node that links only
+    nodeToLink = (SKTBNodeT*)alloc2->NewLastEntry(1);
+    assert(nodeToLink);
+    nodeToLink->nodeType = CKTBAxes::EE_Link;
+    n = (SKTBNodeT*)(alloc2->NewEntryInNewBlock(2));
+    // This is the link
+    nodeToLink->right = n;    
+  } // if n
+
+  assert(n);
+  assert(nodeToLink);
+
+  // Set the interior node
+  assert((axis >=0) && (axis < 3));
+  n->nodeType = (CKTBAxes::Axes)(axis + (int)CKTBAxes::EE_X_axisBox);
+  n->splitPlane = position;
+
+  // Set the box itself
+  // the address to the parent min box node
+  (n+1)->parentBoxNode = prevMinBoxNode;
+
+  // Here we simply allocate box to the address in the node
+  SBBox *badr = new SBBox;
+  assert(badr);
+  (n+1)->minbox = badr;
+  // and store the depth for debugging
+  (n+1)->nodeType = CKTBAxes::Axes(depthStore);
+  
+#else // _SHORT_FORM_MINBOX
+  // Alloc two single nodes (24 Bytes) + two nodes for box (24 Bytes) = 48 Bytes
+  SKTBNodeT *n = (SKTBNodeT*)(alloc2->New(4));
+  nodeToLink = n;
+  if (n == 0) {
+    // we have to insert a special node that links only
+    nodeToLink = (SKTBNodeT*)alloc2->NewLastEntry(1);
+    assert(nodeToLink);
+    nodeToLink->nodeType = CKTBAxes::EE_Link;
+    n = (SKTBNodeT*)(alloc2->NewEntryInNewBlock(4));
+    // This is the link
+    nodeToLink->right = n;    
+  } // if n
+
+  assert(n);
+  assert(nodeToLink);
+
+  // Set the interior node
+  assert((axis >=0) && (axis < 3));
+  n->nodeType = (CKTBAxes::Axes)(axis + (int)CKTBAxes::EE_X_axisBox);
+  n->splitPlane = position;
+
+  // Set the min box node itself
+
+  // the address to the parent min box node
+  (n+1)->parentBoxNode = prevMinBoxNode;
+  // and store the depth for debugging
+  (n+1)->nodeType = CKTBAxes::Axes(depthStore);
+  (n+1)->minbox = 0; // only to make it zero for debugging
+  
+  // Here we simply allign to 48 Bytes, since we have one node of size 12 Bytes,
+  // and SBBox takes 24 Bytes, so we just want to align to the boundary of 8 Bytes.
+  SBBox *badr = (SBBox*)(((char*)n)+24);  
+#endif // _SHORT_FORM_MINBOX
+
+  // and copy the box content
+  *(badr) = tsbox;
+    
+  // Return the set node, but do not forget to
+  // use in the parent node to use nodeToLink !!!!
+  return n;
+}
+
+// Set the pointers to children for the interior node
+void
+CKTBAllocMan::SetInteriorNodeLinks(SKTBNodeT *node,
+				   SKTBNodeT *leftChild,
+				   SKTBNodeT *rightChild)
+{
+  leftChild = leftChild; // to satisfy the compiler
+
+  // Check on correctness of DFS order
+  assert( (node+1 == leftChild) || (node+2 == leftChild) || (node+4 == leftChild) );
+  
+  node->right = rightChild;
+}
+
+// Create the representation of the leaf. Note that possibly there
+// can be special cases, such as 0, 1, 2, or 3 objects, or in general
+// N objects.
+SKTBNodeT*
+CKTBAllocMan::AllocLeaf(int cntObjects)
+{
+#ifdef _DEBUG
+  nodeToLink = 0;
+#endif
+
+#ifdef _KTB_CONSTR_STATS
+  _stats_leafNodeCount++;
+  _sumLeafDepth += _currDepth;
+  if (cntObjects) {
+    _sumFullLeafDepth += _currDepth;
+    // The count of object references in leaves
+    _sumObjectRefCount += cntObjects;
+    // The maximum number of object references in a leaf
+    if (cntObjects > _maxObjectRefInLeaf)
+      _maxObjectRefInLeaf = cntObjects;
+  }
+  else
+    _stats_emptyLeftNodeCount++;
+#endif
+  
+  // Alloc a single node
+  SKTBNodeT *n = (SKTBNodeT*)(alloc2->New(1));
+  nodeToLink = n;
+  if (n == 0) {
+    // we have to insert a special node that links only
+    n = nodeToLink = (SKTBNodeT*)alloc2->NewLastEntry(1);
+    assert(nodeToLink);
+    // Allocate a new block for the next allocation
+    alloc2->AllocNewBlock();
+  } // if n
+
+  n->nodeType = CKTBAxes::EE_Leaf;
+  n->objlist = 0;
+  n->right = 0;
+  
+  // Return the node
+  return n;
+}
+
+// if active node is empty, then is replaced by full leaf with
+// the object list. In success returns 0, for failure returns 1.
+// The object list is used as it is .. it is not copied !!
+int
+CKTBAllocMan::SetFullLeaf(SKTBNodeT *node, const ObjectContainer *objlist)
+{
+  assert(node);
+  assert(node->nodeType == CKTBAxes::EE_Leaf);
+
+  if ( (objlist == NULL) ||
+       (objlist->size() == 0) ) {
+    node->objlist = 0;
+  }
+  else {
+    // Set the pointer to the list of objects
+    node->objlist = (ObjectContainer *)objlist;
+  }
+
+  return 0;
+}
+
+} // namespace
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/sbbox.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/sbbox.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/sbbox.h	(revision 2582)
@@ -0,0 +1,429 @@
+// ===================================================================
+// $Id: sbbox.h $
+//
+// sbbox.h
+//
+// Class: SBBox
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, December 2005
+
+#ifndef __SBBOX_H__
+#define __SBBOX_H__
+
+// ANSI C++ headers
+#include <cassert>
+#include <iostream>
+#include <ostream>
+
+// GOLEM headers
+#include "configh.h"
+#include "common.h"
+#include "AxisAlignedBox3.h"
+#include "SimpleRay.h"
+#include "Vector3.h"
+
+namespace GtpVisibilityPreprocessor {
+
+// Forward declarations
+
+// --------------------------------------------------------
+// The definition of the bounding box having 24 Bytes only
+struct SBBox
+{
+public:
+  SBBox() {}
+  SBBox(const Vector3 &a, const Vector3 &b) {
+    pp[0] = a; pp[1] = b;
+  }
+  // member functions
+  const Vector3& Min() const { return pp[0]; }
+  const Vector3& Max() const { return pp[1]; }
+  Vector3& Min() { return pp[0]; }
+  Vector3& Max() { return pp[1]; }
+  const float& Min(int i) const { return pp[0][i]; }
+  const float& Max(int i) const { return pp[1][i]; }
+  float& Min(int i) { return pp[0][i]; }
+  float& Max(int i) { return pp[1][i]; }
+
+  // Access to individual components, maybe it is not a good idea
+  const float& MinX() const { return pp[0].x; }
+  const float& MaxX() const { return pp[1].x; }
+  float& MinX() { return pp[0].x; }
+  float& MaxX() { return pp[1].x; }
+  const float& MinY() const { return pp[0].y; }
+  const float& MaxY() const { return pp[1].y; }
+  float& MinY() { return pp[0].y; }
+  float& MaxY() { return pp[1].y; }
+  const float& MinZ() const { return pp[0].z; }
+  const float& MaxZ() const { return pp[1].z; }
+  float& MinZ() { return pp[0].z; }
+  float& MaxZ() { return pp[1].z; }
+
+  void SetMin(float x, float y, float z) {
+    pp[0].x=x; pp[0].y=y; pp[0].z=z; }
+  void SetMax(float x, float y, float z) {
+    pp[1].x=x; pp[1].y=y; pp[1].z=z; }
+
+  // initialization to the non existing bounding box
+  inline void Initialize() {
+    pp[0] = Vector3(MAXFLOAT);
+    pp[1] = Vector3(-MAXFLOAT);
+  }
+  inline void Convert(const AxisAlignedBox3 &b) {
+    pp[0] = b.Min();
+    pp[1] = b.Max();
+  }
+  Vector3 Diagonal() const { return pp[1] - pp[0];}
+
+  // Compute the center of the box
+  void ComputeCentroid(Vector3 &c) const {
+    c.x = (pp[0].x + pp[1].x)*0.5f;
+    c.y = (pp[0].y + pp[1].y)*0.5f;
+    c.z = (pp[0].z + pp[1].z)*0.5f;
+  }
+
+  // Compute half of surface area of the box
+  float SA2() const {
+    float t1 = (pp[1].x-pp[0].x);
+    float t2 = (pp[1].y-pp[0].y);
+    float t3 = (pp[1].z-pp[0].z);
+    return t1*t2 + t2*t3 + t1*t3;
+  }
+  // Compute volume of the box
+  float GetVolume() const {
+    return (pp[1].x-pp[0].x)*(pp[1].y-pp[0].y)*(pp[1].z-pp[0].z);
+  }
+  
+  void SetMin(int axis, const float value) {
+    pp[0][axis] = value;
+  }
+  void SetMax(int axis, const float value) {
+    pp[1][axis] = value;
+  }
+  // Write acess to min and max
+  void SetMin(const Vector3& bmin) { pp[0] = bmin;}
+  void SetMax(const Vector3& bmax) { pp[1] = bmax;}
+  
+  // Decrease box by given splitting plane
+  void Reduce(int axis, int right, float value) {
+    if ( (value >= pp[0][axis]) && (value <= pp[1][axis]) ) {
+      if (right)
+        pp[0][axis] = value;
+      else
+        pp[1][axis] = value;
+    }
+  }
+  inline void Include(const AxisAlignedBox3 &bbox);
+  inline void Include(const SBBox  &bbox);
+  inline bool RayIntersect(const SimpleRay &r,
+			   float &tmin,
+			   float &tmax) const;
+
+  inline void ComputeMaxT(const SimpleRay &r,
+			  float &tmax) const;
+  inline void ComputeMinT(const SimpleRay &r,
+			  float &tmin) const;
+  
+  // Query functions
+
+  // Includes returns true if this box includes box b (completely)
+  bool Includes(const SBBox &b) const;
+  bool Includes(const SBBox &b, float eps) const;
+
+  // Returns false if the box 'b' is fully contained in 'this', see the code
+  inline bool ExcludesPartially(const SBBox &b) const;
+
+  // Returs true if this box includes a point
+  inline bool Includes(const Vector3 &vec) const;
+
+  // Includes returns true if this box includes box b including boundary
+  inline bool IncludesS(const Vector3 &vec) const;
+
+  inline bool IncludesS(const Vector3 &vec, float eps) const;
+
+  inline bool Equal(const SBBox &b, float eps = 0.f) const;
+    
+  // Test if the box is really sensefull
+  bool IsCorrect();
+
+  // Overlap returns 1 if the two axis-aligned boxes overlap .. only strongly
+  friend inline bool OverlapS(const SBBox &, const SBBox &);
+  
+protected:
+  // pp[0] is minimum, pp[1] is maximum
+  Vector3 pp[2];
+};
+
+// --------------------------------------------------------
+// Inline functions
+
+inline void
+SBBox::Include(const AxisAlignedBox3 &bbox)
+{
+  Minimize(pp[0], bbox.Min());
+  Maximize(pp[1], bbox.Max());
+}
+
+inline void
+SBBox::Include(const SBBox &bbox)
+{
+  Minimize(pp[0], bbox.pp[0]);
+  Maximize(pp[1], bbox.pp[1]);
+}
+
+inline bool
+SBBox::Equal(const SBBox &b, float eps) const
+{
+  if ( (!EpsilonEqual(pp[0].x, b.pp[0].x, eps)) ||
+       (!EpsilonEqual(pp[0].y, b.pp[0].y, eps)) ||
+       (!EpsilonEqual(pp[0].z, b.pp[0].z, eps)) ||
+       (!EpsilonEqual(pp[1].x, b.pp[1].x, eps)) ||
+       (!EpsilonEqual(pp[1].y, b.pp[1].y, eps)) ||
+       (!EpsilonEqual(pp[1].z, b.pp[1].z, eps)) )
+    return false; // they are not equal
+  return true;
+}
+
+inline bool
+SBBox::IsCorrect()
+{
+  if ( (pp[0].x > pp[1].x) ||
+       (pp[0].y > pp[1].y) ||
+       (pp[0].z > pp[1].z) )
+    return false; // box is not formed
+  return true;
+}
+
+inline bool
+OverlapS(const SBBox &x, const SBBox &y)
+{
+  if (x.pp[1].x <= y.pp[0].x ||
+      x.pp[0].x >= y.pp[1].x ||
+      x.pp[1].y <= y.pp[0].y ||
+      x.pp[0].y >= y.pp[1].y ||
+      x.pp[1].z <= y.pp[0].z ||
+      x.pp[0].z >= y.pp[1].z) {
+    return false;
+  }
+  return true;
+}
+
+// Returns true if the boxes are either disjoint or only
+// share a single face !
+inline bool
+SBBox::ExcludesPartially(const SBBox &b) const
+{
+  if (b.pp[1].x <= pp[0].x ||
+      b.pp[1].y <= pp[0].y ||
+      b.pp[1].z <= pp[0].z ||
+      b.pp[0].x >= pp[1].x ||
+      b.pp[0].y >= pp[1].y ||
+      b.pp[0].z >= pp[1].z)
+    // box 'b' is not fully contained in 'this', also true when neighboring faces
+    return true; 
+  return false; // box 'b' contained in this box
+}
+
+inline bool
+SBBox::Includes(const Vector3 &vec) const
+{
+  if (vec.x < pp[0].x ||
+      vec.x > pp[1].x ||
+      vec.y < pp[0].y ||
+      vec.y > pp[1].y ||
+      vec.z < pp[0].z ||
+      vec.z > pp[1].z) {
+    return false;
+  }
+  return true;
+}
+
+inline bool
+SBBox::IncludesS(const Vector3 &vec) const
+{
+  if (vec.x <= pp[0].x ||
+      vec.x >= pp[1].x ||
+      vec.y <= pp[0].y ||
+      vec.y >= pp[1].y ||
+      vec.z <= pp[0].z ||
+      vec.z >= pp[1].z) {
+    return false;
+  }
+  return true;
+}
+
+inline bool
+SBBox::IncludesS(const Vector3 &vec, float eps) const
+{
+  if (vec.x <= (pp[0].x-eps) ||
+      vec.x >= (pp[1].x+eps) ||
+      vec.y <= (pp[0].y-eps) ||
+      vec.y >= (pp[1].y+eps) ||
+      vec.z <= (pp[0].z-eps) ||
+      vec.z >= (pp[1].z+eps) ) {
+    return false; // outside
+  }
+  return true; // point inside
+}
+
+// Function describing the box
+extern void
+Describe(const SBBox &b, std::ostream &app, int indent);
+
+// Function describing the box
+extern void
+DescribeXYZ(const SBBox &b, std::ostream &app, int indent);
+
+#if 1
+// The implementation I, the first version implemented by Vlastimil
+// Havran, without looking into the literature
+inline bool
+SBBox::RayIntersect(const SimpleRay &ray,
+		    float &tmin, float &tmax) const
+{
+   float interval_min = tmin;
+   float interval_max = tmax;
+
+   const Vector3 &rayLoc = ray.mOrigin;
+   const Vector3 &rayDir = ray.mDirection;
+   
+   float t0, t1;
+   if (rayDir.x > 0) {
+     t0 = (pp[0].x - rayLoc.x) / rayDir.x;
+     t1 = (pp[1].x - rayLoc.x) / rayDir.x;
+   }
+   else {
+     t0 = (pp[1].x - rayLoc.x) / rayDir.x;
+     t1 = (pp[0].x - rayLoc.x) / rayDir.x;
+   }
+   assert(t0 <= t1);     
+   if (t0 > interval_min)
+     interval_min = t0;
+   if (t1 < interval_max)
+     interval_max = t1;
+   if (interval_min > interval_max)
+     return false;
+
+   if (rayDir.y > 0) {
+     t0 = (pp[0].y - rayLoc.y) / rayDir.y;
+     t1 = (pp[1].y - rayLoc.y) / rayDir.y;
+   }
+   else {
+     t0 = (pp[1].y - rayLoc.y) / rayDir.y;
+     t1 = (pp[0].y - rayLoc.y) / rayDir.y;
+   }
+   assert(t0 <= t1);     
+   if (t0 > interval_min)
+     interval_min = t0;
+   if (t1 < interval_max)
+     interval_max = t1;
+   if (interval_min > interval_max)
+     return false;
+
+   if (rayDir.z > 0) {
+     t0 = (pp[0].z - rayLoc.z) / rayDir.z;
+     t1 = (pp[1].z - rayLoc.z) / rayDir.z;
+   }
+   else {
+     t0 = (pp[1].z - rayLoc.z) / rayDir.z;
+     t1 = (pp[0].z - rayLoc.z) / rayDir.z;
+   }
+   assert(t0 <= t1);     
+   if (t0 > interval_min)
+     interval_min = t0;
+   if (t1 < interval_max)
+     interval_max = t1;
+
+   // return true if the box is intersected
+   // return false if not intersected by ray
+   if ( (interval_max > 0.0f) &&
+	(interval_min <= interval_max) ) {
+     // yes, intersected, update tmin and tmax for current node
+     tmin = interval_min;
+     tmax = interval_max;
+     return true; // intersected
+   }
+   return false; // not intersected
+}
+#endif
+
+#if 1
+// Here we compute exit signed distance along the ray
+// from the box
+inline void
+SBBox::ComputeMaxT(const SimpleRay &ray,
+		   float &tmax) const
+{
+  float interval_max = tmax;
+
+  const Vector3 &rayLoc = ray.mOrigin;
+  const Vector3 &rayDir = ray.mDirection;
+  
+  float t;
+  assert(pp[1].x >= pp[0].x);
+  if (rayDir.x > 0)
+    t = (pp[1].x - rayLoc.x) / rayDir.x;
+  else
+    t = (pp[0].x - rayLoc.x) / rayDir.x;
+  if (t > interval_max)
+    interval_max = t;
+  assert(pp[1].y >= pp[0].y);
+  if (rayDir.y > 0)
+    t = (pp[1].y - rayLoc.y) / rayDir.y;
+  else
+    t = (pp[0].y - rayLoc.y) / rayDir.y;
+  if (t > interval_max)
+    interval_max = t;
+  assert(pp[1].z >= pp[0].z);
+  if (rayDir.z > 0)
+    t = (pp[1].z - rayLoc.z) / rayDir.z;
+  else
+    t = (pp[0].z - rayLoc.z) / rayDir.z;
+  if (t > interval_max)
+    interval_max = t;
+}
+#endif
+
+#if 1
+// Here we compute entry signed distance along the ray
+// into the box
+inline void
+SBBox::ComputeMinT(const SimpleRay &ray,
+		   float &tmin) const
+{
+  float interval_min = tmin;
+
+  const Vector3 &rayLoc = ray.mOrigin;
+  const Vector3 &rayDir = ray.mDirection;
+  
+  float t;
+  assert(pp[1].x >= pp[0].x);
+  if (rayDir.x > 0)
+    t = (pp[0].x - rayLoc.x) / rayDir.x;
+  else
+    t = (pp[1].x - rayLoc.x) / rayDir.x;
+  if (t < interval_min)
+    interval_min = t;
+  assert(pp[1].y >= pp[0].y);
+  if (rayDir.y > 0)
+    t = (pp[0].y - rayLoc.y) / rayDir.y;
+  else
+    t = (pp[1].y - rayLoc.y) / rayDir.y;
+  if (t < interval_min)
+    interval_min = t;
+  assert(pp[1].z >= pp[0].z);
+  if (rayDir.z > 0)
+    t = (pp[0].z - rayLoc.z) / rayDir.z;
+  else
+    t = (pp[1].z - rayLoc.z) / rayDir.z;
+  if (t < interval_min)
+    interval_min = t;
+}
+#endif
+
+}
+
+#endif // __SBBOX_H__
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/configh.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/configh.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/configh.h	(revision 2582)
@@ -0,0 +1,91 @@
+// ================================================================
+// $Id: configh.h $
+//
+// configh.h
+//
+//      Global configuration things for header files.
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2006 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlastimil Havran, 2000.
+
+#ifndef __CONFIGH_H__
+#define __CONFIGH_H__
+
+#ifndef USE_GOLEM_NAMESPACE
+// without namespaces
+#define  __BEGIN_GOLEM_HEADER
+#define  __END_GOLEM_HEADER
+#else
+// with namespace 
+#define NAMESPACEDEF     GOLEMLIB
+// use of namespace commands inside the library sources
+#define  __BEGIN_GOLEM_HEADER namespace NAMESPACEDEF { using namespace NAMESPACEDEF;
+#define  __END_GOLEM_HEADER
+#endif
+
+
+__BEGIN_GOLEM_HEADER
+
+// definition of numeric data types in the library
+
+// floating point type (min. 4 bytes, IEEE754 single)
+typedef float float4;
+// floating point type (min.  8 bytes, IEEE754 double)
+typedef double float8;
+// floating point type (min. 12 bytes, IEEE854 extended)
+typedef long double float12;
+
+// unsigned byte type (exactly 1 byte)
+typedef unsigned char byte;
+// unsigned integer type (min. 1 byte)
+typedef unsigned char uint1;
+// signed integer type (min. 1 byte)
+typedef signed char int1;
+
+// unsigned integer type (min. 2 bytes)
+typedef unsigned short int uint2;
+// signed integer type (min. 2 bytes)
+typedef signed short int int2;
+
+// unsigned integer type (min. 4 bytes)
+typedef unsigned int uint4;
+// signed integer type (min. 4 bytes)
+typedef signed int int4;
+
+// signed integer type (min. 8 bytes)
+// -- see file int8.h
+
+#ifdef _MSC_VER
+// disable some Microsoft Visual Compiler warnings if necessary
+#pragma warning( disable:4305 )
+#pragma warning( disable:4786 )
+#pragma warning( disable:4800 )
+#pragma warning( disable:4244 )
+#ifdef min
+#undef min
+#endif
+#ifdef max
+#undef max
+#endif
+#ifdef ERROR
+#undef ERROR
+#endif
+#ifdef GetObject
+#undef GetObject
+#endif
+#endif // _MSC_VER
+ 
+#ifndef _EXPORT_
+#if defined(_MSC_VER)
+#define _EXPORT_  __declspec(dllexport)
+#else
+#define _EXPORT_ 
+#endif
+#endif
+ 
+__END_GOLEM_HEADER
+
+#endif // __CONFIGH_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbtrav.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbtrav.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbtrav.h	(revision 2582)
@@ -0,0 +1,454 @@
+// ===================================================================
+// $Id: $
+//
+// ktbtrav.h
+//      Traversal class for CKTB structures
+//
+// Class: CKTBTraversal
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, 2006
+
+#ifndef __KTBTRAV_H__
+#define __KTBTRAV_H__
+
+// GOLEM headers
+#include "configh.h"
+#include "ktbconf.h"
+#include "ktb.h"
+#include "ktb8b.h"
+#include "raypack.h"
+// From the framework of Jiri Bittner et al. GTP
+#include "SimpleRay.h"
+
+
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+namespace GtpVisibilityPreprocessor {
+
+class RayPacket2x2;
+  
+//#define TRV000
+//#define TRV001
+//#define TRV002
+//#define TRV003
+//#define TRV004
+//#define TRV005
+//#define TRV006
+//#define TRV007
+#define TRV00F
+
+// forward declarations
+class SKTBNode;
+
+// This is debugging of traversal for a new traversal variant
+//#define _DEBUGKTB
+
+// This is debugging of traversal storing depth at the stack
+//#define _KTBEXTSTACK
+  
+// VERSION1 - the version, where we prepare a sequence of boxes
+//            which never overlap (file ktbmtrav.cpp)
+// VERSION2 - the sequence of boxes can overlap and we solve which
+//            boxes to traverse online during the traversal (file ktbm2trv.cpp)
+// VERSION3 - the stackless algorithm based on interval tracking
+//            keeping entry and exit point (file ktbm3trv.cpp)
+// VERSION4 - the stack-based algorithm rewritten from ktbm3trv.cpp
+//            by adding the stack (file ktbm4trv.cpp)
+// VERSION5 - another stackless algorithm based on a single point and
+//            virtual box tracking (file ktbm5trv.cpp)
+// VERSION6 - simple sequential traversal algorithm without stack (TA_A)
+//            published originally already in year 1985 by Kaplan
+//            (file ktbm6trv.cpp)
+
+// //#define _KTBTRAV_VERSION0
+//#define _KTBTRAV_VERSION1
+//#define _KTBTRAV_VERSION2
+//#define _KTBTRAV_VERSION3
+//#define _KTBTRAV_VERSION4
+#define _KTBTRAV_VERSION5
+//#define _KTBTRAV_VERSION6
+
+// We cull away the nodes to be visited if they would be the same
+// as the next box in the sequence of nodes with boxes
+#define _CULL_IN_INTERIOR_NODES
+
+// If this macro is defined, then we extract the sequence of boxes to
+// the output buffer when visiting a leaf. When this macro is disabled,
+// we make test upon visiting a box node, which can be faster, as the
+// number of box nodes is smaller than the number of leaves visited 
+#define EXTRACTSEQENENCEINLEAVES
+
+// This is special development debug
+#define _DEBUG_SAMELEAF
+
+// Pseudo visualization
+#define VIS_TRAVERSEDNODED
+
+// If this macro is defined, we use increment of
+// the signed distance to avoid visiting the same node again
+// by multiplication and addition
+// Otherwise (macro commented) we use a special function for that
+// based on IEEE754 representation of floating-point
+//#define INCTMIN
+
+// These are constants to increase signed distance when exiting leaf
+#define onePlusEps 1.000008f
+#define epsAdd 0.000008f
+
+//#define onePlusEps 1.00005f
+//#define epsAdd 0.0001f
+//const float onePlusEps = 1.0001f;
+//const float epsAdd = 0.0001f;
+//const float onePlusEps = 1.00008f;
+//const float epsAdd = 0.00005f;	
+//const float onePlusEps = 1.000008f; 
+//const float epsAdd = 0.000008f;             
+//const float onePlusEps = 1.0000008f;
+//const float epsAdd = 0.00001f;	
+
+// Here are the macros to avoid traversing the same leaf again
+#define _DEBUGULPS
+#define INCULPS 1
+
+#ifndef _KTB8Bytes
+// 12 Bytes representation
+#undef  SKTBNodeT
+#define SKTBNodeT CKTBNodeAbstract::SKTBNode
+#else
+// 8 Bytes representation
+#undef  SKTBNodeT
+#define SKTBNodeT CKTB8BNodeAbstract::SKTBNode
+#endif
+
+// 12 Bytes representation
+class CKTBNodeIteratorPredecessor:
+#ifndef _KTB8Bytes
+  public CKTBNodeIterator
+#else
+  public CKTB8BNodeIterator
+#endif
+{
+public:
+  virtual int FindNearestI(const SimpleRay &ray) { return 0; }
+  void SetOffset(int offset) { rayOffset = offset; }
+  virtual int FindNearestI_16oneDir(SimpleRayContainer &rays) { return 0; }
+  virtual int FindNearestI_16oneDir(SimpleRayContainer &rays, int offset)
+  { return 0; } 
+  virtual int FindNearestI_16twoDir(SimpleRayContainer &rays) { return 0; }
+
+  // the number of nested kd-trees at most
+  enum { MAX_NESTING = 2};
+  
+  // The same operations for packets of rays, if implemented by
+  // a particular ASDS, otherwise it is emulated by decomposition
+  // of a packet to individual rays and traced individually.
+  virtual void FindNearestI(RayPacket2x2 &raypack) { }
+  virtual void FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax) { }
+
+  virtual void PrintStatsTR(ostream &) { }
+  virtual void DynamicStatsReset() { }
+};
+
+// ---------------------------------------------------------------------------
+// Note on the usage:
+// Allow only one macro from the tree: _KTBTRAV_JANSEN86, _KTBTRAV_JGT98
+// and  _KTBTRAV_OPTIMIZED86
+
+// macro for using algorithm for traversal CKTB trees as stated by Jansen86,
+// Arvo88, and Kelving/Sung92 in Gems III. 
+//#define _KTBTRAV_JANSEN86
+
+// Faster and robust algorithm is used, published in JGT 98
+// by Havran+Bittner+Kopal+Zara. It is fastest at the moment, measured in year 2005/6
+#define _KTBTRAV_JGT98
+
+// Modified algorithm from Jansen86 (Arvo88, Kelving/Sung92), optimized for
+// modern processors.
+//#define _KTBTRAV_OPTIMIZED86
+
+// ------------------------------------------------------------
+#undef _COMPUTE_INVERTED_DIR_KTB
+// This avoids the division when computed signed distance by precomputation
+// of the inverse of ray.dir for all three components
+#define _COMPUTE_INVERTED_DIR_KTB
+
+// Check if the only traversal algorithm was used.
+#ifdef _KTBTRAV_JANSEN86
+#if (defined(_KTBTRAV_JGT98) || defined(_KTBTRAV_OPTIMIZED86))
+#error "Allow only one of macros  _KTBTRAV_OPTIMIZED86, _KTBTRAV_JGT98, _KTBTRAV_OPTIMIZED86"
+#endif
+#endif
+//-------------------------
+#ifdef _KTBTRAV_JGT98
+#if (defined(_KTBTRAV_JANSEN86) || defined(_KTBTRAV_OPTIMIZED86))
+#error "Allow only one of macros  _KTBTRAV_OPTIMIZED86, _KTBTRAV_JGT98, _KTBTRAV_OPTIMIZED86"
+#endif
+#endif
+//-------------------------
+#ifdef _KTBTRAV_OPTIMIZED86
+#if (defined(_KTBTRAV_JANSEN86) || defined(_KTBTRAV_JGT98))
+#error "Allow only one of macros  _KTBTRAV_OPTIMIZED86, _KTBTRAV_JGT98, _KTBTRAV_OPTIMIZED86"
+#endif
+#endif
+
+// -------------------------------------------------------------------
+// robust statistically optimized algorithm for CKTB ray-traversal
+// version 025
+// This version appeared in JGT(Journal of Graphics Tools, Vol. 2, No.4,
+// 1997, pp.15-23. with title:
+// "FAST Robust KD-Tree Traversal Algorithm for Ray Tracing"
+
+class CKTBTraversal:
+  public CKTBNodeIteratorPredecessor
+{
+public:
+  // maximal height of the CKTB tree for nesting
+  enum { MAX_TRAVERSAL_HEIGHT = (MAX_HEIGHT * MAX_NESTING) };
+
+protected:
+  // the stack element for CKTB tree traversal 
+  struct SStackElem {
+    SKTBNodeT *nodep;  // pointer to the node
+    // Vector3 point;  // entry/exit point
+    float    x,y,z;  // entry/exit point
+    float    t;      // signed distance of the point
+    SStackElem *prev;
+    SKTBNodeT *lastBoxNode; // here is the alingment
+#ifdef _KTBEXTSTACK
+    int       dummy; // storing the depth here
+#endif    
+  };
+
+  // the stack element for CKTB tree traversal 
+  struct SStackElem2 {
+    SKTBNodeT *nodep;  // pointer to the node
+    int      dummy;
+    float    tmin;      // entry signed distance
+    float    tmax;      // exit signed distance
+  };
+  struct SStackElem3 {
+    SKTBNodeT *nodep;  // pointer to the node
+    float    tmax;     // exit signed distance
+  };
+
+  struct SStackElem4 {
+    SKTBNodeT *nodep;  // pointer to the node
+    int      mask;     // mask
+    int      pad[2];   // alignment to 16 bytes
+    union { float tmin4[4];
+#ifdef __SSE__
+      __m128 tmin_4;
+#endif
+    };
+    union { float tmax4[4];
+#ifdef __SSE__
+      __m128 tmax_4;
+#endif
+    };
+  };
+
+  
+  // the stack of elems - declared as static not to allocate it every time
+  static struct SStackElem stack[MAX_TRAVERSAL_HEIGHT];
+  static struct SStackElem2 stack2[MAX_TRAVERSAL_HEIGHT];
+  static struct SStackElem3 stack3[MAX_TRAVERSAL_HEIGHT];
+  static struct SStackElem4 stack4[MAX_TRAVERSAL_HEIGHT];
+
+#define cntMaxRays 16
+  static struct CKTBTraversal::SStackElem3 stackA[cntMaxRays * MAX_HEIGHT];
+
+  // the axis aligned box for CKTB tree space
+  AxisAlignedBox3 bbox;
+  // root node of the CKTB tree
+  SKTBNodeT *root;
+  // the small epsilon that is computed from the size of the whole box
+  float epsilon;
+
+  // sets the stack pointers that are used for the traversal.
+  void GetStackPointers(struct SStackElem *&entryPointer,
+			struct SStackElem *&exitPointer);
+  void GetStartStackPointer(struct SStackElem *&exitPointer);
+  
+  // this function should be called when exiting from the traversal function
+  // to keep the track on the traversalDepth (of kd-trees, when they are nested).
+  void RestoreStackPointers();
+
+  // the depth of traversal when kd-trees are nested. The global (the highest
+  // level) kd-tree is at the depth 0.
+  static int traversalDepth;
+
+#ifdef __TRAVERSAL_STATISTICS
+  long unsigned int _allNodesTraversed;
+  long unsigned int _fullLeavesTraversed;
+  long unsigned int _emptyLeavesTraversed;
+#endif
+
+public:
+  // default constructor
+  CKTBTraversal();
+
+  // destructor
+  virtual ~CKTBTraversal() {}
+
+  // sets the bbox and the root node for this traversal class
+  virtual void Setup(const AxisAlignedBox3 &box, SKTBNodeT *Nroot)
+    { bbox = box; root = Nroot; epsilon=(float)(1e-6*Magnitude(bbox.Size())); }
+
+  // potentionally, sets the list of unbounded objects if required
+  virtual void Setup2(CObjectList *) { // int count = unboundeds->ListCount();
+  }
+
+  virtual int FindNearestI(const SimpleRay &ray);
+  virtual int FindNearestI(const SimpleRay &ray, const AxisAlignedBox3 &localbox);
+
+  virtual int FindNearestI_16oneDir(SimpleRayContainer &rays) {
+    return FindNearestI_16oneDir(rays, 0);
+  }
+  // $$JB correction
+  virtual int FindNearestI_16oneDir(SimpleRayContainer &rays, int offset) {
+	return 0;
+  }
+  int PrecomputeData(SimpleRayContainer &rays);
+  void ReverseRay(const int indexA);
+  virtual int FindNearestI_16twoDir(SimpleRayContainer &rays);
+
+#ifdef __SSE__
+  // The same operations for packets of rays, if implemented by
+  // a particular ASDS, otherwise it is emulated by decomposition
+  // of a packet to individual rays and traced individually.
+  virtual void FindNearestI(RayPacket2x2 &raypack);
+  virtual void FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax);
+#endif // __SSE__
+
+  virtual void PrintStatsTR(ostream &) { }
+
+  void AssignIDs(SKTBNodeT *node = NULL);
+
+  // this resets the nesting to start from the zero depth (root)
+  virtual void ResetTraversalDepth() { traversalDepth = 0;}
+
+  // Here we find the node (preferably minbox node) containing
+  // the point
+  virtual const SKTBNode* Locate(const Vector3 &position);
+};
+
+#if 0
+// The version taking into account min boxes sparsely distributed in
+// the kd-tree.
+class CKTBMinBoxesTraversal:
+  public CKTBNodeIteratorPredecessor
+{
+protected:
+  // the stack element for CKTB tree traversal 
+  struct SStackElem {
+    SKTBNodeT *nodep;  // pointer to the node
+    // Vector3 point;  // entry/exit point
+    float    x,y,z;  // entry/exit point
+    float    t;      // signed distance of the point
+    SStackElem *prev;
+    SKTBNodeT *lastBoxNode; // here is the alingment
+//#ifdef _KTBEXTSTACK
+    int       dummy; // storing the depth here
+//#endif    
+  };
+
+  // maximal height of the CKTB tree for nesting
+  enum { MAX_TRAVERSAL_HEIGHT = (MAX_HEIGHT * MAX_NESTING) };
+  
+  // the stack of elems - declared as static not to allocate it every time
+  static struct SStackElem stack[MAX_TRAVERSAL_HEIGHT];
+
+  // the axis aligned box for CKTB tree space
+  AxisAlignedBox3 bbox;
+  // root node of the CKTB tree
+  SKTBNodeT *root;
+  // the small epsilon that is computed from the size of the whole box
+  float epsilon;
+  // size of the write buffer
+  int size1D;
+
+  // sets the stack pointers that are used for the traversal.
+  void GetStackPointers(struct SStackElem *&entryPointer,
+			struct SStackElem *&exitPointer);
+  void GetStartStackPointer(struct SStackElem *&exitPointer);
+  
+  // this function should be called when exiting from the traversal function
+  // to keep the track on the traversalDepth (of kd-trees, when they are nested).
+  void RestoreStackPointers();
+
+  // the depth of traversal when kd-trees are nested. The global (the highest
+  // level) kd-tree is at the depth 0.
+  static int traversalDepth;
+
+#ifdef __TRAVERSAL_STATISTICS
+  long unsigned int _allNodesTraversed;
+  long unsigned int _fullLeavesTraversed;
+  long unsigned int _emptyLeavesTraversed;
+#endif
+  
+public:
+  // default constructor
+  CKTBMinBoxesTraversal(int size1Dv);
+
+  // destructor
+  virtual ~CKTBMinBoxesTraversal();
+
+  // sets the bbox and the root node for this traversal class
+  virtual void Setup(const AxisAlignedBox3 &box, SKTBNodeT *Nroot)
+    { bbox = box; root = Nroot; epsilon=(float)(1e-6*Magnitude(bbox.Size())); }
+
+  // potentionally, sets the list of unbounded objects if required
+  virtual void Setup2(CObjectList *) { // int count = unboundeds->ListCount();
+  }
+
+  virtual int FindNearestI(SimpleRay &ray);
+
+#ifdef __SSE__
+  // The same operations for packets of rays, if implemented by
+  // a particular ASDS, otherwise it is emulated by decomposition
+  // of a packet to individual rays and traced individually.
+  virtual void FindNearestI(RayPacket2x2 &raypack);
+  virtual void FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax);
+#endif // __SSE__
+
+  virtual void DynamicStatsReset();
+  
+  virtual void PrintStatsTR(ostream &);
+
+  void AssignIDs(SKTBNodeT *node = NULL);
+
+  // this resets the nesting to start from the zero depth (root)
+  virtual void ResetTraversalDepth() { traversalDepth = 0;}
+
+#ifdef __TRAVERSAL_STATISTICS
+  unsigned long int statsMB_UpTraversals;
+  unsigned long int statsMB_DownTraversals;
+  unsigned long int statsMB_cntRays;
+  unsigned long int statsMB_cntRaysHB;
+  unsigned long int statsMB_UseTraversals;
+  unsigned long int statsMB_UseValidTraversals;
+  unsigned long int statsMB_allNodesTraversed;
+  unsigned long int statsMB_fullLeavesTraversed;
+  unsigned long int statsMB_emptyLeavesTraversed;
+  unsigned long int bugTheSameLeaf;
+  unsigned long int statsMB_writtenBoxes;
+  unsigned long int statsMB_readBoxes;
+  unsigned long int statsMB_cntWrittenBoxSequenceEvent;
+  unsigned long int statsMB_cntReadBoxSequenceEvent;
+#endif
+
+  // Here we find the node (preferably minbox node) containing
+  // the point
+  virtual const SKTBNode* Locate(const Vector3 &position);
+};
+#endif
+  
+} // namespace
+
+#endif // __KTBTRAV_H__
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbftrav.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbftrav.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbftrav.cpp	(revision 2582)
@@ -0,0 +1,1535 @@
+// ===================================================================
+// $Id: $
+//
+// ktbftrav.cpp
+//
+// class: CKTBTraversal
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, February 2007 (copy from kdrtrav.cpp)
+
+// GOLEM headers
+#include "ktbconf.h"
+#include "ktbtrav.h"
+#include "Intersectable.h"
+
+namespace GtpVisibilityPreprocessor {
+
+#ifdef TRV00F
+
+#if 0
+// the depth of traversal when kd-trees are nested. The global (the highest
+// level) kd-tree is at the depth 0.
+int
+CKTBTraversal::traversalDepth = 0;
+
+// sets the stack pointers that are used for the traversal.
+void
+CKTBTraversal::GetStackPointers(struct SStackElem *&entryPointer,
+				struct SStackElem *&exitPointer)
+{
+  assert(traversalDepth < MAX_NESTING);
+  
+  int index = traversalDepth * MAX_HEIGHT;
+  entryPointer = &(stack[index]);
+  exitPointer = &(stack[index + 1]);
+
+  traversalDepth++;  
+  return;
+}
+
+// sets the stack pointers that are used for the traversal.
+void
+CKTBTraversal::RestoreStackPointers()
+{
+  assert(traversalDepth >= 0);
+  traversalDepth--;  
+  return;
+}
+
+
+// default constructor
+CKTBTraversal::CKTBTraversal()
+{
+  bbox = AxisAlignedBox3(Vector3(MAXFLOAT),
+			 Vector3(-MAXFLOAT));
+  root = 0;
+  epsilon = 0;
+
+#ifdef __TRAVERSAL_STATISTICS
+  _allNodesTraversed = 0L;
+  _fullLeavesTraversed = 0L;
+  _emptyLeavesTraversed = 0L;
+#endif
+}
+  
+// Here we find the node (preferably minbox node) containing
+// the point
+const SKTBNodeT*
+CKTBTraversal::Locate(const Vector3 &position)
+{
+  const SKTBNodeT *current, *next = root;
+  const SKTBNodeT *returnNode = 0;
+
+  do {
+    current = next;
+    switch (GetNodeType(current)) {
+      // -------------------------------------------------
+      case CKTBAxes::EE_X_axis: {
+	if (position[CKTBAxes::EE_X_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	break;
+      }
+      case CKTBAxes::EE_Y_axis: {
+	if (position[CKTBAxes::EE_Y_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	break;
+      }
+      case CKTBAxes::EE_Z_axis: {
+	if (position[CKTBAxes::EE_Z_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	break;
+      }
+      case CKTBAxes::EE_X_axisBox: {
+	if (position[CKTBAxes::EE_X_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	returnNode = current;
+	break;
+      }
+      case CKTBAxes::EE_Y_axisBox: {
+	if (position[CKTBAxes::EE_Y_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	returnNode = current;
+	break;
+      }
+      case CKTBAxes::EE_Z_axisBox: {
+	if (position[CKTBAxes::EE_Z_axis] < current->splitPlane)
+	  next =  GetLeft(current);
+	else
+	  next = GetRight(current);
+	returnNode = current;
+	break;
+      }
+      case CKTBAxes::EE_Leaf: {
+	next = 0; // finishing
+	break;
+      }
+      case CKTBAxes::EE_Link:{
+	next = GetLinkNode(current);
+	// cout << "Link node was accessed" << endl;
+	break;
+      }
+    } // switch
+  }
+  while (next != NULL);
+
+  if (returnNode)
+    return returnNode;
+
+  // return the last (leaf node) visited on the path
+  return current;
+}
+#endif
+  
+  
+#if 1
+int
+CKTBTraversal::FindNearestI(const SimpleRay &ray)
+{
+#if 0
+  static int counter = 0;
+  counter++;
+  bool debug = false;
+  if (counter == 530) {
+    debug = true;
+    cout << "COUNTER = " << counter << endl;
+    cout << "DEBUG starts" << endl;    
+  }
+#endif
+  
+  // passing through parameters
+  float tmin, tmax;
+  
+  // test if the whole CKTB tree is missed by the input ray
+  if ( (!root) ||
+       (!bbox.ComputeMinMaxT(ray.mOrigin, ray.mDirection, &tmin, &tmax)) ||
+       (tmax <= tmin) ||
+       (tmax <= 0.f) ) {
+    SimpleRay::IntersectionRes[0].intersectable = 0;
+    return 0; // no object can be intersected
+  }
+
+//#define _DEBUGKTB
+#ifdef _DEBUGKTB
+  int ib = 0;
+  int depth = 0; 
+#endif
+  
+#ifdef __TRAVERSAL_STATISTICS
+  int allNodesTraversed = 0L;
+  int fullLeavesTraversed = 0L;
+  int emptyLeavesTraversed = 0L;
+#endif // __TRAVERSAL_STATISTICS
+
+  Vector3 invertedDir;
+  invertedDir.x = 1.0f / ray.mDirection.x;
+  invertedDir.y = 1.0f / ray.mDirection.y;
+  invertedDir.z = 1.0f / ray.mDirection.z;
+  
+  // start from the root node
+  if (tmin < 0.f)
+    tmin = 0.f;
+
+  int index = 1;
+  stack3[1].nodep = root;
+  stack3[1].tmax = tmax;
+  tmax = tmin;
+  SKTBNodeT * childNodes[2];
+  int RayDirs[3];
+  RayDirs[0] = ray.mDirection.x < 0.f ? 1 : 0;
+  RayDirs[1] = ray.mDirection.y < 0.f ? 1 : 0;
+  RayDirs[2] = ray.mDirection.z < 0.f ? 1 : 0;
+  
+  // we have to check the node
+  // current node is not the leaf, empty leaves are NULL pointers
+  while (index) {
+    register SKTBNodeT *currNode = stack3[index].nodep;
+    tmin = tmax;
+    tmax = stack3[index].tmax;
+#if 0
+    if (debug) {
+      cout << "node = " << (void*)currNode
+	   << " tmin = " << tmin << " tmax = " << tmax
+	   << endl;
+    }
+#endif
+    
+    assert(tmin <= tmax);
+    
+#ifdef __TRAVERSAL_STATISTICS
+    allNodesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+    register const int nodeType = GetNodeType(currNode);
+	
+    if (nodeType < CKTBAxes::EE_Leaf) {
+      float tval = (GetSplitValue(currNode) - ray.mOrigin[nodeType]);
+      tval *= invertedDir[nodeType];
+      SKTBNodeT *near, *far;
+      childNodes[0] = GetLeft(currNode);
+      childNodes[1] = GetRight(currNode);
+      int rayDir = RayDirs[nodeType];
+      near = childNodes[rayDir];
+      far = childNodes[rayDir ^ 0x1];
+      
+      stack3[index].nodep = far;
+      // stack3[index].tmax = tmax; // not necessary, this is already there !
+      // int c = tval < tmax ? 1 : 0;
+      index += tval < tmax ? 1 : 0;
+      stack3[index].nodep = near;
+      stack3[index].tmax = Min(tval, tmax);
+      tmax = tmin;
+      // int d = tval < tmin ? -1 : 0;
+      index += tval < tmin ? -1 : 0;
+    }
+    else {
+      if (nodeType == CKTBAxes::EE_Leaf) {
+	// test objects for intersection
+#ifdef _DEBUGKTB
+	cout << "Leaf " << endl;
+	depth++;
+#endif
+#ifdef _DEBUGKTB
+	DEBUG << "currNode = " << currNode << " entp.t = " << entp->t
+	      << " extp.t = " << extp->t << endl;
+#endif
+	if (!IsEmptyLeaf_(currNode)) {
+#ifdef _DEBUGKTB
+	  cout << "Full leaf at depth= " << depth << endl; 
+#endif      
+
+#ifdef __TRAVERSAL_STATISTICS
+	  fullLeavesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+	  // test the objects in the full leaf against the ray
+	  
+	  SimpleRay::IntersectionRes[0].maxt = stack3[index].tmax;
+#if 0
+	  // using subroutine
+	  if (TestFullLeaf(ray, currNode))
+#else
+	  // Avoiding function call by copying the code
+	  const ObjectContainer * const list = GetObjList(currNode); 
+	  int intersected = 0;
+	  // iterate the whole list and find out the nearest intersection
+	  ObjectContainer::const_iterator sc_end = list->end();
+	  for (ObjectContainer::const_iterator sc = list->begin(); sc != sc_end; sc++) {
+	    // if the intersection realy lies in the node        
+	    intersected += ((*sc)->CastSimpleRay(ray));
+	  } // for all objects
+	  if (intersected)
+#endif
+	  {
+#ifdef _DEBUGKTB
+	    cout << "Full leaf HIT " << endl; 
+#endif 	
+	      
+#ifdef __TRAVERSAL_STATISTICS
+	    _allNodesTraversed += allNodesTraversed;
+	    _fullLeavesTraversed += fullLeavesTraversed;
+	    _emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+	    
+	    // signed distance should be already set in TestFullLeaf
+	    // the first object intersected was found	
+	    return 1;
+	  }
+	} // full leaf
+#ifdef __TRAVERSAL_STATISTICS
+	else {
+#ifdef _DEBUGKTB
+	  cout << "Empty leaf at depth= " << depth << endl; 
+#endif      
+	  emptyLeavesTraversed++;
+	}
+#endif // __TRAVERSAL_STATISTICS
+
+#ifdef _DEBUGKTB
+	cout << "Pop the node" << endl;
+#endif      
+    
+	// pop farChild from the stack
+	// restore the current values
+	index--;
+	continue;
+      }
+      else {
+	assert(nodeType == CKTBAxes::EE_Link);
+#ifdef _DEBUGKTB
+	cout << "Link " << endl;
+#endif
+	stack3[index].nodep = GetLinkNode(currNode);
+	// cout << "Link node was accessed" << endl;
+	continue;
+      }
+    }
+  } // while current node is not the leaf
+
+#ifdef __TRAVERSAL_STATISTICS
+  _allNodesTraversed += allNodesTraversed;
+  _fullLeavesTraversed += fullLeavesTraversed;
+  _emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+
+  // no objects found along the ray path
+  return 0;
+} // FindNearestI - single ray
+#endif
+
+#if 1
+int
+CKTBTraversal::FindNearestI(const SimpleRay &ray, const AxisAlignedBox3 &localbox)
+{
+#if 0
+  static int counter = 0;
+  counter++;
+  bool debug = false;
+  if (counter == 530) {
+    debug = true;
+    cout << "COUNTER = " << counter << endl;
+    cout << "DEBUG starts" << endl;    
+  }
+#endif
+  
+  // passing through parameters
+  float tmin, tmax;
+  
+  // test if the whole CKTB tree is missed by the input ray
+  if ( (!root) ||
+       (!localbox.ComputeMinMaxT(ray.mOrigin, ray.mDirection, &tmin, &tmax)) ||
+       (tmax <= tmin) ||
+       (tmax <= 0.f) ) {
+    SimpleRay::IntersectionRes[0].intersectable = 0;
+    return 0; // no object can be intersected
+  }
+
+//#define _DEBUGKTB
+#ifdef _DEBUGKTB
+  int ib = 0;
+  int depth = 0; 
+#endif
+  
+#ifdef __TRAVERSAL_STATISTICS
+  int allNodesTraversed = 0L;
+  int fullLeavesTraversed = 0L;
+  int emptyLeavesTraversed = 0L;
+#endif // __TRAVERSAL_STATISTICS
+
+  Vector3 invertedDir;
+  invertedDir.x = 1.0f / ray.mDirection.x;
+  invertedDir.y = 1.0f / ray.mDirection.y;
+  invertedDir.z = 1.0f / ray.mDirection.z;
+  
+  // start from the root node
+  if (tmin < 0.f)
+    tmin = 0.f;
+
+  int index = 1;
+  stack3[1].nodep = root;
+  stack3[1].tmax = tmax;
+  tmax = tmin;
+  SKTBNodeT * childNodes[2];
+  int RayDirs[3];
+  RayDirs[0] = ray.mDirection.x < 0.f ? 1 : 0;
+  RayDirs[1] = ray.mDirection.y < 0.f ? 1 : 0;
+  RayDirs[2] = ray.mDirection.z < 0.f ? 1 : 0;
+  
+  // we have to check the node
+  // current node is not the leaf, empty leaves are NULL pointers
+  while (index) {
+    register SKTBNodeT *currNode = stack3[index].nodep;
+    tmin = tmax;
+    tmax = stack3[index].tmax;
+#if 0
+    if (debug) {
+      cout << "node = " << (void*)currNode
+	   << " tmin = " << tmin << " tmax = " << tmax
+	   << endl;
+    }
+#endif
+    
+    assert(tmin <= tmax);
+    
+#ifdef __TRAVERSAL_STATISTICS
+    allNodesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+    register const int nodeType = GetNodeType(currNode);
+    if (nodeType < CKTBAxes::EE_Leaf) {
+      float tval = (GetSplitValue(currNode) - ray.mOrigin[nodeType]);
+      tval *= invertedDir[nodeType];
+      SKTBNodeT *near, *far;
+      childNodes[0] = GetLeft(currNode);
+      childNodes[1] = GetRight(currNode);
+      int rayDir = RayDirs[nodeType];
+      near = childNodes[rayDir];
+      far = childNodes[rayDir ^ 0x1];
+      
+      stack3[index].nodep = far;
+      // stack3[index].tmax = tmax; // not necessary, this is already there !
+      // int c = tval < tmax ? 1 : 0;
+      index += tval < tmax ? 1 : 0;
+      stack3[index].nodep = near;
+      stack3[index].tmax = Min(tval, tmax);
+      tmax = tmin;
+      // int d = tval < tmin ? -1 : 0;
+      index += tval < tmin ? -1 : 0;
+    }
+    else {
+      if (nodeType == CKTBAxes::EE_Leaf) {
+	// test objects for intersection
+#ifdef _DEBUGKTB
+	cout << "Leaf " << endl;
+	depth++;
+#endif
+#ifdef _DEBUGKTB
+	DEBUG << "currNode = " << currNode << " entp.t = " << entp->t
+	      << " extp.t = " << extp->t << endl;
+#endif
+	if (!IsEmptyLeaf_(currNode)) {
+#ifdef _DEBUGKTB
+	  cout << "Full leaf at depth= " << depth << endl; 
+#endif      
+
+#ifdef __TRAVERSAL_STATISTICS
+	  fullLeavesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+	  // test the objects in the full leaf against the ray
+	  
+	  SimpleRay::IntersectionRes[0].maxt = stack3[index].tmax;
+#if 0
+	  // using subroutine
+	  if (TestFullLeaf(ray, currNode))
+#else
+	  // Avoiding function call by copying the code
+	  const ObjectContainer * const list = GetObjList(currNode); 
+	  int intersected = 0;
+	  // iterate the whole list and find out the nearest intersection
+	  ObjectContainer::const_iterator sc_end = list->end();
+	  for (ObjectContainer::const_iterator sc = list->begin(); sc != sc_end; sc++) {
+	    // if the intersection realy lies in the node        
+	    intersected += ((*sc)->CastSimpleRay(ray));
+	  } // for all objects
+	  if (intersected)
+#endif
+	  {
+#ifdef _DEBUGKTB
+	    cout << "Full leaf HIT " << endl; 
+#endif 	
+	      
+#ifdef __TRAVERSAL_STATISTICS
+	    _allNodesTraversed += allNodesTraversed;
+	    _fullLeavesTraversed += fullLeavesTraversed;
+	    _emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+	    
+	    // signed distance should be already set in TestFullLeaf
+	    // the first object intersected was found	
+	    return 1;
+	  }
+	} // full leaf
+#ifdef __TRAVERSAL_STATISTICS
+	else {
+#ifdef _DEBUGKTB
+	  cout << "Empty leaf at depth= " << depth << endl; 
+#endif      
+	  emptyLeavesTraversed++;
+	}
+#endif // __TRAVERSAL_STATISTICS
+
+#ifdef _DEBUGKTB
+	cout << "Pop the node" << endl;
+#endif      
+    
+	// pop farChild from the stack
+	// restore the current values
+	index--;
+	continue;
+      }
+      else {
+	assert(nodeType == CKTBAxes::EE_Link);
+#ifdef _DEBUGKTB
+	cout << "Link " << endl;
+#endif
+	stack3[index].nodep = GetLinkNode(currNode);
+	// cout << "Link node was accessed" << endl;
+	continue;
+      }
+    }
+  } // while current node is not the leaf
+
+#ifdef __TRAVERSAL_STATISTICS
+  _allNodesTraversed += allNodesTraversed;
+  _fullLeavesTraversed += fullLeavesTraversed;
+  _emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+
+  // no objects found along the ray path
+  return 0;
+} // FindNearestI - single ray
+#endif
+  
+
+// ---------------------------------------------------------------------------
+// This is an attempt using SSE instructions - not successfull 31/12/2007
+#if 0
+int
+CKTBTraversal::FindNearestI(const SimpleRay &ray)
+{
+#if 0
+  static int counter = 0;
+  counter++;
+  bool debug = false;
+  if (counter == 530) {
+    debug = true;
+    cout << "COUNTER = " << counter << endl;
+    cout << "DEBUG starts" << endl;    
+  }
+#endif
+  
+  // passing through parameters
+  float tmin, tmax;
+  
+  // test if the whole CKTB tree is missed by the input ray
+  if ( (!root) ||
+       (!bbox.ComputeMinMaxT(ray.mOrigin, ray.mDirection, &tmin, &tmax)) ||
+       (tmax <= tmin) ||
+       (tmax <= 0.f) ) {
+    SimpleRay::IntersectionRes[0].intersectable = 0;
+    return 0; // no object can be intersected
+  }
+
+//#define _DEBUGKTB
+#ifdef _DEBUGKTB
+  int ib = 0;
+  int depth = 0; 
+#endif
+  
+#ifdef __TRAVERSAL_STATISTICS
+  int allNodesTraversed = 0L;
+  int fullLeavesTraversed = 0L;
+  int emptyLeavesTraversed = 0L;
+#endif // __TRAVERSAL_STATISTICS
+
+  Vector3 invertedDir;
+  invertedDir.x = 1.0f / ray.mDirection.x;
+  invertedDir.y = 1.0f / ray.mDirection.y;
+  invertedDir.z = 1.0f / ray.mDirection.z;
+  
+  // start from the root node
+  if (tmin < 0.f)
+    tmin = 0.f;
+
+  int index = 1;
+  stack3[1].nodep = root;
+  stack3[1].tmax = tmax;
+  tmax = tmin;
+  SKTBNodeT * childNodes[2];
+  int RayDirs[3];
+  RayDirs[0] = ray.mDirection.x < 0.f ? 1 : 0;
+  RayDirs[1] = ray.mDirection.y < 0.f ? 1 : 0;
+  RayDirs[2] = ray.mDirection.z < 0.f ? 1 : 0;
+  
+  // we have to check the node
+  // current node is not the leaf, empty leaves are NULL pointers
+  while (index) {
+    SKTBNodeT *currNode = stack3[index].nodep;
+    tmin = tmax;
+    tmax = stack3[index].tmax;
+#if 0
+    if (debug) {
+      cout << "node = " << (void*)currNode
+	   << " tmin = " << tmin << " tmax = " << tmax
+	   << endl;
+    }
+#endif
+    
+    assert(tmin <= tmax);
+    
+#ifdef __TRAVERSAL_STATISTICS
+    allNodesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+    const unsigned int nodeType = GetNodeType(currNode);
+    if (nodeType < CKTBAxes::EE_Leaf) {
+      float tval = (GetSplitValue(currNode) - ray.mOrigin[nodeType]);
+      tval *= invertedDir[nodeType];
+      SKTBNodeT *near, *far;
+      childNodes[0] = GetLeft(currNode);
+      childNodes[1] = GetRight(currNode);
+      int rayDir = RayDirs[nodeType];
+      near = childNodes[rayDir];
+      far = childNodes[rayDir ^ 0x1];
+      // This code is slower than above !!!!!
+      stack3[index].nodep = far;
+      // stack3[index].tmax = tmax; // this is already there, not necessary!
+      __m128 tsim = _mm_set_ss(tval);
+      // index += tval < tmax ? 1 : 0;
+      __m128 tother = _mm_set_ss(tmax);
+      index += _mm_ucomilt_ss(tsim, tother);
+      stack3[index].nodep = near;
+      // stack3[index].tmax = Min(tval, tmax);
+      _mm_store_ss(&(stack3[index].tmax), _mm_min_ps(tsim, tother));
+      tmax = tmin;
+      // index += tval < tmin ? -1 : 0;
+      __m128 tother2 = _mm_set_ss(tmin);
+      index -= _mm_ucomilt_ss(tsim, tother2);
+    }
+    else {
+      if (nodeType == CKTBAxes::EE_Leaf) {
+	// test objects for intersection
+#ifdef _DEBUGKTB
+	cout << "Leaf " << endl;
+	depth++;
+#endif
+#ifdef _DEBUGKTB
+	DEBUG << "currNode = " << currNode << " entp.t = " << entp->t
+	      << " extp.t = " << extp->t << endl;
+#endif
+	if (!IsEmptyLeaf_(currNode)) {
+#ifdef _DEBUGKTB
+	  cout << "Full leaf at depth= " << depth << endl; 
+#endif      
+
+#ifdef __TRAVERSAL_STATISTICS
+	  fullLeavesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+	  // test the objects in the full leaf against the ray
+	  
+	  SimpleRay::IntersectionRes[0].maxt = stack3[index].tmax;
+	  if (TestFullLeaf(ray, currNode)) {
+#ifdef _DEBUGKTB
+	    cout << "Full leaf HIT " << endl; 
+#endif 	
+	      
+#ifdef __TRAVERSAL_STATISTICS
+	    _allNodesTraversed += allNodesTraversed;
+	    _fullLeavesTraversed += fullLeavesTraversed;
+	    _emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+	    
+	    // signed distance should be already set in TestFullLeaf
+	    // the first object intersected was found	
+	    return 1;
+	  }
+	} // full leaf
+#ifdef __TRAVERSAL_STATISTICS
+	else {
+#ifdef _DEBUGKTB
+	  cout << "Empty leaf at depth= " << depth << endl; 
+#endif      
+	  emptyLeavesTraversed++;
+	}
+#endif // __TRAVERSAL_STATISTICS
+
+#ifdef _DEBUGKTB
+	cout << "Pop the node" << endl;
+#endif      
+    
+	// pop farChild from the stack
+	// restore the current values
+	index--;
+	continue;
+      }
+      else {
+	assert(nodeType == CKTBAxes::EE_Link);
+#ifdef _DEBUGKTB
+	cout << "Link " << endl;
+#endif
+	stack3[index].nodep = GetLinkNode(currNode);
+	// cout << "Link node was accessed" << endl;
+	continue;
+      }
+    }
+  } // while current node is not the leaf
+
+#ifdef __TRAVERSAL_STATISTICS
+  _allNodesTraversed += allNodesTraversed;
+  _fullLeavesTraversed += fullLeavesTraversed;
+  _emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+
+  // no objects found along the ray path
+  return 0;
+} // FindNearestI - single ray
+#endif
+
+#if 0
+// Reasonably fast - about 101,500 rays per second for single dir!
+// It allows fast switching context from one ray to the next ray so it it
+// virtually independent of memory latency !
+int
+CKTBTraversal::FindNearestI_16oneDir(SimpleRayContainer &rays, int offset)
+{
+  // passing through parameters
+  int cntRays = 0;
+  if (!root)
+    return 0;
+
+  // The auxiliary variables to be precomputed
+  static float invertedDir[cntMaxRays * 4];
+  static float rayOrig[cntMaxRays * 4];
+  static int rayDirs[cntMaxRays * 4];
+  static int indexRay[cntMaxRays];
+  static int indexArray[cntMaxRays];
+  static int indexStack[cntMaxRays];
+  const int LOG2_MAX_HEIGHT = 5;
+  const int MAX_HEIGHT = 1 << LOG2_MAX_HEIGHT;
+  assert(MAX_HEIGHT == 32);
+  static struct SStackElem3 stackA[cntMaxRays * MAX_HEIGHT];
+  static float tmaxArray[cntMaxRays];
+  int cntHits = 0;
+  
+  float tmin, tmax;
+  for (int i = 0; i < cntMaxRays; i++) {
+  // test if the whole CKTB tree is missed by the input ray
+    if ((!bbox.ComputeMinMaxT(rays[i+offset].mOrigin,
+			      rays[i+offset].mDirection,
+			      &tmin, &tmax)) ||
+	(tmax <= tmin) ||
+	(tmax <= 0.f) ) {
+      SimpleRay::IntersectionRes[i].intersectable = 0;
+    }
+    else {
+      int indexR = (cntRays << 2);
+      rayOrig[indexR + 0] = rays[i+offset].mOrigin.x;
+      rayOrig[indexR + 1] = rays[i+offset].mOrigin.y;
+      rayOrig[indexR + 2] = rays[i+offset].mOrigin.z;
+      //rayOrig[indexR + 3] = 0.f;
+      invertedDir[indexR + 0] = 1.0f / (rays[i+offset].mDirection.x);
+      invertedDir[indexR + 1] = 1.0f / (rays[i+offset].mDirection.y);
+      invertedDir[indexR + 2] = 1.0f / (rays[i+offset].mDirection.z);
+      //invertedDir[indexR + 2] = 0.f;
+      rayDirs[indexR + 0] = rays[i+offset].mDirection.x < 0.f ? 1 : 0;
+      rayDirs[indexR + 1] = rays[i+offset].mDirection.y < 0.f ? 1 : 0;
+      rayDirs[indexR + 2] = rays[i+offset].mDirection.z < 0.f ? 1 : 0;
+      //rayDirs[indexR + 3] = 0; 
+      indexRay[cntRays] = i; // the index to the ray
+      indexArray[cntRays] = cntRays; // the index to the array
+      int indexS = (cntRays << LOG2_MAX_HEIGHT) + 1;
+      indexStack[cntRays] = indexS; // the index in the stack
+      stackA[indexS].nodep = root; // we start from the root
+      stackA[indexS].tmax = tmax; // maximum distance
+      if (tmin < 0.f) tmin = 0.f;
+      tmaxArray[cntRays] = tmin;
+      cntRays++;
+    }
+  }
+
+//#define _DEBUGKTB
+#ifdef _DEBUGKTB
+  int ib = 0;
+  int depth = 0;
+#endif
+  
+#ifdef __TRAVERSAL_STATISTICS
+  int allNodesTraversed = 0L;
+  int fullLeavesTraversed = 0L;
+  int emptyLeavesTraversed = 0L;
+#endif // __TRAVERSAL_STATISTICS
+  
+  SKTBNodeT * childNodes[2];
+
+#define PREF_DEFAULT _MM_HINT_T0
+  
+  // we have to check the node
+  // current node is not the leaf, empty leaves are NULL pointers
+  while (cntRays) {
+    // we assume that all the nodes are interior nodes
+    for (int i = 0; i < cntRays; i++) {
+      // which indices to array should be used
+      int indexA = indexArray[i];
+      float tmin = tmaxArray[indexA];
+
+      // the stack indexing is here
+      int indexSA = indexStack[indexA];
+      SKTBNodeT *currNode = stackA[indexSA].nodep;
+      
+#if 0
+      if (debug) {
+	cout << "node = " << (void*)currNode
+	     << " tmin = " << tmin << " tmax = " << tmax
+	     << endl;
+      }
+#endif
+
+#if 0
+      if (tmin > tmax) {
+	cout << "PROBLEM tmin = " << tmin << " tmax = " << tmax;
+	cout << endl;
+      }
+#endif      
+      assert(tmin <= tmax);
+    
+#ifdef __TRAVERSAL_STATISTICS
+      allNodesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+      const unsigned int nodeType = (GetNodeType(currNode)) & 0x7;
+      if (nodeType < CKTBAxes::EE_Leaf) {
+	int indexRayOD = (indexA << 2) + nodeType;
+	float tval = (GetSplitValue(currNode) - rayOrig[indexRayOD])
+	  * invertedDir[indexRayOD];
+	SKTBNodeT *near, *far;
+	childNodes[0] = GetLeft(currNode);
+	childNodes[1] = GetRight(currNode);
+	int rayDir = rayDirs[indexRayOD];
+	near = childNodes[rayDir];
+	far = childNodes[rayDir ^ 0x1];
+	
+	stackA[indexSA].nodep = far; // store far node
+	//stackA[indexSA].tmax = tmax; // with correct dist - the same as before
+	float tmax = tmaxArray[indexA] = stackA[indexSA].tmax;
+	int c = tval < tmax ? 1 : 0;
+	indexSA += c;
+	stackA[indexSA].nodep = near; // store near node
+	stackA[indexSA].tmax = Min(tval, tmax); // with correct dist
+	int d = tval < tmin ? 1 : 0;
+	indexSA -= d;
+	// This is prefetching - so the next time we have it
+	// in the cache !
+	GPREFETCH(stackA[indexSA].nodep, PREF_DEFAULT);
+	// store tmax and index to the stack
+	indexStack[indexA] = indexSA;
+	tmaxArray[indexA] = tmin;	
+      }
+      else {
+	if (nodeType == CKTBAxes::EE_Leaf) {
+	  // test objects for intersection
+#ifdef _DEBUGKTB
+	  cout << "Leaf " << endl;
+	  depth++;
+#endif
+#ifdef _DEBUGKTB
+	  DEBUG << "currNode = " << currNode << " entp.t = " << entp->t
+		<< " extp.t = " << extp->t << endl;
+#endif
+	  float tmax = tmaxArray[indexA] = stackA[indexSA].tmax;
+	  if (!IsEmptyLeaf_(currNode)) {
+#ifdef _DEBUGKTB
+	    cout << "Full leaf at depth= " << depth << endl; 
+#endif      
+
+#ifdef __TRAVERSAL_STATISTICS
+	    fullLeavesTraversed++;
+#endif // __TRAVERSAL_STATISTICS
+	  // test the objects in the full leaf against the ray
+	  
+	    // which ray is processed
+	    int indexR = indexRay[indexA];
+	    SimpleRay::IntersectionRes[indexR].maxt = tmax;
+	    if (TestFullLeaf(rays[indexR+offset], currNode, indexR)) {
+
+	      // we remove the ray from the calculation
+	      indexArray[i] = indexArray[cntRays-1];
+	      cntRays--; // we decrease the number of rays
+	      cntHits++;
+#ifdef _DEBUGKTB
+	      cout << "Full leaf HIT " << endl; 
+#endif 	
+	      
+#ifdef __TRAVERSAL_STATISTICS
+	      _allNodesTraversed += allNodesTraversed;
+	      _fullLeavesTraversed += fullLeavesTraversed;
+	      _emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS	    
+	    
+	      // signed distance should be already set in TestFullLeaf
+	      // the first object intersected was found	
+	      continue;
+	    }
+	  } // full leaf
+#ifdef __TRAVERSAL_STATISTICS
+	  else {
+#ifdef _DEBUGKTB
+	    cout << "Empty leaf at depth= " << depth << endl; 
+#endif      
+	    emptyLeavesTraversed++;
+	  }
+#endif // __TRAVERSAL_STATISTICS
+
+#ifdef _DEBUGKTB
+	  cout << "Pop the node" << endl;
+#endif      
+    
+	  // pop farChild from the stack
+	  // restore the current values
+	  --indexSA;
+	  // This is bits 0,1,2,3,4,5 - the stack depth = 32 !
+	  if ( (indexSA & 0x1f) == 0) {
+	    // we remove the ray from the calculation
+	    indexArray[i] = indexArray[cntRays-1];
+	    cntRays--; // we decrease the number of rays
+	  }
+	  else {
+	    indexStack[indexA] = indexSA;
+	    // we prefetch the data to be accessible
+	    // the next time
+	    GPREFETCH(stackA[indexSA].nodep, PREF_DEFAULT);
+	  }
+	  continue;
+	}
+	else {
+	  assert(nodeType == CKTBAxes::EE_Link);
+#ifdef _DEBUGKTB
+	  cout << "Link " << endl;
+#endif
+	  stackA[indexSA].nodep = GetLinkNode(currNode);
+	  // cout << "Link node was accessed" << endl;
+	  continue;
+	}
+      } // empty leaf or link
+    } // for all active rays
+  } // while cntRays
+
+#ifdef __TRAVERSAL_STATISTICS
+  _allNodesTraversed += allNodesTraversed;
+  _fullLeavesTraversed += fullLeavesTraversed;
+  _emptyLeavesTraversed += emptyLeavesTraversed;
+#endif // __TRAVERSAL_STATISTICS
+
+  // no objects found along the ray path
+  return cntHits;
+}
+#endif
+
+#ifdef __SSE__
+
+#if 1
+// Even faster - about 125,500 rays per second for single dir and 164 rps
+// for double dir !
+int
+CKTBTraversal::FindNearestI_16oneDir(SimpleRayContainer &rays, int offset)
+{
+  static RayPacket2x2 raypack;
+  struct SResultI {
+    Intersectable *intersectable;
+    float          tdist;    
+  };
+  static SResultI results[16];
+    
+  for (int i = 0; i < 4; i++) {
+    int k = i * 4 + offset;
+    for (int j = 0; j < 4; j++, k++) {
+      raypack.SetLoc(j, rays[k].mOrigin);
+      raypack.SetDir(j, rays[k].mDirection);      
+    }
+    // Here either use ray packet traversal or
+    // casting individual rays
+    FindNearestI(raypack);
+    k = i * 4;
+    for (int j = 0; j < 4; j++, k++) {
+      results[k].intersectable = raypack.GetObject(j);
+      results[k].tdist = raypack.GetT(j);
+    } // for j
+  } // for i
+
+  // Copy the results to the output array
+  for (int i = 0; i < 16; i++) {
+    SimpleRay::IntersectionRes[i].intersectable =
+      results[i].intersectable;
+    SimpleRay::IntersectionRes[i].tdist =
+      results[i].tdist;
+  } // for i
+}
+#endif
+  
+#if 0
+// This code works well 1/1/2008 - 11:00
+// The same operations for packets of rays for the same signs,
+// otherwise it is emulated by decomposition
+// of a packet to individual rays and traced individually.
+void
+CKTBTraversal::FindNearestI(RayPacket2x2 &rp)
+{
+  int m1 = _mm_movemask_ps(rp.dx4);
+  if ((m1 == 0)||(m1 == 15)) {
+  m1 = _mm_movemask_ps(rp.dy4);
+  if ((m1 == 0)||(m1 == 15)) {
+  m1 = _mm_movemask_ps(rp.dz4);
+  if ((m1 == 0)||(m1 == 15)) {
+    rp.Init();
+    // all the signs for 4 rays are the same, use
+    // ray packet traversal
+    // Compute min and max distances
+    GALIGN16 union { float tmin4[4]; __m128 tmin_4; };
+    GALIGN16 union { float tmax4[4]; __m128 tmax_4; };
+    SimpleRay sray[4];
+    int maxIntersections = 4;
+    GALIGN16 union { int inters[4]; __m128 inters_4; };
+    inters[0] = inters[1] = inters[2] = inters[3] = 1;
+    unsigned int inters32 = 0xf;
+    for (int i = 0; i < 4; i++) {
+      bbox.ComputeMinMaxT(rp.GetLoc(i), rp.GetDir(i), &(tmin4[i]), &(tmax4[i]));
+      if ( (tmin4[i] >= tmax4[i]) ||
+	   (tmax4[i] < 0.f) ) {
+	inters[i] = 0; // finished
+	inters32 &= ~(1 << i); // bit zero when ray is invalid
+	maxIntersections--;
+      }      
+      if (tmin4[i] < 0.f)
+	tmin4[i] = 0.f;
+      sray[i].mOrigin = rp.GetLoc(i);
+      sray[i].mDirection = rp.GetDir(i);
+    } // for i
+    if (maxIntersections == 0)
+      return;
+
+    SKTBNodeT * childNodes[2];
+    int RayDirs[3];
+    RayDirs[0] = (rp.dx[0] > 0.f) ? 1 : 0;
+    RayDirs[1] = (rp.dy[0] > 0.f) ? 1 : 0;
+    RayDirs[2] = (rp.dz[0] > 0.f) ? 1 : 0;
+    //int activeMask=_mm_movemask_ps(_mm_cmplt_ps( tmin_4, tmax_4 ))&inters32;
+    int activeMask = inters32;
+    int indexStack = 0;
+    SKTBNodeT *currNode = root;
+    unsigned int k = GetNodeType(currNode);
+    for (;;) {      
+      while (k < CKTBAxes::EE_Leaf) {
+	// the 3 operations below can be brought down to 3 simple float
+	// calculations by precomputing min/max of the inverse dir
+	const __m128 node_split = _mm_set_ps1(GetSplitValue(currNode));
+	const __m128 t4 =
+	  _mm_mul_ps(_mm_sub_ps(node_split, rp.orig[k]), rp.idir[k]);
+	childNodes[0] = GetLeft(currNode);
+	childNodes[1] = GetRight(currNode);
+	int rayDir = RayDirs[k];
+        SKTBNodeT *far = childNodes[rayDir];
+	if (!(_mm_movemask_ps(_mm_cmpgt_ps(t4, tmin_4)) & activeMask))
+	{
+	  currNode = far;
+	  k = GetNodeType(currNode);
+	  continue;
+	}
+	currNode = childNodes[rayDir ^ 0x1]; // this is near node
+	k = GetNodeType(currNode);	
+	if (! (_mm_movemask_ps(_mm_cmplt_ps( t4, tmax_4)) & activeMask))
+	  continue;
+
+	// pop far node to the stack
+	stack4[indexStack].nodep = far;
+	stack4[indexStack].tmax_4 = tmax_4;
+	stack4[indexStack].tmin_4 = _mm_max_ps(t4, tmin_4);
+	// stack4[indexStack].mask = activeMask;
+	indexStack++;
+	
+	tmax_4 = _mm_min_ps(t4, tmax_4); 
+	activeMask &= _mm_movemask_ps(_mm_cmplt_ps( tmin_4, tmax_4 ));
+      } // while this is an interior node
+
+      // either a leaf or a link
+      if (k == CKTBAxes::EE_Leaf) {
+	// test objects for intersection
+	if (!IsEmptyLeaf_(currNode)) {
+	  // cout << "Full leaf" << endl;
+	  
+	  // test the objects in the full leaf against the ray	  
+	  for (int i = 0; i < 4; i++) {
+	    if (inters[i] ) {
+	      // no intersection so far !
+	      SimpleRay::IntersectionRes[i].maxt = tmax4[i];
+	      // Test only rays that were not finished
+	      if (TestFullLeaf(sray[i], currNode, i)) {
+		// intersection for this ray found
+		inters[i] = 0;
+		inters32 &= ~(1 << i);
+		rp.SetT(i, SimpleRay::IntersectionRes[0].maxt);
+		rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);		
+		// signed distance should be already set in TestFullLeaf
+		// the first object intersected was found
+		if (--maxIntersections == 0)
+		  return;
+	      }
+	    } // if this ray did not hit the triangle so far
+	  } // for all 4 rays
+	} // full leaf
+	// pop farChild from the stack
+	// restore the current values
+	// update the minimum distance since we traverse to the next one
+
+	if (indexStack == 0)
+	  return;
+	indexStack--;
+	currNode = stack4[indexStack].nodep;
+	k = GetNodeType(currNode);
+	tmin_4 = stack4[indexStack].tmin_4;
+	tmax_4 = stack4[indexStack].tmax_4;
+	activeMask = _mm_movemask_ps(_mm_cmple_ps( tmin_4, tmax_4 )) & inters32;
+	continue;
+      }
+      // cout << "Link node was accessed" << endl;
+      assert(k == CKTBAxes::EE_Link);
+      currNode = GetLinkNode(currNode);
+      k = GetNodeType(currNode);
+    } // for
+    return;
+  }}}
+
+  // Trace ray by ray
+  SimpleRay ray;
+  for (int i = 0; i < 4; i++) {
+    ray.mOrigin = rp.GetLoc(i);
+    ray.mDirection = rp.GetDir(i);
+    FindNearestI(ray);
+    rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);
+    rp.SetT(i, SimpleRay::IntersectionRes[0].tdist);
+    // SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
+  } // for
+}
+#endif
+
+
+#if 1
+// This code also works well 1/1/2008 - 14:00
+// Using mask of 128-bits width - the code works as well, only a bit
+// faster than the code above
+void
+CKTBTraversal::FindNearestI(RayPacket2x2 &rp)
+{
+  int m1 = _mm_movemask_ps(rp.dx4);
+  if ((m1 == 0)||(m1 == 15)) {
+  m1 = _mm_movemask_ps(rp.dy4);
+  if ((m1 == 0)||(m1 == 15)) {
+  m1 = _mm_movemask_ps(rp.dz4);
+  if ((m1 == 0)||(m1 == 15)) {
+    rp.Init();
+    // all the signs for 4 rays are the same, use
+    // ray packet traversal
+    // Compute min and max distances
+    GALIGN16 union { float tmin4[4]; __m128 tmin_4; };
+    GALIGN16 union { float tmax4[4]; __m128 tmax_4; };
+    GALIGN16 union { float activeMask[4]; __m128 activeMask_4; };
+    GALIGN16 union { float liveMask[4]; __m128 liveMask_4; };
+    liveMask[0] = liveMask[1] = liveMask[2] = liveMask[3] = 0xffffffff;
+
+    GALIGN16 SimpleRay sray[4];
+    int maxIntersections = 4;
+    // unsigned int inters32 = 0xf;
+    for (int i = 0; i < 4; i++) {
+      rp.SetObject(i, 0);
+      bbox.ComputeMinMaxT(rp.GetLoc(i), rp.GetDir(i), &(tmin4[i]), &(tmax4[i]));
+      if ( (tmin4[i] >= tmax4[i]) ||
+	   (tmax4[i] < 0.f) ) {
+	liveMask[i] = 0; // finished
+	// inters32 &= ~(1 << i); // bit zero when ray is invalid
+	maxIntersections--;
+      }
+      if (tmin4[i] < 0.f)
+	tmin4[i] = 0.f;
+      sray[i].mOrigin = rp.GetLoc(i);
+      sray[i].mDirection = rp.GetDir(i);
+    } // for i
+    if (maxIntersections == 0)
+      return;
+
+    // This is the mask 128 bits witdth
+    //activeMask_4 =
+    //  _mm_and_ps(_mm_cmple_ps(tmin_4, tmax_4),
+    //		 _mm_cmplt_ps(tmax_4, _mm_setzero_ps()));
+    activeMask_4 = liveMask_4;
+
+    SKTBNodeT * childNodes[2];
+    int RayDirs[4];
+    RayDirs[0] = (rp.dx[0] > 0.f) ? 1 : 0;
+    RayDirs[1] = (rp.dy[0] > 0.f) ? 1 : 0;
+    RayDirs[2] = (rp.dz[0] > 0.f) ? 1 : 0;
+    int indexStack = 0;
+    SKTBNodeT *currNode = root;
+    unsigned int k = GetNodeType(currNode);
+    for (;;) {
+      // traverse until we find a leaf
+      while (k < CKTBAxes::EE_Leaf) {
+	// the 3 operations below can be brought down to 3 simple float
+	// calculations by precomputing min/max of the inverse dir
+	// const __m128 node_split = ;
+	const __m128 t4 =
+	  _mm_mul_ps(_mm_sub_ps(_mm_set_ps1(GetSplitValue(currNode)),
+				rp.orig[k]), rp.idir[k]);
+	childNodes[0] = GetLeft(currNode);
+	childNodes[1] = GetRight(currNode);
+	int rayDir = RayDirs[k];
+        SKTBNodeT *far = childNodes[rayDir];
+	if (_mm_movemask_ps(_mm_and_ps(_mm_cmpge_ps(t4, tmin_4),
+				       activeMask_4))) {	  
+	  currNode = far;
+	  k = GetNodeType(currNode);
+	  continue;
+	}
+
+	currNode = childNodes[rayDir ^ 0x1]; // this is near node
+	k = GetNodeType(currNode);	
+	if (_mm_movemask_ps(_mm_and_ps(_mm_cmple_ps(t4, tmax_4),
+				       activeMask_4)))
+	  continue;
+
+	// pop far node to the stack
+	stack4[indexStack].nodep = far;
+	stack4[indexStack].tmax_4 = tmax_4;
+
+// Uncomenting this macro is unsafe!
+// Not convinced if for packet of 4 rays we can say that since when
+// one ray is different than the others, it could bring to wrong state
+// It is surely true for one ray when tmin < t < tmax, but for a packet
+// of rays this condition can be true only for a single ray
+//   tmin4 = max(t4, tmin4) = min(t4, tmax4)
+//#define _NOT_STORE_MINT
+
+#ifdef _NOT_STORE_MINT	
+#else
+	// store mint onto the stack
+	stack4[indexStack].tmin_4 = _mm_max_ps(t4, tmin_4);
+#endif	
+	// stack4[indexStack].mask = activeMask;
+	indexStack++;
+	
+	tmax_4 = _mm_min_ps(t4, tmax_4); 
+	activeMask_4 = _mm_cmplt_ps( tmin_4, tmax_4 );
+      } // while this is an interior node
+
+      // either a leaf or a link
+      if (k == CKTBAxes::EE_Leaf) {
+	// test objects for intersection
+	if (!IsEmptyLeaf_(currNode)) {
+	  // cout << "Full leaf" << endl;
+	  
+	  // test the objects in the full leaf against the ray	  
+	  for (int i = 0; i < 4; i++) {
+	    if (liveMask[i] ) {
+	      // no intersection so far !
+	      SimpleRay::IntersectionRes[i].maxt = tmax4[i];
+#if 0
+	      // Using subroutine
+	      // Test only rays that were not finished
+	      if (TestFullLeaf(sray[i], currNode, i))
+#else
+	      // avoiding one call
+	      const ObjectContainer * const list = GetObjList(currNode); 
+	      int intersected = 0;
+	      // iterate the whole list and find out the nearest intersection
+	      ObjectContainer::const_iterator sc_end = list->end();
+	      for (ObjectContainer::const_iterator sc = list->begin(); sc != sc_end; sc++) {
+		// if the intersection realy lies in the node        
+		intersected |= ((*sc)->CastSimpleRay(sray[i], i));
+	      } // for all objects
+	      if (intersected)
+#endif
+	      {
+		rp.SetT(i, SimpleRay::IntersectionRes[0].maxt);
+		rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);
+		// signed distance should be already set in TestFullLeaf
+		// the first object intersected was found
+		if (--maxIntersections == 0)
+		  return;
+		// inters32 &= ~(1 << i);
+		liveMask[i] = 0;
+	      }
+	    } // if this ray did not hit the triangle so far
+	  } // for all 4 rays
+	} // full leaf
+
+	// pop farChild from the stack
+	// restore the current values
+	// update the minimum distance since we traverse to the next one
+	do {
+	  if (indexStack == 0)
+	    return;
+	  indexStack--;
+	  currNode = stack4[indexStack].nodep;
+	  k = GetNodeType(currNode);
+#ifdef _NOT_STORE_MINT
+	  // this is an attempt !
+	  tmin_4 = tmax_4;
+#else
+ 	  // This surrely works
+	  tmin_4 = stack4[indexStack].tmin_4;
+#endif	  
+	  tmax_4 = stack4[indexStack].tmax_4;
+	  activeMask_4 = _mm_and_ps(_mm_cmple_ps( tmin_4, tmax_4 ), liveMask_4);
+	}
+	while (_mm_movemask_ps(activeMask_4) == 0);
+      }
+      else {
+	// cout << "Link node was accessed" << endl;
+	assert(k == CKTBAxes::EE_Link);
+	currNode = GetLinkNode(currNode);
+	k = GetNodeType(currNode);
+      }
+    } // for(;;)
+    return;
+  }}}
+
+  // Trace ray by ray
+  SimpleRay ray;
+  for (int i = 0; i < 4; i++) {
+    ray.mOrigin = rp.GetLoc(i);
+    ray.mDirection = rp.GetDir(i);
+    FindNearestI(ray);
+    rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);
+    rp.SetT(i, SimpleRay::IntersectionRes[0].tdist);
+    // SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
+  } // for
+}
+#endif
+
+#if 1
+// This code also works well 1/1/2008 - 14:00
+// Using mask of 128-bits width - the code works as well, only a bit
+// faster than the code above
+void
+CKTBTraversal::FindNearestI(RayPacket2x2 &rp, Vector3 &boxmin, Vector3 &boxmax)
+{
+  static AxisAlignedBox3 localbox;
+  localbox.SetMin(boxmin);
+  localbox.SetMax(boxmax);
+
+  int m1 = _mm_movemask_ps(rp.dx4);
+  if ((m1 == 0)||(m1 == 15)) {
+  m1 = _mm_movemask_ps(rp.dy4);
+  if ((m1 == 0)||(m1 == 15)) {
+  m1 = _mm_movemask_ps(rp.dz4);
+  if ((m1 == 0)||(m1 == 15)) {
+    rp.Init();
+    
+    // all the signs for 4 rays are the same, use
+    // ray packet traversal
+    // Compute min and max distances
+    GALIGN16 union { float tmin4[4]; __m128 tmin_4; };
+    GALIGN16 union { float tmax4[4]; __m128 tmax_4; };
+    GALIGN16 union { float activeMask[4]; __m128 activeMask_4; };
+    GALIGN16 union { float liveMask[4]; __m128 liveMask_4; };
+    liveMask[0] = liveMask[1] = liveMask[2] = liveMask[3] = 0xffffffff;
+
+    GALIGN16 SimpleRay sray[4];
+    int maxIntersections = 4;
+    // unsigned int inters32 = 0xf;
+    for (int i = 0; i < 4; i++) {
+      rp.SetObject(i, 0);
+      localbox.ComputeMinMaxT(rp.GetLoc(i), rp.GetDir(i), &(tmin4[i]), &(tmax4[i]));
+      if ( (tmin4[i] >= tmax4[i]) ||
+	   (tmax4[i] < 0.f) ) {
+	liveMask[i] = 0; // finished
+	// inters32 &= ~(1 << i); // bit zero when ray is invalid
+	maxIntersections--;
+      }
+      if (tmin4[i] < 0.f)
+	tmin4[i] = 0.f;
+      sray[i].mOrigin = rp.GetLoc(i);
+      sray[i].mDirection = rp.GetDir(i);
+    } // for i
+    if (maxIntersections == 0)
+      return;
+
+    // This is the mask 128 bits witdth
+    //activeMask_4 =
+    //  _mm_and_ps(_mm_cmple_ps(tmin_4, tmax_4),
+    //		 _mm_cmplt_ps(tmax_4, _mm_setzero_ps()));
+    activeMask_4 = liveMask_4;
+
+    SKTBNodeT * childNodes[2];
+    int RayDirs[4];
+    RayDirs[0] = (rp.dx[0] > 0.f) ? 1 : 0;
+    RayDirs[1] = (rp.dy[0] > 0.f) ? 1 : 0;
+    RayDirs[2] = (rp.dz[0] > 0.f) ? 1 : 0;
+    int indexStack = 0;
+    SKTBNodeT *currNode = root;
+    unsigned int k = GetNodeType(currNode);
+    for (;;) {
+      // traverse until we find a leaf
+      while (k < CKTBAxes::EE_Leaf) {
+	// the 3 operations below can be brought down to 3 simple float
+	// calculations by precomputing min/max of the inverse dir
+	// const __m128 node_split = ;
+	const __m128 t4 =
+	  _mm_mul_ps(_mm_sub_ps(_mm_set_ps1(GetSplitValue(currNode)),
+				rp.orig[k]), rp.idir[k]);
+	childNodes[0] = GetLeft(currNode);
+	childNodes[1] = GetRight(currNode);
+	int rayDir = RayDirs[k];
+        SKTBNodeT *far = childNodes[rayDir];
+	if (_mm_movemask_ps(_mm_and_ps(_mm_cmpge_ps(t4, tmin_4),
+				       activeMask_4))) {	  
+	  currNode = far;
+	  k = GetNodeType(currNode);
+	  continue;
+	}
+
+	currNode = childNodes[rayDir ^ 0x1]; // this is near node
+	k = GetNodeType(currNode);	
+	if (_mm_movemask_ps(_mm_and_ps(_mm_cmple_ps(t4, tmax_4),
+				       activeMask_4)))
+	  continue;
+
+	// pop far node to the stack
+	stack4[indexStack].nodep = far;
+	stack4[indexStack].tmax_4 = tmax_4;
+
+// Uncomenting this macro is unsafe!
+// Not convinced if for packet of 4 rays we can say that since when
+// one ray is different than the others, it could bring to wrong state
+// It is surely true for one ray when tmin < t < tmax, but for a packet
+// of rays this condition can be true only for a single ray
+//   tmin4 = max(t4, tmin4) = min(t4, tmax4)
+//#define _NOT_STORE_MINT
+
+#ifdef _NOT_STORE_MINT	
+#else
+	// store mint onto the stack
+	stack4[indexStack].tmin_4 = _mm_max_ps(t4, tmin_4);
+#endif	
+	// stack4[indexStack].mask = activeMask;
+	indexStack++;
+	
+	tmax_4 = _mm_min_ps(t4, tmax_4); 
+	activeMask_4 = _mm_cmplt_ps( tmin_4, tmax_4 );
+      } // while this is an interior node
+
+      // either a leaf or a link
+      if (k == CKTBAxes::EE_Leaf) {
+	// test objects for intersection
+	if (!IsEmptyLeaf_(currNode)) {
+	  // cout << "Full leaf" << endl;
+	  
+	  // test the objects in the full leaf against the ray	  
+	  for (int i = 0; i < 4; i++) {
+	    if (liveMask[i] ) {
+	      // no intersection so far !
+	      SimpleRay::IntersectionRes[i].maxt = tmax4[i];
+#if 0
+	      // Using subroutine
+	      // Test only rays that were not finished
+	      if (TestFullLeaf(sray[i], currNode, i))
+#else
+	      // avoiding one call
+	      const ObjectContainer * const list = GetObjList(currNode); 
+	      int intersected = 0;
+	      // iterate the whole list and find out the nearest intersection
+	      ObjectContainer::const_iterator sc_end = list->end();
+	      for (ObjectContainer::const_iterator sc = list->begin(); sc != sc_end; sc++) {
+		// if the intersection realy lies in the node        
+		intersected |= ((*sc)->CastSimpleRay(sray[i], i));
+	      } // for all objects
+	      if (intersected)
+#endif
+	      {
+		rp.SetT(i, SimpleRay::IntersectionRes[0].maxt);
+		rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);
+		// signed distance should be already set in TestFullLeaf
+		// the first object intersected was found
+		if (--maxIntersections == 0)
+		  return;
+		// inters32 &= ~(1 << i);
+		liveMask[i] = 0;
+	      }
+	    } // if this ray did not hit the triangle so far
+	  } // for all 4 rays
+	} // full leaf
+
+	// pop farChild from the stack
+	// restore the current values
+	// update the minimum distance since we traverse to the next one
+	do {
+	  if (indexStack == 0)
+	    return;
+	  indexStack--;
+	  currNode = stack4[indexStack].nodep;
+	  k = GetNodeType(currNode);
+#ifdef _NOT_STORE_MINT
+	  // this is an attempt !
+	  tmin_4 = tmax_4;
+#else
+ 	  // This surrely works
+	  tmin_4 = stack4[indexStack].tmin_4;
+#endif	  
+	  tmax_4 = stack4[indexStack].tmax_4;
+	  activeMask_4 = _mm_and_ps(_mm_cmple_ps( tmin_4, tmax_4 ), liveMask_4);
+	}
+	while (_mm_movemask_ps(activeMask_4) == 0);
+      }
+      else {
+	// cout << "Link node was accessed" << endl;
+	assert(k == CKTBAxes::EE_Link);
+	currNode = GetLinkNode(currNode);
+	k = GetNodeType(currNode);
+      }
+    } // for(;;)
+    return;
+  }}}
+
+  // Trace ray by ray
+  SimpleRay ray;
+  for (int i = 0; i < 4; i++) {
+    ray.mOrigin = rp.GetLoc(i);
+    ray.mDirection = rp.GetDir(i);
+    FindNearestI(ray, localbox);
+    rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);
+    rp.SetT(i, SimpleRay::IntersectionRes[0].tdist);
+    // SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
+  } // for
+}
+#endif
+
+#endif // __SSE__
+
+#endif //  TRV00F
+
+} // namespace
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb.h	(revision 2582)
@@ -0,0 +1,364 @@
+// ===================================================================
+// $Id: $
+//
+// ktb.h
+//      definition of classes for CKTB tree building up and traversal
+//
+// Class: CKTBNodeAbstract, SKTBNode, CKTBAllocMan, CKTBNodeIterator
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, February 2007
+
+#ifndef __KTB_H__
+#define __KTB_H__
+
+// GOLEM headers
+#include "configh.h"
+#include "AxisAlignedBox3.h"
+#include "Intersectable.h"
+#include "Containers.h"
+#include "allocgo2.h"
+#include "ktbconf.h"
+#include "sbbox.h"
+#include "Vector3.h"
+
+// standard headers
+#include <vector>
+
+namespace GtpVisibilityPreprocessor {
+
+// Forward declarations
+class CRayPacket2x2;
+
+// 12 Bytes representation of the node
+// This is only due to writing simplification
+#undef SKTBNodeT
+#define SKTBNodeT CKTBNodeAbstract::SKTBNode
+
+//===============================================
+// Representation of one node of CKTB
+class CKTBNodeAbstract
+{
+public:
+  // maximal height of the CKTB tree
+  enum { MAX_HEIGHT = 32 };
+
+  // the basic element of CKTB tree .. node of tree
+  // it must be accessible by more classes
+
+  // but must be declared because of compilation
+  struct SKTBNode {
+    // the axis, where cut is performed or type of node in general
+    CKTBAxes::Axes  nodeType;
+
+    union {
+      float splitPlane; // the position of splitting plane
+      ObjectContainer *objlist; // object list for a leaf or tagged interior node
+      SKTBNodeT *parentBoxNode; // the pointer to the same node type
+      int        depth; // the depth of the node (useful only for minBoxes)
+    };
+    
+    // SKTBNode *left; // pointer to the left child is implict in DFS order
+    union {
+      Intersectable *object; // the pointer to the object, if only one object
+      SKTBNodeT  *right; // pointer to the right child
+      SBBox     *encbox; // enclosing bounding box for this node
+      SBBox     *minbox; // minimum bounding box for this node
+    };
+
+    bool IsLeaf() const {
+      return ( nodeType == CKTBAxes::EE_Leaf);
+    }
+    bool IsEmptyLeaf() const {
+      return (this == 0);
+    }
+  }; // struct SKTBNode
+
+public:
+
+  // It was _KTB_R2
+  // default constructor
+  CKTBNodeAbstract() { }
+  // default destructor
+  virtual ~CKTBNodeAbstract() { }
+
+  bool IsEmptyLeaf_(const SKTBNode *p) const {
+    assert(p->nodeType == CKTBAxes::EE_Leaf);
+    return (p->objlist == NULL);
+  }
+
+  bool IsFullLeaf_(const SKTBNode *p) const {
+    return ((p->nodeType == CKTBAxes::EE_Leaf) &&
+	    (p->objlist != NULL));
+  }
+  
+  bool IsLeaf_(const SKTBNode *p) const
+  { return (p->nodeType == CKTBAxes::EE_Leaf); }
+  
+  bool HasMinBox_(const SKTBNode *p) const
+  { return ( p->nodeType >= CKTBAxes::EE_X_axisBox); }
+
+  // ------------------------------------------------------
+  // Common functions for iterator and allocator
+
+  CKTBAxes::Axes GetNodeType(const SKTBNode *nodep) const {
+    return nodep->nodeType;
+  }
+  SKTBNode* GetLeft(const SKTBNode *nodep) const {
+    return (SKTBNode*)(nodep+1); // We assume linking in DFS order
+  }
+  // We assume linking in DFS order, this is for EncBox
+  SKTBNode* GetLeftLong(const SKTBNode *nodep) const {
+    return (SKTBNode*)(((char*)nodep) + 3*sizeof(SKTBNode)); 
+  }
+  SKTBNode* GetRight(const SKTBNode *nodep) const {
+    return nodep->right;
+  }
+  SKTBNodeT* GetLinkNode(const SKTBNodeT *nodep) const {
+    return nodep->right;
+  }  
+  ObjectContainer* GetObjList(const SKTBNode *nodep) const {
+    return nodep->objlist;
+  }
+
+  SKTBNode* GetParentBoxNode(const SKTBNode *nodep) const {
+    return (SKTBNode*)(nodep+1)->parentBoxNode;
+  }
+
+  // This can be used only for nodes X_AxisBox, Y_AxisBox, Z_AxisBox
+  int GetDepth(const SKTBNode *nodep) const {
+    return (int)((nodep+1)->nodeType);
+  }
+#ifdef _SHORT_FORM_MINBOX
+  SKTBNode* GetLeftMinBox(const SKTBNode *nodep) const {
+    return (SKTBNode*)(nodep+2);
+  }
+#else
+  SKTBNode* GetLeftMinBox(const SKTBNode *nodep) const {
+    return (SKTBNode*)(((char*)nodep) + 4*sizeof(SKTBNode)); 
+  }  
+#endif // _SHORT_FORM_MINBOX
+
+}; // CKTBNodeAbstract
+
+//----------------------------------------------------------------
+// this class should be used as the base class for allocating
+// and connecting the nodes in the CKTB tree and for
+// for manipulating the nodes during building up
+class CKTBAllocMan:
+  public CKTBNodeAbstract
+{
+protected:
+#ifdef LEAVES_ARRAYS
+  CObjectArray arrayAlloc;
+#endif
+  
+  // init the stack of auxiliary variables from min to max
+  virtual void InitAux(int min, int max, int maxItemsAtOnce);
+
+  // the direction of traversal through CKTB tree
+  enum EDirection { LEFT = 0, RIGHT = 1, NOWHERE = 2 };
+
+//#ifdef _KTB_R2
+  SKTBNode* _AllocEmptyLeaf() {
+#ifdef _KTB_CONSTR_STATS
+    _stats_emptyLeftNodeCount++;
+#endif
+    return (SKTBNode*)0;
+  }
+protected:
+  // data required as the input parameter for construction of CKTB tree
+  int maxDepthAllowed; // maximal depth of CKTB tree
+  int maxListLength; // maximal list length of CKTB tree  
+public:
+  // default constructor
+  CKTBAllocMan() { InitForConstructor(); }
+
+  // default destructor
+  virtual ~CKTBAllocMan() { }
+
+  // forget the content that is created by previous kd-tree construction
+  // or just init for the first use.
+  void InitForConstructor();
+  
+  // the function, which reads the parameters from envinroment/commandline
+  virtual void InitPars();
+  
+  // -------------------------------------------------------
+  // allocate and free functions for SKTBNode
+  CAllocContinuous *alloc2; // the allocator saving space
+  SKTBNodeT *root; // this is the root node of the whole tree
+  
+  // This is the node to return from the allocation functions
+  // Here it can be implemented some linking when DFS order allocation,
+  // so the node can be different than the representation of the real
+  // node with the information
+  SKTBNodeT *nodeToLink;
+
+  // Create the representation of the interior node
+  SKTBNodeT* AllocInteriorNode(int axis, float position,
+			       int cntLeft, int cntRight);
+
+  // Create the representation of the interior node with box, where box
+  // can be used during the traversal
+  SKTBNodeT* AllocInteriorNodeWithBox(int axis, float position,
+				      int cntLeft, int cntRight,
+				      const SBBox &tsbox,
+				      SKTBNodeT* prevMinBoxNode,
+				      int depthStore);
+  
+  // Create the representation of the node with the bounding box
+  SKTBNodeT* AllocEncBoxNode(const SBBox &sbox);
+  
+  // Create the representation of the leaf. Note that possibly there
+  // can be special cases, such as 0, 1, 2, or 3 objects, or in general
+  // N objects.
+  SKTBNodeT* AllocLeaf(int cntObjects);
+  
+  // -------------------------------------------------------
+  // linking and setting functions for CKTB tree
+
+  // Set the pointers to children for the interior node
+  void SetInteriorNodeLinks(SKTBNodeT *node,
+			    SKTBNodeT *leftChild,
+			    SKTBNodeT *rightChild);
+
+  // Set the objects list to the leaf. The object list is used as it is
+  // ... it is not copied !!
+  virtual int SetFullLeaf(SKTBNodeT *node, const ObjectContainer *objlist);
+
+  // -------------------------------------------------------
+  // inquiry functions for CKTB tree nodes for current node
+
+  // returns the pointer to the root node of tree
+  virtual SKTBNode *GetRootNode() { return root;}
+
+  // postprocessing of CKTB tree after its initial construction
+  virtual void PostBuild();
+
+  // provides the information on the method used for CKTB tree
+  // and some setting parameters to given stream
+  virtual void ProvideID(ostream &app) = 0;
+  
+  // ---- Get Statistical Data ---------------------------------
+  void GetKTBTreeStats(int &nodes, int &leaves, int &emptyLeaves)
+  {
+#ifdef _KTB_CONSTR_STATS
+    nodes = _stats_interiorCount + _stats_bboxCount + _stats_minbboxCount
+      + _stats_leafNodeCount + _stats_emptyLeftNodeCount;
+    leaves = _stats_leafNodeCount + _stats_emptyLeftNodeCount;
+    emptyLeaves = _stats_emptyLeftNodeCount;
+#endif
+  }
+
+  // constructs the CKTB tree for given objectlist and given bounding box
+  virtual SKTBNodeT* BuildUp(ObjectContainer &objlist,
+			     const AxisAlignedBox3 &box,
+			     bool verbose = true) = 0;
+
+  // deletes all the structure starting from the root node
+  virtual void Remove();
+
+  // The current depth in the tree
+  inline int GetDepth() const {return _currDepth;}
+  void IncDepth() {_currDepth++;}
+  void DecDepth() {_currDepth--;}
+  
+  // --------------------------------------------------------------
+  // Statistics
+public:
+#ifdef _KTB_CONSTR_STATS
+  int _stats_interiorCount;
+  int _stats_bboxCount;
+  int _stats_minbboxCount;
+  int _stats_leafNodeCount;
+  int _stats_emptyLeftNodeCount;
+
+  // maximal depth of the currently built path during building up
+  int _maxDepth;  
+  // Sum of depths of leaf nodes (empty + full)
+  unsigned long int _sumLeafDepth;
+  // Sum of depths of empty leaves
+  unsigned long int _sumFullLeafDepth;
+  // The count of object references in leaves
+  unsigned long int _sumObjectRefCount;
+  // The maximum number of object references in a leaf
+  unsigned long int _maxObjectRefInLeaf;
+  // Surface area of leaves and interior nodes
+  float _sumSurfaceAreaLeaves;
+  float _sumSurfaceAreaMULcntLeaves;
+  float _sumSurfaceAreaInteriorNodes;
+#endif // _KTB_CONSTR_STATS
+
+  // General statistics on the depth of current node
+  // the depth of the currently accessed node during building up
+  int _currDepth;
+};
+
+//------------------------------------------------------
+// class which enables to use some functions with direct
+// access to the members of the tree
+// traversal classes should be derived from this class
+class CKTBNodeIterator:
+  public CKTBNodeAbstract
+{
+protected:
+  int rayOffset;  
+public:
+  // default constructor
+  CKTBNodeIterator() { }
+  // default destructor
+  ~CKTBNodeIterator() { }
+
+  ObjectContainer* GetObjList(const SKTBNode *nodep) const {
+    return nodep->objlist;
+  }
+  
+  float GetSplitValue(const SKTBNode *nodep) const {
+    return nodep->splitPlane;
+  }
+    
+#ifdef _SHORT_FORM_MINBOX
+  SBBox* GetMinBox(const SKTBNodeT *nodep) const {
+    return (nodep+1)->minbox;
+  }  
+#else // _SHORT_FORM_MINBOX
+  SBBox* GetMinBox(const SKTBNodeT *nodep) const {
+    // Here is the overlapping to save some memory !!! 
+    return (SBBox*)(((char*)nodep)+24);
+  }  
+#endif // _SHORT_FORM_MINBOX
+  
+  ObjectContainer* GetTagObjList(const SKTBNode *node) const {
+    return node->objlist;
+  }
+
+  // test the objects in the full leaf p and if finds the closest intersection
+  // with object so tmin<= t <= tmax, returns the pointer to that
+  // object, t is returned in tmax
+  int TestFullLeaf(const SimpleRay &ray, const SKTBNode *p);
+  int TestFullLeaf(const SimpleRay &ray, const SKTBNode *p, int rayIndex);
+
+  // test the objects in the full leaf and finds out any intersection
+  // in this case returns the pointer to the object, otherwise NULL
+  int HitAnyObj(const SimpleRay &ray, const SKTBNode *p);
+
+  // ------------------------------------------------------------------------
+  // Only abstract functions to simplify the interface
+
+  // this resets the nesting to start from the zero depth (root)
+  virtual void ResetTraversalDepth() = 0;
+
+  // sets the bbox and the root node for this traversal class
+  virtual void Setup(const AxisAlignedBox3 &box, SKTBNodeT *Nroot) = 0;
+
+  // Find the minimum box on containg a point or leaf, if there are
+  // no boxes on the way from a point to the leaf containing the point
+  virtual const SKTBNode* Locate(const Vector3 &point);
+}; // class CKTBNodeIterator
+
+}
+
+#endif // __KTB_H__ 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/timer.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/timer.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/timer.h	(revision 2582)
@@ -0,0 +1,98 @@
+// ================================================================
+// $Id: timer.h,v $
+//
+// timer.h
+//     CTimer class to measure the elapsed time
+//
+// Class: CTimer
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlastimil Havran, 1998.
+
+#ifndef __TIMER_H__
+#define __TIMER_H__
+
+// GOLEM headers
+#include "configh.h"
+
+// standard headers
+#ifdef __UNIX__
+#include <sys/resource.h>
+#endif
+
+#include <ctime>
+
+namespace GtpVisibilityPreprocessor {
+
+// Class CTimer is designed to measure the user/(user+system)/real time
+// taken by the processor within a portion of source code.
+class CTimer
+{
+private: // data
+#ifdef __UNIX__
+  // timing in OS UNIX
+  mutable struct rusage begrusage;
+  mutable struct rusage endrusage;
+#endif // __UNIX__
+
+  /// true if InitTiming() has already been called
+  static bool initTimingCalled;
+
+  /// accumulated real time (returned by RealTime() method)
+  mutable double realTime;
+  /// accumulated userTime
+  mutable double userTime;
+  /// accumulated user+system time
+  mutable double systemTime;
+  /// real time at the last start event
+  mutable double lastRealTime;
+  /// user time at the last start event
+  mutable double lastUserTime;
+  /// system time at the last start event
+  mutable double lastSystemTime;
+
+  /// the number of stopping this timer
+  mutable int  countStop; 
+  /// if the timer is running at this time
+  mutable bool running;   
+
+private: // methods
+
+  /// interior implementation of Stop()
+  void _start() const;
+  // interior implementation of Start()
+  void _stop() const;
+
+  /// finds out whether performance timer is present (WIN32)
+  void _initTiming();
+
+public: // methods
+
+  /// default constructor 
+  CTimer() { Reset();  if( ! initTimingCalled ) _initTiming();  }
+  /// default destructor
+  ~CTimer() {}
+  /// reset the time to zero all time values
+  void Reset();
+  /// restart the timer from zero
+  void Restart() { Reset(); Start();}
+  /// start/restart the timer to measure the following events
+  void Start() { _start(); }
+  /// stop the timer not to measure the following events
+  void Stop()  { _stop(); }
+  /// returns true if timer is running, otherwise false
+  bool IsRunning() const { return running;}
+  /// returns the real time measured by timer in seconds
+  double RealTime() const;
+  /// returns the user time measured by timer in seconds
+  double UserTime() const;
+  /// returns the user+system time measured by timer in seconds
+  double SystemTime() const;
+};
+
+
+}
+
+#endif // __TIMER_H__
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbai.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbai.cpp	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbai.cpp	(revision 2582)
@@ -0,0 +1,4655 @@
+// ===================================================================
+// $Id: $
+//
+// ktbai.cpp
+//     The classes for building up CKTB tree by statistical optimization.
+//     The bounding boxes of the all objects are sorted along all
+//     axes (x,y,z) in the array-based structure by radix sort algorithm.
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
+// Initial coding by Vlasta Havran, 2005.
+
+// standard headers
+#include <algorithm>
+#include <iostream>
+#include <string>
+
+// GOLEM headers
+#include "ktbai.h"
+#include "timer.h"
+#include "Environment.h"
+
+//#define _DEBUG
+
+#define AVOIDCHECKLIST
+
+#define _USE_OPTIMIZE_DIVIDE_AX
+
+// Note that the RADIX SORT does not work properly with -mtune=pentium3 for GCC.4.0 !!!!
+// Note that the RADIX SORT does not work properly with -mtune=pentium4 for GCC.3.4 !!!!
+// The reason is unknown, probably the bug in compiler
+
+namespace GtpVisibilityPreprocessor {
+
+// for testing accuracy of setting position from the ideal position
+//#define _RANDOMIZE_POSITION
+
+
+// This is epsilon for randomization
+static
+float randomEps = 0.0f; // By max 5 percent = 0.05
+
+static void
+RandomizePosition(float &value, float vmin, float vmax)
+{
+  assert(vmax > vmin);
+  assert( ((value >= vmin) && (value <= vmax) ) );
+
+  // copy the value
+  const float origvalue = value;
+  float offset = 0.f;
+
+#define _RND_OFFSET  
+#ifdef _RND_OFFSET
+  const int maxCount = 10;
+  int count = 0;
+  do {
+    if (count > maxCount) {
+      value = origvalue;
+      break;
+    }
+    offset = -(vmax - vmin) * randomEps/2.0f;
+    offset += randomEps * RandomValue(vmin,vmax);    
+    value = origvalue + offset;
+    count++;
+  }
+  while (! ((value > vmin) && (value < vmax)) );
+#else
+  offset = (vmax - vmin) * randomEps/2.0f;
+  if (RandomValue(0.f, 1.f) < 0.5f)
+    offset = -offset;  
+  value = origvalue + offset;
+  if ( (value < vmin) || (value > vmax) )
+    value = origvalue - offset;
+  //cout << "offset = " << 100.0f * offset / (vmax-vmin) << "\n";
+#endif
+
+  float epsShift = 1e-5;
+  if ( (value <= (vmin + (vmax-vmin) * epsShift)) ||
+       (value >= (vmax - (vmax-vmin) * epsShift)) ) {
+    value = origvalue;
+  }
+
+  assert( ((value >= vmin) && (value <= vmax) ) );
+  
+  return;
+}
+
+// ------------------------------------------------
+// for debugging cost function in the scene
+//#define _DEBUG_COSTFUNCTION
+#ifdef _DEBUG_COSTFUNCTION
+
+const int indexToFindSS = 0;
+
+static CFileIO ffcost;
+static int     costEvalCnt;
+static int     costCntObjects;
+static int     costIndexDebug;
+static string  fnameCost;
+static float   maxCost;
+static float   minCost;
+static float   maxPos;
+static float   minPos;
+static float   minPosAxis;
+static float   maxPosAxis;
+static bool _alreadyDebugged = false;
+static bool _streamOpened = false;
+
+static void
+InitCostStream(int indexDebug, int cntObjects,
+	       float minx, float maxx)
+{
+  maxCost = -INFINITY;
+  minCost = INFINITY;
+  costEvalCnt = 0;
+  costIndexDebug = indexDebug;
+  costCntObjects = cntObjects;
+  minPosAxis = minx;
+  maxPosAxis = maxx;
+  
+  // and init the stream - rewrite
+  string name = "debugcostfile"
+  //Environment::GetSingleton()->GetBoolValue("OutputFileName", name);
+  char lns[100];
+  sprintf(lns, "%05d.res", indexDebug);
+  ChangeFilenameExtension(name, string(lns), fnameCost);
+
+  ffcost.SetFilename(fnameCost.c_str());
+  if (ffcost.OpenInMode(CFileIO::EE_Mode_w)) {
+    cerr << "Opening of stream failed" << endl;
+    abort();;
+  }
+  cout << "Saving debug to " << fnameCost << endl;
+  ffcost.WriteChars("\n");
+  sprintf(lns, "#CntObjects = %d\n", costCntObjects);
+  ffcost.WriteChars(lns);
+  sprintf(lns, "#IndexToDebug = %d\n", costIndexDebug);
+  ffcost.WriteChars(lns);
+  ffcost.WriteChars("#File ");
+  ffcost.WriteChars(fnameCost.c_str());
+  ffcost.WriteChars("\n");
+  ffcost.WriteChars("#==============================================\n");
+
+  cout << "#---------------------------------------" << endl;
+  _streamOpened = true;
+}
+
+static void
+CloseCostStream()
+{
+  if (_streamOpened) {    
+    char lns[255];
+    ffcost.WriteChars("#==============================================\n");
+    ffcost.WriteChars("#EndOfFile\n");
+    sprintf(lns, "#minCost = %8.6f minPos = %8.6f\n", minCost, minPos);
+    ffcost.WriteChars(lns);    
+    sprintf(lns, "#maxCost = %8.6f maxPos = %8.6f\n", maxCost, maxPos);
+    ffcost.WriteChars(lns);    
+    sprintf(lns, "#ratioMin/Max =                                %6.5f\n",
+	    minCost/maxCost);
+    ffcost.WriteChars(lns);    
+    sprintf(lns, "#CntEval = %d\n", costEvalCnt);
+    ffcost.WriteChars(lns);
+    sprintf(lns, "#CntObjects = %d\n", costCntObjects);
+    ffcost.WriteChars(lns);    
+    sprintf(lns, "#IndexToDebug = %d\n", costIndexDebug);
+    ffcost.WriteChars(lns);
+    sprintf(lns, "#MinPosAxis = %8.6f maxPosAxis = %8.6f\n", minPosAxis, maxPosAxis);
+    ffcost.WriteChars(lns);
+    ffcost.WriteChars("#File ");
+    ffcost.WriteChars(fnameCost.c_str());
+    ffcost.WriteChars("\n");
+    ffcost.Close();
+    //cout << "#=======================================" << endl;
+    _streamOpened = false;
+    _alreadyDebugged = true;
+    // Temporarily
+    exit(0);
+  }
+}
+
+static void
+ReportCostStream(float pos, float cost)
+{
+  // Here we normalize a position to the interval <0-1>
+  float posn = (pos - minPosAxis)/(maxPosAxis - minPosAxis);
+
+  if (_streamOpened) {
+    costEvalCnt++;
+    if (cost < minCost) {
+      minCost = cost;
+      minPos = pos;
+    }
+    if (cost > maxCost) {
+      maxCost = cost;
+      maxPos = pos;
+    }
+    char lns[255];
+    sprintf(lns, "%8.6f %8.6f\n", posn, cost);
+    //cout << lns << endl;
+    ffcost.WriteChars(lns);    
+  }
+}
+#endif // _DEBUG_COSTFUNCTION
+
+//----------------------------------------------------------------
+//---------- Implementation of CKTB tree with irregular -----------
+//---------- placed splitting planes -----------------------------
+//----------------------------------------------------------------
+
+// default constructor
+CKTBABuildUp::CKTBABuildUp()
+{
+  // verbose is set
+  verbose = true;
+
+  // Maximum depth of the tree is set and stack is allocated
+  maxTreeDepth = 50;
+  stackDepth = 2*maxTreeDepth;
+  stackID = new GALIGN16 SInputData[stackDepth];
+  assert(stackID);
+  stackIndex = 0;
+  return;
+}
+
+//  destructor
+CKTBABuildUp::~CKTBABuildUp()
+{
+  delete [] stackID;
+  stackID = 0;
+}
+
+void
+CKTBABuildUp::ProvideID(ostream &app)
+{
+  bool tempvar;
+
+  Environment::GetSingleton()->GetBoolValue("BSP.splitclip", tempvar);
+  if (tempvar)
+    app << "#BSP.splitClip \t\tChange of bboxes(splitclip) "
+        << "dis/en\n" << tempvar << "\n";
+  Environment::GetSingleton()->GetBoolValue("BSP.emptyCut", tempvar);
+  app << "#BSP.emptyCut\t\tLate cutting off empty space in leaves"
+      << " dis/en\n" << tempvar << "\n";
+
+  if (tempvar) {
+    app << "#BSP.absMaxAllowedDepth\tMaximum abs depth for empty cutting\n";
+    app << absMaxAllowedDepth << "\n";
+    app << "#BSP.maxEmptyCutDepth\tMaximum allowed depth for late cutting"
+	<< "(0-6)\n";
+    app << maxEmptyCutDepth << "\n";
+  }
+  
+  string termCrit;
+  Environment::GetSingleton()->GetStringValue("BSP.termCrit", termCrit);
+  app << "#BSP.termCrit\t\tTermination criteria to build up BSP tree\n";
+  app << termCrit << "\n";
+
+  maxCountTrials = 0;
+  if ( (!termCrit.compare("auto")) &&
+       (!termCrit.compare("auto2")) ) {
+    // everything except auto settings, when depth is determined 
+    // It should be reported for adhoc and possibly others
+    Environment::GetSingleton()->GetIntValue("BSP.maxDepthAllowed",
+					     maxDepthAllowed);
+    Environment::GetSingleton()->GetIntValue("BSP.maxListLength",
+					     maxListLength);
+    app << "#MaxDepth (Dmax)\tMaximal allowed depth of the BSP tree\n";
+    app << maxDepthAllowed << "\n";
+    app << "#MaxListLength (Noilf)\tMaximal number of solids in one cell\n";
+    app << maxListLength << "\n";
+    // maximum number of trials to further subdivide
+    maxCountTrials = (int)(1.0 + 0.2 * (float)maxDepthAllowed);
+    if (maxCountTrials < 3)
+      maxCountTrials = 3;
+  }
+  else {
+    if (!termCrit.compare("auto2") ) {
+      Environment::GetSingleton()->GetIntValue("BSP.maxListLength",
+					       maxListLength);
+      app << "#MaxDepth (Dmax)\tMaximal allowed depth of the BSP tree\n";
+    }
+  }
+  
+  float eCt, eCi, eCd;
+  Environment::GetSingleton()->GetFloatValue("BSP.decisionCost", eCd);
+  Environment::GetSingleton()->GetFloatValue("BSP.intersectionCost", eCi);
+  Environment::GetSingleton()->GetFloatValue("BSP.traversalCost", eCt);
+
+  // Ci should no be changed from 1.0, only Cd and Ct should be changed
+  app << "#SetBSP.(Cd, Ci, Ct) \tDecision, Intersection, ";
+  app << "and Traversal costs\n";
+  app << " ( " << eCd << ", " << eCi << " ," << eCt << " )\n";
+
+  return;
+}
+
+// -------------------------------------------------------
+// the next two axes for a given one
+const CKTBAxes::Axes
+CKTBABuildUp::oaxes[3][2]=
+{{CKTBAxes::EE_Y_axis, CKTBAxes::EE_Z_axis},
+ {CKTBAxes::EE_Z_axis, CKTBAxes::EE_X_axis},
+ {CKTBAxes::EE_X_axis, CKTBAxes::EE_Y_axis}};
+
+// -------------------------------------------------------
+// compare function passed to quicksort
+int
+CKTBABuildUp::Compare(const SItem *p, const SItem *q)
+{
+  register float pv = p->pos;
+  register float qv = q->pos;
+
+  if (pv < qv)
+    return 1;
+  else
+    if (pv > qv)
+      return -1;
+    else
+      // the coordinates are equal
+      if ( (p->IsRightBoundary()) &&
+           (q->IsLeftBoundary()) )
+        return 1; // right_boundary < left_boundary
+      else
+        if ( (p->IsLeftBoundary()) &&
+	     (q->IsRightBoundary()) )
+          return -1; // left_boundary > right_boundary
+
+  return 0; // coordinates are equal, the same value and type
+}
+
+// --------------------------------------------
+// This is sorting using quicksort
+void
+CKTBABuildUp::SortOneAxis(SItemVec &itemvec, int cnt, int * const stack)
+{
+  // the pointer to the stack
+  int stackUk = 0;
+  // setting initial beg and end index for the whole array
+  stack[++stackUk] = 0;
+  stack[++stackUk] = cnt - 1;
+  SItem auxSwap;
+  int e, b, i, j;
+  
+  while ( stackUk !=0 ) {
+    // retrieving indeces from the stack
+    j = e = stack[stackUk--]; // begin and end in the array
+    i = b = stack[stackUk--]; // auxiliary indeces
+
+    // selecting pivot .. in the best case median
+    SItem X = itemvec[(i+j) / 2];
+    do {
+      while (Compare(&(itemvec[i]), &X) > 0)
+        i++; // find the array[i] > array[x]=pivot
+      while (Compare(&(itemvec[j]), &X) < 0)
+        j--; // find the array[j] < array[x]=pivot
+      if (i < j) { // swap the elements
+        auxSwap = itemvec[i];
+        itemvec[i] = itemvec[j];
+        itemvec[j] = auxSwap;
+        i++; j--;
+      }
+      else
+        if (i == j) {
+          i++;
+          j--;
+        }
+    }
+    while (i <= j);
+    // Now all the elements on the left are smaller than pivot and
+    // all the right are larger than pivot
+#if 0
+#ifdef _DEBUG
+    int t;
+    for (t = b; t < j; t++) {
+      if (X.pos < itemvec[t].pos) {
+	cout << "Problem 1 for t = " << t << endl;
+	cout << "X->pos = " << X.pos << "a[t]= " << itemvec[t].pos << endl;
+      }
+    }
+    for (t = i; t < e; t++) {
+      if (X.pos > itemvec[t].pos) {
+	cout << "Problem 2 for t = " << t << endl;
+	cout << "X->pos = " << X.pos << "a[t]= " << itemvec[t].pos << endl;
+      }
+    }
+#endif    
+#endif    
+    if (b < j) { // go to the left
+      stack[++stackUk] = b;
+      stack[++stackUk] = j;
+    }
+    if (i < e) { // go to the right
+      stack[++stackUk] = i;
+      stack[++stackUk] = e;
+    }
+    // Just a check
+    assert(stackUk <= cnt);
+  } // while (stackUk)
+
+  return;
+}
+
+void
+CKTBABuildUp::CopyToAuxArray(const SItemVec &bounds, SItemVecRadix &aux)
+{
+  // assume that both arrays are of the same size
+  assert(bounds.size() <= aux.capacity());
+
+#if 1
+  // source iterator
+  SItemVec::const_iterator src = bounds.begin();
+  for (SItemVecRadix::iterator it = aux.begin();
+       it != aux.end();
+       it++, src++)
+  {
+    *it = *src; // copy one elem
+  }
+#else
+  // Attempt for vectorization
+  int i;
+  const int cnt = aux.size();
+  for (i = 0; i < cnt; i++) {
+    aux[i] = bounds[i];
+  }
+#endif
+  
+  return;
+}
+
+// -----------------------------------------------------------------
+// The first pass of radix sort setting the links
+void
+CKTBABuildUp::RadixPassHoffset11(SItemVecRadix &bounds, int bit,
+				 SRadix *rb, float offset,
+				 SItemRadix **start)
+{
+  // preparing the hash table
+  memset(rb, 0, sizeof(SRadix) * RXBUFS30);
+
+  SItemRadix *p;
+  SItemRadix *q;
+  //SRadix *r;
+
+  // linearly process the input array
+  //for (SItemVecRadix::iterator it = bounds.begin(); it != bounds.end(); it++)
+  const int cnt = bounds.size();
+  for (int i = 0; i < cnt; i++)
+  {
+    // Take the element linearly from the array
+    //p = &(*it);
+    p = &(bounds[i]);
+
+    // add offset to get positive value to be sorted
+    p->pos += offset;
+    assert(p->pos >= 0.f);
+    
+    // compute the index of the bucket
+    unsigned int *val = (unsigned int*)&(p->pos);
+    unsigned int bucket = (( (*val) >> bit) & (RXBUFS30 - 1));
+    assert( bucket < RXBUFS30 );
+    // compute the address of correct bucket
+    //r = rb + bucket;
+    if (!rb[bucket].beg) {
+      rb[bucket].end = rb[bucket].beg = p;   // inserting into empty cell, mark begin
+      p->next = 0; // new item is the end of chain
+    }
+    else {
+      // if the end of bounding box
+      if (p->IsRightBoundary()) {
+	// right boundary - store item at the beginning of the group
+	p->next = rb[bucket].beg;
+	rb[bucket].beg = p;
+      }
+      else {
+	// left boundary - store item at the end of the group
+	p->next = 0; // it is the end elem
+        rb[bucket].end->next = p;   // chain last item to new item
+	rb[bucket].end = p;
+      }
+    }
+  } // for all input data
+
+  // append groups together
+  // q used as start item
+  SItemRadix **fset = &q;
+
+  for(int j = 0; j < RXBUFS30; j++) {
+    // only used elements
+    if (rb[j].beg) {
+      *fset = rb[j].beg;             // store pointer to the next group
+      fset = &(rb[j].end->next); // prepare group's end for update
+    }
+  } // for all buckets
+
+  *start = q;
+  return;
+}
+
+// radix sort pass starting with 'bit' over 'axis', using buckets in 'rb'
+void
+CKTBABuildUp::RadixPass11(SItemRadix **start, int cnt, int bit, SRadix *rb)
+{
+  // preparing the hash table
+  memset(rb, 0, sizeof(SRadix) * RXBUFS30);
+
+  // list grouping
+  SItemRadix *p = *start;
+  SItemRadix *q;
+  //SRadix *r;
+
+  // process the items using links
+  for (int i = 0; i < cnt; i++) {
+    assert(p);
+    unsigned int *val = (unsigned int*)&(p->pos);
+    unsigned int bucket = (( (*val) >> bit) & (RXBUFS30 - 1));
+    assert(bucket < RXBUFS30);
+    //r = rb + bucket;
+    if (!rb[bucket].beg)
+      rb[bucket].beg = p;   // inserting into empty cell, mark begin
+    else
+      rb[bucket].end->next = p;   // chain last item to new item
+
+    rb[bucket].end = p;  // update the end of group
+    q = p->next; // save the next position
+    p->next = 0; // new item is the end of chain
+    p = q;
+  } // for all items
+
+  // append groups together
+  //r = rb;
+  // q used as start item
+  SItemRadix **fset = &q;
+
+  for(int j = 0; j < RXBUFS30; j++)
+    // only used elements
+    if (rb[j].beg) {
+      *fset = rb[j].beg;       // store pointer to the next group
+      fset = &(rb[j].end->next); // prepare group's end for update
+    }
+
+  *start = q;
+  return;
+}
+
+// radix sort pass starting with 'bit' over 'axis', using buckets in 'rb'
+void
+CKTBABuildUp::RadixPassOffset10(SItemRadix **start, int cnt, int bit,
+				SRadix *rb, float offset)
+{
+  // preparing the hash table
+  memset(rb, 0, sizeof(SRadix) * RXBUFS30_2);
+
+  // list grouping
+  SItemRadix *p = *start;
+  SItemRadix *q;
+  //SRadix *r;
+  
+  // process the items using links
+  for (int i = 0; i < cnt; i++) {
+    assert(p);
+    unsigned int *val = (unsigned int*)&(p->pos);
+    unsigned int bucket = (( (*val) >> bit) & (RXBUFS30_2 - 1));
+    assert(bucket < RXBUFS30_2);
+    //r = rb + bucket;
+    if (!(rb[bucket].beg)) {
+      rb[bucket].beg = p;   // inserting into empty cell, mark begin
+    }
+    else {
+      rb[bucket].end->next = p;   // chain last item to new item
+    }
+
+    rb[bucket].end = p;  // update the end of group
+
+    // Compute the correct value back, using the offset for the
+    // first pass
+    p->pos -= offset;
+
+    // go to the next item
+    q = p->next; // save the next position
+    p->next = 0; // new item is the end of chain
+    p = q; // take the next item
+  } // for all items
+
+  // append groups together and set bidirectional links
+  //r = rb;
+  SItemRadix *prev = 0;
+  for (int j = 0; j < RXBUFS30_2; j++) {
+    if (rb[j].beg) {
+      if (prev) {
+	// set forward link
+	prev->next = rb[j].beg; 
+      }
+      prev = rb[j].end;
+    }
+  } // for i
+
+  // Find the first item in the list
+  //r = rb;
+  for (int k = 0; k < RXBUFS30_2; k++) {
+    if (rb[k].beg) {
+      // find the beginning of the chain
+      *start = rb[k].beg;
+      break;
+    }
+  } // for
+  
+  return;
+}
+
+void
+CKTBABuildUp::CopyFromAuxArray(SItemRadix *sorted, SItemVec &bounds)
+{
+  // source iterator
+  SItemRadix *src = sorted;
+  //for (SItemVec::iterator it = bounds.begin(); it != bounds.end(); it++)
+
+  int i;
+  const int cnt = bounds.size();
+  for (i = 0; i < cnt; i++)
+  {
+    bounds[i] = *src; // copy one elem, forgetting the pointer 'next' 
+    src = src->next;
+  }
+
+  return;
+}
+
+
+// ---------------------------------------------------------------
+// sort the boundaries of objects' bounding boxes along all 3 axes
+void
+CKTBABuildUp::SortAxes(SInputData *data)
+{
+  // Note that cnt is the number of boundaries = odd number
+  assert(data);
+  assert(data->count);
+  
+  CTimer timer;
+  timer.Start();
+
+  // the number of boundaries
+  int cnt = 2*data->count;
+
+  if (!_useRadixSort) {
+    cout << "Sorting by quicksort " << flush;    
+#if 1
+    // this is the worst case allocation !!!
+    int *stackQuickSort = new GALIGN16 int [cnt+1];    
+    if (stackQuickSort == NULL) {
+      cerr << " ktbai.cpp: quicksort allocation failed\n";
+      exit(3);;
+    }
+    cout << " Qsort, sizeof(SItem)=" << sizeof(SItem)
+	 << " size(vec[0])= " << sizeof(data->xvec[0]) << endl;
+    assert(cnt == data->xvec->size());
+    assert(cnt == data->yvec->size());
+    assert(cnt == data->zvec->size());
+    // Sort all three axis by Quicksort
+    //cout << "Sort x" << endl;
+    SortOneAxis(*(data->xvec), data->xvec->size(), stackQuickSort);
+    //cout << "Check x" << endl;
+    Check1List(data->xvec, 0, data->xvec->size()/2);
+    //cout << "Sort y" << endl;
+    SortOneAxis(*(data->yvec), data->yvec->size(), stackQuickSort);
+    //cout << "Check y" << endl;
+    Check1List(data->yvec, 0, data->yvec->size()/2);
+    //cout << "Sort z" << endl;
+    SortOneAxis(*(data->zvec), data->zvec->size(), stackQuickSort);
+    //cout << "Check z" << endl;
+    Check1List(data->zvec, 0, data->zvec->size()/2);
+ 
+    // delete the data
+    delete [] stackQuickSort;
+#endif
+#if 0
+    sort(data->xvec->begin(), data->xvec->end());
+    sort(data->yvec->begin(), data->yvec->end());
+    sort(data->zvec->begin(), data->zvec->end());
+#endif
+#if 0
+    qsort(&(data->xvec[0]), data->xvec->size(), sizeof(data->xvec[0]),
+	  (int(*)(const void*, const void*))(&Compare));
+    Check1List(data->xvec, 0, data->xvec->size()/2);
+    
+    qsort(&(data->yvec[0]), data->yvec->size(), sizeof(data->yvec[0]),
+	  (int(*)(const void*, const void*))(&Compare));
+    qsort(&(data->zvec[0]), data->zvec->size(), sizeof(data->zvec[0]),
+	  (int(*)(const void*, const void*))(&Compare));
+#endif
+  }
+  else {
+    // -----------------------------------------------
+    // Implementation by RadixSort with 3 passes, faster by 30% or so
+    // than 4-passes RadixSort, see ktbi.cpp
+    cout << "Sorting by radixsort3 " << flush;
+    SRadix *rb = new GALIGN16 SRadix[RXBUFS30];
+    assert(rb);
+    // the auxiliary array for sorting
+    SItemVecRadix *aux = new GALIGN16 SItemVecRadix();
+    assert(aux);
+    aux->resize(cnt);
+    // change axis
+    for(int i = 0; i < 3; i++) {      
+      // Offset to get only positive values to be sorted
+      float offset = -(wBbox.Min(i));
+      // Get a single array of bounds
+      SItemVec *bounds = data->GetItemVec(i);
+      assert(bounds);
+      // sort 3 times using 10 bits in one pass
+      CopyToAuxArray(*bounds, *aux);
+      // take the first elem and start radix sort
+      SItemRadix *start = 0;
+      // first pass: bits 0-10
+      RadixPassHoffset11(*aux, RXBITS30 * 0, rb, offset, &start);
+      // second pass: bits 11-21
+      RadixPass11(&start, cnt, RXBITS30 * 1, rb);
+      // third pass: bits 22-31 (bit 32 is sign)
+      RadixPassOffset10(&start, cnt, RXBITS30 * 2, rb, offset);
+      // Copy the sorted data back to the array, forgetting pointer 'next'
+      CopyFromAuxArray(start, *bounds);
+    }
+    // delete aux array
+    delete aux;
+    delete [] rb;
+    // end of radix sort
+  }
+
+  timer.Stop();
+  // ------------------------------------------
+  cout << " finished in " << timer.UserTime() << " [s] - user time " << endl;
+
+#ifdef _DEBUG
+  // check if the lists are correctly sorted .. in debug
+  // DEBUG << "SortAxis check\n" << flush;
+  Check3List(data);
+#endif
+
+  return;
+}
+
+// test if the lists are correctly sorted
+void
+CKTBABuildUp::Check3List(SInputData *data)
+{
+#ifndef AVOIDCHECKLIST
+#ifdef _DEBUG
+  assert(data);
+  if (data->xvec->size() != (unsigned int)data->count*2) {
+    cerr << "The number of X boundaries does not match" << endl;
+    abort();;
+  }
+  if (data->yvec->size() != (unsigned int)data->count*2) {
+    cerr << "The number of Y boundaries does not match" << endl;
+    abort();;
+  }
+  if (data->zvec->size() != (unsigned int)data->count*2) {
+    cerr << "The number of Z boundaries does not match" << endl;
+    abort();;
+  }
+  Check1List(data, 0, data->count);
+  Check1List(data, 1, data->count);
+  Check1List(data, 2, data->count);
+#endif // _DEBUG
+#endif // AVOIDCHECKLIST
+  return;
+}
+
+// test if one list is correctly sorted
+void
+CKTBABuildUp::Check1List(SInputData *data, int axis, int countExpected)
+{
+#ifndef AVOIDCHECKLIST
+#ifdef _DEBUG
+  assert((axis >= 0) && (axis < 3));  
+  SItemVec *vec = data->GetItemVec(axis);
+  assert(vec);
+  if (countExpected)
+    Check1List(vec, axis, countExpected);
+  else {
+    if (vec->size() > 0) {
+      cerr << "The array of objects should be of zero size"<<endl;
+      abort();;
+    }
+  }
+#endif // _DEBUG
+#endif // AVOIDCHECKLIST
+}
+
+// test if one list is correctly sorted
+void
+CKTBABuildUp::Check1List(SItemVec *vec, int axis, int countExpected)
+{
+#ifndef AVOIDCHECKLIST
+#ifdef _DEBUG
+  int cntl,cntr; // the number of left/right boundaries
+  
+  // DEBUG << "Check1List starting\n";
+  cntl = 0; // the number of left boundaries
+  cntr = 0; // the number of right boundaries
+  int cntDups = 0; // the number of duplications for current position
+
+  // the position to check
+  SItemVec::iterator prev = vec->begin();
+  
+  // DEBUG << p->value[i] << "\n";
+  if ( (*prev).IsLeftBoundary()) {
+    cntl++;
+    cntDups++;
+  }
+  else {
+    cntr++;
+    cntDups--;
+  }
+  // the next item
+  SItemVec::iterator it = vec->begin();
+  it++;
+  // start from the second item
+  int index = 1;
+  bool firstDupsProb = false;
+  for ( ; it != vec->end(); it++, prev++, index++)
+  {
+    const SItem &p = *it;
+
+    if (p.obj->ToBeRemoved()) {
+      cout << "Object to be removed, obj = "
+	   << p.obj << " -- it should not happen" << endl;
+    }
+    
+    // DEBUG << p->value[i] << "\n";
+    if (p.IsLeftBoundary()) {
+      cntl++;
+      cntDups++;
+    }
+    else {
+      cntr++;
+      cntDups--;
+    }
+
+    if (cntDups < 0) {
+      cerr << "The array is sorted in wrong way, cntDups = "
+	    << cntDups << " index= " << index << " indexMax="
+	    << countExpected*2 << endl;
+      if (!firstDupsProb) {
+	int imin = index-3;
+	if (imin < 0) imin = 0;
+	int imax = index+3;
+	if (imax > countExpected*2) imax = countExpected*2;
+	for (int i = imin; i < imax; i++) {
+	  cout << "i= " << i << "  pos = " << (*vec)[i].pos;
+	  if ((*vec)[i].IsLeftBoundary())
+	    cout << "  L  ";
+	  else
+	    cout << "  R  ";
+	  cout << (*vec)[i].obj << endl;
+	}
+      }      
+      firstDupsProb = true;
+    }
+    
+    if ( (*prev).pos > p.pos) {
+      cerr << "The array is for axis=" <<(int)axis<<" incorrectly sorted\n";
+      cerr << "prevPos = " << (*prev).pos << " curr->pos="
+	    << p.pos << "\n";
+      abort();;
+    }
+    else {
+      if ( ((*prev).pos == p.pos) &&
+	   ( (*prev).IsLeftBoundary()) &&
+	   ( (*it).IsRightBoundary()) )  {
+	if (countExpected > 1) {
+	  cerr << "The right and left boundary are incorrectly sorted, axis = "
+		<< axis << "\n";
+	  int i = 0;
+	  for (SItemVec::iterator itt = vec->begin(); itt != vec->end(); itt++, i++)
+	    {
+	      cout << i << " = ";
+	      if ((*itt).IsLeftBoundary())
+		cout << "L"; else cout << "R";	  
+	      cout << " obj = " << (*itt).obj << " pos = " << (*itt).pos << endl;
+	    }
+	} // if more than one object
+      }
+    }
+  } // for all items
+
+  if (cntl != cntr) {
+    cerr << "The #left boundaries <> #right boundaries\n";
+    cerr << " #left boundaries= " << cntl << " #right boundaries= "
+	  << cntr  << "  axis= " << (int)axis << "\n";
+    abort();;
+  }
+    
+  if (countExpected > 0) {
+    if (cntl != countExpected) {
+      cerr << "The number of found left boundaries = " << cntl
+	    << " does not equal to expected count = " << countExpected << endl;
+    }
+    if (cntr != countExpected) {
+      cerr << "The number of found right boundaries = " << cntr
+	    << " does not equal to expected count = " << countExpected << endl;
+    }
+  } // if checking of count is allowed
+  
+  cerr << flush;
+#endif // _DEBUG  
+#endif // AVOIDCHECKLIST
+}
+
+// Init required parameters
+void
+CKTBABuildUp::InitReqPref(SReqPrefParams *pars)
+{
+  // nothing is obligatory as default
+  pars->reqPosition = Limits::Infinity;
+  pars->reqAxis = CKTBAxes::EE_Leaf;
+  pars->useReqAxis = false;
+  
+  // the values for automatic termination criteria, since it was
+  // not subdivided
+  pars->ratioLast = 1000.0;
+  pars->ratioLastButOne = 1000.0;
+  pars->failedSubDivCount = 0;
+
+  Environment::GetSingleton()->GetIntValue("BSP.axisSelectionAlg",
+					   _algorithmForAxisSelection);
+  if (_algorithmForAxisSelection != 0) {
+    // The axis as prefered one - testing all 3 axes. Start
+    // from the axis cutting the longest side of the box
+    pars->reqAxis = (CKTBAxes::Axes)(wBbox.Diagonal().DrivingAxis());
+  }
+
+  return;
+}
+
+// creates all the auxiliary structures for building up CKTB tree
+CKTBABuildUp::SInputData*
+CKTBABuildUp::Init(ObjectContainer *objlist, const AxisAlignedBox3 &box)
+{
+#ifdef  _RANDOMIZE_POSITION
+  //world->_environment.GetFloat("SetBSP.randomizePosition.Eps", randomEps);
+#endif // _RANDOMIZE_POSITION
+  
+#ifdef _KTB_CONSTR_STATS
+  _stats_interiorCount = 0;
+  _stats_bboxCount = 0;
+  _stats_leafNodeCount = 0;
+  _stats_emptyLeftNodeCount = 0;
+  // Aggregate statistics
+  _maxDepth = 0;  
+  _sumLeafDepth = 0;
+  _sumFullLeafDepth = 0;
+  _sumObjectRefCount = 0;
+  _maxObjectRefInLeaf = 0;
+  // surface areas
+  _sumSurfaceAreaLeaves = 0.f;
+  _sumSurfaceAreaMULcntLeaves = 0.f;
+  _sumSurfaceAreaInteriorNodes = 0.f;
+#endif
+  // If to print out the tree during contruction
+  Environment::GetSingleton()->GetBoolValue("BSP.printCuts", _printCuts);
+
+  // if to cut off empty space in postprocessing and how it is performed
+  Environment::GetSingleton()->GetBoolValue("BSP.emptyCut", cutEmptySpace);
+  Environment::GetSingleton()->GetBoolValue("BSP.useRadixSort", _useRadixSort);
+  Environment::GetSingleton()->GetIntValue("BSP.absMaxAllowedDepth",
+					   absMaxAllowedDepth);
+  Environment::GetSingleton()->GetIntValue("BSP.maxEmptyCutDepth",
+					   maxEmptyCutDepth);
+  Environment::GetSingleton()->GetIntValue("BSP.algAutoTermination",
+					   algorithmAutoTermination);
+  Environment::GetSingleton()->GetFloatValue("BSP.biasFreeCuts",
+					     biasFreeCuts);
+#ifdef _BIDIRLISTS
+  // if to clip the bounding boxes
+  Environment::GetSingleton()->GetBoolValue("BSP.splitclip", splitClip);
+#else
+  // Without bidirectional list we cannot make split clipping
+  splitClip = false;
+#endif // _BIDIRLISTS
+
+  // if to make tagging lists inside the tree
+  Environment::GetSingleton()->GetBoolValue("BSP.minBoxes.use",
+					    makeMinBoxes);
+  Environment::GetSingleton()->GetBoolValue("BSP.minBoxes.tight",
+					    makeTightMinBoxes);
+  Environment::GetSingleton()->GetIntValue("BSP.minBoxes.minObjects",
+					    minObjectsToCreateMinBox);
+  Environment::GetSingleton()->GetIntValue("BSP.minBoxes.minDepthDistance",
+					   minDepthDistanceBetweenMinBoxes);
+  Environment::GetSingleton()->GetFloatValue("BSP.minBoxes.minSA2ratio",
+					     minSA2ratioMinBoxes);
+
+  // How many items can be allocated at once
+  int maxItemsAtOnce = 1;
+  if (makeMinBoxes) {
+#ifdef _KTB8Bytes    
+    // We need to allocate for boxes the memory in a row
+    maxItemsAtOnce = 5; // 8x5=40 = 16+24;
+#else
+    maxItemsAtOnce = 4; // 12x4=48 = 24+24;
+#endif // _KTB8Bytes
+    assert(minObjectsToCreateMinBox >= 1);
+    assert(minDepthDistanceBetweenMinBoxes >= 0);
+    assert(minDepthDistanceBetweenMinBoxes <= 50);
+  }
+
+  // Initiate the allocator
+  InitAux(0, MAX_HEIGHT - 1, maxItemsAtOnce);
+  
+  // since six planes are enough to cull empty space from leaves
+  if ( (maxEmptyCutDepth < 0) ||
+       (maxEmptyCutDepth > 6) ) {
+    cerr << "BSP.maxEmptyCutDepth = " << maxEmptyCutDepth
+	  << " must be in range <0,6>\n";
+    abort();;
+  }
+
+  wBbox.Convert(box); // the box of the whole scene
+  boxSize = box.Diagonal(); // the size of the box along the axes
+  
+  wholeBoxArea = wBbox.SA2(); // the half of the surface area of the box
+  
+  // the array of bounding boxes and duplications to the objects
+  int objlistcnt = objlist->size();
+
+  // Here create the auxiliary array
+  //solidArray.reserve(objlistcnt);
+  // $$JB - crashed below 
+  solidArray.resize(objlistcnt);
+
+  // Here create the first entry of boundaries for all objects
+  SInputData* data = AllocNewData();
+  // set the box
+  data->box = wBbox;
+  // which algorithm to use for break-ax
+#if 1
+  data->algorithmBreakAx = 0; // position based
+#else  
+  data->algorithmBreakAx = 1; // pointer based
+#endif
+
+#ifdef _RANDOMIZE_POSITION
+  data->algorithmBreakAx = 0; // position based
+#endif
+
+  resetFlagsForBreakAx = true;
+  
+  assert(objlistcnt > 0);
+  
+  // allocate the array of boundaries for all 3 axes
+  data->Alloc(data->count*2);
+  // set the number of objects
+  data->count = objlistcnt;
+  int i = 0;
+  // cout << data->xvec->size()  << "  " << data->count*2 << endl;
+  // create the list of bounding boxes
+  for (ObjectContainer::iterator scr = objlist->begin();
+       scr != objlist->end(); scr++, i++) {
+    // set the object
+    solidArray[i].obj = *scr;
+    solidArray[i].flags = 0;
+    SSolid *solid = &(solidArray[i]);
+    // create bounding box of the object
+    SBBox abox;
+    abox.Convert((*scr)->GetBox());    
+    // copy the boundaries to the arrays
+    // max boundaries as first because of stable quicksort
+    SItem itemX;
+    itemX.pos = abox.Min(0);
+    itemX.obj = solid;
+    itemX.axis = 0;
+    itemX.SetLeftBoundary();
+    data->xvec->push_back(itemX);
+
+    SItem itemY;
+    itemY.pos = abox.Min(1);
+    itemY.obj = solid;
+    itemY.axis = 1;
+    itemY.SetLeftBoundary();
+    data->yvec->push_back(itemY);
+
+    SItem itemZ;
+    itemZ.pos = abox.Min(2);
+    itemZ.obj = solid;
+    itemZ.axis = 2;
+    itemZ.SetLeftBoundary();
+    data->zvec->push_back(itemZ);
+
+    // max boundaries
+    itemX.pos = abox.Max(0);
+    itemX.SetRightBoundary();
+    data->xvec->push_back(itemX);
+
+    itemY.pos = abox.Max(1);
+    itemY.SetRightBoundary();
+    data->yvec->push_back(itemY);
+
+    itemZ.pos = abox.Max(2);
+    itemZ.SetRightBoundary();
+    data->zvec->push_back(itemZ);
+  } // for all objects
+
+  // cout << data->xvec->size()  << "  " << data->count*2 << endl;
+  
+  assert(data->xvec->size() == (unsigned int)data->count*2);
+  data->xvec->resize(data->count*2);
+  assert(data->yvec->size() == (unsigned int)data->count*2);
+  data->yvec->resize(data->count*2);
+  assert(data->zvec->size() == (unsigned int)data->count*2);
+  data->zvec->resize(data->count*2);
+  
+  // If to use radix sort or quicksort
+  //_useRadixSort = true;
+  // Note that quicksort does not work for some reason !! 27/12/2005
+  //_useRadixSort = false;
+
+  // sort all the bounding boxes along the axes
+  if ((initcnt = objlist->size()) != 0)
+    SortAxes(data);
+
+  // The statistics init
+  cntDuplicate = 0;
+
+  // Init the parameters from the environment file
+  InitReqPref(&(data->pars));
+
+  // Init the termination criteria
+  string termCrit;
+  Environment::GetSingleton()->GetStringValue("BSP.termCrit", termCrit);
+
+  maxCountTrials = 0;
+  if (!termCrit.compare("adhoc")) {
+    // termination criteria are the max depth of the hierarchy, number
+    // of primitives
+    data->modeSubDiv = EE_SUBDIVADHOC;
+    Environment::GetSingleton()->GetIntValue("BSP.maxListLength",
+					     maxListLength);
+    Environment::GetSingleton()->GetIntValue("BSP.maxDepthAllowed",
+					     maxDepthAllowed);
+  }
+  else {
+    if ( (!termCrit.compare("auto")) ||
+	 (!termCrit.compare("auto2")) ) {
+      // automatic termination criteria are used, everything is computed
+      // automatically from number of objects etc.
+      int estHeight = (int)(log((float)initcnt)/log((float)2.0) + 0.9);
+      // cout << "EstHeight=" << estHeight << endl;
+      maxDepthAllowed = (int)((float)estHeight * 1.2 + 2.0);
+
+      // maximum number of trials to further subdivide
+      maxCountTrials = (int)(1.0 + 0.2 * (float)maxDepthAllowed);
+      if (maxCountTrials < 3)
+	maxCountTrials = 3;
+      
+      // for 'auto2' we specify the length of the object list by hand
+      if (!termCrit.compare("auto2"))
+	Environment::GetSingleton()->GetIntValue("BSP.maxListLength",
+						 maxListLength);
+      else
+	// for 'auto' we set the length of the object list that is supposed
+	// to be the best for ray shooting
+	maxListLength = 1;
+
+      if (verbose) {
+	cout << "TERMCRIT:maximum height of a leaf set to "
+	       << maxDepthAllowed << "\n";
+	cout << "TERMCRIT:maximum number of objects in leaf set to "
+	       << maxListLength << "\n" ;
+      }
+      // set the mode to be recognized
+      data->modeSubDiv = EE_SUBDIVAUTOMATIC;
+    }
+    else {
+      cerr << " unknown termination criteria for BSP tree\n";
+      cerr << "It was specified: " << termCrit << "\n";
+      cerr << "Allowed types = auto, auto2, adhoc" << endl;
+      exit(3);;
+    }
+  }
+
+  // for some evaluation it is necessary to determine the following costs
+  Environment::GetSingleton()->GetFloatValue("BSP.traversalCost", Ct);
+  Environment::GetSingleton()->GetFloatValue("BSP.intersectionCost", Ci);
+  if (verbose)
+    cout << "Ct=" << Ct << " Ci=" << Ci << "\n";
+  
+  if (cutEmptySpace) {
+    // correct the maximum abs depth, when late cutting is allowed
+    if (absMaxAllowedDepth < maxDepthAllowed)
+      absMaxAllowedDepth = maxDepthAllowed;
+    if (absMaxAllowedDepth > (maxDepthAllowed + maxEmptyCutDepth) )
+      absMaxAllowedDepth = maxDepthAllowed + maxEmptyCutDepth;
+    if (absMaxAllowedDepth >= MAX_HEIGHT) {
+      absMaxAllowedDepth = MAX_HEIGHT;
+      maxDepthAllowed = MAX_HEIGHT - maxEmptyCutDepth;
+    }
+    
+    if (verbose) {
+      cout << "Cutting off empty spaces ON\n";
+      cout << "BSP.absMaxAllowedDepth = " << absMaxAllowedDepth << "\n";
+      cout << "BSP.maxEmptyCutDepth = " << maxEmptyCutDepth << endl;
+    }
+  }
+
+  if (verbose)
+    cout << "MaxListLength = " << maxListLength << endl;  
+
+  return data;
+}
+
+// interface function for building up CKTB tree
+SKTBNodeT*
+CKTBABuildUp::BuildUp(ObjectContainer &objlist,
+		      const AxisAlignedBox3 &box,
+		      bool verboseF)
+{
+  // check the number of objects
+  if (objlist.size() == 0)
+    return 0; // nothing
+  cerr<<"hh44"<<endl;
+  // initialize the whole box of the kd-tree and sort
+  // the boundary entries
+  SInputData *d = Init(&objlist, box);
+
+  cerr<<"hh45"<<endl;
+
+  // copy verbose to be used consistenly further on
+  this->verbose = verboseF;
+  
+  if (verbose)
+    cout << "Building up KTB tree for " << objlist.size()
+		 << " objects." << endl << flush;
+
+  // Initialization of the first value to insert the min boxes
+  d->lastMinBoxSA2 = box.SurfaceArea() * 10000.f;
+  d->lastDepthForMinBoxes = -20; // for root you always put the node
+  d->lastMinBoxNode = 0;
+  
+  // -----------------------------------------------
+  // Start to build the tree
+  if ( (cutEmptySpace) &&
+       (initcnt <= maxListLength)) {
+    // only cutting off empty space for initial leaf
+    d->modeSubDiv = EE_SUBDIVCUTEMPTY;
+    root = SubDiv(d);
+  }
+  else {
+    // normal subdivision scheme, creating whole tree
+    root = SubDiv(d);
+  }
+
+#ifdef _DEBUG
+  if (GetDepth() != 0) {
+    cerr << "Using depth value does not work correctly, depth = "
+	  << GetDepth() << endl;
+  }
+#endif  
+  assert(root);  
+
+  // ----------------------------------------------------
+  // Deallocate all auxiliary data
+  DeleteAuxiliaryData();
+
+  // delete the temporary data array
+  solidArray.resize(0);
+  
+  // the pointer to the root node
+  return GetRootNode();
+}
+
+int
+CKTBABuildUp::UpdateEvaluation(float &eval, const float &newEval)
+{
+  if (newEval < eval) {
+    eval = newEval;
+    return 1; // updated
+  }
+  return 0; // not updated
+}
+
+// recursive function for subdividing the CKTB tree into two
+// halves .. creates one node of CKTB tree
+// list .. list of boundaries, count .. number of objects in current node
+// bb .. current bounding box of node, (pars,reqGlobAxis, modeSubDiv) .. cut pref.
+SKTBNodeT*
+CKTBABuildUp::SubDiv(SInputData *d)
+{ 
+#ifdef _DEBUG
+  Check3List(d);
+#endif
+
+#if 0
+  static int index = 0;
+  cout << "SubDiv index = " << index << endl;
+  const int indexToFind = 13916;
+  if (index == indexToFind) {
+    cout << " IndexToFind = " << indexToFind << endl;
+    cout << " You should start debug" << endl;
+  }
+  index++;
+#endif
+
+  // This is the node to return from this function
+  SKTBNodeT *nodeToReturn = 0;
+
+  // if to make the interior node extended by the box here
+  makeMinBoxHere = false;
+
+  // -----------------------------------------------------
+  if (makeMinBoxes) {
+#if 1
+    if ( (d->count >= minObjectsToCreateMinBox) &&
+	 (GetDepth() - d->lastDepthForMinBoxes >= minDepthDistanceBetweenMinBoxes) )  {
+	makeMinBoxHere = true;
+	d->lastDepthForMinBoxes = GetDepth();
+	d->lastMinBoxSA2 = d->box.SA2();
+    }
+#endif
+#if 0
+    if (d->count >= minObjectsToCreateMinBox) {
+      if ( (d->lastMinBoxSA2 >= d->box.SA2() * minSA2ratioMinBoxes) &&
+	   (GetDepth() - d->lastDepthForMinBoxes >= minDepthDistanceBetweenMinBoxes) ) {
+	makeMinBoxHere = true;
+	d->lastDepthForMinBoxes = GetDepth();
+	d->lastMinBoxSA2 = d->box.SA2();
+      }
+    }
+#endif
+#if 0
+    if ( (d->count >= minObjectsToCreateMinBox) &&
+	 (GetDepth() % minDepthDistanceBetweenMinBoxes == 0) ) {
+      makeMinBoxHere = true;
+      d->lastDepthForMinBoxes = GetDepth();
+      d->lastMinBoxSA2 = d->box.SA2();
+    }
+#endif
+  }
+
+  if ( (makeMinBoxHere) && (makeTightMinBoxes) ) {
+    // In case we should make the box of the current
+    // interior node and this should be tight, we have
+    // to first compute its extent before splitting
+    SBBox tightbox;
+    GetTightBox(*d, tightbox);
+    // Here we decrease the box to the minimum size
+    d->box = tightbox;
+  }
+  
+  // ------------------------------------------------------------------
+  // if we are forced to make subdivision at given point
+  if (d->pars.reqPosition != Limits::Infinity) {
+    // this code preceeds switch(mode) since 2-level evaluation
+    d->position = d->pars.reqPosition;
+    d->axis = d->pars.reqAxis;
+    // next subdivison will not be forced
+    d->pars.reqPosition = Limits::Infinity; 
+    d->pars.reqAxis = CKTBAxes::EE_Leaf;
+    IncDepth();
+    SKTBNodeT* n = MakeOneCut(d);
+    if (!nodeToReturn)
+      nodeToReturn = n;
+    DecDepth();
+    return nodeToReturn;
+  }
+  
+  // -------------------------------------------------------------------------
+  // determine between subdivision modes - different termination criteria
+  switch (d->modeSubDiv) { // subdivision mode
+    case EE_SUBDIVCUTEMPTY: { // cutting off empty space
+      if ((GetDepth() >= absMaxAllowedDepth) ||
+	  (GetDepth() >= (startEmptyCutDepth + maxEmptyCutDepth)) ||
+	  (d->count == 0) ) {
+        SKTBNodeT* n = MakeLeaf(d);
+	if (!nodeToReturn)
+	  nodeToReturn = n;
+	// cout << "LEC\n";
+        return nodeToReturn;
+      }
+      // to require the axis has no meaning in cutting off 
+      d->pars.reqAxis = d->axis = CKTBAxes::EE_Leaf;
+      break;
+    }
+    // both adhoc, clustering and automatic termination criteria
+    case EE_SUBDIVADHOC:
+    case EE_SUBDIVAUTOMATIC: {
+      // automatic termination criteria are used in this phase as
+      // the absolute threshold similarly to SUBDIVADHOC mode
+      if ( (GetDepth() >= maxDepthAllowed) ||
+	   (d->count <= maxListLength)) {
+        SKTBNodeT* n = MakeLeaf(d);
+	if (!nodeToReturn)
+	  nodeToReturn = n;
+	// cout << "LLA\n";
+        return nodeToReturn;
+      }
+      break;
+    }
+    default: {
+      cerr << " unknown subdivision mode in ibsp.cpp\n";
+      abort();;
+    }
+  } // switch(modeSubDiv)
+  
+  // the axis where splitting should be done
+  CKTBAxes::Axes axis = CKTBAxes::EE_Leaf;
+  d->twoSplits = -1;
+  d->bestCost = WorstEvaluation() * 0.5f;
+  d->position = MAXFLOAT;
+  d->cntThickness = 0;
+
+// which calls should be used, standard or optimized
+#if 1
+#define CallGetSplitPlaneX GetSplitPlaneOpt2
+#define CallGetSplitPlaneY GetSplitPlaneOpt2
+#define CallGetSplitPlaneZ GetSplitPlaneOpt2
+#endif
+#if 0
+// This does not work for unknown reason... VH 2006/01/08
+#define CallGetSplitPlaneX GetSplitPlaneOpt3
+#define CallGetSplitPlaneY GetSplitPlaneOpt3
+#define CallGetSplitPlaneZ GetSplitPlaneOpt3
+#endif
+#if 0
+#define CallGetSplitPlaneX GetSplitPlaneOptUnroll4
+#define CallGetSplitPlaneY GetSplitPlaneOptUnroll4
+#define CallGetSplitPlaneZ GetSplitPlaneOptUnroll4
+#endif
+  
+  // if the axis is required in pars structure for some reasons
+  if (d->pars.useReqAxis) {
+    axis = d->pars.reqAxis;
+    // The next subdivision is not prescribed
+    d->pars.useReqAxis = false;
+    switch(axis) {
+      case CKTBAxes::EE_X_axis : {
+	state.InitXaxis(d->count, d->box); // init
+	CallGetSplitPlaneX(d->xvec, 0); // evaluate
+	break;
+      }
+      case CKTBAxes::EE_Y_axis : {
+	state.InitYaxis(d->count, d->box); // init
+	CallGetSplitPlaneY(d->yvec, 1); // evaluate
+	break;
+      }
+      case CKTBAxes::EE_Z_axis : {
+	state.InitZaxis(d->count, d->box); // init
+	CallGetSplitPlaneZ(d->zvec, 2); // evaluate
+	break;
+      }
+      default: {
+	cerr << "No other option is allowed here" << endl;
+	abort();;
+      }
+    }
+    // compute the cost, normalized by surface area
+    state.NormalizeCostBySA2();
+    d->bestCost /= state.areaWholeSA2;
+    if (UpdateEvaluation(d->bestCost, state.bestCost)) {
+      // Compute correct position to be used for splitting
+      d->position = (*(state.bestIterator)).pos;
+      d->bestIterator = state.bestIterator;
+      d->twoSplits = state.bestTwoSplits; // one or two splitting planes planed
+      d->cntThickness = state.bestThickness;
+      if (d->twoSplits > 1) {
+	SItemVec::iterator it = state.bestIterator; it++;      
+	if (it != d->GetItemVec(axis)->end())
+	  d->position2 = (*it).pos;
+	else
+	  d->position2 = state.box.Max(axis);
+      }
+    }
+  }
+  else {
+    int algorithmForAxisSel = _algorithmForAxisSelection;
+    if (d->modeSubDiv == EE_SUBDIVCUTEMPTY)
+      algorithmForAxisSel = 0;
+
+    // only a single axis will be tested
+    bool useSingleAxis = true;
+        
+    // the required axis is by global function .. e.g. cyclic change x, y, z
+    switch (algorithmForAxisSel) {
+      case 0: {
+	// all three axis will be used, starting from x, y, z
+	useSingleAxis = false;
+	break;
+      }
+      case 1: {
+	// cyclic order of axes, x, y, z, x, y....
+	axis = d->pars.reqAxis;
+	// compute the axis for the next subdivision step
+	d->pars.reqAxis = oaxes[axis][0];
+	break;
+      }
+      case 2 : {
+	// The next time will be determined the same way
+	axis = (CKTBAxes::Axes)(d->box.Diagonal().DrivingAxis());
+	break;
+      }
+      case 3 : {
+	float p = RandomValue(0.0f, 1.0f);
+	const float thresholdAxisP = 0.8f;
+	if (p < thresholdAxisP) {	  
+	  axis = (CKTBAxes::Axes)(d->box.Diagonal().DrivingAxis());
+	}
+	else {
+	  // Use the axis prescribed from previous step
+	  axis = d->pars.reqAxis;
+	}
+	// for the next time, different axis
+	d->pars.reqAxis = oaxes[axis][0];
+	break;
+      }
+      case 4 : {
+	float p = RandomValue(0.0f, 1.0f);
+	const float thresholdAxisP = 0.3f;
+	if (p < thresholdAxisP) {	  
+	  axis = (CKTBAxes::Axes)(d->box.Diagonal().DrivingAxis());
+	}
+	else {
+	  // Use the axis prescribed from previous step
+	  axis = d->pars.reqAxis;
+	}
+	// for the next time, different axis
+	d->pars.reqAxis = oaxes[axis][0];
+	break;
+      }
+      case 5 : {
+	float p = RandomValue(0.0f, 1.0f);
+	const float thresholdAxisP = 0.2f;
+	d->pars.reqAxis = (CKTBAxes::Axes)-1;
+	if (p < thresholdAxisP) {
+	  axis = (CKTBAxes::Axes)(d->box.Diagonal().DrivingAxis());
+	  // for the next time, different axis
+	}
+	else {
+	  // Use the axis for which cost model gets minimum,
+	  // compute it for all axes x, y, z
+	  useSingleAxis = false;
+	}
+	break;
+      }
+      default: {
+	cerr << "Selection algorithm = " << algorithmForAxisSel
+	      << " for axis is not implemented" << endl;
+	abort();;
+      }
+    } // switch
+
+    // How the algorithm is used
+    if (useSingleAxis) {
+      // -------------------------------------------
+      // Compute subdivision only for one axis
+      switch(axis) {
+        case CKTBAxes::EE_X_axis : {
+	  state.InitXaxis(d->count, d->box); // init
+	  CallGetSplitPlaneX(d->xvec, 0); // evaluate
+	  break;
+	}
+        case CKTBAxes::EE_Y_axis : {
+	  state.InitYaxis(d->count, d->box); // init
+	  CallGetSplitPlaneY(d->yvec, 1); // evaluate
+	  break;
+	}
+        case CKTBAxes::EE_Z_axis : {
+	  state.InitZaxis(d->count, d->box); // init
+	  CallGetSplitPlaneZ(d->zvec, 2); // evaluate
+	  break;
+	}
+	//case CKTBAxes::EE_Leaf : {
+	//goto MAKE_LEAF;
+        //}
+        default: {
+	  cerr << "Selection algorithm = " << algorithmForAxisSel
+		<< " for axis = " << axis <<" is not implemented" << endl;
+	  abort();;
+	}
+      }
+      state.NormalizeCostBySA2();
+      d->bestCost /= state.areaWholeSA2;
+      if (UpdateEvaluation(d->bestCost, state.bestCost)) {
+	// Compute correct position to be used for splitting
+	d->position = (*(state.bestIterator)).pos;
+	d->bestIterator = state.bestIterator;
+	d->twoSplits = state.bestTwoSplits; // one or two splitting planes planed
+	d->cntThickness = state.bestThickness;
+	if (d->twoSplits > 1) {
+	  SItemVec::iterator it = state.bestIterator; it++;      
+	  if (it != d->GetItemVec(axis)->end())
+	    d->position2 = (*it).pos;
+	  else
+	    d->position2 = state.box.Max(axis);
+	}
+      }
+    }
+    else {
+      // no axis is required, we can pickup any we like. We test all three axis
+      // and we pickup the minimum cost for all three axes.
+      state.InitXaxis(d->count, d->box); // init for x axis
+      CallGetSplitPlaneX(d->xvec, 0); // evaluate for x axis
+      if (UpdateEvaluation(d->bestCost, state.bestCost)) {      
+	axis = CKTBAxes::EE_X_axis; // the x-axis should be used
+	// Compute correct position to be used for splitting
+	d->bestCost = state.bestCost;
+	d->position = (*(state.bestIterator)).pos;
+	d->bestIterator = state.bestIterator;
+	d->twoSplits = state.bestTwoSplits; // one or two splitting planes planed
+	d->cntThickness = state.bestThickness;
+	if (d->twoSplits > 1) {
+	  SItemVec::iterator it = state.bestIterator;
+	  it++;
+	  if (it != d->xvec->end())
+	    d->position2 = (*it).pos;
+	  else
+	    d->position2 = state.box.Max().x;
+	}
+      }
+      // -----------------------
+      // now test for y axis
+      state.ReinitYaxis(d->count, d->box); // init for x axis
+      //state.InitYaxis(d->count, d->box); // init for x axis
+      CallGetSplitPlaneY(d->yvec, 1); // evaluate for x axis
+      if (UpdateEvaluation(d->bestCost, state.bestCost)) {
+	axis = CKTBAxes::EE_Y_axis; // the y-axis should be used
+	// Compute correct position to be used for splitting
+	d->position = (*(state.bestIterator)).pos;
+	d->bestIterator = state.bestIterator;
+	d->twoSplits = state.bestTwoSplits; // one or two splitting planes planed
+	d->cntThickness = state.bestThickness;
+	if (d->twoSplits > 1) {
+	  SItemVec::iterator it = state.bestIterator;
+	  it++;
+	  if (it != d->yvec->end())
+	    d->position2 = (*it).pos;
+	  else
+	    d->position2 = state.box.Max().y;
+	}
+      }
+      // -----------------------
+      // now test for z axis
+      state.ReinitZaxis(d->count, d->box); // init for x axis
+      //state.InitZaxis(d->count, d->box); // init for x axis
+      CallGetSplitPlaneZ(d->zvec, 2); // evaluate for x axis
+      if (UpdateEvaluation(d->bestCost, state.bestCost)) {
+	axis = CKTBAxes::EE_Z_axis; // the z-axis should be used
+	// Compute correct position to be used for splitting
+	d->position = (*(state.bestIterator)).pos;
+	d->bestIterator = state.bestIterator;
+	d->twoSplits = state.bestTwoSplits; // one or two splitting planes planed
+	d->cntThickness = state.bestThickness;
+	if (d->twoSplits > 1) {
+	  SItemVec::iterator it = state.bestIterator;
+	  it++;
+	  if (it != d->zvec->end())
+	    d->position2 = (*it).pos;
+	  else
+	    d->position2 = state.box.Max().z;
+	}
+      }
+      // Now we have to renormalize the cost for purpose of termination the building
+      d->bestCost /= state.areaWholeSA2;
+    } // arbitrary order of axes
+  } // for which axis to compute surface area heuristics
+
+  // ----------------------------------------------------------
+  // when automatic termination criteria should be used
+  if (d->modeSubDiv == EE_SUBDIVAUTOMATIC) {
+    bool stopSubdivision = false;
+    float ratio;
+    // which algorithm to use for automatic termination criteria
+    switch (algorithmAutoTermination) {
+      // --------------------------------------------------
+      case 0: { // This is described in my thesis.
+	// This is the cost of unsubdivided node
+	float leafCost = (float)(d->count);
+	ratio = d->bestCost / leafCost;
+	const float minRatio = 0.75;
+	if (ratio > minRatio)
+	  stopSubdivision = true;
+	break;
+      }
+      // --------------------------------------------------
+      case 1: {
+	// This is the cost of unsubdivided node, with uniformly distributed
+	// objects and the spatial median subdivision, without any object straddling
+	// the splitting plane. In some sense ideal setting for uniform distribution.
+	Vector3 s = d->box.Diagonal();
+	// Taking the widest side of the object to be subdivided
+	int diagAxis = s.DrivingAxis();
+	// Half of the width
+	// ----------------------
+	float w2 = s[diagAxis] * 0.5;
+	float t = s[oaxes[diagAxis][0]];
+	float h = s[oaxes[diagAxis][1]];
+	float sah2 = w2*(t+h) + h*t; // half of the surface area of a child
+	// This is the cost for case when the node is subdivided in the half and
+	// the half of the object is on the left and half of the objects on the right
+	// This is not the best cost possible !!!
+	// = float subdividedCost = 2 * (sah2/state.areaWholeSA2 * count/2);
+	float subdividedCost = sah2/state.areaWholeSA2 * (float)(d->count);
+	ratio = d->bestCost / subdividedCost;
+ 	// This is the max ratio allowed for splitting node subdivision
+
+	// The computed ratio = 1.0 corresponds to 'ideal case', so the threshold
+	// must be higher than 1.0 !
+	const float minRatio = 1.1;
+	if (ratio > minRatio)
+	  stopSubdivision = true;
+	break;
+      }
+      default : {
+	cerr << "Uknown algorithm for automatic termination criteria = "
+	      << algorithmAutoTermination << endl;
+      }
+       
+    } // switch
+    
+    //cout << "R=" << ratio << " ";
+    if (stopSubdivision) {
+      // cout << "F" << pars.failedSubDivCount << " ";
+      // when small improvement by the subdivision is reached
+      d->pars.failedSubDivCount++;
+      if (d->pars.failedSubDivCount > maxCountTrials) {
+	// make leaf and finish with this KD-tree branch
+	// cout << "L, cnt=" << count << " ,d=" << GetDepth()()
+	//     << " ,c=" << bestQ << " ,rat=" << ratio << "\n";
+	// possibly cut empty space before leaf is created
+	if (cutEmptySpace) {
+	  // setting initial depth if empty space cutting
+	  startEmptyCutDepth = GetDepth();
+	  IncDepth();
+	  d->modeSubDiv = EE_SUBDIVCUTEMPTY;
+	  // create the leaf first, with late empty cutting
+	  SKTBNodeT *n = SubDiv(d);
+	  if (!nodeToReturn)
+	    nodeToReturn = n;
+	  DecDepth();
+	  return nodeToReturn; // and finish by constructing a leaf
+	}
+
+	// make leaf and finish
+	SKTBNodeT *n = MakeLeaf(d);
+	if (!nodeToReturn)
+	  nodeToReturn = n;
+	return nodeToReturn;
+      }
+    }
+
+    // Do not stop subdivision now
+    
+    // update the progress in the parameters
+    d->pars.ratioLastButOne = d->pars.ratioLast;
+    d->pars.ratioLast = ratio;
+
+    // assure that axis is defined, if finding the
+    // splitting plane has failed
+    if ( (axis == CKTBAxes::EE_Leaf) ||
+	 (d->position == MAXFLOAT) ) {
+      // compute the spatial median for arbitrary axis
+      axis = (CKTBAxes::Axes)int(RandomValue(0.f, 2.98f));
+      // set position based algorithm for the next cut and children
+      d->algorithmBreakAx = 0;
+      resetFlagsForBreakAx = true;
+      d->position = (d->box.Min(axis) + d->box.Max(axis)) * 0.5f;
+      d->twoSplits = 1;
+    }
+  } // subdivision automatic
+
+  // -----------------------------------------------
+  // We have evaluated surface area heuristics above
+  // if no winner for subdivision exists, make a leaf
+  if ( (axis == CKTBAxes::EE_Leaf) ||
+       (d->position == MAXFLOAT) )
+  {
+    //cerr << "This shall not happen" << endl;
+    SKTBNodeT *n = MakeLeaf(d);
+    if (!nodeToReturn)
+      nodeToReturn = n;
+    // cout << "LL\n";
+    return nodeToReturn;
+  }
+  
+  if (verbose) {
+#ifdef _DEBUG
+
+//#define _KTBPRINTCUTS
+#ifndef _KTBPRINTCUTS
+    if (GetDepth() == 0) 
+#else
+    if (_printCuts)
+#endif
+    {
+      cout << "position: " << d->position << ", axis: "
+	     << (int)axis << ", depth=" << GetDepth() << ", box:" << endl;
+      Describe(d->box, cout, 0);
+      cout << endl;
+    }
+#endif // _DEBUG
+  }
+
+#ifdef _DEBUG
+  if (d->twoSplits == -1) {
+    cerr << "Some problem in implementation" << endl;
+    abort();;
+  }
+#endif
+
+  // copy the parameters to use for splitting
+  d->axis = axis;
+
+  if (d->twoSplits == 1) {
+    // create interior node with two successors
+    // case (1)
+    // DEBUG << "case 1 \n";
+    // Make easy cut, using one position
+    IncDepth();
+    SKTBNodeT* n = MakeOneCut(d);
+    if (!nodeToReturn)
+      nodeToReturn = n;
+    DecDepth();
+    return nodeToReturn;
+  }
+
+#if 1
+  cerr << "Unexpected use in this implementation" << endl;
+  cerr << "ABORTING " << endl;
+  abort();;
+#endif
+  
+//  case       case
+//  (2)   or   (3) structure must be created
+//   O          O                #
+//  / \        / \               #
+// L  RI      LI  R              #
+//   /  \    / \                 #
+//   RL RR  LL LR                #
+
+#ifdef _DEBUG
+  if ( (d->box.Min()[axis] >= d->position) ||
+       (d->position >= d->position2) ||
+       (d->position2 >= d->box.Max()[axis]) ) {
+    cerr << " the case 2 or 3 is defined incorrectly\n";
+    abort();;
+  }
+#endif
+
+  // To be reworked !!!
+  abort();;
+  if (d->twoSplits == 2) {
+    // -----------------------------------------
+    // case (2)
+    // DEBUG << "case 2 \n";
+
+    // make L part, linked in DFS order
+    int cntLeft = 1;
+    int cntRight = 0;
+    IncDepth();
+    SKTBNodeT *n = MakeOneCut(d);
+    if (!nodeToReturn)
+      nodeToReturn = n;
+
+    // make RI part, linked to the left node explictly
+    SBBox rbb = d->box; // the bounding box
+    rbb.Reduce(axis, 1, d->position);
+    d->box = rbb;
+    d->pars.reqAxis = axis;
+    d->pars.reqPosition = d->position2;    
+    SKTBNodeT *n2 = SubDiv(d);
+    DecDepth();
+    //Link the node
+    SetInteriorNodeLinks(n, 0, n2);
+    return nodeToReturn;
+  }
+
+  // -----------------------------------------
+  // case (3) ????????????????? I am not sure if this is correct implementation !!! VH
+  // DEBUG << "case 3 \n";
+  
+  // make LI part
+  SBBox lbb = d->box; // the bounding box
+  lbb.Reduce(axis, 0, d->position2);
+  int cntLeft = 0;
+  int cntRight = 1;
+  d->box = lbb;
+  d->position = d->position2;
+  d->axis = axis;
+  // the next subdivision step for R part
+  d->pars.reqAxis = axis;
+  d->pars.reqPosition = d->position;
+  
+  IncDepth();
+  SKTBNodeT *nl = SubDiv(d);
+  if (!nodeToReturn)
+    nodeToReturn = nl;
+  
+  // make R part
+  SKTBNodeT *n = MakeOneCut(d);
+  DecDepth();
+  SetInteriorNodeLinks(nl, 0, n);
+  // return left node, linked in DFS order to the previous one
+  return nodeToReturn;
+}
+
+// makes cutting on the given position on given axis
+// at value position, bb is the bounding box of current node,
+// count is the number of objects in the node
+// flags LeftF and RightF declares if to continue down after the recursion
+SKTBNodeT *
+CKTBABuildUp::MakeOneCut(SInputData *d)
+{
+// for testing accuracy of setting position from the ideal position
+#ifdef _RANDOMIZE_POSITION
+  assert(d->algorithmBreakAx == 0); // position based
+  RandomizePosition(d->position, d->box.Min(d->axis), d->box.Max(d->axis));
+#endif //_RANDOMIZE_POSITION
+
+#ifdef _DEBUG
+  assert(d->position >= d->box.Min(d->axis));
+  assert(d->position <= d->box.Max(d->axis));
+#endif
+  
+  SKTBNodeT *nodeToReturn = 0;
+
+#ifdef  _KTB_CONSTR_STATS
+  // surface area of the interior nodes to be subdivided
+  _sumSurfaceAreaInteriorNodes += d->box.SA2();
+#endif // _KTB_CONSTR_STATS
+  
+  if (splitClip) {
+    // empty object list to store the pointers to the split objects
+    ObjectContainer objlist;
+    cerr << "Not yet handled" << endl;
+    abort();;
+  }
+
+#if 0
+  // check if the lists are correctly sorted .. in debug
+  static int index = 0;
+#if 1
+  cout << "MakeOneCut index = " << index << " .. check axis = "
+	<< d->axis << " count = " << d->count
+	<< " depth = " << GetDepth() << endl;
+  const int indexToFind = 3743;
+  if (index == indexToFind) {
+    
+    cout << "Debug should start " << endl;
+    cout << "index = indexToFind" << endl;
+  }
+#endif
+  index++;  
+#endif
+  
+#ifdef _DEBUG
+  // We do not know the number of boundaries
+  Check3List(d);
+#endif
+  
+//#define _VYPIS
+#ifdef _VYPIS
+  DEBUG << "START: Subdivision at pos="
+	<< position << " axis = " << axis << "\n";
+  PrintOut(axis, 1, list+axis, sec+axis, Limits::Infinity);
+#endif
+
+  // axis .. the axis perpendicular to splitting plane positioned at position
+  // break active axis = split the list into two pieces
+  // list[axis] .. start of the first list in axis direction .. input
+  // second[axis] .. start of the second list in axis direction .. output
+  // objlist .. the list of objects that are duplicated
+#ifdef _DEBUG
+  Check1List(d, d->axis, d->count);
+  //cout << "Axis = " << axis << endl;
+#endif
+
+  // We have to allocate a new node for right child
+  SInputData* rightData = AllocNewData(2*d->count);
+  // Copy the basic data from parent
+  rightData->CopyBasicData(d);
+
+  // The number of objects for left children and right children
+  int cntL, cntR;
+
+//#ifdef _DEBUG
+#if 1
+  if (d->cntThickness < 0) {
+    cerr << "Problem, d->cntThickness = " << d->cntThickness << endl;
+    abort();;
+  }
+#endif
+
+  // Correct for cutting off empty space and many left
+  // boundaries on the splitting plane.
+  SItemVec *vec = d->GetItemVec(d->axis);
+
+  if (d->algorithmBreakAx) {
+    // Use pointer-based break-ax algorithm
+    if (d->bestIterator == vec->begin()) {
+      assert(d->cntThickness == 0);
+      d->bestIterator--;
+    }
+    else {
+      if (d->count > 1) {
+	int origThickness = d->cntThickness;
+	SItemVec::iterator origIterator = d->bestIterator;
+	SItemVec::iterator it = d->bestIterator;
+	int caseBreak = 0;
+	if ((*(it)).IsLeftBoundary()) {
+	  float pos = d->position;
+	  it--;
+	  int ir = 1;
+	  assert(it != vec->begin()-1);
+	  for ( ; true; ) {
+	    if ( (*(it)).pos < pos) {
+	      caseBreak = 0;
+	      d->bestIterator = it;
+	      if (ir > 1)
+		d->cntThickness -= ir;
+	      break;
+	    }
+	    if (it == vec->begin()) {
+	      // cutting off, #objects on the left = 0
+	      d->cntThickness = 0;
+	      it--;
+	      d->bestIterator = it;
+	      caseBreak = 1;
+	      break;
+	    }
+	    if ((*(it)).IsRightBoundary()) {
+	      d->bestIterator = it;
+	      if (ir > 1)
+		d->cntThickness -= ir;
+	      caseBreak = 2;
+	      break;
+	    }
+	    it--;
+	    ir++;
+	  } // for
+#ifdef _DEBUG
+	  if (d->cntThickness < 0) {
+	    cerr << "Problem, d->cntThickness = " << d->cntThickness << endl;
+	    cerr << " origThickness = " << origThickness << " Depth = "
+		  << GetDepth() << endl;
+	    for (SItemVec::iterator iq = it; iq != origIterator; iq++) {
+	      cout << "  pos = " << (*iq).pos;
+	      if ((*iq).IsLeftBoundary())
+		cout << "  L  ";
+	      else
+		cout << "  R  ";
+	      cout << (*iq).obj << endl;	  
+	    } // for
+	    cout << "AAAA" << endl;
+	    abort();;
+	}
+#endif
+	} // if left boundary
+      } // if d->count > 1
+    } // if d->vec is not the beginning of the list
+  } // pointer based break-ax algorithm
+    
+#if 0
+  DEBUG << "MakeOneCut cntL = " << cntL << " cntR = " << cntR << endl;
+#endif
+
+  // Here is the breaking the arrays into two arrays, compute the number
+  // of objects on the left and on the right of the splitting plane
+  int dCountTagging = 0;
+  // Use either 
+  if (d->algorithmBreakAx == 0)
+    BreakAxPosition(d, d->axis, rightData, cntL, cntR);
+  else
+    BreakAx(d, d->axis, rightData, cntL, cntR);
+    
+#ifdef _DEBUG
+  // the number of objects on the left and on the right
+  int cntL_B = cntL;
+  int cntR_B = cntR;
+#if 0
+  cout << "B - Count*2 = " << d->count*2
+       << " countSum = " << cntL_B + cntR_B
+       << " CntL_B = " << cntL_B
+       << " cntR_B = " << cntR_B << endl;
+#endif
+  //Check1List(alist, axis, cntL_B, true, position);
+  Check1List(d, d->axis, cntL_B);
+  Check1List(rightData, d->axis, cntR_B);
+  // cout << "AxisNext = " << oax0 << endl;
+#endif
+  
+  // DEBUG << "THE CHECK at DEPTH=" << GetDepth() << endl;
+  
+#ifdef _VYPIS
+  DEBUG << "After Break at pos="
+	<< position << " axis = " << axis << "\n";
+  PrintOut(d, axis, d->position);
+#endif
+
+#ifdef _VYPIS
+  DEBUG << "BEFORE oax0\n";
+  PrintOut(d, oax0, Limits::Infinity);
+#endif
+
+  // --------------------------------------------------
+  // break other two axes
+  CKTBAxes::Axes oax0 = oaxes[d->axis][0];
+#ifdef _DEBUG
+  Check1List(d, oax0, d->count);
+#endif
+  
+  SItemVec *vecc = d->GetItemVec(oax0);
+  if (vecc->size() != 2 * d->count) {
+    cout << "AAAA 1" << endl;
+  }
+  
+  // Here break the list in the next axis
+#ifdef _USE_OPTIMIZE_DIVIDE_AX
+  DivideAx_I_opt(d, oax0, rightData, cntL, cntR);
+#else
+  DivideAx_I(d, oax0, rightData, cntL, cntR);
+#endif
+
+  if (vecc->size() != 2 * cntL) {
+    cout << "AAAA 3" << endl;
+  }
+  if (rightData->GetItemVec(oax0)->size() != 2 * cntR) {
+    cout << "AAAA 4" << endl;
+    cout << "cntR * 2 = " << 2 * cntR << endl;
+    cout << "vecSize = " << rightData->GetItemVec(oax0)->size() << endl;
+  }
+  
+#ifdef _DEBUG
+  // the number of objects on the left and on the right
+  int cntL_I = cntL;
+  int cntR_I = cntR;
+#if 0
+  cout << "I - Count*2 = " << count*2
+       << " countSum = " << cntL_I + cntR_I
+       << " CntL_B = " << cntL_I
+       << " cntR_B = " << cntR_I << endl;
+#endif
+  
+  if (cntL_I != cntL_B) {
+    cerr << "FirstList - Problem with DivideAx_I, cntL_B = " << cntL_B
+	  << " and cntL_I = " << cntL_I << endl;
+  }
+  if (cntR_I != cntR_B) {
+    cerr << "SecondList = Problem with DivideAx_I, cntR_B = " << cntR_B
+	  << " and cntR_I = " << cntR_I << endl;
+  }
+  
+  Check1List(d, oax0, cntL_B);
+  Check1List(rightData, oax0, cntR_B);
+
+  //cout << "AxisNextNext = " << oax1 << endl;
+
+#endif
+  
+#ifdef _VYPIS
+  DEBUG << "AFTER DivideAx oax0\n";
+  PrintOut(oax0, 3, alist + oax0, sec+oax0, 0);
+#endif
+
+#ifdef _VYPIS
+  DEBUG << "BEFORE oax1\n";
+  PrintOut(oax1, 1, alist + oax1, sec+oax1, Limits::Infinity);
+#endif
+
+  // Her break the list in the next next axis
+  CKTBAxes::Axes oax1 = oaxes[d->axis][1];
+
+  SItemVec *vec2 = d->GetItemVec(oax1);
+  if (vec2->size() != 2 * d->count) {
+    cout << "BBBB 1" << endl;
+  }
+  
+#ifdef _USE_OPTIMIZE_DIVIDE_AX
+  DivideAx_II_opt(d, oax1, rightData, cntL, cntR);
+#else
+  DivideAx_II(d, oax1, rightData, cntL, cntR);
+#endif
+
+  if (vec2->size() != 2 * cntL) {
+    cout << "BBBB 3" << endl;
+    cout << "cntL * 2 = " << 2 * cntL << endl;
+    cout << "vec2size = " << vec2->size() << endl;
+  }
+  if (rightData->GetItemVec(oax1)->size() != 2 * cntR) {
+    cout << "BBBB 4" << endl;
+    cout << "cntR * 2 = " << 2 * cntR << endl;
+    cout << "vecSize = " << rightData->GetItemVec(oax1)->size() << endl;
+  }
+  
+#ifdef _DEBUG
+  int cntL_II = cntL;
+  int cntR_II = cntR;
+#if 0
+  cout << "II - Count*2 = " << count*2
+       << " countSum = " << cntL_II + cntR_II
+       << " CntL_B = " << cntL_II
+       << " cntR_B = " << cntR_II << endl;
+#endif
+  if (cntL_II != cntL_B) {
+    cerr << "FirstList - Problem with DivideAx_II, cntL_B = " << cntL_B
+	  << " and cntL_I = " << cntL_I 
+	  << " and cntL_II = " << cntL_II << endl; 
+  }
+  if (cntR_II != cntR_B) {
+    cerr << "Second List - Problem with DivideAx_II, cntR_B = " << cntR_B
+	  << " and cntR_I = " << cntR_I
+	  << " and cntR_II = " << cntR_II << endl;
+  }
+  
+  Check1List(d, oax1, cntL_B);
+  Check1List(rightData, oax1, cntR_B);
+
+  if ( (cntL_I != cntL_II) ||
+       (cntR_I != cntR_II) ) {
+    cout << "Problem with dividing axis II: cntL_I = " << cntL_I
+	 << " cntL_II = " << cntL_II
+	 << " cntR_I = " << cntR_I
+	 << " cntR_II = " << cntR_II << endl;      
+  }
+#endif
+  
+#ifdef _VYPIS
+  DEBUG << "AFTER DivideAx oax1\n";
+  PrintOut(oax1, 3, alist + oax1, sec+oax1, position);
+#endif
+  
+  // Allocate the representation of the interior node
+  SKTBNodeT *node = 0;
+
+  if (makeMinBoxHere) {
+    // -------------------------------------------------------
+    // interior node with the box
+    node = AllocInteriorNodeWithBox(// interior node data
+				    d->axis, d->position, cntL, cntR, 
+				    // box data
+				    d->box, d->lastMinBoxNode, d->lastDepthForMinBoxes);
+
+    //cout << "depth = " << GetDepth() << " node = " << node
+    //	 << " lastMinBoxNode = " << d->lastMinBoxNode << endl;
+    
+    d->lastMinBoxNode = node; // we have to remember the last node
+    rightData->lastMinBoxNode = node;
+    makeMinBoxHere = false; // reset for the next time
+  }
+  else
+    // normal interior node (=without box)
+    node = AllocInteriorNode(d->axis, d->position, cntL, cntR);
+  
+#ifdef _DEBUG
+  if (!node) {
+    cerr << "Allocation of Interior Node failed.\n";
+    abort();;
+  }
+#endif // _DEBUG
+  // set the node to be returned
+  if (!nodeToReturn)
+    nodeToReturn = nodeToLink;
+  assert(node);
+  assert(nodeToReturn);
+
+#if 0  
+  // If we make split clipping, then we want to reduce the boxes for
+  // the objects straddling the splitting plane now.
+  if ((splitClip) && (objlist.ListCount() > 0 )) {
+    // if the objects are split by splitting plane
+    //DEBUG << "Reduces box ax=" << axis << " position="
+    // << position << "#split_objs=" << objlist.ListCount() << "\n" << flush;
+    ReduceBBoxes(d, d->axis, rightData, d->position);
+  }
+#endif
+  
+  // ---------------------------------------------
+  // initialize the left bounding box 'bb'
+  d->box.Reduce(d->axis, 0, d->position);
+
+  // initialize the right bounding box 'rbb'
+  rightData->box.Reduce(d->axis, 1, d->position);
+
+  // Set correct number of objects
+  d->count = cntL;
+  rightData->count = cntR;
+  
+  // The children nodes to be created
+  SKTBNodeT *nodeL=0, *nodeR=0;
+
+  // Recurse to the left child
+  if (d->makeSubdivisionLeft) {
+    // subdivide branches
+    ESubdivMode modeLeft = d->modeSubDiv ;
+    if ( (cutEmptySpace) &&
+	 (modeLeft != EE_SUBDIVCUTEMPTY) &&
+	 (d->count <= maxListLength) ) {
+      // setting initial depth if empty space cutting
+      startEmptyCutDepth = GetDepth();
+      d->modeSubDiv = EE_SUBDIVCUTEMPTY;
+    }
+    // DEBUG << "Left cnt= " << (cnt[0] >> 1) << " depth= "
+    //       << GetDepth() << "\n";
+    nodeL = SubDiv(d);
+  }
+  
+  // Recurse to the right child
+  if (rightData->makeSubdivisionRight) {
+    ESubdivMode modeRight = d->modeSubDiv ;
+    if ( (cutEmptySpace) &&
+	 (modeRight != EE_SUBDIVCUTEMPTY) &&
+	 (rightData->count <= maxListLength) ) {
+      // setting initial depth if empty space cutting
+      startEmptyCutDepth = GetDepth();
+      rightData->modeSubDiv = EE_SUBDIVCUTEMPTY;
+    }
+    // DEBUG << "Right cnt= " << (cnt[1] >> 1) << " depth= "
+    // << GetDepth() << "\n";
+    nodeR = SubDiv(rightData);
+
+  }
+
+  // Free the data to be reused further on
+  FreeLastData();
+
+  // Set the node pointers to the children for created node
+  SetInteriorNodeLinks(node, nodeL, nodeR);
+
+  return nodeToReturn; // return the node 
+}
+
+// returns a box enclosing all the objects in the node
+void
+CKTBABuildUp::GetTightBox(const SInputData &i, SBBox &tbox)
+{
+  // Index to the last boundary
+  int cnt = 2*i.count-1;  
+
+  tbox.MinX() = (*(i.xvec))[0].pos; 
+  tbox.MinY() = (*(i.yvec))[0].pos; 
+  tbox.MinZ() = (*(i.zvec))[0].pos; 
+  tbox.MaxX() = (*(i.xvec))[cnt].pos; 
+  tbox.MaxY() = (*(i.yvec))[cnt].pos; 
+  tbox.MaxZ() = (*(i.zvec))[cnt].pos;
+
+  assert(tbox.MinX() >= i.box.MinX());
+  assert(tbox.MaxX() <= i.box.MaxX());
+  assert(tbox.MinY() >= i.box.MinY());
+  assert(tbox.MaxY() <= i.box.MaxY());
+  assert(tbox.MinZ() >= i.box.MinZ());
+  assert(tbox.MaxZ() <= i.box.MaxZ());
+}
+
+
+// returns a box enclosing all the objects in the node
+int
+CKTBABuildUp::GetEBox(const SInputData &i, SBBox &tbox)
+{
+  // LEFT BOX
+  // initialization
+
+  // Index to the last boundary
+  int cnt = 2*i.count-1;  
+  int changed = 0; // number of planes, that are changed by bounding box
+
+  float xMin = (*(i.xvec))[0].pos;
+  changed = (xMin > i.box.Min(0)) ? changed+1 : changed;    
+  float xMax = (*(i.xvec))[cnt].pos;
+  changed = (xMax < i.box.Max(0)) ? changed+1 : changed;    
+
+  float yMin = (*(i.yvec))[0].pos;
+  changed = (yMin > i.box.Min(1)) ? changed+1 : changed;    
+  float yMax = (*(i.yvec))[cnt].pos;
+  changed = (yMax < i.box.Max(1)) ? changed+1 : changed;    
+
+  float zMin = (*(i.zvec))[0].pos;
+  changed = (zMin > i.box.Min(2)) ? changed+1 : changed;    
+  float zMax = (*(i.zvec))[cnt].pos;
+  changed = (zMax < i.box.Max(2)) ? changed+1 : changed;    
+
+  // Set the bounding (reduced) box
+  tbox.Min() = Vector3(xMin, yMin, zMin);
+  tbox.Max() = Vector3(xMax, yMax, zMax);
+
+  // Return the number of bounding splitting planes with respect to original box
+  return changed;
+}
+
+
+// This is only for debugging purposes, to be removed!
+static
+CKTBABuildUp::SSolid* objtf = (CKTBABuildUp::SSolid*)0x0;
+
+// removes the objects specified in "tagobjlist" from boundary "list"
+// it supposes the "tagobjlist" is ordered in the left boundary order
+// in CKTBAxes::EE_X_axis.
+void
+CKTBABuildUp::RemoveObjects(SItemVec *vec, int cntObjects)
+{
+  assert(vec);
+  assert(cntObjects);
+  
+  // number of removed left boundaries
+  int cnt = 0;
+
+  SItemVec::iterator curr;
+#ifdef _DEBUG
+  int cnt2 = 0;
+  for (curr = vec->begin(); curr != vec->end(); curr++)
+  {
+    if (curr->obj->ToBeRemoved()) {
+      //cout << cnt2 << "  " << curr - vec->begin() << endl;
+      cnt2++;
+    }
+    //if (curr->obj == objtf)
+    //  cout << "Index found cnt2 = " << cnt2 << endl;
+  } // for
+  if (cnt2 != 2*cntObjects) {
+    cerr << "Some problem with data marking" << endl;
+    abort();;
+  }
+#endif
+
+  // Find the first boundary
+  for (curr = vec->begin(); curr != vec->end(); curr++)
+  {
+    //if (curr->obj == objtf)
+    //cout << "2 Index found cnt2 = " << cnt2 << endl;
+
+    if (curr->obj->ToBeRemoved()) {
+      cnt++; // the number of removed boundaries
+      assert(curr->IsLeftBoundary());
+      //cout << cnt << "  objToRemove=" << curr->obj << endl;
+      break;
+    }
+  }
+  // the first element to be overwritten
+  SItemVec::iterator it = curr;
+  curr++; 
+
+  for ( ; curr != vec->end(); curr++) {
+    //if (curr->obj == objtf) {
+    //  cout << "3 Index found cnt2 = " << cnt2 << endl;
+
+    if (curr->obj->ToBeRemoved()) {
+      cnt++; // the number of removed boundaries
+      //cout << cnt << "  " << curr->obj << endl;
+      if (cnt == cntObjects*2) {
+	curr++;
+	break;
+      }	
+    }
+    else {
+      // copy the element to the right place
+      *it = *curr;
+      it++;
+    }
+  } // for
+
+#ifdef _DEBUG
+  if (cnt != 2*cntObjects) {
+    cerr << "Problem with removing objects implementation" << endl;
+    abort();;
+  }
+#endif
+
+  // copy the rest of the list to the right place
+  for ( ; curr != vec->end(); curr++, it++)
+  {
+    //if (curr->obj == objtf) {
+    //  cout << "4 Index found cnt2 = " << cnt2 << endl;
+
+    // copy the element to the right place
+    *it = *curr;
+  }
+      
+  // resize the vector correctly
+  int oldSize = vec->size();
+  assert(oldSize >= cnt);
+  if (oldSize == cnt)
+    vec->erase(vec->begin(), vec->end());
+  else
+    vec->resize(oldSize - cnt);
+  assert(vec->size() % 2 == 0);
+  assert(vec->size() == oldSize - cnt);
+
+#ifdef _DEBUG    
+  for (curr = vec->begin(); curr != vec->end(); curr++)
+  {
+    if (curr->obj->ToBeRemoved()) {
+      cerr << "Implementation bug" << endl;
+      abort();;
+    } // if left boundary
+  } // for
+#endif
+
+  //cout << "size = " << vec->size() << endl;
+
+  return;
+}
+
+// removes the objects specified in "tagobjlist" from boundary "list"
+// it supposes the "tagobjlist" is ordered in the left boundary order
+// in CKTBAxes::EE_X_axis.
+void
+CKTBABuildUp::RemoveObjectsReset(SItemVec *vec, int cntObjects)
+{
+  assert(vec);
+  assert(cntObjects);
+  
+  // number of removed left boundaries
+  int cnt = 0;
+  SItemVec::iterator curr;
+
+#ifdef _DEBUG
+  int cnt2 = 0;
+  for (curr = vec->begin(); curr != vec->end(); curr++)
+  {
+    if (curr->obj->ToBeRemoved()) {
+      //cout << cnt2 << "  " << curr - vec->begin() << endl;
+      cnt2++;
+    }
+  } // for
+  if (cnt2 != 2*cntObjects) {
+    cerr << "Some problem with data marking" << endl;
+    abort();;
+  }
+#endif
+
+  // Find the first boundary
+  for (curr = vec->begin(); curr != vec->end(); curr++)
+  {
+    if (curr->obj->ToBeRemoved()) {
+      cnt++; // the number of removed boundaries
+      assert(curr->IsLeftBoundary());
+      curr++;
+      break;
+    }
+  }
+  SItemVec::iterator it = curr;
+  it--; // the first element to be overwritten
+
+  for ( ; curr != vec->end(); curr++) {
+    if (curr->obj->ToBeRemoved()) {
+      cnt++; // the number of removed boundaries
+      if (curr->IsRightBoundary()) {
+	curr->obj->ResetFlags();
+	assert(curr->obj->flags == 0);
+      }
+      if (cnt == cntObjects*2) {
+	curr++;
+	break;
+      }	
+    }
+    else {
+      // copy the element to the right place
+      *it = *curr;
+      it++;
+    }
+  } // for
+  
+#ifdef _DEBUG
+  if (cnt != 2*cntObjects) {
+    cerr << "Problem with removing objects implementation" << endl;
+    abort();;
+  }
+#endif
+
+  // copy the rest of the list to the right place
+  for ( ; curr != vec->end(); curr++, it++)
+  {
+    // copy the element to the right place
+    *it = *curr;
+  }
+      
+  // resize the vector correctly
+  int oldSize = vec->size();
+  assert(oldSize >= cnt);
+  if (oldSize == cnt)
+    vec->erase(vec->begin(), vec->end());
+  else
+    vec->resize(oldSize - cnt);
+  assert(vec->size() % 2 == 0);
+  assert(vec->size() == oldSize - cnt);
+
+#ifdef _DEBUG    
+  for (curr = vec->begin(); curr != vec->end(); curr++)
+  {
+    if (curr->obj->ToBeRemoved()) {
+      cerr << "Implementation bug" << endl;
+      abort();;
+    } // if left boundary
+  } // for
+#endif
+
+  //cout << "size = " << vec->size() << endl;
+  
+  return;
+}
+
+
+// make the full leaf from current node
+SKTBNodeT*
+CKTBABuildUp::MakeLeaf(SInputData *d)
+{
+#ifdef  _KTBPRINTCUTS
+  cout << " Creating leaf, depth = " << GetDepth()
+       << " cntObjs = " << count << endl;
+  //exit(3);
+#endif
+  
+#ifdef _KTB_CONSTR_STATS
+  // update the statistics
+  float sa2bb;
+  _sumSurfaceAreaLeaves += (sa2bb = d->box.SA2());
+  _sumSurfaceAreaMULcntLeaves += ((float)d->count * sa2bb);
+#endif // _KTB_CONSTR_STATS
+  
+  // ------------------------------------------------------
+  // The version with allocating empty leaves. This makes
+  // sense since in DFS order it works correctly
+  SKTBNodeT *node = AllocLeaf(d->count);
+
+  if (d->count > 0) {
+    // copy the list of objects
+    ObjectContainer *objlist = NULL;
+    objlist = new ObjectContainer;
+
+    SItemVec *vec = d->GetItemVec(0);
+    SItemVec::iterator curr;    
+    for (curr = vec->begin(); curr != vec->end(); curr++) {
+      if ( (*curr).IsLeftBoundary()) // skip all right boundaries
+        objlist->push_back( (*curr).obj->obj);
+    }
+
+    assert(objlist->size() != 0);
+    // Do not delete the object list, it is used as allocated above
+    SetFullLeaf(node, objlist);
+  }
+
+  // We assume that the allocation of the single leaf cannot
+  // fail, since this one shall be the last in the sequence.
+  assert(node == nodeToLink);
+  
+  // Return the node to be used in the linking
+  return nodeToLink;
+}
+
+// split the list along the required axis
+// first is the begin of the SItem list, axis is the axis, where
+// to split, val is the splitting value in integer notation.
+// The output of the function are two lists, first and second
+// Optionally, objlist store the objects that straddle the splitting plane
+void
+CKTBABuildUp::BreakAx(SInputData *d, int axis,
+		      SInputData *rightData,
+		      int &cntLout, int &cntRout)
+{
+  // the number of object boundaries for left array
+  int cntLeft = (d->bestIterator) - d->GetItemVec(axis)->begin() + 1;
+  assert(cntLeft >= 0);
+  assert(cntLeft <= 2*d->count);  
+  // the number of object boundaries for right array
+  int cntRight = d->count*2 - cntLeft;
+  assert(cntRight >= 0);
+  assert(cntRight <= 2*d->count);
+  assert(d->cntThickness >= 0);
+  cntLeft += d->cntThickness; // duplicated boundaries for left array
+  cntRight += d->cntThickness; // duplicated boundaries for right array
+  assert(cntLeft + cntRight == (d->count + d->cntThickness) * 2);
+
+#ifdef _DEBUG
+  if ( (cntLeft % 2 != 0) ||
+       (cntRight % 2 != 0) ) {
+    int i = 0;
+    SItemVec *vec = d->GetItemVec(axis);
+    cout << "d->count = " << d->count ;
+    cout << "cntLeft = " << cntLeft << " cntRight" << cntRight << endl;
+    cout << "bestIterator = " << (int)(d->bestIterator - vec->begin());
+    cout << " cntThickness= " << d->cntThickness << " position=" << d->position << endl;
+    for (SItemVec::iterator itt = vec->begin(); itt != vec->end(); itt++, i++)
+    {
+      cout << i << " = ";
+      if ((*itt).IsLeftBoundary())
+	cout << "L"; else cout << "R";
+      cout << " obj = " << (*itt).obj << " pos = " << (*itt).pos << endl;
+    }
+    abort();;
+  }
+#endif
+  
+  // A special case, right list is empty
+  if (cntRight == 0) {
+    assert(d->cntThickness == 0);
+    rightData->Alloc(0);
+    rightData->count = 0;
+    // The final setting of number of objects
+    cntLout = cntLeft / 2;
+    cntRout = cntRight / 2;   
+    return; // nothing to do
+  }
+
+  // We have some problem that is difficult to detect, when tagging objects
+  // are allowed, the flags are not always reset to zero in some cases. 
+  // VH 2/1/2006. The flags are always left boundaries (=1).
+  // Therefore here it is a hack to assure that the flags are definitely zero.
+  if (resetFlagsForBreakAx) {
+    SItemVec *vecd = d->GetItemVec(axis);
+    for (SItemVec::iterator itt = vecd->begin(); itt != vecd->end(); itt++) {
+      (*itt).obj->ResetFlags();
+    } // for 
+  } // if
+  
+#ifdef _DEBUG
+  SItemVec *vecd = d->GetItemVec(axis);
+  for (SItemVec::iterator itt = vecd->begin(); itt != vecd->end(); itt++) {
+    if ((*itt).obj->Flags() != 0) {
+      cout << "Init ERROR 1 in original list, flags = "
+	   << (*itt).obj->Flags() << " obj = " << (void*)((*itt).obj) << endl;
+    }
+  } // for
+#endif // _DEBUG  
+
+  assert(cntRight > 0);
+  
+  // Allocate the appropriate size for right array, for all 3 axes
+  rightData->Alloc(cntRight);
+  
+  // First find create all left boundaries for right array
+  SItem boundary; // create left boundary
+  SItemVec *vecRight = rightData->GetItemVec(axis);
+
+#define _USE_PUSHBACK
+#ifdef _USE_PUSHBACK
+  vecRight->resize(0);
+#else
+  vecRight->resize(cntRight);
+#endif  
+  if (d->cntThickness) {
+    boundary.pos = d->position;
+    boundary.axis = axis;
+    boundary.SetLeftBoundary();
+#ifdef _USE_PUSHBACK
+    int i;
+    for (i = 0; i < d->cntThickness; i++) {
+      vecRight->push_back(boundary); // Note that the objects pointed to are not set !!!
+    } // for i;
+#else
+    for (int i = 0; i < d->cntThickness; i++) {
+      (*vecRight)[i] = boundary; // Note that the objects pointed to are not set !!!
+    } // for i;
+#endif
+  }
+  const SItemVec::iterator itendLeft = d->bestIterator + 1;
+  SItemVec *vec = d->GetItemVec(axis);
+  SItemVec::iterator it;
+  //int cntSetLeft = 0;
+  for (it = vec->begin(); it != itendLeft; it++) {
+    // Mark all the items to be in the first list
+    (*it).obj->SetInFirstList();
+    //cntSetLeft++;
+  } // for
+  // The boundaries that belong definitely to the second list
+  //int cntSetRight = 0;
+#ifdef _USE_PUSHBACK
+  const SItemVec::iterator itend = vec->end();
+  for (; it != itend; it++) {
+    // Mark all the items to be in the second list
+    (*it).obj->SetInSecondList();
+    // and copy the item to the right array
+    vecRight->push_back(*it);
+    //cntSetRight++;
+  } // for
+#else
+  const int imax = vec->end() - (d->bestIterator + 1);
+  int ir = d->cntThickness;
+  for (int i = 0; i < imax; i++) {
+    (*it).obj->SetInSecondList();
+    // and copy the item to the right array
+    (*vecRight)[ir] = (*it);
+    ir++; it++;
+  }
+  assert(ir == cntRight);
+#endif
+  
+#ifdef _DEBUG
+  if (vecRight->size() != cntRight) {
+    cerr << "Implementation problem vecRight->size() = "
+	  << vecRight->size() << "  cntRight = " << cntRight
+	  << " d->cntThickness = " << d->cntThickness << endl;
+    abort();;
+  }
+#endif  
+  // Only check, if right boundary is set correctly
+  assert(vecRight->size() == cntRight);
+  
+  if (d->cntThickness) {
+    // Now go only through the items on the left side of the splitting plane
+    SItemVec::iterator itR = vecRight->begin(); // to set left boundaries in right array
+    SItemVec::iterator itL = itendLeft; // to set new right boundaries in left array
+    boundary.SetRightBoundary();
+#ifdef _USE_PUSHBACK
+    for (it = vec->begin(); it != itendLeft; it++) {
+      if ((*it).obj->InBothLists()) {
+	// set new right boundaries in left array
+	(*itL) = boundary;
+	(*itL).obj = (*it).obj; // set the right object
+	itL++;
+	// and set new left boundary in right array, only object is set
+	(*itR).obj = (*it).obj;
+	itR++;
+      }
+    } // for
+#else
+    int imax = itendLeft - vec->begin();
+    int i;
+    for (i = 0; i < imax ; i++) {
+      if ((*vec)[i].obj->InBothLists()) {
+	// set new right boundaries in left array
+	(*itL) = boundary;
+	(*itL).obj = (*vec)[i].obj; // set the right object
+	itL++;
+	// and set new left boundary in right array, only object is set
+	(*itR).obj = (*vec)[i].obj;
+	itR++;
+      }
+    } // for
+#endif
+#ifdef _DEBUG
+    int sizeL = itL - vec->begin();
+    assert(sizeL == cntLeft);
+    int sizeR = itR - vecRight->begin();
+    assert(sizeR == d->cntThickness);
+#endif
+  }
+#ifdef _DEBUG
+  else {
+    vec->resize(cntLeft);    
+    assert(d->cntThickness == 0);
+    int cntLL = 0;
+    int cntRR = 0;
+    for (it = vec->begin(); it != vec->end(); it++) {
+      if ((*it).obj->InBothLists()) {
+	cntLL++;
+	cout << "ERROR in left list " << cntLL << endl;
+      }
+    } // for    
+    for (it = vecRight->begin(); it != vecRight->end(); it++) {
+      if ((*it).obj->InBothLists()) {
+	cntRR++;
+	cout << "ERROR in right list " << cntRR << endl;
+      }
+    } // for    
+  }  
+#endif // _DEBUG  
+  
+  // The boundary on the left, unused items are not used
+  vec->resize(cntLeft);
+
+  // The final setting of size
+  cntLout = cntLeft / 2;
+  cntRout = cntRight / 2;
+
+  return;
+}
+
+
+void
+CKTBABuildUp::BreakAxPosition(SInputData *d, int axis,
+			      SInputData *rightData,
+			      int &cntLout, int &cntRout)
+{
+  // the number of object boundaries for left array is not known
+  int cntLeft = 0;
+  int cntRight = 0;
+  d->cntThickness = 0;
+  const float positionToDecide = d->position;
+
+  // We have some problem that is difficult to detect, when tagging objects
+  // are allowed, the flags are not always reset to zero in some cases. 
+  // VH 2/1/2006. The flags are always left boundaries (=1).
+  // Therefore here it is a hack to assure that the flags are definitely zero.
+  if (resetFlagsForBreakAx) {
+    SItemVec *vecd = d->GetItemVec(axis);
+    for (SItemVec::iterator itt = vecd->begin(); itt != vecd->end(); itt++) {
+      (*itt).obj->ResetFlags();
+    } // for 
+  } // if
+  
+#ifdef _DEBUG
+  SItemVec *vecd = d->GetItemVec(axis);
+  for (SItemVec::iterator itt = vecd->begin(); itt != vecd->end(); itt++) {
+    if ((*itt).obj->Flags() != 0) {
+      cout << "Init ERROR 2 in original list, flags = "
+	   << (*itt).obj->Flags() << " obj = " << (void*)((*itt).obj) << endl;
+    }
+  } // for
+#endif // _DEBUG  
+
+  // Allocate the appropriate size for right array, for all 3 axes
+  // This is only estimated at this algorithm.
+  int estimatedSize = (int)(0.6f * (float)d->count);
+  if (estimatedSize < 10)
+    estimatedSize = 10;
+  rightData->Alloc(estimatedSize * 2);
+  
+  // First find create all left boundaries for right array
+  SItemVec *vecRight = rightData->GetItemVec(axis);
+
+  // Resize to 0 to start from the beginning
+  vecRight->resize(0);
+  SItemVec *vec = d->GetItemVec(axis);
+  SItemVec::iterator it;
+  const SItemVec::iterator itEnd = vec->end();
+  for (it = vec->begin(); it != itEnd; it++) {
+    const float &pos = (*it).pos;  
+    if (pos < positionToDecide) {
+      cntLeft++;
+      // Mark the item to be in the first list
+      (*it).obj->SetInFirstList();
+    }
+    else {
+      if (pos > positionToDecide) {
+	// It belongs to the right list
+	break;
+      }
+      else {
+	// pos == positionToDecide
+	if ((*it).IsRightBoundary()) {
+	  // it belongs to the left list
+	  cntLeft++;
+	  (*it).obj->SetInFirstList();
+	}
+	else {
+	  // this is the left boundary
+	  // it belongs already to the right list
+	  break;
+	}
+      }
+    }
+  } // for it
+
+  // Remember the position of the iterator, where right
+  // list has to start
+  SItemVec::iterator itStart = it;
+  int cntDups = 0;
+  SItem boundary;
+
+  // create left boundaries for right list
+  boundary.pos = d->position;
+  boundary.axis = axis;
+  boundary.SetLeftBoundary();
+  for (; it != itEnd; it++) {
+    assert((*it).pos >= positionToDecide);
+    // Mark all the items to be in the second list
+    if ((*it).obj->InFirstList()) {
+      // and copy the newly created boundary to the right array
+      boundary.obj = (*it).obj;
+      vecRight->push_back(boundary);
+      cntDups++;
+      cntRight++;
+    }
+  } // for
+
+  // Now go through the right part of the list again
+  // and copy the rest of the list to the right list
+  for (it = itStart; it != itEnd; it++) {
+    (*it).obj->SetInSecondList();
+    assert((*it).pos >= positionToDecide);
+    vecRight->push_back((*it));
+    cntRight++;
+  } // for
+
+  // in final pass create the new boundaries for the left list
+  int i;
+  SItemVec::iterator srcIt = vecRight->begin();
+  for (it = itStart, i = 0 ; i < cntDups; it++, srcIt++, i++) {
+    cntLeft++;
+    // first copy the boundary from the beginning of the right list
+    *it = *srcIt;
+    // then set the right boundary in copied item
+    (*it).SetRightBoundary();
+    assert( (*srcIt).IsLeftBoundary());
+  } // for it
+  
+  // The boundary on the left, unused items are not used
+  vec->resize(cntLeft);
+  assert(cntLeft % 2 == 0);
+  assert(cntRight % 2 == 0);
+  assert(cntLeft+cntRight == 2*(d->count+cntDups));
+  
+  // The final setting of size
+  cntLout = cntLeft / 2;
+  cntRout = cntRight / 2;
+  // Set correctly also the number of objects
+  d->cntThickness = cntDups;
+
+#ifdef _DEBUG
+  SItemVec *vecdL = d->GetItemVec(axis);
+  int cntL = 0; int cntL_LB = 0; int cntL_RB = 0; int cntL_LR = 0;
+  for (SItemVec::iterator itl = vecdL->begin(); itl != vecdL->end(); itl++) {
+    if ((*itl).obj->InBothLists())
+      cntL_LR++;
+    if ((*itl).IsLeftBoundary()) cntL_LB++;
+    if ((*itl).IsRightBoundary()) cntL_RB++;
+    cntL++;
+  } // for
+  SItemVec *vecdR = rightData->GetItemVec(axis);
+  int cntR = 0; int cntR_LB = 0; int cntR_RB = 0; int cntR_LR = 0;
+  for (SItemVec::iterator itr = vecdR->begin(); itr != vecdR->end(); itr++) {
+    if ((*itr).obj->InBothLists())
+      cntR_LR++;
+    if ((*itr).IsLeftBoundary()) cntR_LB++;
+    if ((*itr).IsRightBoundary()) cntR_RB++;
+    cntR++;
+  } // for
+  assert(cntL_LR == cntR_LR);
+  assert(cntL_LB == cntL_RB);
+  assert(cntR_LB == cntR_RB);
+#endif
+  
+  return;
+}
+
+#if 0
+// This below was an attempt to do it differently in Vienna, Dec 2007.
+// VH
+
+// ---------------------------------------------------------
+// split the list along the required axis
+// first is the begin of the SItem list, axis is the axis, where
+// to split, val is the splitting value in integer notation.
+// The output of the function are two lists, first and second
+// Optionally, objlist store the objects that straddle the splitting plane
+void
+CKTBABuildUp::BreakAxPosition(SInputData *d, int axis,
+			      SInputData *rightData,
+			      int &cntLout, int &cntRout)
+{
+  // the number of object boundaries for left array is not known
+  int cntLeft = 0;
+  int cntRight = 0;
+  d->cntThickness = 0;
+  const float positionToDecide = d->position;
+
+  // We have some problem that is difficult to detect, when tagging objects
+  // are allowed, the flags are not always reset to zero in some cases. 
+  // VH 2/1/2006. The flags are always left boundaries (=1).
+  // Therefore here it is a hack to assure that the flags are definitely zero.
+  if (resetFlagsForBreakAx) {
+    SItemVec *vecd = d->GetItemVec(axis);
+    for (SItemVec::iterator itt = vecd->begin(); itt != vecd->end(); itt++) {
+      (*itt).obj->ResetFlags();
+    } // for 
+  } // if
+  
+#ifdef _DEBUG
+  SItemVec *vecd = d->GetItemVec(axis);
+  for (SItemVec::iterator itt = vecd->begin(); itt != vecd->end(); itt++) {
+    if ((*itt).obj->Flags() != 0) {
+      cout << "Init ERROR 2 in original list, flags = "
+	   << (*itt).obj->Flags() << " obj = " << (void*)((*itt).obj) << endl;
+    }
+  } // for
+#endif // _DEBUG  
+
+  // Allocate the appropriate size for right array, for all 3 axes
+  // This is only estimated at this algorithm.
+  int estimatedSize = (int)(0.6f * (float)d->count);
+  if (estimatedSize < 10)
+    estimatedSize = 10;
+  assert(estimatedSize > 0);
+  rightData->Alloc(estimatedSize * 2);
+  
+  // First find create all left boundaries for right array
+  SItemVec *vecRight = rightData->GetItemVec(axis);
+
+  // Resize to 0 to start from the beginning
+  vecRight->resize(0);
+  SItemVec *vec = d->GetItemVec(axis);
+  SItemVec::iterator it;
+  SItemVec::iterator itLeft;
+  const SItemVec::iterator itEnd = vec->end();
+  bool foundBoundary = false;  
+  for (it = vec->begin(); it != itEnd; it++) {
+    const float &pos = (*it).pos;  
+    if (pos < positionToDecide) {
+      cntLeft++;
+      // Mark the item to be in the first list
+      (*it).obj->SetInFirstList();
+    }
+    else {
+      if (pos > positionToDecide) {
+	cntRight++;
+	(*it).obj->SetInSecondList();
+	if (!foundBoundary) {
+	  foundBoundary = true;
+	  itLeft = it;
+	}
+	// It belongs to the right list
+      }
+      else {
+	// pos == positionToDecide
+	if ((*it).IsRightBoundary()) {
+	  // it belongs to the left list
+	  cntLeft++;
+	  (*it).obj->SetInFirstList();
+	}
+	else {
+	  // this is the left boundary
+	  // it belongs already to the right list
+	  cntRight++;
+	  (*it).obj->SetInSecondList();
+	  if (!foundBoundary) {
+	    foundBoundary = true;
+	    itLeft = it;
+	  }
+	}
+      }
+    }
+  } // for it
+
+  // Remember the position of the iterator, where right
+  // list has to start
+  SItem boundary;
+  int cntDups = 0;
+  cntLeft = 0;
+  cntRight = 0;
+  
+  // create left boundaries for right list
+  boundary.pos = d->position;
+  boundary.axis = axis;
+  boundary.SetLeftBoundary();
+  for (it = itLeft; it != itEnd; it++) {
+    assert((*it).pos >= positionToDecide);
+    // Mark all the items to be in the second list
+    if ((*it).obj->InFirstList()) {
+      // and copy the newly created boundary to the right array
+      boundary.obj = (*it).obj;
+      vecRight->push_back(boundary);
+      cntDups++;
+      cntRight++;
+    }
+  } // for
+
+  // Now go through the right part of the list again
+  // and copy the rest of the list to the right list
+  for (it = vec->begin(); it != itEnd; it++) {
+    const float &pos = (*it).pos;
+    if (pos < positionToDecide) {
+      // we copy the boundary to the left list
+      *itLeft = *it;
+      itLeft++;
+      cntLeft++;
+    }    
+    if (pos > positionToDecide) {
+      // we copy the boundary to the right list
+      vecRight->push_back(*it);
+      cntRight++;
+    }
+    else {
+      if (pos == positionToDecide) {
+	if ((*it).obj->InBothLists()) {
+	  if ((*it).IsRightBoundary()) {
+	    // right boundary is added to the right as
+	    // we already created left boundaries
+	    vecRight->push_back(*it);
+	    cntRight++;
+	  }
+	  else {
+	    // we copy the left boundary to the left list
+	    *itLeft = *it;
+	    itLeft++;
+	    cntLeft++;
+	  }
+	}
+	else {
+	  // This boundary belongs to only a single list
+	  if ((*it).obj->InFirstList()) {
+	    // we copy this boundary  to the left list
+	    *itLeft = *it;
+	    itLeft++;
+	    cntLeft++;
+	  }
+	  else 
+	  if ((*it).obj->InSecondList()) {
+	    // we copy this boundary to the right list
+	    vecRight->push_back(*it);
+	    cntRight++;	    
+	  }
+	}
+      }
+    }
+  } // for
+
+  
+  // in final pass create the new boundaries for the left list
+  int i;
+  SItemVec::iterator srcIt = vecRight->begin();
+  for (it = itLeft, i = 0 ; i < cntDups; it++, srcIt++, i++) {
+    cntLeft++;
+    // first copy the boundary from the beginning of the right list
+    assert( (*srcIt).IsLeftBoundary());
+    *it = *srcIt;
+    // then set the right boundary in copied item
+    (*it).SetRightBoundary();
+    assert( (*it).IsRightBoundary());
+  } // for it
+  
+  // The boundary on the left, unused items are not used
+  vec->resize(cntLeft);
+  assert(cntLeft % 2 == 0);
+  assert(cntRight % 2 == 0);
+  assert(cntLeft+cntRight == 2*(d->count+cntDups));
+  
+  // The final setting of size
+  cntLout = cntLeft / 2;
+  cntRout = cntRight / 2;
+  // Set correctly also the number of objects
+  d->cntThickness = cntDups;
+
+#ifdef _DEBUG
+  SItemVec *vecdL = d->GetItemVec(axis);
+  int cntL = 0; int cntL_LB = 0; int cntL_RB = 0; int cntL_LR = 0;
+  for (SItemVec::iterator itl = vecdL->begin(); itl != vecdL->end(); itl++) {
+    if ((*itl).obj->InBothLists())
+      cntL_LR++;
+    if ((*itl).IsLeftBoundary()) cntL_LB++;
+    if ((*itl).IsRightBoundary()) cntL_RB++;
+    cntL++;
+  } // for
+  SItemVec *vecdR = rightData->GetItemVec(axis);
+  int cntR = 0; int cntR_LB = 0; int cntR_RB = 0; int cntR_LR = 0;
+  for (SItemVec::iterator itr = vecdR->begin(); itr != vecdR->end(); itr++) {
+    if ((*itr).obj->InBothLists())
+      cntR_LR++;
+    if ((*itr).IsLeftBoundary()) cntR_LB++;
+    if ((*itr).IsRightBoundary()) cntR_RB++;
+    cntR++;
+  } // for
+  assert(vecdL->size() == 2 * cntLout);
+  assert(vecdR->size() == 2 * cntRout);
+  assert(vecdL->size() == cntL_LB + cntL_RB);
+  assert(vecdR->size() == cntR_LB + cntR_RB);  
+  assert(cntL_LR == cntR_LR);
+  assert(cntL_LB == cntL_RB);
+  assert(cntR_LB == cntR_RB);
+#endif
+  
+  return;
+}
+#endif
+
+// ------------------------------------------------------------------
+// break the given list of SItem into two parts by reference axis
+// and reference value, the output is in the first and second SItem
+void
+CKTBABuildUp::DivideAx_I(SInputData *d, int axis,
+			 SInputData *rightData,
+			 int &cntLout, int &cntRout)
+{
+  // First check, if this is not only singular case
+  if (cntRout == 0) {
+    assert(d->cntThickness == 0);
+    return; // nothing to do
+  }
+  
+  // the number of found boundaries on the left and on the right
+  int cntLeft = 0;
+  int cntRight = 0;
+  
+  // vector for left and right part
+  SItemVec *vec = d->GetItemVec(axis);
+#ifdef _DEBUG
+  if (d->cntThickness == 0) {
+    SItemVec::iterator it;
+    for (it = vec->begin(); it != vec->end(); it++) {
+      if ((*it).obj->InBothLists()) {
+	cout << "ERROR in left 3 list" << endl;
+      }
+      if ((*it).obj->flags > 3) {
+	cout << "Problem with 4 flags = " << (*it).obj->flags << endl;	  
+      }
+    } // for    
+  }  
+#endif // _DEBUG  
+  
+  assert(vec->size() == d->count*2);
+  SItemVec *vecRight = rightData->GetItemVec(axis);
+  vecRight->resize(0);
+  
+  // Now go through source list
+  SItemVec::iterator itDest = vec->begin();
+  SItemVec::iterator itSrc = vec->begin();
+  // traverse all boundaries, belonging only to the left part
+  int i = 0;
+  const int imax = d->count*2;
+  for (; i != imax; itSrc++, i++) {    
+    // Check if the item belongs to the second list
+    if ((*itSrc).obj->InSecondList()) {
+      break; // we can copy the 
+    }
+    // Check if the item belongs to the first list
+    if ((*itSrc).obj->InFirstList()) {
+      // copy the content to the first list
+      // Note that *itDest = *itSrc is not necessary, since itDest = itSrc
+      cntLeft++;
+    }
+  } // for
+
+  // for newly copied object in the next step
+  itDest = itSrc;
+
+  // the boundaries can belong to both parts
+  for (; i != imax; itSrc++, i++) {    
+    // Check if the item belongs to the second list
+    if ((*itSrc).obj->InSecondList()) {
+      vecRight->push_back((*itSrc));
+      cntRight++;
+    }
+    // Check if the item belongs to the first list
+    if ((*itSrc).obj->InFirstList()) {
+      // copy the content to the first list
+      *itDest = *itSrc;
+      itDest++; // and move the iterator
+      cntLeft++;
+    }
+  } // for
+
+  assert(cntLeft % 2 == 0);
+  assert(cntRight % 2 == 0);
+  assert(cntLeft == 2 * cntLout);
+  assert(cntRight == 2 * cntRout);
+
+  vec->resize(cntLeft);  
+
+  return;
+}
+
+// break the given list of SItem into two parts by reference axis
+// and reference value, the output is in the first and second SItem
+void
+CKTBABuildUp::DivideAx_II(SInputData *d, int axis,
+			  SInputData *rightData,
+			  int &cntLout, int &cntRout)
+{
+  // First check, if this is not only singular case
+  if (cntRout == 0) {
+    assert(d->cntThickness == 0);
+    return; // nothing to do
+  }
+  
+  // the number of found boundaries on the left and on the right
+  int cntLeft = 0;
+  int cntRight = 0;
+  
+  // vector for left and right part
+  SItemVec *vec = d->GetItemVec(axis);
+#ifdef _DEBUG
+  if (d->cntThickness == 0) {
+    SItemVec::iterator it;
+    for (it = vec->begin(); it != vec->end(); it++) {
+      if ((*it).obj->InBothLists()) {
+	cout << "ERROR in left list" << endl;
+      }
+      if ((*it).obj->flags > 3) {
+	cout << "Problem with flags = " << (*it).obj->flags << endl;	  
+      }
+    } // for    
+  }
+#endif // _DEBUG  
+  
+  assert(vec->size() == d->count*2);
+  SItemVec *vecRight = rightData->GetItemVec(axis);
+  vecRight->resize(0);
+  
+  // Now go through the source list
+  SItemVec::iterator itDest = vec->begin();
+  SItemVec::iterator itSrc = vec->begin();
+  // traverse all boundaries, belonging only to the left part
+  int i = 0;
+  const int imax = d->count*2;
+  for (; i != imax; itSrc++, i++) {    
+    // Check if the item belongs to the second list
+    if ((*itSrc).obj->InSecondList()) {
+      break; // we can copy the 
+    }
+    // Check if the item belongs to the first list
+    if ((*itSrc).obj->InFirstList()) {
+      // copy the content to the first list
+      // Note that *itDest = *itSrc is not necessary, since itDest = itSrc
+      cntLeft++;
+    }
+    // Reset flags for the next subdivision step
+    if ((*itSrc).IsRightBoundary())
+      (*itSrc).obj->ResetFlags();
+  } // for
+
+  // for newly copied object in the next step
+  itDest = itSrc;
+
+  // !!!!!!!!!!!!!!
+  // for newly copied object in the next step
+  itDest = itSrc;
+
+  // the boundaries can belong to both parts
+  for (; i != imax; itSrc++, i++) {    
+    //if ((*itSrc).obj == objtf) {
+    //  cout << "DivideAxII - obj found2 , i = " << i << endl;
+
+    // Reset flags for the next subdivision step
+    if ((*itSrc).IsRightBoundary()) {
+      // This is the right boundary, we have to reset flags
+      bool inFirstList = (*itSrc).obj->InFirstList();
+      bool inSecondList = (*itSrc).obj->InSecondList();
+      (*itSrc).obj->ResetFlags();
+      if (inSecondList) {
+	cntRight++;
+	vecRight->push_back((*itSrc));
+      }
+	
+      // Check if the item belongs to the first list
+      if (inFirstList) {
+	cntLeft++;
+	// copy the content to the first list
+	*itDest = *itSrc;
+	itDest++; // and move the iterator
+      }
+    }
+    else { // left boundary
+      // Check if the item belongs to the second list
+      if ((*itSrc).obj->InSecondList()) {
+	cntRight++;
+	vecRight->push_back((*itSrc));
+      }
+      // Check if the item belongs to the first list
+      if ((*itSrc).obj->InFirstList()) {
+	cntLeft++;
+	// copy the content to the first list
+	*itDest = *itSrc;
+	itDest++; // and move the iterator
+      }
+    } // end of left boundary
+  } // for
+  
+  assert(cntLeft % 2 == 0);
+  assert(cntRight % 2 == 0);
+  assert(cntLeft == 2 * cntLout);
+  assert(cntRight == 2 * cntRout);
+  vec->resize(cntLeft);  
+
+#ifdef _DEBUG
+  for (SItemVec::iterator itt = vec->begin(); itt != vec->end(); itt++) {
+    if ((*itt).obj->Flags() != 0) {
+      cout << "DivideAxII ERROR 1 in final left list, flags = "
+	   << (*itt).obj->Flags() << " obj = " << (void*)((*itt).obj) << endl;
+      abort();;
+    }
+  } // for
+  for (SItemVec::iterator itt = vecRight->begin(); itt != vecRight->end(); itt++) {
+    if ((*itt).obj->Flags() != 0) {
+      cout << "DivideAxII ERROR 1 in final right list, flags = "
+	   << (*itt).obj->Flags() << " obj = " << (void*)((*itt).obj) << endl;
+      abort();;
+    }
+  } // for
+#endif // _DEBUG  
+  
+  return;
+}
+
+
+// break the given list of SItem into two parts by reference axis
+// and reference value, the output is in the first and second SItem
+void
+CKTBABuildUp::DivideAx_I_opt(SInputData *d, int axis,
+			     SInputData *rightData,
+			     int cntLout, int cntRout)
+{
+  // First check, if this is not only singular case
+  if (cntRout == 0) {
+    assert(d->cntThickness == 0);
+    return; // nothing to do
+  }
+  
+  // vector for left and right part
+  SItemVec *vec = d->GetItemVec(axis);
+
+#ifdef _DEBUG
+  if (vec->size() != d->count*2) {
+    cout << "vec->size() = " << vec->size()
+	 << " d->count*2 = " << d->count*2 << endl;
+  }
+
+  if (d->cntThickness == 0) {
+    SItemVec::iterator it;
+    for (it = vec->begin(); it != vec->end(); it++) {
+      if ((*it).obj->InBothLists()) {
+	cout << "ERROR in left list" << endl;
+      }
+      if ((*it).obj->flags > 3) {
+	cout << "Problem with flags = " << (*it).obj->flags << endl;	  
+      }
+    } // for    
+  }  
+#endif // _DEBUG  
+  
+  assert(vec->size() == d->count*2);
+  SItemVec *vecRight = rightData->GetItemVec(axis);
+  vecRight->resize(0);
+  
+  // Now go through source list
+  SItemVec::iterator itDest = vec->begin();
+  SItemVec::iterator itSrc = vec->begin();
+#if 1
+  if (vec->size() != d->count * 2) {
+    cout << "Something wrong HERE vec->size="
+	 << vec->size() << " d->count*2 = "
+	 << d->count*2 << endl;
+    abort();
+  }
+#endif  
+
+  // traverse all boundaries, belonging only to the left part
+  int i = 0;
+  const int imax = d->count*2;
+  for (; i != imax; itSrc++, i++) {    
+    // Check if the item belongs to the second list
+    if ((*itSrc).obj->InSecondList()) {
+      break; // we can copy the 
+    }
+  } // for
+
+  // for newly copied object in the next step
+  itDest = itSrc;
+  
+  // the boundaries can belong to both parts
+  for (; i != imax; itSrc++, i++) {
+    SItem &itt = *itSrc;
+    // Check if the item belongs to the second list    
+    if (itt.obj->InSecondList()) {
+      // and first copy the right boundary to a new list
+      vecRight->push_back((*itSrc));
+    }
+    // Check if the item belongs to the first list
+    if (itt.obj->InFirstList()) {
+      // copy the content to the first list
+      *itDest = *itSrc;
+      itDest++; // and move the iterator
+    }
+  } // for
+  
+  // Shorten the left array by resizing
+  vec->resize(cntLout*2);
+  assert(vecRight->size() == cntRout*2);
+  
+  return;
+}
+
+// break the given list of SItem into two parts by reference axis
+// and reference value, the output is in the first and second SItem
+void
+CKTBABuildUp::DivideAx_II_opt(SInputData *d, int axis,
+			      SInputData *rightData,
+			      int cntLout, int cntRout)
+{
+  // First check, if this is not only singular case
+  if (cntRout == 0) {
+    assert(d->cntThickness == 0);
+    return; // nothing to do
+  }
+    
+  // vector for left and right part
+  SItemVec *vec = d->GetItemVec(axis);
+  assert(vec->size() == d->count*2);
+#ifdef _DEBUG
+  if (d->cntThickness == 0) {
+    SItemVec::iterator it;
+    for (it = vec->begin(); it != vec->end(); it++) {      
+      if ((*it).obj->InBothLists()) {
+	cout << "ERROR in left list" << endl;
+      }
+      if ((*it).obj->flags > 3) {
+	cout << "Problem with flags = " << (*it).obj->flags << endl;	  
+      }
+    } // for    
+  }
+  {
+    SItemVec::iterator ittt;
+    for (ittt = vec->begin(); ittt != vec->end(); ittt++) {
+      if ((*ittt).obj->ToBeRemoved()) {
+	cout << "ERROR - to be removed in the left list" << endl;
+      }
+    }
+  }
+#endif // _DEBUG  
+  
+  assert(vec->size() == d->count*2);
+  SItemVec *vecRight = rightData->GetItemVec(axis);
+  vecRight->resize(0);
+  
+  // Now go through the source list
+  SItemVec::iterator itDest = vec->begin();
+  SItemVec::iterator itSrc = vec->begin();
+#if 1
+  if (vec->size() != d->count * 2) {
+    cout << "Something wrong HERE II vec->size="
+	 << vec->size() << " d->count*2 = "
+	 << d->count*2 << endl;
+    abort();
+  }
+#endif  
+  // traverse all boundaries, belonging only to the left part
+  int i = 0;
+  const int imax = d->count*2;
+  for (; i != imax; itSrc++, i++) {
+    //if ((*itSrc).obj == objtf) {
+    //  cout << "DivideAxII - obj found1 , i = " << i << endl;
+
+    // Check if the item belongs to the second list
+    if ((*itSrc).obj->InSecondList()) {
+      break; // we can copy the 
+    }
+    // Reset flags for the next subdivision step
+    if ((*itSrc).IsRightBoundary())
+      (*itSrc).obj->ResetFlags();
+  } // for
+
+  // for newly copied object in the next step
+  itDest = itSrc;
+
+  // the boundaries can belong to both parts
+  for (; i != imax; itSrc++, i++) {    
+    //if ((*itSrc).obj == objtf) {
+    //  cout << "DivideAxII - obj found2 , i = " << i << endl;
+
+    bool inFirstList = (*itSrc).obj->InFirstList();
+    bool inSecondList = (*itSrc).obj->InSecondList();
+
+    // Reset flags for the next subdivision step
+    if ((*itSrc).IsRightBoundary()) {
+      // This is the right boundary, we have to reset flags
+      if (inSecondList)
+	vecRight->push_back((*itSrc));
+      // Check if the item belongs to the first list
+      if (inFirstList) {
+	// copy the content to the first list
+	*itDest = *itSrc;
+	itDest++; // and move the iterator
+      }
+    }
+    else { // left boundary
+      // Check if the item belongs to the second list
+      if (inSecondList) {
+	vecRight->push_back((*itSrc));
+      }
+      // Check if the item belongs to the first list
+      if (inFirstList) {
+	// copy the content to the first list
+	*itDest = *itSrc;
+	itDest++; // and move the iterator
+      }
+    } // end of left boundary
+  } // for
+
+  // Shorten the left array by resizing
+  vec->resize(cntLout*2);
+  assert(vecRight->size() == cntRout*2);
+
+#if 0
+#ifdef _DEBUG
+  for (SItemVec::iterator itt2 = vec->begin(); itt2 != vec->end(); itt2++) {
+    if ((*itt2).obj->Flags() != 0) {
+      cout << "DivideAxII ERROR 1 in final left list, flags = "
+	   << (*itt2).obj->Flags() << " obj = "
+	   << (void*)((*itt2).obj) << endl;
+      abort();;
+    }
+  } // for
+  for (SItemVec::iterator itt3 = vecRight->begin(); itt3 != vecRight->end(); itt3++) {
+    if ((*itt3).obj->Flags() != 0) {
+      cout << "DivideAxII ERROR 1 in final right list, flags = "
+	   << (*itt3).obj->Flags() << " obj = "
+	   << (void*)((*itt3).obj) << endl;
+      abort();;
+    }
+  } // for
+#endif // _DEBUG  
+#endif
+  
+  return;
+}
+
+#ifdef _VYPIS
+void
+CKTBABuildUp::PrintOut(CKTBAxes::Axes axis, int stat, SItem **first,
+		       SItem **second, float /*position*/)
+{
+#if 1
+  int cnt = 0;
+  SItem *t = *first;
+  if (stat & 1) {
+    DEBUG << "----FIRST--- axis=" << (int)axis << "\n";
+    while (t != NULL) {
+#define _VYP
+
+#ifdef _VYP
+      float v = t->value[axis];
+      DEBUGW << "curr=" << t
+#ifdef _BIDIRLISTS
+	     << " prev=" << t->prev[axis]
+#endif
+	     << " next="
+	     << t->next[axis] << " val=" << v
+	     << " " << (t->IsRightBoundary() ? 1 : 0);
+      if (t->IsRightBoundary())
+	DEBUGW << "   obj= " << t->obj;
+      else
+	DEBUGW << "   pair= " << t->pairF;
+      
+      DEBUGW << endl;
+#endif // _VYP
+      t = t->next[axis];
+      cnt++;
+    }
+    
+    DEBUG<< "FIRST cnt= " << cnt <<"\n" << flush;
+  }
+
+  if (stat & 2) {
+    // the right list
+    t = *second;
+    cnt = 0;
+    DEBUG << "----SECOND-----\n";
+    while (t != NULL) {
+#ifdef _VYP
+      float v = t->value[axis];
+      DEBUGW << "curr=" << t
+#ifdef _BIDIRLISTS
+	     << " prev=" << t->prev[axis]
+#endif
+	     << " next="
+	    << t->next[axis] << " val=" << v
+	    << " " << ((t->IsRightBoundary()) ? 1 : 0);
+      if (t->IsRightBoundary())
+	DEBUGW << "   obj= " << t->obj;
+      else
+	DEBUGW << "   pair= " << t->pairF;
+      DEBUGW << "\n" << flush;
+#endif // _VYP
+      t = t->next[axis];
+      cnt++;
+    }
+    DEBUGW << "SECOND cnt= " << cnt <<"\n" << flush;
+  }
+#endif
+}
+#endif // _VYPIS
+
+// --------------------------------------------------------------------
+// class CKTBABuildUp::CTestAx
+
+// The initialization for the first axis to be tested, this time *****Z axis*******
+void
+CKTBABuildUp::SSplitState::InitXaxis(int cnt, const SBBox &boxN)
+{
+  // initialize the variables, mainly for surface area estimates
+  cntAll = cnt;     // the number of all objects in the bounding box
+  cntLeft = 0;      // the count of bounding boxes on the left
+  cntRight = cnt;   // the count of bounding boxes on the right
+  thickness = 0;    // the count of bounding boxes straddling the splitting plane
+  axis = CKTBAxes::EE_X_axis; // the axis, where the splitting is proposed
+  box = boxN;        // the box, that is subdivided
+  //int topAxis = 1;        // axis that is considered in top .. depth
+  //int frontAxis = 2;      // axis that is considered in front .. height  
+  // the size of bounding box along the axis to be split
+  width = box.Max().x - box.Min().x;
+  // and along two other axes  
+  topw = box.Max().y - box.Min().y;
+  frontw = box.Max().z - box.Min().z;
+  // surface area of the splitting plane .. one face !!
+  areaSplitPlane = topw * frontw;
+  // the sum of length of the boxes not to be subdivided
+  areaSumLength = topw + frontw;
+  // The surface are of the whole box
+  areaWholeSA2 = width * areaSumLength + areaSplitPlane;
+  // initial evaluation .. the worst cost
+  bestCost = WorstEvaluation();
+}
+
+// The initialization for the first axis to be tested, this time *****Y axis*******
+// This can be run independently.
+void
+CKTBABuildUp::SSplitState::InitYaxis(int cnt, const SBBox &boxN)
+{
+  // initialize the variables, mainly for surface area estimates
+  cntAll = cnt;     // the number of all objects in the bounding box
+  cntLeft = 0;      // the count of bounding boxes on the left
+  cntRight = cnt;   // the count of bounding boxes on the right
+  thickness = 0;    // the count of bounding boxes straddling the splitting plane
+  axis = CKTBAxes::EE_Y_axis; // the axis, where the splitting is proposed
+  box = boxN;        // the box, that is subdivided
+  //int frontAxis = oaxes[axis][0]; // axis that is considered in front .. height - x-axis
+  //int topAxis = oaxes[axis][1]; // axis that is considered in top .. depth - y-axis
+  // the size along the second axis - height
+  frontw = box.Max().x - box.Min().x;
+  // the size of bounding box along the axis to be split - width
+  width = box.Max().y - box.Min().y;
+  // The size along third axis - depth
+  topw = box.Max().z - box.Min().z;
+  // surface area of the splitting plane .. one face !!
+  areaSplitPlane = topw * frontw;
+  // the sum of length of the boxes not to be subdivided
+  areaSumLength = topw + frontw;
+  areaWholeSA2 = width * areaSumLength + areaSplitPlane;
+  // initial evaluation .. the worst cost
+  bestCost = WorstEvaluation();
+}
+
+// The initialization for the first axis to be tested, this time *****Z axis*******
+// This can be run independently.
+void
+CKTBABuildUp::SSplitState::InitZaxis(int cnt, const SBBox &boxN)
+{
+  // initialize the variables, mainly for surface area estimates
+  cntAll = cnt;     // the number of all objects in the bounding box
+  cntLeft = 0;      // the count of bounding boxes on the left
+  cntRight = cnt;   // the count of bounding boxes on the right
+  thickness = 0;    // the count of bounding boxes straddling the splitting plane
+  axis = CKTBAxes::EE_Z_axis; // the axis, where the splitting is proposed
+  box = boxN;       // the box, that is subdivided
+  //int frontAxis = oaxes[axis][1]; // axis that is considered in front .. height - x axis
+  //int topAxis = oaxes[axis][0]; // axis that is considered in top .. depth - y axis
+  // The size along third axis - depth
+  topw = box.Max().x - box.Min().x;
+  // the size along the second axis - height
+  frontw = box.Max().y - box.Min().y;
+  // the size of bounding box along the axis to be split - width
+  width = box.Max().z - box.Min().z;
+  // surface area of the splitting plane .. one face !!
+  areaSplitPlane = topw * frontw;
+  // the sum of length of the boxes not to be subdivided
+  areaSumLength = topw + frontw;
+  areaWholeSA2 = width * areaSumLength + areaSplitPlane;
+  // initial evaluation .. the worst cost
+  bestCost = WorstEvaluation();
+}
+
+// --------------------------------------------------------------------
+// The initialization for the first axis to be tested, use only in case
+// when all 3 axes are tested. It can be called only when InitXaxis was called before !!!!
+void
+CKTBABuildUp::SSplitState::ReinitYaxis(int cnt, const SBBox &boxN)
+{
+  // initialize the variables, mainly for surface area estimates
+  assert(cntAll == cnt); // the number of all objects in the bounding box
+  cntLeft = 0;      // the count of bounding boxes on the left
+  cntRight = cnt;   // the count of bounding boxes on the right
+  thickness = 0;    // the count of bounding boxes straddling the splitting plane
+  axis = CKTBAxes::EE_Y_axis; // the axis, where the splitting is proposed
+  //int topAxis = 2;      // axis that is considered in top .. depth
+  //int frontAxis = 0;    // axis that is considered in front .. height  
+  // Swap the width, height, and depth
+  float tS = width;
+  // the size of bounding box along the axis to be split
+  width = topw;
+  // and along two other axes
+  topw = frontw;
+  frontw = tS; // copy the temporary variable
+  // surface area of the splitting plane .. one face !!
+  areaSplitPlane = topw * frontw;
+  // the sum of length of the boxes not to be subdivided
+  areaSumLength = topw + frontw;
+  //assert(areaWholeSA2 == width * SumLength + areaSplitPlane);
+}
+
+// The initialization for the first axis to be tested, use only in case
+// when all 3 axes are tested. It can be called only when ReinitYaxis was called before !!!
+void
+CKTBABuildUp::SSplitState::ReinitZaxis(int cnt, const SBBox &boxN)
+{
+  // initialize the variables, mainly for surface area estimates
+  assert(cntAll == cnt); // the number of all objects in the bounding box
+  cntLeft = 0;      // the count of bounding boxes on the left
+  cntRight = cnt;   // the count of bounding boxes on the right
+  thickness = 0;    // the count of bounding boxes straddling the splitting plane
+  axis = CKTBAxes::EE_Z_axis; // the axis, where the splitting is proposed
+  // Swap the width, height, and depth
+  float tS = width;
+  // the size of bounding box along the axis to be split
+  width = topw;
+  // and along two other axes  
+  topw = frontw;
+  frontw = tS; // copy the temporary variable
+  // surface area of the splitting plane .. one face !!
+  areaSplitPlane = topw * frontw;
+  // the sum of length of the boxes not to be subdivided
+  areaSumLength = topw + frontw;
+  //assert(areaWholeSA2 == width * stateSumLength + areaSplitPlane);
+}
+
+// This is the computation of the cost using surface area heuristics
+// using LINEAR EXTIMATE
+void
+CKTBABuildUp::EvaluateCost(SSplitState &state)
+{
+  // the surface area of the bounding box for the left child
+  assert(state.position > -1e-9);
+  float areaLeft = state.position * state.areaSumLength + state.areaSplitPlane;
+
+  // the surface area of the right bounding box for the right child
+  assert(state.width - state.position > -1e-9);
+  float areaRight = (state.width - state.position) * state.areaSumLength +
+                    state.areaSplitPlane;
+
+  // computation of the cost .. smaller is better
+  float cost = areaLeft * state.cntLeft + areaRight * state.cntRight;
+
+#ifdef _DEBUG_COSTFUNCTION
+  // Put there normalized position and cost also normalized somehow
+  ReportCostStream(state.position / state.width,
+		   cost / (state.areaWholeSA2 * state.cntAll));
+#endif
+  
+  // This normalization is not in fact necessary here
+  //cost //= state.areaWholeSA2;
+  if (cost < state.bestCost) {
+    state.bestCost = cost;
+    // The iterator pointing to the best boundary
+    state.bestIterator = state.it;
+    // The number of objects whose boundaries are duplicated
+    state.bestThickness = state.thickness;
+  }
+  return;
+}
+
+// This is the computation of the cost using surface area heuristics
+void
+CKTBABuildUp::EvaluateCostFreeCut(SSplitState &state)
+{
+  // This is assumed to work for free cut (no object intersected)
+  assert(state.thickness == 0);
+  
+  // the surface area of the bounding box for the left child
+  assert(state.position > -1e-9);
+  float areaLeft = state.position * state.areaSumLength + state.areaSplitPlane;
+
+  // the surface area of the right bounding box for the right child
+  assert(state.width - state.position > -1e-9);
+  float areaRight = (state.width - state.position) * state.areaSumLength +
+                    state.areaSplitPlane;
+
+  // computation of the cost .. smaller is better
+  float cost = biasFreeCuts *(areaLeft * state.cntLeft + areaRight * state.cntRight);
+
+#ifdef _DEBUG_COSTFUNCTION
+  // Put there normalized position and cost also normalized somehow
+  ReportCostStream(state.position / state.width,
+		   cost / (state.areaWholeSA2 * state.cntAll));
+#endif
+  
+  // This normalization is not in fact necessary here
+  //cost //= state.areaWholeSA2;
+  if (cost < state.bestCost) {
+    state.bestCost = cost;
+    // The iterator pointing to the best boundary
+    state.bestIterator = state.it;
+    // The number of objects whose boundaries are duplicated
+    state.bestThickness = 0;
+  }
+  return;
+}
+
+// -------------------------------------------------------------------------------
+// TRIAL TO IMPROVE for a given X-axis search for the best splitting plane position.
+// Starts from start item, the rest of the information is set to 'state' variable.
+void
+CKTBABuildUp::GetSplitPlaneOpt(SItemVec *vec, int axisToTest)
+{
+#ifdef _DEBUG
+  if ((vec == NULL) || (vec->size() == 0)) {
+    cerr << "Trying to subdivide some node without an object" << endl;
+    abort();;
+  }
+#endif // _DEBUG  
+
+#if 0
+  static int index = 0;
+  cout << "index = " << index << endl;
+  const int indexToFind = 8;
+  if (index == indexToFind) {
+    cout << "Index found = " << index << endl;
+  }  
+  index++;
+#endif
+  
+  // some necessary space is required to cut off
+  const float eps = 1.0e-6 * state.width;
+  const float MinPosition = state.box.Min(axisToTest);
+  const float MaxPosition = state.box.Max(axisToTest);
+  //float MinPositionAccept = MinPosition + eps;
+  //float MaxPositionAccept = MaxPosition - eps;
+
+  // wherefrom to start
+  SItemVec::iterator curr = vec->begin();
+  SItemVec::iterator next = vec->begin() + 1;
+  // Set the type of splitting by this function, which is in this case
+  // not overwritten in Evaluate() function
+  state.bestTwoSplits = 1;
+  float val = (*curr).pos;
+  float nval;
+  float pval = val;
+
+  // Evaluate the first possible position, cutting off empty
+  // space on the left of the splitting plane
+  state.position = val - MinPosition;
+  if (state.position > 0.f) {
+    state.position2 = next->pos - MinPosition;
+    state.it = curr;
+    // Here evaluate the cost of surface area heuristics
+    EvaluateCostFreeCut(state);
+  }
+  
+  //-------------------- TEST LOOP ---------------------------------------
+  // make evaluation for each splitting position
+  const int imax = vec->size()-1;
+  int ii;
+  for (ii = 0; ii < imax; ii++)
+  {
+    nval = next->pos;
+
+#if 0
+    if (axisToTest == 2) {
+      if ((val > 0.866) && (val < 0.870)) {       
+	cout << "val = " << val;
+	cout << "  nval = " << nval;
+	if (curr->IsRightBoundary())
+	  cout << " R ";
+	else
+	  cout << " L ";
+	cout << " thickness = " << state.thickness << endl;
+	
+      }
+    }
+#endif    
+    // update left box and rightbox properties
+    if (curr->IsRightBoundary()) { // we are on the right boundary of an object
+      state.cntRight--;
+      state.thickness--;
+      // Check possibly the position
+      if ( (val != nval) ||
+	   ((curr->IsRightBoundary()) && (next->IsLeftBoundary())) )
+	{
+	  state.position = val - MinPosition;
+	  state.position2 = nval - MinPosition;
+	  state.it = curr;
+	  // Here evaluate the cost of surface area heuristics
+	  EvaluateCost(state);
+	}      
+    }
+    else {
+      // the left boundary .. enter the object from left
+
+      // Check possibly the position
+      if ( (pval != val)
+	   // || ((curr->IsRightBoundary()) && (next->IsLeftBoundary()))
+	   )
+	{
+	  state.position = val - MinPosition;
+	  state.position2 = nval - MinPosition;
+	  state.it = curr;
+	  // Here evaluate the cost of surface area heuristics
+	  EvaluateCost(state);
+	}    
+      
+      state.cntLeft++;
+      state.thickness++;
+    }
+        
+    curr = next; // pointer to the boundary
+    next++;
+    pval = val;
+    val = nval; // value of splitting plane
+  } // while 
+
+  //cout << "i = " << i << endl;
+  
+  assert(state.cntLeft == state.cntAll);
+  state.cntRight--;
+  assert(state.cntRight == 0);
+  state.thickness--;
+  assert(state.thickness == 0);  
+  
+  // Evaluate last possible position 
+  state.position = val - MinPosition;
+  if (state.position < MaxPosition) {
+    state.position2 = state.width;
+    state.it = curr;
+    // Here evaluate the cost of surface area heuristics
+    EvaluateCostFreeCut(state);
+  }
+   
+  // In this case the best result is kept in 'state' variable
+  return;
+} // CTestAx::GetSplitPlaneOpt (for X, Y, Z)
+
+// -------------------------------------------------------------------------------
+// TRIAL TO IMPROVE for a given X/Y/Z-axis search for the best splitting plane position.
+// Starts from start item, the rest of the information is set to 'state' variable.
+void
+CKTBABuildUp::GetSplitPlaneOpt2(SItemVec *vec, int axisToTest)
+{
+#ifdef _DEBUG
+  if ((vec == NULL) || (vec->size() == 0)) {
+    cerr << "Trying to subdivide some node without an object" << endl;
+    abort();;
+  }
+#endif // _DEBUG  
+  
+  // some necessary space is required to cut off
+  const float eps = 1.0e-6 * state.width;
+  const float MinPosition = state.box.Min(axisToTest);
+  const float MaxPosition = state.box.Max(axisToTest);
+  //float MinPositionAccept = MinPosition + eps;
+  //float MaxPositionAccept = MaxPosition - eps;
+
+  // wherefrom to start
+  SItemVec::iterator curr = vec->begin();
+  SItemVec::iterator next = vec->begin() + 1;
+  // Set the type of splitting by this function, which is in this case
+  // not overwritten in Evaluate() function
+  state.bestTwoSplits = 1;
+  state.thickness = 0;
+  float val = (*curr).pos;
+  float nval;
+  float pval = val;
+
+//#if 1
+#ifdef _DEBUG_COSTFUNCTION
+  static int indexToFind = 0;
+  static int indexSS = 0;
+  if ( (indexSS == indexToFindSS) &&
+       (!_alreadyDebugged)) {
+    cout << "Debugging cost function, index = " << indexSS << endl;
+    InitCostStream(indexSS, state.cntAll,
+		   (val-state.box.Min(axisToTest))/state.width,
+		   //(val-MinPosition)/state.width,
+		   //(MinPosition)/state.width,
+		   (state.box.Max(axisToTest)-MinPosition)/state.width);
+  }
+  indexSS++;
+#endif
+  
+  // Evaluate the first possible position, cutting off empty
+  // space on the left of the splitting plane
+  state.position = val - MinPosition;
+  if (state.position > 0.f) {
+    state.position2 = next->pos - MinPosition;
+    state.it = curr;
+    // Here evaluate the cost of surface area heuristics
+    EvaluateCostFreeCut(state);
+  }
+  
+  //-------------------- TEST LOOP ---------------------------------------
+  // make evaluation for each splitting position
+  const int imax = vec->size()-1;
+  int ii;
+  for (ii = 1; ii <= imax; ii++)
+  {
+    nval = (*vec)[ii].pos;
+    // update left box and rightbox properties
+    if (curr->IsRightBoundary()) {
+      // the right boundary of an object
+      state.cntRight--;
+      state.thickness--;
+      
+      // Check possibly the position
+      if ( (val != nval) ||
+	   ((curr->IsRightBoundary()) && (next->IsLeftBoundary())) )
+	{
+	  if (state.thickness >= 0) {
+	    state.position = val - MinPosition;
+	    state.position2 = nval - MinPosition;
+	    state.it = curr;
+	    // Here evaluate the cost of surface area heuristics
+	    EvaluateCost(state);
+	  }
+	}
+    }
+    else {
+      // the left boundary .. enter the object from left
+
+      // Check possibly the position
+      if (pval != val)
+      {
+	if (state.thickness >= 0) {
+	  state.position = val - MinPosition;
+	  state.position2 = nval - MinPosition;
+	  state.it = curr;
+	  // Here evaluate the cost of surface area heuristics
+	  EvaluateCost(state);
+	}
+      }      
+      state.cntLeft++;
+      state.thickness++;
+    }
+        
+    curr = next; // pointer to the boundary
+    pval = val;
+    val = nval; // value of splitting plane
+    next++;
+  } // while 
+
+  //cout << "i = " << i << endl;
+  
+  assert(state.cntLeft == state.cntAll);
+  state.cntRight--;
+  assert(state.cntRight == 0);
+  state.thickness--;
+  assert(state.thickness == 0);  
+
+#if 0
+  if (state.thickness < 0) {
+    cout << "SSSomething wrong happened here at end\n" << endl;
+  }
+#endif      
+
+#ifdef _DEBUG
+  if (curr != vec->end()-1) {
+    cerr << "Implementation bug in pointers" << endl;
+    cout << "curr = " << curr - vec->begin()
+	 << " vec->end()-1 = " << vec->end()-1 - vec->begin() << endl;
+    abort();;
+  }
+#endif
+  
+  // Evaluate last possible position 
+  state.position = val - MinPosition;
+  if (state.position < MaxPosition) {
+    state.position2 = state.width;
+    state.it = curr;
+    // Here evaluate the cost of surface area heuristics
+    EvaluateCostFreeCut(state);
+  }
+  
+#ifdef _DEBUG_COSTFUNCTION
+  CloseCostStream();
+#endif
+  
+  // In this case the best result is kept in 'state' variable
+  return;
+} // CTestAx::GetSplitPlaneOpt (for X, Y, Z)
+
+// -------------------------------------------------------------------------------
+// TRIAL TO IMPROVE for a given X/Y/Z-axis search for the best splitting plane position.
+// Using unrolling possibly understandable for inteligent compiler.
+// Starts from start item, the rest of the information is set to 'state' variable.
+void
+CKTBABuildUp::GetSplitPlaneOpt3(SItemVec *vec, int axisToTest)
+{
+#ifdef _DEBUG
+  if ((vec == NULL) || (vec->size() == 0)) {
+    cerr << "Trying to subdivide some node without an object" << endl;
+    abort();;
+  }
+#endif // _DEBUG  
+
+#if 0
+  static int index = 0;
+  cout << "index = " << index << endl;
+  const int indexToFind = 27;
+  if (index == indexToFind) {
+    cout << "Index found = " << index << endl;
+  }  
+  index++;
+#endif
+  
+  // some necessary space is required to cut off
+  const float eps = 1.0e-6 * state.width;
+  const float MinPosition = state.box.Min(axisToTest);
+  const float MaxPosition = state.box.Max(axisToTest);
+  //float MinPositionAccept = MinPosition + eps;
+  //float MaxPositionAccept = MaxPosition - eps;
+
+  // wherefrom to start
+  SItemVec::iterator curr = vec->begin();
+  SItemVec::iterator next = vec->begin() + 1;
+  // Set the type of splitting by this function, which is in this case
+  // not overwritten in Evaluate() function
+  state.bestTwoSplits = 1;
+  float val = (*curr).pos;
+  // value at previous and next position
+  float pval, nval;
+  pval = MinPosition;
+
+  // Evaluate the first possible position, cutting off empty
+  // space on the left of the splitting plane
+  state.position = val - MinPosition;
+  // The first boundary must be left
+  assert(curr->IsLeftBoundary());
+  if (state.position > 0.f) {    
+    state.position2 = next->pos - MinPosition;
+    state.it = curr;
+    // Here evaluate the cost of surface area heuristics
+    EvaluateCostFreeCut(state);
+  } // ------------------------------
+  // Update for the next iteration
+  state.cntLeft++;
+  state.thickness++;
+  pval = val;
+  
+  //-------------------- TEST LOOP ---------------------------------------
+  // make evaluation for each splitting position, minus the first and
+  // the last one
+  int imax = vec->size()-2;
+  // Setting unrolling
+  const int MaxUNROLL = 4;
+  const int loops = imax / MaxUNROLL;
+  const int remainder = imax % MaxUNROLL;
+  // There is some bug, when using this version, the boundaries are
+  // incorrectly sorted.
+  assert(remainder < MaxUNROLL);
+  int ii = 1;
+  if (loops > 0) {
+    // The outer loop
+    for (int l = 0; l < loops; l++, ii += MaxUNROLL)
+    {
+      // This has to be unrolled by compiler such as Intel Compiler or GCC4.1
+      // The number of loops is known in advance !
+      for (int qq = 0; qq < MaxUNROLL; qq++)
+      {
+	curr = vec->begin() + ii + qq;
+	next = curr + 1;
+	#if 1
+	val = (*curr).pos;
+	nval = (*next).pos;
+	#else
+	val = (*vec)[ii+qq].pos;
+	nval = (*vec)[ii+qq+1].pos;
+	#endif
+	
+	// update left box and rightbox properties
+	if (curr->IsRightBoundary()){// we are on the right boundary of an object
+	  state.cntRight--;
+	  state.thickness--;
+	  // Check possibly the position
+	  if ( (val != nval) ||
+	       ((curr->IsRightBoundary()) && (next->IsLeftBoundary())) )
+	  {
+	    state.position = val - MinPosition;
+	    state.position2 = nval - MinPosition;
+	    state.it = curr;
+	    // Here evaluate the cost of surface area heuristics
+	    EvaluateCost(state);
+ 	    // It does make sense to change boundary value
+	    pval = (*vec)[ii+qq].pos; 
+	  }
+	}
+	else {
+	  // the left boundary .. enter the object from left
+	
+	  // Check possibly the position
+	  if (pval != val)
+	  {
+	    state.position = val - MinPosition;
+	    state.position2 = nval - MinPosition;
+	    state.it = curr;
+	    // Here evaluate the cost of surface area heuristics
+	    EvaluateCost(state);
+ 	    // It makes sense to change boundary value
+	    pval = (*vec)[ii+qq].pos;
+	  }
+	  state.cntLeft++;
+	  state.thickness++;
+	} // left or right boundary      
+      } // for qq
+    } // for ii
+
+    // Set the correct pointer for the next iteration
+    curr = next; next++;
+    pval = val;
+  }
+  else {
+    //cout << "No loop" << endl;
+    pval = val;
+    curr = next;
+    next++;
+  }
+
+  // The rest of the loop
+  if (ii <= imax) {
+    // Set the correct pointer  
+    for ( ;ii <= imax; ii++) {
+      nval = curr->pos;
+      // update left box and rightbox properties
+      if (curr->IsRightBoundary()) { // we are on the right boundary of an object
+	state.cntRight--;
+	state.thickness--;
+	// Check possibly the position
+	if ( (val != nval) ||
+	     ((curr->IsRightBoundary()) && (next->IsLeftBoundary())) )
+	{
+	  state.position = val - MinPosition;
+	  state.position2 = nval - MinPosition;
+	  state.it = curr;
+	  // Here evaluate the cost of surface area heuristics
+	  EvaluateCost(state);
+	}
+      }
+      else {
+	// the left boundary .. enter the object from left
+      
+	// Check possibly the position
+	if (pval != val)
+	{
+	  state.position = val - MinPosition;
+	  state.position2 = nval - MinPosition;
+	  state.it = curr;
+	  // Here evaluate the cost of surface area heuristics
+	  EvaluateCost(state);
+	}
+	state.cntLeft++;
+	state.thickness++;
+      } // if right/left boundary
+    
+      curr = next; // pointer to the boundary
+      pval = val;
+      val = nval; // value of splitting plane
+      next++;
+    } // for qq
+
+    // For the last evaluation
+  }
+  else {
+    if (!loops) {
+      curr = next;
+      val = nval;
+    }
+  }
+
+  //cout << "i = " << i << endl;
+
+#ifdef _DEBUG  
+  if (curr != vec->end()-1) {
+    cerr << "Implementation bug in pointers" << endl;
+    cout << "curr = " << curr - vec->begin()
+	 << "vec->end()-1 = " << vec->end()-1 - vec->begin() << endl;
+    abort();;
+  }
+#endif
+  
+  assert(state.cntLeft == state.cntAll);
+  state.cntRight--;
+  assert(state.cntRight == 0);
+  state.thickness--;
+  assert(state.thickness == 0);
+  
+  // Evaluate last possible position
+  state.position = val - MinPosition;
+  if (state.position < MaxPosition) {
+    state.position2 = state.width;
+    state.it = curr;
+    // Here evaluate the cost of surface area heuristics
+    EvaluateCostFreeCut(state);
+  }
+   
+  // In this case the best result is kept in 'state' variable
+  return;
+} // CTestAx::GetSplitPlaneOpt3 (for X, Y, Z)
+
+#if 0
+// Here is some bug, that is clearly visible for tree.nff !! The resulting
+// tree is much less efficient. 3/1/2006 VH.
+// -------------------------------------------------------------------------------
+// TRIAL TO IMPROVE for a given X,Y,Z-axis search for the best splitting plane position.
+// Starts from start item, the rest of the information is set to 'state' variable.
+// It does not work for gcc compiler better than GetSplitPlaneOpt
+void
+CKTBABuildUp::GetSplitPlaneOptUnroll4(SItemVec *vec, int axisToTest)
+{
+#ifdef _DEBUG
+  if ((vec == NULL) || (vec->size() == 0)) {
+    cerr << "Trying to subdivide some node without an object" << endl;
+    abort();;
+  }
+#endif // _DEBUG  
+
+#if 0
+  static int index = 0;
+  cout << "index = " << index << endl;
+  const int indexToFind = 8;
+  if (index == indexToFind) {
+    cout << "Index found = " << index << endl;
+  }  
+  index++;
+#endif
+  
+  // some necessary space is required to cut off
+  const float eps = 1.0e-6 * state.width;
+  const float MinPosition = state.box.Min(axisToTest);
+  const float MaxPosition = state.box.Max(axisToTest);
+  //float MinPositionAccept = MinPosition + eps;
+  //float MaxPositionAccept = MaxPosition - eps;
+
+  // wherefrom to start
+  // Set the type of splitting by this function, which is in this case
+  // not overwritten in Evaluate() function
+  state.bestTwoSplits = 1;
+  float val4 = MinPosition;
+  
+  //-------------------- TEST LOOP ---------------------------------------
+  // make evaluation for each splitting position
+
+  // the first position was already evaluated and the last is also a special case
+  const int imax = vec->size() - 1;
+  int cntDebug = 0;
+  int imax4 = 4*(imax/4);
+  int imax4rest = imax % 4;
+  int i;
+  // This is manual unrolling
+  if (imax4 >= 4) {
+  for(i = 0; i < imax4; i += 4)
+  {
+    // The evaluation I
+    cntDebug++;
+    float pval1 = val4;
+    SItem* curr1 = &((*vec)[i+0]); float val1 = (*vec)[i+0].pos;
+    SItem* next1 = &((*vec)[i+1]); float nval1 = (*vec)[i+1].pos;
+    if (curr1->IsRightBoundary()) {
+      state.cntRight--; state.thickness--;
+      if ( (val1 != nval1) ||
+	   ((curr1->IsRightBoundary()) && (next1->IsLeftBoundary())) ) {
+	state.position = val1 - MinPosition; state.position2 = nval1 - MinPosition;
+	state.it = vec->begin() + i; EvaluateCost(state);
+      }
+    }
+    else {
+      if (pval1 != val1) {
+	  state.position = val1 - MinPosition; state.position2 = nval1 - MinPosition;
+	  state.it = vec->begin() + i; EvaluateCost(state);
+      }
+      state.cntLeft++; state.thickness++;
+    }
+    // The evaluation II
+    cntDebug++;
+    float pval2 = (*vec)[i+0].pos;
+    SItem* curr2 = &((*vec)[i+1]); float val2 = (*vec)[i+1].pos;
+    SItem* next2 = &((*vec)[i+2]); float nval2 = (*vec)[i+2].pos;
+    if (curr2->IsRightBoundary()) {
+      state.cntRight--; state.thickness--;
+      if ( (val2 != nval2) ||
+	   ((curr2->IsRightBoundary()) && (next2->IsLeftBoundary())) ) {
+	state.position = val2 - MinPosition; state.position2 = nval2 - MinPosition;
+	state.it = vec->begin() + i + 1; EvaluateCost(state);
+      }
+    }
+    else {
+      if (pval2 != val2) {
+	  state.position = val2 - MinPosition; state.position2 = nval2 - MinPosition;
+	  state.it = vec->begin() + i + 1; EvaluateCost(state);
+      }
+      state.cntLeft++; state.thickness++;
+    }
+    // The evaluation III
+    cntDebug++;
+    float pval3 = (*vec)[i+1].pos;
+    SItem* curr3 = &((*vec)[i+2]); float val3 = (*vec)[i+2].pos;
+    SItem* next3 = &((*vec)[i+3]); float nval3 = (*vec)[i+3].pos;
+    if (curr3->IsRightBoundary()) {
+      state.cntRight--; state.thickness--;
+      if ( (val3 != nval3) ||
+	   ((curr3->IsRightBoundary()) && (next3->IsLeftBoundary())) ) {
+	state.position = val3 - MinPosition; state.position2 = nval3 - MinPosition;
+	state.it = vec->begin() + i + 2; EvaluateCost(state);
+      }
+    }
+    else {
+      if (pval3 != val3) {
+	  state.position = val3 - MinPosition; state.position2 = nval3 - MinPosition;
+	  state.it = vec->begin() + i + 2; EvaluateCost(state);
+      }
+      state.cntLeft++; state.thickness++;
+    }
+    // The evaluation IV
+    cntDebug++;
+    float pval4 = (*vec)[i+2].pos;
+    SItem* curr4 = &((*vec)[i+3]); val4 = (*vec)[i+3].pos;
+    SItem* next4 = &((*vec)[i+4]); float nval4 = (*vec)[i+4].pos;
+    if (curr4->IsRightBoundary()) {
+      state.cntRight--; state.thickness--;
+      if ( (val4 != nval4) ||
+	   ((curr4->IsRightBoundary()) && (next4->IsLeftBoundary())) ) {
+	state.position = val4 - MinPosition; state.position2 = nval4 - MinPosition;
+	state.it = vec->begin() + i + 3; EvaluateCost(state);
+      }
+    }
+    else {
+      if (pval4 != val4) {
+	  state.position = val4 - MinPosition; state.position2 = nval4 - MinPosition;
+	  state.it = vec->begin() + i + 3; EvaluateCost(state);
+      }
+      state.cntLeft++; state.thickness++;
+    }
+  } // for, unrolled loop by factor 4
+  } // if more than 4 evaluations
+  
+  for(i = imax4; i < imax; i ++)
+  {
+    cntDebug++;
+    float pvalI = val4;
+    SItem* currI = &((*vec)[i+0]); float valI = (*vec)[i+0].pos;
+    SItem* nextI = &((*vec)[i+1]); float nvalI = (*vec)[i+1].pos;
+    if (currI->IsRightBoundary()) {
+      state.cntRight--; state.thickness--;
+      if ( (valI != nvalI) ||
+	   ((currI->IsRightBoundary()) && (nextI->IsLeftBoundary())) ) {
+	state.position = valI - MinPosition; state.position2 = nvalI - MinPosition;
+	state.it = vec->begin() + i; EvaluateCost(state);
+      }
+    }
+    else {
+      if (pvalI != valI) {
+	  state.position = valI - MinPosition; state.position2 = nvalI - MinPosition;
+	  state.it = vec->begin() + i; EvaluateCost(state);
+      }
+      state.cntLeft++; state.thickness++;
+    }
+    val4 = valI;
+  } // for i
+  
+  //cout << "i = " << i << endl;
+  assert(cntDebug == imax);
+  
+  assert(state.cntLeft == state.cntAll);
+  state.cntRight--;
+  assert(state.cntRight == 0);
+  state.thickness--;
+  assert(state.thickness == 0);  
+  
+  // Evaluate last possible position 
+  state.position = (*vec)[imax-1].pos - MinPosition;
+  if (state.position < MaxPosition) {
+    state.position2 = state.width;
+    state.it = vec->end() - 1;
+    // Here evaluate the cost of surface area heuristics
+    EvaluateCost(state);
+  }
+   
+  // In this case the best result is kept in 'state' variable
+  return;
+} // CTestAx::GetSplitPlaneX,Y,Z
+#endif
+
+}
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbconf.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbconf.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbconf.h	(revision 2582)
@@ -0,0 +1,95 @@
+// ===================================================================
+// $Id: $
+//
+// ktb.h
+//      definition of classes for CKTB tree building up and traversal
+//
+// Class: CKTBNodeAbstract, SKTBNode, CKTBAllocMan, CKTBNodeIterator
+//
+// REPLACEMENT_STRING
+//
+// Copyright by Vlastimil Havran, 2006 - email to vhavran AT seznam.cz
+// Initial coding by Vlastimil Havran, 2006
+
+#ifndef __KTBCONF_H__
+#define __KTBCONF_H__
+
+// GOLEM headers
+#include "configh.h"
+#include "subdivm.h"
+#ifdef __SSE__
+// SSE supported
+#include <xmmintrin.h>
+#endif
+
+namespace GtpVisibilityPreprocessor {
+
+#ifdef __SSE__
+// The second parameter is
+//  
+#define GPREFETCH(A, B) _mm_prefetch((const char*)A, B)
+#else
+#define GPREFETCH(A, B)  
+#endif
+  
+#if defined(__INTEL_COMPILER)||defined(_MSC_VER)
+// Intel compiler or Microsoft Compiler
+#define GALIGN16 __declspec(align(16))
+#endif
+#ifndef __INTEL_COMPILER
+#ifdef __GNUC__
+// GNU compiler - somehow correct, but it crashes during
+// compilation for GCC 4.1.2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//#define GALIGN16 __attribute((aligned(16)))
+#undef  GALIGN16
+#define GALIGN16 
+#endif
+#endif
+  
+
+// forward declarations
+class CObjectList;
+
+// The statistics for construction
+#define _KTB_CONSTR_STATS
+
+// If to use 8 Bytes representation of the node
+#define _KTB8Bytes
+
+// If to use allocated boxes in minbox nodes or allocate
+// them as a whole nodes, the difference is access time
+// when the boxes are not needed
+#define _SHORT_FORM_MINBOX
+
+// -----------------------------------------------
+// The containter at the leaves or interior node (tagged object lists)
+// We use vector<CObject3D*> representation of object list
+typedef CObjectList* CKTBObjectContainer;
+
+// ==============================================
+// definition of axes of spatial subdivision
+
+class CKTBAxes
+{
+public:
+  enum Axes {
+    // The axes of a splitting plane
+    EE_X_axis = 0,
+    EE_Y_axis = 1,
+    EE_Z_axis = 2,
+    // The leaf node, full or empty
+    EE_Leaf = 3,
+    // The link node for DFS order representation
+    EE_Link = 4,
+    EE_X_axisBox = 5,
+    EE_Y_axisBox = 6,
+    EE_Z_axisBox = 7,
+  };
+  enum {
+    EE_Mask = 0x7
+  };
+};
+
+}
+
+#endif //  __KTBCONF_H__
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HavranRayCaster.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HavranRayCaster.h	(revision 2582)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HavranRayCaster.h	(revision 2582)
@@ -0,0 +1,92 @@
+#ifndef _HavranRayCaster_H__
+#define _HavranRayCaster_H__
+
+#include "RayCaster.h"
+#include "Containers.h"
+#include <string>
+#include "havran/raypack.h"
+
+
+namespace GtpVisibilityPreprocessor {
+
+
+class Intersectable;
+class VssRay;
+class KdTree;
+class Ray;
+class RayPacket2x2;
+class SimpleRayContainer;
+class AxisAlignedBox3;
+class Vector3;
+struct VssRayContainer;
+class Preprocessor;
+struct SimpleRay;
+class CKTB;
+  
+
+/** This class provides an interface for ray casting.
+*/
+class HavranRayCaster: public RayCaster
+{
+public:
+  /** Default constructor initialising e.g., KD tree
+   */
+  HavranRayCaster(const Preprocessor &preprocessor);
+  virtual ~HavranRayCaster();
+
+  void Build(ObjectContainer &objlist);
+  
+  int Type() const { return HAVRAN_RAYCASTER; }
+
+  // Using packet of 4 rays supposing that these are coherent
+  // We give a box to which each ray is clipped to before the
+  // ray shooting is computed !
+  virtual void CastRaysPacket4(Vector3 &minBox,
+			       Vector3 &maxBox,
+			       Vector3 origin4[],
+			       Vector3 direction4[],
+			       int     result4[],
+			       float   dist4[]);
+  
+  virtual int CastRay(
+		      const SimpleRay &simpleRay,
+		      VssRayContainer &vssRays,
+		      const AxisAlignedBox3 &box,
+		      const bool castDoubleRay,
+		      const bool pruneInvalidRays = true
+		      );
+  
+  virtual void CastRays16(SimpleRayContainer &rays, 
+			  VssRayContainer &vssRays,
+			  const AxisAlignedBox3 &sbox,
+			  const bool castDoubleRay,
+			  const bool pruneInvalidRays = true
+			  );
+
+  virtual void CastRays16(SimpleRayContainer &rays,
+			  int offset,
+			  VssRayContainer &vssRays,
+			  const AxisAlignedBox3 &sbox,
+			  const bool castDoubleRay,
+			  const bool pruneInvalidRays = true
+			  );  
+  void
+  CastSimpleForwardRays(SimpleRayContainer &rays,
+			const AxisAlignedBox3 &sbox
+			);
+
+  virtual void CastRays(
+			SimpleRayContainer &rays,
+			VssRayContainer &vssRays,
+			const AxisAlignedBox3 &sbox,
+			const bool castDoubleRay,
+			const bool pruneInvalidRays = true);
+protected:
+  CKTB *mKtbtree;
+  static RayPacket2x2 raypack;
+};
+
+
+} // namespace
+
+#endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro	(revision 2582)
@@ -1,6 +1,9 @@
 CONFIG += release
+#CONFIG += debug
 CONFIG += console warn_off thread mlrt qt
 
 TEMPLATE = app
+
+#CONFIG -= qt
 
 TARGET = preprocessor
@@ -82,5 +85,5 @@
 CONFIG(qt) {
 win32:LIBS += cg.lib cgGL.lib
-DEFINES += USE_QT
+#DEFINES += USE_QT
 }
 
@@ -117,16 +120,24 @@
 Timer/BenchTimer.cpp Timer/merror.cpp \
 Intersectable.cpp TraversalTree.cpp ObjectPvs.cpp ObjectsParser.cpp \
-FilterBasedDistribution.cpp DifferenceSampling.cpp HavranRayCaster.cpp
+FilterBasedDistribution.cpp DifferenceSampling.cpp HavranRayCaster.cpp \
+OcclusionQuery.cpp 
 
 
 SOURCES += BoostPreprocessorThread.cpp 
 
+INCLUDEPATH+=havran
+SOURCES += havran/allocgo2.cpp havran/ktbai.cpp havran/ktbtrav.cpp \
+havran/ktb.cpp havran/ktball.cpp havran/sbbox.cpp \
+havran/ktb8b.cpp havran/ktbftrav.cpp havran/timer.cpp
+
+
 CONFIG(qt) {
 HEADERS += QtInterface/QtPreprocessorThread.h QtInterface/QtGlRenderer.h \
 QtInterface/QtGlViewer.h
-SOURCES += OcclusionQuery.cpp QtInterface/QtPreprocessorThread.cpp \
+SOURCES +=  QtInterface/QtPreprocessorThread.cpp \
 QtInterface/QtGlRenderer.cpp QtInterface/QtGlViewer.cpp 
+SOURCES +=  QtInterface/LogReader.cpp QtInterface/LogWriter.cpp
 } else {
-SOURCES += BoostPreprocessorThread.cpp 
+#SOURCES += BoostPreprocessorThread.cpp 
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.cpp	(revision 2575)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/AxisAlignedBox3.cpp	(revision 2582)
@@ -1552,7 +1552,7 @@
   // from the sphere center
 
-  const float *minp = &(mMin[0]);
-  const float *maxp = &(mMax[0]);
-  const float *pcenter = &(point[0]);
+  const float *minp = &(mMin.x);
+  const float *maxp = &(mMax.x);
+  const float *pcenter = &(point.x);
   
   // for x-axis
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp	(revision 2580)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp	(revision 2582)
@@ -227,5 +227,5 @@
 																  r[2]));
 
-	direction = mPreprocessor.mKdTree->GetBox().GetRandomPoint(Vector3(r[3],
+	direction = mPreprocessor.sceneBox.GetRandomPoint(Vector3(r[3],
 																	   r[4],
 																	   r[5])
