Index: GTP/trunk/App/Demos/Vis/CHC_revisited/Material.h
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/Material.h	(revision 2747)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/Material.h	(revision 2747)
@@ -0,0 +1,84 @@
+#ifndef __MATERIAL_H
+#define __MATERIAL_H
+
+//namespace CHCDemo 
+//{
+
+
+class RgbColor 
+{
+public:
+  float r, g, b;
+
+  RgbColor():r(0.5f),g(0.5f),b(0.5f)
+  {
+  }
+
+  RgbColor(const float _r,
+	   const float _g,
+	   const float _b):r(_r),g(_g),b(_b)
+  {
+  }
+
+  friend RgbColor
+  RandomColor(const float a=0.0f, const float b=1.0f);
+
+  // Mapping from interval 0.0-1.0 to RGB using "rainbow" color map
+  // (range of hue from 0-240)
+
+  friend RgbColor RainbowColorMapping(const float value);
+  
+};
+
+
+// Forward declarations
+RgbColor RandomColor(const float a, const float b);
+
+// Mapping from interval 0.0-1.0 to RGB using "rainbow" color map
+// (range of hue from 0-240)
+RgbColor RainbowColorMapping(const float value);
+
+  
+
+class Material 
+{
+public:
+  RgbColor mDiffuseColor;
+  RgbColor mSpecularColor;
+  RgbColor mAmbientColor;
+  
+  Material(): mId(0)
+  {
+  }
+  
+  Material(const int id): mId(id)
+  {
+  }
+
+  Material(const RgbColor &color):mDiffuseColor(color),
+								  mAmbientColor(color),
+								  mSpecularColor(0,0,0), mId(0)
+  {
+  }
+  
+  friend Material RandomMaterial();
+  
+  /** Returns unique material id.
+  */
+  int GetId() const
+  {
+	  return mId;
+  }
+
+protected:
+
+	// unique material id
+	int mId;
+};
+
+
+extern Material RandomMaterial();
+
+//}
+
+#endif
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.h
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.h	(revision 2747)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.h	(revision 2747)
@@ -0,0 +1,30 @@
+#ifndef _BinaryLoader_H__
+#define _BinaryLoader_H__
+
+// note use forward declaration instead
+#include <string>
+
+
+class igzstream;
+class Shape3D;
+class BranchGroup;
+class Appearance;
+class Geometry;
+
+
+class BinaryLoader
+{
+public:
+
+	BranchGroup *Load(const std::string &filename);
+
+protected:
+
+	Shape3D *LoadShape(igzstream &str);
+
+	Appearance *LoadAppearance(igzstream &str);
+
+	Geometry *LoadGeometry(igzstream &str);
+};
+
+#endif
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/AxisAlignedBox3.h
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/AxisAlignedBox3.h	(revision 2747)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/AxisAlignedBox3.h	(revision 2747)
@@ -0,0 +1,390 @@
+#ifndef _AxisAlignedBox3_H__
+#define _AxisAlignedBox3_H__
+
+
+
+#include "Matrix4x4.h"
+#include "Vector3.h"
+//#include "Plane3.h"
+#include "Containers.h"
+
+
+//namespace CHCDemo
+//{
+
+struct Triangle3;
+
+/** Axis alignedd box class.
+This is a box in 3-space, defined by min and max
+corner vectors.  Many useful operations are defined
+on this
+*/
+class AxisAlignedBox3
+{
+
+public:
+
+	// Constructors.
+	AxisAlignedBox3() { }
+
+	AxisAlignedBox3(const Vector3 &nMin, const Vector3 &nMax)
+	{
+		mMin = nMin; mMax = nMax;
+	}
+
+	/** initialization to the non existing bounding box
+	*/
+	void Initialize();
+	/** The center of the box
+	*/
+	Vector3 Center() const;
+	/** The diagonal of the box
+	*/
+	Vector3 Diagonal() const;
+
+	float Center(const int axis) const;
+
+	float Min(const int axis) const;
+
+	float Max(const int axis) const;
+
+	float Size(const int axis) const;
+
+	// Read-only const access tomMin and max vectors using references
+	const Vector3& Min() const;
+	const Vector3& Max() const;
+
+	void Enlarge (const Vector3 &v);
+
+	void EnlargeToMinSize();
+
+	void SetMin(const Vector3 &v);
+
+	void SetMax(const Vector3 &v);
+
+	void SetMin(int axis, const float value);
+
+	void SetMax(int axis, const float value);
+
+	// Decrease box by given splitting plane
+	void Reduce(int axis, int right, float value); 
+
+	bool Intersects(const Vector3 &lStart, const Vector3 &lEnd) const;
+
+	// the size of the box along all the axes
+	Vector3 Size() const;
+	float Radius() const { return 0.5f*Magnitude(Size()); }
+	float SqrRadius() const { return 0.5f*SqrMagnitude(Size()); }
+
+	// Return whether the box is unbounded.  Unbounded boxes appear
+	// when unbounded objects such as quadric surfaces are included.
+	bool Unbounded() const;
+
+	// Expand the axis-aligned box to include the given object.
+	void Include(const Vector3 &newpt);
+	void Include(const AxisAlignedBox3 &bbox);
+	/** Expand the axis-aligned box to include given values in particular axis.
+	*/
+	void Include(const int &axis, const float &newBound);
+	// int Side(const Plane3 &plane) const;
+
+	// Overlap returns 1 if the two axis-aligned boxes overlap .. even weakly
+	friend inline bool Overlap(const AxisAlignedBox3 &, const AxisAlignedBox3 &);
+
+	// Overlap returns 1 if the two axis-aligned boxes overlap .. only strongly
+	friend inline bool OverlapS(const AxisAlignedBox3 &,const AxisAlignedBox3 &);
+
+	/** Overlap returns 1 if the two axis-aligned boxes overlap for a given
+	epsilon. If eps > 0.0, then the boxes has to have the real intersection
+	box, if eps < 0.0, then the boxes need not intersect really, they
+	can be at eps distance in the projection.
+	*/
+	friend inline bool Overlap(const AxisAlignedBox3 &,
+		const AxisAlignedBox3 &,
+		float eps);
+
+	/** Includes returns true if a includes b (completely)
+	*/
+	bool Includes(const AxisAlignedBox3 &b) const;
+
+	/** Returns true if this point is inside box.
+	*/
+	virtual int IsInside(const Vector3 &v) const;
+	/** Test if the box makes sense.
+	*/
+	virtual bool IsCorrect();
+	/** To answer true requires the box of real volume of non-zero value.
+	*/
+	bool IsSingularOrIncorrect() const;
+	/** When the box is not of non-zero or negative surface area.
+	*/
+	bool IsCorrectAndNotPoint() const;
+	/** Returns true when the box degenerates to a point.
+	*/
+	bool IsPoint() const;
+	/** Scales the box with the factor.
+	*/
+	void Scale(const float scale);
+
+	void Scale(const Vector3 &scale);
+	/** Translates the box with the factor.
+	*/
+	void Translate(const Vector3 &shift);
+
+	/** Returns the square of the minimal and maximal distance to 
+	a point on the box.
+	*/
+	void
+		GetSqrDistances(const Vector3 &point,
+		float &minDistance,
+		float &maxDistance
+		) const;
+
+
+
+	Vector3 GetRandomPoint(const Vector3 &r) const;
+	Vector3 GetRandomPoint() const;
+
+	Vector3 GetPoint(const Vector3 &p) const 
+	{
+		return mMin + p*Size(); 
+	}
+
+
+protected:
+	Vector3 mMin, mMax;
+
+public:
+
+	// Returns the smallest axis-aligned box that includes all points
+	// inside the two given boxes.
+	friend inline AxisAlignedBox3 Union(const AxisAlignedBox3 &x,
+		const AxisAlignedBox3 &y);
+
+	// Returns the intersection of two axis-aligned boxes.
+	friend inline AxisAlignedBox3 Intersect(const AxisAlignedBox3 &x,
+		const AxisAlignedBox3 &y);
+
+	// Given 4x4 matrix, transform the current box to new one.
+	friend inline AxisAlignedBox3 Transform(const AxisAlignedBox3 &box,
+		const Matrix4x4 &tform);
+
+
+	// returns true when two boxes are completely equal
+	friend inline int operator== (const AxisAlignedBox3 &A, 
+		const AxisAlignedBox3 &B);
+
+	virtual float SurfaceArea() const;
+	virtual float GetVolume() const 
+	{
+		return (mMax.x - mMin.x) * (mMax.y - mMin.y) * (mMax.z - mMin.z);
+	}
+
+	// Six faces are distuinguished by their name.
+	enum EFaces {ID_Back = 0, 
+		ID_Left = 1, 
+		ID_Bottom = 2, 
+		ID_Front = 3,
+		ID_Right = 4, 
+		ID_Top = 5};
+
+	// Writes a brief description of the object, indenting by the given
+	// number of spaces first.
+	virtual void Describe(std::ostream& app, int ind) const;
+
+	// For edge .. number <0..11> returns two incident vertices
+	void GetEdge(const int edge, Vector3 *a, Vector3 *b) const;
+
+	// Compute the coordinates of one vertex of the box for 0/1 in each axis
+	// 0 .. smaller coordinates, 1 .. large coordinates
+	Vector3 GetVertex(int xAxis, int yAxis, int zAxis) const;
+
+	// Compute the vertex for number N=<0..7>, N = 4*x + 2*y + z, where
+	// x,y,z are either 0 or 1; (0 .. lower coordinate, 1 .. large coordinate)
+	// (xmin,ymin, zmin) .. N = 0, (xmax, ymax, zmax) .. N= 7
+	void GetVertex(const int N, Vector3 &vertex) const;
+
+	Vector3 GetVertex(const int N) const {
+		Vector3 v;
+		GetVertex(N, v);
+		return v;
+	}
+
+	// Returns 1, if the box includes on arbitrary face a given box
+	int IsPiercedByBox(const AxisAlignedBox3 &box, int &axis) const;
+
+
+	int GetFaceVisibilityMask(const Vector3 &position) const;
+	/** Extracts plane of bounding box.
+	*/
+	//Plane3 GetPlane(const int face) const;
+
+
+	/** Returns vertex indices of edge.
+	*/
+	void GetEdge(const int edge, int  &aIdx, int &bIdx) const;
+
+
+	// get the extent of face
+	float GetExtent(const int &face) const 
+	{
+		if (face < 3)
+			return mMin[face];
+		else
+			return mMax[face - 3];
+	}
+
+	// The vertices that form boundaries of the projected bounding box
+	// for all the regions possible, number of regions is 3^3 = 27,
+	// since two parallel sides of bbox forms three disjoint spaces
+	// the vertices are given in anti-clockwise order .. stopped by -1 elem.
+	static const int bvertices[27][9];
+
+	// The list of all faces visible from a given region (except region 13)
+	// the faces are identified by triple: (axis, min-vertex, max-vertex),
+	// that is maximaly three triples are defined. axis = 0 (x-axis),
+	// axis = 1 (y-axis), axis = 2 (z-axis), -1 .. terminator. Is is always
+	// true that: min-vertex < max-vertex for all coordinates excluding axis
+	static const int bfaces[27][10];
+
+	// The correct corners indexed starting from entry face to exit face
+	// first index determines entry face, second index exit face, and
+	// the two numbers (indx, inc) determines: ind = the index on the exit
+	// face, when starting from the vertex 0 on entry face, 'inc' is
+	// the increment when we go on entry face in order 0,1,2,3 to create
+	// convex shaft with the rectangle on exit face. That is, inc = -1 or 1.
+	static const int pairFaceRects[6][6][2];
+
+	// The vertices that form CLOSEST points with respect to the region
+	// for all the regions possible, number of regions is 3^3 = 27,
+	// since two parallel sides of bbox forms three disjoint spaces.
+	// The vertices are given in anti-clockwise order, stopped by -1 elem,
+	// at most 8 points, at least 1 point.
+	static const int cvertices[27][9];
+	static const int csvertices[27][6];
+
+	// The vertices that form FARTHEST points with respect to the region
+	// for all the regions possible, number of regions is 3^3 = 27,
+	// since two parallel sides of bbox forms three disjoint spaces.
+	// The vertices are given in anti-clockwise order, stopped by -1 elem,
+	// at most 8 points, at least 1 point.
+	static const int fvertices[27][9];  
+	static const int fsvertices[27][9];
+
+	// input and output operator with stream
+	friend std::ostream& operator<<(std::ostream &s, const AxisAlignedBox3 &A);
+	friend std::istream& operator>>(std::istream &s, AxisAlignedBox3 &A);
+};
+
+
+// --------------------------------------------------------------------------
+// Implementation of inline (member) functions
+
+inline bool
+Overlap(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
+{
+	if (x.mMax.x < y.mMin.x ||
+		x.mMin.x > y.mMax.x ||
+		x.mMax.y < y.mMin.y ||
+		x.mMin.y > y.mMax.y ||
+		x.mMax.z < y.mMin.z ||
+		x.mMin.z > y.mMax.z) {
+			return false;
+	}
+	return true;
+}
+
+inline bool
+OverlapS(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
+{
+	if (x.mMax.x <= y.mMin.x ||
+		x.mMin.x >= y.mMax.x ||
+		x.mMax.y <= y.mMin.y ||
+		x.mMin.y >= y.mMax.y ||
+		x.mMax.z <= y.mMin.z ||
+		x.mMin.z >= y.mMax.z) {
+			return false;
+	}
+	return true;
+}
+
+inline bool
+Overlap(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y, float eps)
+{
+	if ( (x.mMax.x - eps) < y.mMin.x ||
+		(x.mMin.x + eps) > y.mMax.x ||
+		(x.mMax.y - eps) < y.mMin.y ||
+		(x.mMin.y + eps) > y.mMax.y ||
+		(x.mMax.z - eps) < y.mMin.z ||
+		(x.mMin.z + eps) > y.mMax.z ) {
+			return false;
+	}
+	return true;
+}
+
+inline AxisAlignedBox3
+Intersect(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
+{
+	if (x.Unbounded())
+		return y;
+	else
+		if (y.Unbounded())
+			return x;
+	AxisAlignedBox3 ret = x;
+	if (Overlap(ret, y)) {
+		Maximize(ret.mMin, y.mMin);
+		Minimize(ret.mMax, y.mMax);
+		return ret;
+	}
+	else      // Null intersection.
+		return AxisAlignedBox3(Vector3(0), Vector3(0));
+	// return AxisAlignedBox3(Vector3(0), Vector3(-1));
+}
+
+inline AxisAlignedBox3
+Union(const AxisAlignedBox3 &x, const AxisAlignedBox3 &y)
+{
+	Vector3 min = x.mMin;
+	Vector3 max = x.mMax;
+	Minimize(min, y.mMin);
+	Maximize(max, y.mMax);
+	return AxisAlignedBox3(min, max);
+}
+
+inline AxisAlignedBox3
+Transform(const AxisAlignedBox3 &box, const Matrix4x4 &tform)
+{
+	Vector3 mmin(MAXFLOAT);
+	Vector3 mmax(-MAXFLOAT);
+
+	AxisAlignedBox3 ret(mmin, mmax);
+	ret.Include(tform * Vector3(box.mMin.x, box.mMin.y, box.mMin.z));
+	ret.Include(tform * Vector3(box.mMin.x, box.mMin.y, box.mMax.z));
+	ret.Include(tform * Vector3(box.mMin.x, box.mMax.y, box.mMin.z));
+	ret.Include(tform * Vector3(box.mMin.x, box.mMax.y, box.mMax.z));
+	ret.Include(tform * Vector3(box.mMax.x, box.mMin.y, box.mMin.z));
+	ret.Include(tform * Vector3(box.mMax.x, box.mMin.y, box.mMax.z));
+	ret.Include(tform * Vector3(box.mMax.x, box.mMax.y, box.mMin.z));
+	ret.Include(tform * Vector3(box.mMax.x, box.mMax.y, box.mMax.z));
+	return ret;
+}
+
+inline float RatioOfOverlap(const AxisAlignedBox3 &box1, const AxisAlignedBox3 &box2)
+{
+	// return ratio of intersection to union
+	const AxisAlignedBox3 bisect = Intersect(box1, box2);
+	const AxisAlignedBox3 bunion = Union(box1, box2);
+
+	return bisect.GetVolume() / bunion.GetVolume();
+}
+
+inline int operator==(const AxisAlignedBox3 &A, const AxisAlignedBox3 &B)
+{
+	return (A.mMin == B.mMin) && (A.mMax == B.mMax);
+}
+
+
+//}
+
+
+#endif
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/Material.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/Material.cpp	(revision 2747)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/Material.cpp	(revision 2747)
@@ -0,0 +1,26 @@
+#include "common.h"
+#include "Material.h"
+
+//namespace CHCDemo
+//{
+
+RgbColor RandomColor(const float a, const float b)
+{
+	return RgbColor(a + Random(b), a + Random(b), a + Random(b));
+}
+
+
+Material RandomMaterial()
+{
+	float a = 0.1f;
+	float b = 0.9f;
+
+	Material m;
+	m.mDiffuseColor = RandomColor(a, b);
+
+	return m;
+}
+
+
+
+//}
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.cpp	(revision 2747)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.cpp	(revision 2747)
@@ -0,0 +1,357 @@
+#include "BinaryLoader.h"
+#include "yare.h"
+#include "yamath.h"
+#include "gzstream.h"
+#include "ImageComponent.h"
+#include "RenderState.h"
+#include "GeometryProcessor.h"
+
+
+using namespace std;
+
+static STL_MAP<String,Texture *> stlm_textures;
+
+
+// clear the texture table (called on new file load)
+static void clear_textures()
+{
+	STL_MAP<String,Texture *>::iterator it, it_end = stlm_textures.end();
+
+	for (it = stlm_textures.begin(); it != it_end; ++ it)
+	{
+		it->second->unref();
+		delete [] it->first;
+
+		it ++;
+	}
+
+	stlm_textures.clear();
+}
+
+
+static Texture *get_texture(const char *filename, TextureAttributes *&myTextureAttributes)
+{
+	Texture * myTexture = NULL;
+
+	myTextureAttributes = new TextureAttributes;
+	myTextureAttributes->setTextureMode(TextureAttributes::DECAL);
+
+	// Michi: avoid multiple loading of same texture!
+	if (stlm_textures.find(filename) != stlm_textures.end())
+	{
+		myTexture = stlm_textures[filename];
+	}
+	else
+	{
+		ImageComponent *image = new ImageComponent(filename);
+		//Texture *myTexture = new Texture(Texture::BASE_LEVEL, Texture::RGB, image->getWidth(), image->getHeight());
+		myTexture = new Texture(Texture::MULTI_LEVEL_MIPMAP, ImageComponent::FORMAT_RGBP, image->getWidth(), image->getHeight());
+		myTexture->setImage(0, image);
+		
+		myTexture->setMagFilter(Texture::BASE_LEVEL_LINEAR);
+		myTexture->setMinFilter(Texture::MULTI_LEVEL_LINEAR_POINT);
+
+		myTexture->setBoundaryModeS(Texture::WRAP);
+		myTexture->setBoundaryModeT(Texture::WRAP);
+		
+		stlm_textures[filename] = myTexture;
+		/// HACK!!! (texture not deleted on reload!)
+		myTexture->ref();
+	}
+
+	return myTexture;
+}
+
+
+Shape3D *BinaryLoader::LoadShape(igzstream &str)
+{	
+	Geometry *geom = LoadGeometry(str);
+	Appearance *app = LoadAppearance(str);
+
+	Shape3D *shape = new Shape3D(geom, app);
+
+	return shape;
+}
+
+
+Appearance *BinaryLoader::LoadAppearance(igzstream &str)
+{
+	Appearance *app = new Appearance();
+	
+	// texture
+	int texnameSize;
+
+	str.read(reinterpret_cast<char *>(&texnameSize), sizeof(int));
+
+	if (texnameSize)
+	{
+		TextureAttributes *texAttr;
+		char *texname = new char[texnameSize];
+		str.read(texname, sizeof(char) * texnameSize);
+
+		Texture *tex = get_texture(texname, texAttr);
+		app->setTexture(tex);
+		app->setTextureAttributes(texAttr);
+	}
+
+	// material
+	char hasMaterial;
+	str.read(&hasMaterial, sizeof(char));
+	
+	if (hasMaterial)
+	{
+		Color3f amb(0.0f, 0.0f, 0.0f);
+		Color3f dif(0.5f, 0.5f, 0.5f);
+		Color3f spec(0.0f, 0.0f, 0.0f);
+		Color3f emi(0.0f, 0.0f, 0.0f);
+
+		float shine = 0;
+
+		//str.read(reinterpret_cast<char *>(&amb), sizeof(Color3f));
+		str.read(reinterpret_cast<char *>(&dif), sizeof(Color3f));
+		//str.read(reinterpret_cast<char *>(&emi), sizeof(Color3f));
+		//str.read(reinterpret_cast<char *>(&spec), sizeof(Color3f));
+		//str.read(reinterpret_cast<char *>(&shine), sizeof(float));
+#if 1
+		Material *mat = new Material();
+
+		mat->setAmbientColor(amb);
+		mat->setDiffuseColor(dif);
+		mat->setEmissiveColor(emi);
+		mat->setSpecularColor(spec);
+		mat->setShininess(shine);
+
+		app->setMaterial(mat);
+#endif
+	}
+
+	return app;
+}
+
+
+Geometry *BinaryLoader::LoadGeometry(igzstream &str)
+{
+	int vertexCount;
+	int stripCount;
+
+	Point3f *vertices;
+	Vector3f *normals = NULL;
+	Point2f *texCoords = NULL;
+
+	int *stripIndexCounts;
+	int *indices;
+	int *normalIndices;
+
+	// todo
+	int colorCount = 0;
+	int normalCount = 0;
+	int texCount = 0;
+
+	int format;
+
+	// read in format
+	str.read(reinterpret_cast<char *>(&format), sizeof(int));
+	
+	format = IndexedTriangleStripArray::COORDINATES 
+		| IndexedTriangleStripArray::NORMALS
+		;
+
+	//OUT1("new format: " << format);
+
+	// end of file reached
+	if (str.eof())
+		return NULL;
+
+
+	//////////////
+	// read in vertices
+	
+	str.read(reinterpret_cast<char *>(&vertexCount), sizeof(int));
+	
+	vertices = new Point3f[vertexCount];
+    str.read(reinterpret_cast<char *>(vertices), sizeof(Point3f) * vertexCount);
+
+
+	/////////////////
+	// read in strip counters
+	
+	str.read(reinterpret_cast<char *>(&stripCount), sizeof(int));
+
+	stripIndexCounts = new int[stripCount];
+    str.read(reinterpret_cast<char *>(stripIndexCounts), sizeof(int) * stripCount);
+
+
+	//////////
+	// read in indices
+
+	int indexCount;
+	str.read(reinterpret_cast<char *>(&indexCount), sizeof(int));
+	indices = new int[indexCount];
+    str.read(reinterpret_cast<char *>(indices), sizeof(int) * indexCount);
+
+
+	///////////////
+	// read in normals
+	
+	str.read(reinterpret_cast<char *>(&normalCount), sizeof(int));
+
+	if (normalCount)
+	{
+		normals = new Vector3f[normalCount];
+		str.read(reinterpret_cast<char *>(normals), sizeof(Vector3f) * normalCount);
+		normalIndices = new int[indexCount];
+		str.read(reinterpret_cast<char *>(normalIndices), sizeof(int) * indexCount);
+	}
+
+
+	//////////////
+	// read in texCoords
+	
+	str.read(reinterpret_cast<char *>(&texCount), sizeof(int));
+	if (texCount)
+	{
+		texCoords = new Point2f[texCount];
+		str.read(reinterpret_cast<char *>(texCoords), sizeof(Point2f) * texCount);
+	}
+	
+	IndexedTriangleStripArray *geom = 
+		new IndexedTriangleStripArray(vertexCount, 
+									  normalCount, 
+									  texCount, 
+									  colorCount, 
+									  format, 
+									  indexCount, 
+									  stripIndexCounts, 
+									  stripCount);
+
+	geom->setCoordinates(0, vertices, vertexCount);
+	geom->setCoordinateIndices(0, indices, indexCount);
+
+
+	if (texCount)
+	{
+		geom->setTextureCoordinateIndices(0, indices, indexCount);
+		geom->setTextureCoordinates(0, texCoords, texCount);
+	}
+
+	if (normalCount)
+	{
+		geom->setNormals(0, normals, normalCount);
+		geom->setNormalIndices(0, normalIndices, indexCount);
+	}
+	
+
+	///////
+	//-- cleanup
+
+	DELAPTR(stripIndexCounts);
+	DELAPTR(vertices);
+	DELAPTR(normals); 
+	DELAPTR(texCoords);
+	DELAPTR(indices);
+	DELAPTR(normalIndices);
+
+	
+	return geom; 
+}
+
+
+BranchGroup *BinaryLoader::Load(const string &filename)
+{
+	clear_textures(); // clear the texture table
+
+	BranchGroup *root = new BranchGroup();
+	//root->setName("start");
+	igzstream str(filename.c_str());//, ios::binary);
+	
+	if (!str.is_open())
+		return false;
+
+	// #shapes
+	int shapeCount;
+	str.read(reinterpret_cast<char *>(&shapeCount), sizeof(int));
+
+	int progress = 0;
+
+	GeometryProcessor geomConv(500000, NULL);
+
+	for (int i = 0; i < shapeCount; ++ i)
+	{
+		Shape3D *shape = LoadShape(str);
+
+		vector<Shape3D *> newShapes;
+		ShapePair shapePair = ShapePair(shape, -1);
+
+		// check, if this node actually contains any geometry
+		CalcNumTrianglesVisitor	triangleVisitor;
+		triangleVisitor.Apply(shape);
+		const int numTriangles = triangleVisitor.GetNumTriangles();
+
+		// the shape should be subdivided => replace old shape
+		if (geomConv.SubdivideShape(newShapes, shapePair, numTriangles))
+		{
+			OUT1("triangleCount: " << numTriangles  << " => subdividing to " << newShapes.size() << " shapes");			
+			delete shape;//shape->unref();
+		}
+		else
+		{
+			newShapes.push_back(shape);
+		}
+
+		VisibilityGroup * visGrp = new VisibilityGroup();
+		root->addChild(visGrp);
+
+		for (size_t j = 0; j < newShapes.size(); ++ j)
+		{
+			Shape3D *sh = newShapes[j];
+			visGrp->addChild(sh);
+		}
+
+		int p = i * 100 / shapeCount;
+		
+		if (p >= progress)
+		{
+			OUT1("% loaded: " << p);
+			progress += 10;
+		}
+	}
+
+	OUT1("bin loading finished");
+
+	return root;
+}
+
+
+#if 0
+
+collectvertices
+{
+	int newIndex = 0;
+
+	for (int i = 0; i < numTriangles; ++ i)
+	{
+		Triangle tri = mTriangles[i];
+
+		for (int j = 0; j < 3; ++ j)
+		{
+			const int index = tri.mVertexIndices[j];
+			if (!mHashtable[index])
+			{
+				mHashTable[index] = newIndex;
+				mNewVertices.push_back(mVertices[index];
+			}
+	}
+
+	// now loop again, exchange indices;
+	for (int i = 0; i < numTriangles; ++ i
+	{
+		Triangle tri = mTriangles[i];
+
+		for (int j = 0; j < 3; ++ j)
+		{
+			const int index = tri.mVertexIndices[j];
+			tri.mVertexIndices[j] = mHashTable[index];
+	}
+}
+
+#endif
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/AxisAlignedBox3.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/AxisAlignedBox3.cpp	(revision 2747)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/AxisAlignedBox3.cpp	(revision 2747)
@@ -0,0 +1,1007 @@
+#include <cassert>
+#include <iostream>
+#include "AxisAlignedBox3.h"
+
+
+using namespace std;
+
+//namespace CHCDemo
+//{
+
+// AxisAlignedBox3 implementations
+
+// Overload << operator for C++-style output
+ostream& operator<< (ostream &s, const AxisAlignedBox3 &A)
+{
+	return s << '[' << A.mMin.x << ", " << A.mMin.y << ", " << A.mMin.z << "]["
+		<< A.mMax.x << ", " << A.mMax.y << ", " << A.mMax.z << ']';
+}
+
+
+// Overload >> operator for C++-style input
+istream& operator>> (istream &s, AxisAlignedBox3 &A)
+{
+	char a;
+	// read "[min.x, min.y, min.z][mMax.x, mMax.y, mMax.z]"
+	return s >> a >> A.mMin.x >> a >> A.mMin.y >> a >> A.mMin.z >> a >> a
+		>> A.mMax.x >> a >> A.mMax.y >> a >> A.mMax.z >> a;
+}
+
+
+bool AxisAlignedBox3::Unbounded() const
+{
+	return (mMin == Vector3(-MAXFLOAT)) || 
+		(mMax == Vector3(-MAXFLOAT));
+}
+
+
+void AxisAlignedBox3::Include(const Vector3 &newpt)
+{
+	Minimize(mMin, newpt);
+	Maximize(mMax, newpt);
+}
+
+
+void AxisAlignedBox3::Include(const AxisAlignedBox3 &bbox)
+{
+	Minimize(mMin, bbox.mMin);
+	Maximize(mMax, bbox.mMax);
+}
+
+
+bool AxisAlignedBox3::IsCorrect()
+{
+	if ( (mMin.x > mMax.x) ||
+		(mMin.y > mMax.y) ||
+		(mMin.z > mMax.z) )
+		return false; // box is not formed
+	return true;
+}
+
+
+void AxisAlignedBox3::GetEdge(const int edge, Vector3 *a, Vector3 *b) const
+{
+	switch(edge) {
+  case 0:
+	  a->SetValue(mMin.x, mMin.y, mMin.z);
+	  b->SetValue(mMin.x, mMin.y, mMax.z);
+	  break;
+  case 1:
+	  a->SetValue(mMin.x, mMin.y, mMin.z);
+	  b->SetValue(mMin.x, mMax.y, mMin.z);
+	  break;
+  case 2:
+	  a->SetValue(mMin.x, mMin.y, mMin.z);
+	  b->SetValue(mMax.x, mMin.y, mMin.z);
+	  break;
+  case 3:
+	  a->SetValue(mMax.x, mMax.y, mMax.z);
+	  b->SetValue(mMax.x, mMax.y, mMin.z);
+	  break;
+  case 4:
+	  a->SetValue(mMax.x, mMax.y, mMax.z);
+	  b->SetValue(mMax.x, mMin.y, mMax.z);
+	  break;
+  case 5:
+	  a->SetValue(mMax.x, mMax.y, mMax.z);
+	  b->SetValue(mMin.x, mMax.y, mMax.z);
+	  break;
+
+  case 6:
+	  a->SetValue(mMin.x, mMin.y, mMax.z);
+	  b->SetValue(mMin.x, mMax.y, mMax.z);
+	  break;
+  case 7:
+	  a->SetValue(mMin.x, mMin.y, mMax.z);
+	  b->SetValue(mMax.x, mMin.y, mMax.z);
+	  break;
+  case 8:
+	  a->SetValue(mMin.x, mMax.y, mMin.z);
+	  b->SetValue(mMin.x, mMax.y, mMax.z);
+	  break;
+  case 9:
+	  a->SetValue(mMin.x, mMax.y, mMin.z);
+	  b->SetValue(mMax.x, mMax.y, mMin.z);
+	  break;
+  case 10:
+	  a->SetValue(mMax.x, mMin.y, mMin.z);
+	  b->SetValue(mMax.x, mMax.y, mMin.z);
+	  break;
+  case 11:
+	  a->SetValue(mMax.x, mMin.y, mMin.z);
+	  b->SetValue(mMax.x, mMin.y, mMax.z);
+	  break;
+	}
+}
+
+// returns the vertex indices in the range <0..7>, v = 4.x + 2.y + z, where
+// x,y,z are either 0 or 1; (0 .. min coordinate, 1 .. max coordinate)
+void
+AxisAlignedBox3::GetEdge(const int edge, int  &aIdx, int &bIdx) const
+{
+	switch(edge) {
+  case 0: aIdx = 0; bIdx = 1; break;
+  case 1: aIdx = 0; bIdx = 2; break;
+  case 2: aIdx = 0; bIdx = 4; break;
+  case 3: aIdx = 7; bIdx = 6; break;
+  case 4: aIdx = 7; bIdx = 5; break;
+  case 5: aIdx = 7; bIdx = 3; break;
+  case 6: aIdx = 1; bIdx = 3; break;
+  case 7: aIdx = 1; bIdx = 5; break;
+  case 8: aIdx = 2; bIdx = 3; break;
+  case 9: aIdx = 2; bIdx = 6; break;
+  case 10: aIdx = 4; bIdx = 6; break;
+  case 11: aIdx = 4; bIdx = 5; break;
+	}
+}
+
+void
+AxisAlignedBox3::Include(const int &axis, const float &newBound)
+{
+	switch (axis) {
+	case 0: { // x-axis
+		if (mMin.x > newBound)
+			mMin.x = newBound;
+		if (mMax.x < newBound)
+			mMax.x = newBound;
+		break;
+			}
+	case 1: { // y-axis
+		if (mMin.y > newBound)
+			mMin.y = newBound;
+		if (mMax.y < newBound)
+			mMax.y = newBound;
+		break;
+			}
+	case 2: { // z-axis
+		if (mMin.z > newBound)
+			mMin.z = newBound;
+		if (mMax.z < newBound)
+			mMax.z = newBound;
+		break;
+			}
+	}
+}
+
+
+void AxisAlignedBox3::Describe(ostream &app, int ind) const
+{
+	indent(app, ind);
+	app << "AxisAlignedBox3: min at(" << mMin << "), max at(" << mMax << ")\n";
+}
+
+int
+AxisAlignedBox3::IsInside(const Vector3 &v) const
+{
+	return ! ((v.x < mMin.x) ||
+		(v.x > mMax.x) ||
+		(v.y < mMin.y) ||
+		(v.y > mMax.y) ||
+		(v.z < mMin.z) ||
+		(v.z > mMax.z));
+}
+
+
+bool AxisAlignedBox3::Includes(const AxisAlignedBox3 &b) const
+{
+	return (b.mMin.x >= mMin.x &&
+		b.mMin.y >= mMin.y &&
+		b.mMin.z >= mMin.z &&
+		b.mMax.x <= mMax.x &&
+		b.mMax.y <= mMax.y &&
+		b.mMax.z <= mMax.z);
+}
+
+
+// compute the coordinates of one vertex of the box
+Vector3 AxisAlignedBox3::GetVertex(int xAxis, int yAxis, int zAxis) const
+{
+	Vector3 p;
+	if (xAxis)
+		p.x = mMax.x;
+	else
+		p.x = mMin.x;
+
+	if (yAxis)
+		p.y = mMax.y;
+	else
+		p.y = mMin.y;
+
+	if (zAxis)
+		p.z = mMax.z;
+	else
+		p.z = mMin.z;
+	return p;
+}
+
+
+// compute the vertex for number N = <0..7>, N = 4.x + 2.y + z, where
+// x,y,z are either 0 or 1; (0 .. min coordinate, 1 .. max coordinate)
+void AxisAlignedBox3::GetVertex(const int N, Vector3 &vertex) const
+{
+	switch (N) 
+	{
+	case 0: vertex = mMin; break;
+	case 1: vertex.SetValue(mMin.x, mMin.y, mMax.z); break;
+	case 2: vertex.SetValue(mMin.x, mMax.y, mMin.z); break;
+	case 3: vertex.SetValue(mMin.x, mMax.y, mMax.z); break;
+	case 4: vertex.SetValue(mMax.x, mMin.y, mMin.z); break;
+	case 5: vertex.SetValue(mMax.x, mMin.y, mMax.z); break;
+	case 6: vertex.SetValue(mMax.x, mMax.y, mMin.z); break;
+	case 7: vertex = mMax; break;
+	default: 
+		{
+			cerr << "ERROR in AxisAlignedBox3::GetVertex N=" << N <<  "\n";
+			exit(0);
+		}
+	}
+}
+
+
+float AxisAlignedBox3::SurfaceArea() const
+{
+	Vector3 ext = mMax - mMin;
+
+	return 2.0f * (ext.x * ext.y +
+		ext.x * ext.z +
+		ext.y * ext.z);
+}
+
+
+const int AxisAlignedBox3::bvertices[27][9] =
+{                   // region number.. position
+	{5,1,3,2,6,4,-1,-1,-1},      // 0 .. x=0 y=0 z=0
+	{4,5,1,3,2,0,-1,-1,-1},      // 1 .. x=0 y=0 z=1
+	{4,5,7,3,2,0,-1,-1,-1},      // 2 .. x=0 y=0 z=2
+
+	{0,1,3,2,6,4,-1,-1,-1},      // 3 .. x=0 y=1 z=0
+	{0,1,3,2,-1,-1,-1,-1,-1},    // 4 .. x=0 y=1 z=1
+	{1,5,7,3,2,0,-1,-1,-1},      // 5 .. x=0 y=1 z=2
+
+	{0,1,3,7,6,4,-1,-1,-1},      // 6 .. x=0 y=2 z=0
+	{0,1,3,7,6,2,-1,-1,-1},      // 7 .. x=0 y=2 z=1
+	{1,5,7,6,2,0,-1,-1,-1},      // 8 .. x=0 y=2 z=2
+
+	// the regions number <9,17>
+	{5,1,0,2,6,4,-1,-1,-1},      // 9  .. x=1 y=0 z=0
+	{5,1,0,4,-1,-1,-1,-1,-1},    // 10 .. x=1 y=0 z=1
+	{7,3,1,0,4,5,-1,-1,-1},      // 11 .. x=1 y=0 z=2
+
+	{4,0,2,6,-1,-1,-1,-1,-1},    // 12 .. x=1 y=1 z=0
+	{0,2,3,1,5,4,6,7,-1},        // 13 .. x=1 y=1 z=1 .. inside the box
+	{1,5,7,3,-1,-1,-1,-1,-1},    // 14 .. x=1 y=1 z=2
+
+	{4,0,2,3,7,6,-1,-1,-1},      // 15 .. x=1 y=2 z=0
+	{6,2,3,7,-1,-1,-1,-1,-1},    // 16 .. x=1 y=2 z=1
+	{1,5,7,6,2,3,-1,-1,-1},      // 17 .. x=1 y=2 z=2
+
+	// the regions number <18,26>
+	{1,0,2,6,7,5,-1,-1,-1},      // 18 .. x=2 y=0 z=0
+	{1,0,4,6,7,5,-1,-1,-1},      // 19 .. x=2 y=0 z=1
+	{0,4,6,7,3,1,-1,-1,-1},      // 20 .. x=2 y=0 z=2
+
+	{4,0,2,6,7,5,-1,-1,-1},      // 21 .. x=2 y=1 z=0
+	{5,4,6,7,-1,-1,-1,-1,-1},    // 22 .. x=2 y=1 z=1
+	{5,4,6,7,3,1,-1,-1,-1},      // 23 .. x=2 y=1 z=2
+
+	{4,0,2,3,7,5,-1,-1,-1},      // 24 .. x=2 y=2 z=0
+	{5,4,6,2,3,7,-1,-1,-1},      // 25 .. x=2 y=2 z=1
+	{5,4,6,2,3,1,-1,-1,-1},      // 26 .. x=2 y=2 z=2
+};
+
+// the visibility of boundary faces from a given region
+// one to three triples: (axis, min_vertex, max_vertex), axis==-1(terminator)
+const int AxisAlignedBox3::bfaces[27][10] =
+{                              // region number .. position
+	{0,0,3,1,0,5,2,0,6,-1},      // 0 .. x=0 y=0 z=0
+	{0,0,3,1,0,5,-1,-1,-1,-1},   // 1 .. x=0 y=0 z=1
+	{0,0,3,1,0,5,2,1,7,-1},      // 2 .. x=0 y=0 z=2
+
+	{0,0,3,2,0,6,-1,-1,-1,-1},   // 3 .. x=0 y=1 z=0
+	{0,0,3,-1,-1,-1,-1,-1,-1,-1},// 4 .. x=0 y=1 z=1
+	{0,0,3,2,1,7,-1,-1,-1,-1},   // 5 .. x=0 y=1 z=2
+
+	{0,0,3,1,2,7,2,0,6,-1},      // 6 .. x=0 y=2 z=0
+	{0,0,3,1,2,7,-1,-1,-1,-1},   // 7 .. x=0 y=2 z=1
+	{0,0,3,1,2,7,2,1,7,-1},      // 8 .. x=0 y=2 z=2
+
+	// the regions number <9,17>
+	{1,0,5,2,0,6,-1,-1,-1,-1},   // 9  .. x=1 y=0 z=0
+	{1,0,5,-1,-1,-1,-1,-1,-1,-1},// 10 .. x=1 y=0 z=1
+	{1,0,5,2,1,7,-1,-1,-1,-1},   // 11 .. x=1 y=0 z=2
+
+	{2,0,6,-1,-1,-1,-1,-1,-1,-1},// 12 .. x=1 y=1 z=0
+	{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},// 13 .. x=1 y=1 z=1 .. inside the box
+	{2,1,7,-1,-1,-1,-1,-1,-1,-1},// 14 .. x=1 y=1 z=2
+
+	{1,2,7,2,0,6,-1,-1,-1,-1},   // 15 .. x=1 y=2 z=0
+	{1,2,7,-1,-1,-1,-1,-1,-1,-1},// 16 .. x=1 y=2 z=1
+	{1,2,7,2,1,7,-1,-1,-1,-1},   // 17 .. x=1 y=2 z=2
+
+	// the region number <18,26>
+	{0,4,7,1,0,5,2,0,6,-1},      // 18 .. x=2 y=0 z=0
+	{0,4,7,1,0,5,-1,-1,-1,-1},   // 19 .. x=2 y=0 z=1
+	{0,4,7,1,0,5,2,1,7,-1},      // 20 .. x=2 y=0 z=2
+
+	{0,4,7,2,0,6,-1,-1,-1,-1},   // 21 .. x=2 y=1 z=0
+	{0,4,7,-1,-1,-1,-1,-1,-1,-1},// 22 .. x=2 y=1 z=1
+	{0,4,7,2,1,7,-1,-1,-1,-1},   // 23 .. x=2 y=1 z=2
+
+	{0,4,7,1,2,7,2,0,6,-1},      // 24 .. x=2 y=2 z=0
+	{0,4,7,1,2,7,-1,-1,-1,-1},   // 25 .. x=2 y=2 z=1
+	{0,4,7,1,2,7,2,1,7,-1},      // 26 .. x=2 y=2 z=2
+};
+
+// the correct corners indexing from entry face to exit face
+// first index determines entry face, second index exit face, and
+// the two numbers (indx, inc) determines: ind = the index on the exit
+// face, when starting from the vertex 0 on entry face, 'inc' is
+// the increment when we go on entry face in order 0,1,2,3 to create
+// convex shaft with the rectangle on exit face. That is, inc = -1 or 1.
+const int AxisAlignedBox3::pairFaceRects[6][6][2] = {
+	{ // entry face = 0
+		{-1,0}, // exit face 0 .. no meaning
+		{0,-1}, // 1
+		{0,-1}, // 2
+		{0,1}, // 3 .. opposite face
+		{3,1}, // 4
+		{1,1} // 5
+	}, 
+	{ // entry face = 1
+		{0,-1}, // exit face 0
+		{-1,0}, // 1 .. no meaning
+		{0,-1}, // 2
+		{1,1}, // 3
+		{0,1}, // 4 .. opposite face
+		{3,1} // 5
+	},
+	{ // entry face = 2
+		{0,-1}, // 0
+		{0,-1}, // 1 
+		{-1,0}, // 2 .. no meaning
+		{3,1}, // 3
+		{1,1}, // 4
+		{0,1} // 5 .. opposite face
+	},
+	{ // entry face = 3
+		{0,1}, // 0 .. opposite face
+		{3,-1}, // 1 
+		{1,1}, // 2
+		{-1,0}, // 3  .. no meaning
+		{0,-1}, // 4
+		{0,-1} // 5
+	},
+	{ // entry face = 4
+		{1,1}, // 0
+		{0,1}, // 1 .. opposite face
+		{3,1}, // 2
+		{0,-1}, // 3
+		{-1,0}, // 4 .. no meaning
+		{0,-1} // 5
+	},
+	{ // entry face = 5
+		{3,-1}, // 0
+		{1,1}, // 1
+		{0,1}, // 2  .. opposite face
+		{0,-1}, // 3
+		{0,-1}, // 4
+		{-1,0} // 5 .. no meaning
+	}
+};
+
+
+// ------------------------------------------------------------
+// The vertices that form CLOSEST points with respect to the region
+// for all the regions possible, number of regions is 3^3 = 27,
+// since two parallel sides of bbox forms three disjoint spaces.
+// The vertices are given in anti-clockwise order, stopped by value 15,
+// at most 8 points, at least 1 point.
+// The table includes the closest 1/2/4/8 points, followed possibly
+// by the set of coordinates that should be used for testing for
+// the proximity queries. The coordinates to be tested are described by
+// the pair (a,b), when a=0, we want to test min vector of the box,
+//                 when a=1, we want to test max vector of the box
+//                 b=0,1,2 corresponds to the axis (0=x,1=y,2=z)
+// The sequence is ended by 15, number -1 is used as the separator
+// between the vertices and coordinates.
+const int
+AxisAlignedBox3::cvertices[27][9] = 
+{                   // region number.. position
+	{0,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D one vertex
+	{0,1,-1,0,0,0,1,15,15},      // 1 .. x=0 y=0 z=1 D two vertices foll. by 2
+	{1,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D one vertex
+
+	{0,2,-1,0,0,0,2,15,15},      // 3 .. x=0 y=1 z=0 D
+	{0,1,3,2,-1,0,0,15,15},      // 4 .. x=0 y=1 z=1 D
+	{1,3,-1,0,0,1,2,15,15},      // 5 .. x=0 y=1 z=2 D
+
+	{2,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D
+	{2,3,-1,0,0,1,1,15,15},      // 7 .. x=0 y=2 z=1 D
+	{3,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D
+
+	// the regions number <9,17>
+	{0,4,-1,0,1,0,2,15,15},      // 9  .. x=1 y=0 z=0 D
+	{5,1,0,4,-1,0,1,15,15},      // 10 .. x=1 y=0 z=1 D
+	{1,5,-1,0,1,1,2,15,15},      // 11 .. x=1 y=0 z=2 D
+
+	{4,0,2,6,-1,0,2,15,15},      // 12 .. x=1 y=1 z=0 D
+	{0,2,3,1,5,4,6,7,15},        // 13 .. x=1 y=1 z=1 .. inside the box
+	{1,5,7,3,-1,1,2,15,15},      // 14 .. x=1 y=1 z=2 D
+
+	{6,2,-1,0,2,1,1,15,15},      // 15 .. x=1 y=2 z=0 D
+	{6,2,3,7,-1,1,1,15,15},      // 16 .. x=1 y=2 z=1 D
+	{3,7,-1,1,1,1,2,15,15},      // 17 .. x=1 y=2 z=2 D
+
+	// the regions number <18,26>
+	{4,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D
+	{4,5,-1,0,1,1,0,15,15},      // 19 .. x=2 y=0 z=1 D
+	{5,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D
+
+	{4,6,-1,0,2,1,0,15,15},      // 21 .. x=2 y=1 z=0 D
+	{5,4,6,7,-1,1,0,15,15},      // 22 .. x=2 y=1 z=1 D
+	{7,5,-1,1,0,1,2,15,15},      // 23 .. x=2 y=1 z=2 D
+
+	{6,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D
+	{6,7,-1,1,0,1,1,15,15},      // 25 .. x=2 y=2 z=1 D
+	{7,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D
+};
+
+// Table for Sphere-AABB intersection based on the region knowledge
+// Similar array to previous cvertices, but we omit the surfaces
+// which are not necessary for testing. First are vertices,
+// they are finished with -1. Second, there are indexes in
+// the pair (a,b), when a=0, we want to test min vector of the box,
+//                 when a=1, we want to test max vector of the box
+//                 b=0,1,2 corresponds to the axis (0=x,1=y,2=z)
+//
+// So either we check the vertices or only the distance in specified
+// dimensions. There are at all four possible cases:
+//
+//   1) we check one vertex - then sequence start with non-negative index
+//      and is finished with 15
+//   2) we check two coordinates of min/max vector describe by the pair
+//         (a,b) .. a=min/max(0/1) b=x/y/z (0/1/2), sequence starts with 8
+//      and finishes with 15
+//   3) we check only one coordinate of min/max, as for 2), sequence start
+//      with 9 and ends with 15
+//   4) Position 13 - sphere is inside the box, intersection always exist
+//        the sequence start with 15 .. no further testing is necessary
+//        in this case
+const int
+AxisAlignedBox3::csvertices[27][6] = 
+{                   // region number.. position
+	{0,15,15,15,15,15},  // 0 .. x=0 y=0 z=0 D vertex only
+	{8,0,0,0,1,15},      // 1 .. x=0 y=0 z=1 D two coords.
+	{1,15,15,15,15,15},  // 2 .. x=0 y=0 z=2 D vertex only
+
+	{8,0,0,0,2,15},      // 3 .. x=0 y=1 z=0 D two coords
+	{9,0,0,15,15,15},    // 4 .. x=0 y=1 z=1 D one coord
+	{8,0,0,1,2,15},      // 5 .. x=0 y=1 z=2 D two coords.
+
+	{2,15,15,15,15,15},  // 6 .. x=0 y=2 z=0 D one vertex
+	{8,0,0,1,1,15},      // 7 .. x=0 y=2 z=1 D two coords
+	{3,15,15,15,15,15},  // 8 .. x=0 y=2 z=2 D one vertex
+
+	// the regions number <9,17>
+	{8,0,1,0,2,15},      // 9  .. x=1 y=0 z=0 D two coords
+	{9,0,1,15,15,15},    // 10 .. x=1 y=0 z=1 D one coord
+	{8,0,1,1,2,15},      // 11 .. x=1 y=0 z=2 D two coords
+
+	{9,0,2,15,15,15},    // 12 .. x=1 y=1 z=0 D one coord
+	{15,15,15,15,15,15}, // 13 .. x=1 y=1 z=1 inside the box, special case/value
+	{9,1,2,15,15,15},    // 14 .. x=1 y=1 z=2 D one corrd
+
+	{8,0,2,1,1,15},      // 15 .. x=1 y=2 z=0 D two coords
+	{9,1,1,15,15},       // 16 .. x=1 y=2 z=1 D one coord
+	{8,1,1,1,2,15},      // 17 .. x=1 y=2 z=2 D two coords
+
+	// the regions number <18,26>
+	{4,15,15,15,15,15},  // 18 .. x=2 y=0 z=0 D one vertex
+	{8,0,1,1,0,15},      // 19 .. x=2 y=0 z=1 D two coords
+	{5,15,15,15,15,15},  // 20 .. x=2 y=0 z=2 D one vertex
+
+	{8,0,2,1,0,15},      // 21 .. x=2 y=1 z=0 D two coords
+	{9,1,0,15,15,15},    // 22 .. x=2 y=1 z=1 D one coord
+	{8,1,0,1,2,15},      // 23 .. x=2 y=1 z=2 D two coords
+
+	{6,15,15,15,15,15},  // 24 .. x=2 y=2 z=0 D one vertex
+	{8,1,0,1,1,15},      // 25 .. x=2 y=2 z=1 D two coords
+	{7,15,15,15,15,15},  // 26 .. x=2 y=2 z=2 D one vertex
+};
+
+
+// The vertices that form all FARTHEST points with respect to the region
+// for all the regions possible, number of regions is 3^3 = 27,
+// since two parallel sides of bbox forms three disjoint spaces.
+// The vertices are given in anti-clockwise order, stopped by value 15,
+// at most 8 points, at least 1 point.
+// For testing, if the AABB is whole in the sphere, it is enough
+// to test only vertices, either 1,2,4, or 8.
+const int
+AxisAlignedBox3::fvertices[27][9] = 
+{                   // region number.. position
+	{7,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D
+	{6,7,15,15,15,15,15,15,15},  // 1 .. x=0 y=0 z=1 D
+	{6,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D
+
+	{5,7,15,15,15,15,15,15,15},  // 3 .. x=0 y=1 z=0 D
+	{4,5,7,6,15,15,15,15,15},    // 4 .. x=0 y=1 z=1 D
+	{4,6,15,15,15,15,15,15,15},  // 5 .. x=0 y=1 z=2 D
+
+	{5,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D
+	{4,5,15,15,15,15,15,15,15},  // 7 .. x=0 y=2 z=1 D
+	{4,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D
+
+	// the regions number <9,17>
+	{3,7,15,15,15,15,15,15,15},  // 9  .. x=1 y=0 z=0 D
+	{7,3,2,6,15,15,15,15,15},    // 10 .. x=1 y=0 z=1 D
+	{2,6,15,15,15,15,15,15,15},  // 11 .. x=1 y=0 z=2 D
+
+	{5,1,3,7,15,15,15,15,15},    // 12 .. x=1 y=1 z=0 D
+	{0,7,1,6,3,4,5,2,15},        // 13 .. x=1 y=1 z=1 .. inside the box
+	{0,4,6,2,15,15,15,15,15},    // 14 .. x=1 y=1 z=2 D
+
+	{5,1,15,15,15,15,15,15,15},  // 15 .. x=1 y=2 z=0 D
+	{4,0,1,5,15,15,15,15,15},    // 16 .. x=1 y=2 z=1 D
+	{4,0,15,15,15,15,15,15,15},  // 17 .. x=1 y=2 z=2 D
+
+	// the regions number <18,26>
+	{3,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D
+	{2,3,15,15,15,15,15,15,15},  // 19 .. x=2 y=0 z=1 D
+	{2,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D
+
+	{1,3,15,15,15,15,15,15,15},  // 21 .. x=2 y=1 z=0 D
+	{1,0,2,3,15,15,15,15,15},    // 22 .. x=2 y=1 z=1 D
+	{2,0,15,15,15,15,15,15,15},  // 23 .. x=2 y=1 z=2 D
+
+	{1,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D
+	{0,1,15,15,15,15,15,15,15},  // 25 .. x=2 y=2 z=1 D
+	{0,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D
+};
+
+// Similar table as above, farthest points, but only the ones
+// necessary for testing the intersection problem. If we do
+// not consider the case 13, center of the sphere is inside the
+// box, then we can always test at most 2 box vertices to say whether
+// the whole box is inside the sphere.
+// The number of vertices is minimized using some assumptions
+// about the ortogonality of vertices and sphere properties.
+const int
+AxisAlignedBox3::fsvertices[27][9] = 
+{                   // region number.. position
+	{7,15,15,15,15,15,15,15,15}, // 0 .. x=0 y=0 z=0 D 1 vertex
+	{6,7,15,15,15,15,15,15,15},  // 1 .. x=0 y=0 z=1 D 2 vertices
+	{6,15,15,15,15,15,15,15,15}, // 2 .. x=0 y=0 z=2 D 1 vertex
+
+	{5,7,15,15,15,15,15,15,15},  // 3 .. x=0 y=1 z=0 D 2 vertices
+	{4,7,15,5,6,15,15,15,15},    // 4 .. x=0 y=1 z=1 D 4/2 vertices
+	{4,6,15,15,15,15,15,15,15},  // 5 .. x=0 y=1 z=2 D 2 vertices
+
+	{5,15,15,15,15,15,15,15,15}, // 6 .. x=0 y=2 z=0 D 1 vertex
+	{4,5,15,15,15,15,15,15,15},  // 7 .. x=0 y=2 z=1 D 2 vertices
+	{4,15,15,15,15,15,15,15,15}, // 8 .. x=0 y=2 z=2 D 1 vertex
+
+	// the regions number <9,17>
+	{3,7,15,15,15,15,15,15,15},  // 9  .. x=1 y=0 z=0 D 2 vertices
+	{7,2,15,3,6,15,15,15,15},    // 10 .. x=1 y=0 z=1 D 4/2 vertices
+	{2,6,15,15,15,15,15,15,15},  // 11 .. x=1 y=0 z=2 D 2 vertices
+
+	{5,3,15,1,7,15,15,15,15},    // 12 .. x=1 y=1 z=0 D 4/2 vertices
+	{0,7,1,6,3,4,5,2,15},        // 13 .. x=1 y=1 z=1 .. inside the box
+	{0,6,15,4,2,15,15,15,15},    // 14 .. x=1 y=1 z=2 D 4/2 vertices
+
+	{5,1,15,15,15,15,15,15,15},  // 15 .. x=1 y=2 z=0 D 2 vertices
+	{4,1,15,0,5,15,15,15,15},    // 16 .. x=1 y=2 z=1 D 4/2 vertices
+	{4,0,15,15,15,15,15,15,15},  // 17 .. x=1 y=2 z=2 D 2 vertices
+
+	// the regions number <18,26>
+	{3,15,15,15,15,15,15,15,15}, // 18 .. x=2 y=0 z=0 D 1 vertex
+	{2,3,15,15,15,15,15,15,15},  // 19 .. x=2 y=0 z=1 D 2 vertices
+	{2,15,15,15,15,15,15,15,15}, // 20 .. x=2 y=0 z=2 D 1 vertex
+
+	{1,3,15,15,15,15,15,15,15},  // 21 .. x=2 y=1 z=0 D 2 vertices
+	{1,2,15,0,3,15,15,15,15},    // 22 .. x=2 y=1 z=1 D 4/2 vertices
+	{2,0,15,15,15,15,15,15,15},  // 23 .. x=2 y=1 z=2 D 2 vertices
+
+	{1,15,15,15,15,15,15,15,15}, // 24 .. x=2 y=2 z=0 D 1 vertex
+	{0,1,15,15,15,15,15,15,15},  // 25 .. x=2 y=2 z=1 D 2 vertices
+	{0,15,15,15,15,15,15,15,15}, // 26 .. x=2 y=2 z=2 D 1 vertex
+};
+
+
+// The fast computation of arctangent .. the maximal error is less
+// than 4.1 degrees, according to Graphics GEMSII, 1991, pages 389--391
+// Ron Capelli: "Fast approximation to the arctangent"
+float atan22(const float& y)
+{
+	const float x = 1.0;
+	const float c = (float)(M_PI * 0.25);
+
+	if (y < 0.0) {
+		if (y < -1.0)
+			return c * (-2.0f + x / y); // for angle in <-PI/2, -PI/4)
+		else
+			return c * (y / x); // for angle in <-PI/4 , 0>
+	}
+	else {
+		if (y > 1.0)
+			return c * (2.0f - x / y); // for angle in <PI/4, PI/2>
+		else
+			return c * (y / x); // for angle in <0, PI/2>
+	}
+}
+
+
+// This definition allows to be a point when answering true
+bool
+AxisAlignedBox3::IsCorrectAndNotPoint() const
+{
+	if ( (mMin.x > mMax.x) ||
+		(mMin.y > mMax.y) ||
+		(mMin.z > mMax.z) )
+		return false; // box is not formed
+
+	if ( (mMin.x == mMax.x) &&
+		(mMin.y == mMax.y) &&
+		(mMin.z == mMax.z) )
+		return false; // degenerates to a point
+
+	return true;
+}
+
+// This definition allows to be a point when answering true
+bool AxisAlignedBox3::IsPoint() const
+{
+	if ( (mMin.x == mMax.x) &&
+		(mMin.y == mMax.y) &&
+		(mMin.z == mMax.z) )
+		return true; // degenerates to a point
+
+	return false;
+}
+
+// This definition requires shape of non-zero volume
+bool AxisAlignedBox3::IsSingularOrIncorrect() const
+{
+	if ( (mMin.x >= mMax.x) ||
+		(mMin.y >= mMax.y) ||
+		(mMin.z >= mMax.z) )
+		return true; // box is not formed
+
+	return false; // has non-zero volume
+}
+
+
+void AxisAlignedBox3::GetSqrDistances(const Vector3 &point,
+									  float &minDistance,
+									  float &maxDistance) const
+{
+	// some overlap is possible, check the distance of vertices
+	float sumMin = 0;
+	float sumMax = 0;
+
+	// Try to minimize the function of a distance
+	// from the sphere center
+
+	const float *minp = &(mMin.x);
+	const float *maxp = &(mMax.x);
+	const float *pcenter = &(point.x);
+
+	// for x-axis
+	for (int i = 0; i < 3; i++, minp++, maxp++, pcenter++) {
+		float minsqr = sqr(*minp - *pcenter);
+		float maxsqr = sqr(*maxp - *pcenter);
+		if (*pcenter < *minp)
+			sumMin += minsqr;
+		else
+			if (*pcenter > *maxp)
+				sumMin += maxsqr;
+		sumMax += (minsqr > maxsqr) ? minsqr : maxsqr;
+	}
+
+	minDistance = sumMin;
+	maxDistance = sumMax;
+}
+
+#if TOIMPLEMENT
+int AxisAlignedBox3::Side(const Plane3 &plane) const
+{
+	Vector3 v;
+	int i, m=3, M=-3, s;
+
+	for (i=0;i<8;i++) {
+		GetVertex(i, v);
+		if((s = plane.Side(v)) < m)
+			m=s;
+		if(s > M)
+			M=s;
+		if (m && m==-M)
+			return 0;
+	}
+
+	return (m == M) ? m : m + M;
+}
+
+
+Plane3 AxisAlignedBox3::GetPlane(const int face) const
+{
+	switch (face) 
+	{
+
+	case 0:
+		return Plane3(Vector3(-1, 0, 0), mMin);
+	case 1: 
+		return Plane3(Vector3(1, 0, 0), mMax);
+	case 2:
+		return Plane3(Vector3(0, -1, 0), mMin);
+	case 3:
+		return Plane3(Vector3(0, 1, 0), mMax);
+	case 4:
+		return Plane3(Vector3(0, 0, -1), mMin);
+	case 5:
+		return Plane3(Vector3(0, 0, 1), mMax);
+	}
+
+	// should not come here
+	return Plane3();
+}
+#endif
+
+
+void AxisAlignedBox3::Scale(const float scale) 
+{
+	Vector3 newSize = Size()*(scale*0.5f);
+	Vector3 center = Center();
+	mMin = center - newSize;
+	mMax = center + newSize;
+}
+
+
+void AxisAlignedBox3::Scale(const Vector3 &scale) 
+{
+	Vector3 newSize = Size()*(scale*0.5f);
+	Vector3 center = Center();
+	mMin = center - newSize;
+	mMax = center + newSize;
+}
+
+
+void AxisAlignedBox3::Translate(const Vector3 &shift) 
+{
+	mMin += shift;
+	mMax += shift;
+}
+
+
+void AxisAlignedBox3::Initialize() 
+{
+	mMin = Vector3(MAXFLOAT);
+	mMax = Vector3(-MAXFLOAT);
+}
+
+
+Vector3 AxisAlignedBox3::Center() const 
+{ 
+	return 0.5 * (mMin + mMax); 
+}
+
+
+Vector3 AxisAlignedBox3::Diagonal() const 
+{ 
+	return (mMax - mMin); 
+}
+
+
+float AxisAlignedBox3::Center(const int axis) const 
+{
+	return  0.5f * (mMin[axis] + mMax[axis]);
+}
+
+
+float AxisAlignedBox3::Min(const int axis) const 
+{
+	return mMin[axis];
+}
+
+
+float AxisAlignedBox3::Max(const int axis) const 
+{
+	return  mMax[axis];
+}
+
+
+float AxisAlignedBox3::Size(const int axis) const 
+{
+	return  Max(axis) - Min(axis);
+}
+
+// Read-only const access tomMin and max vectors using references
+const Vector3& AxisAlignedBox3::Min() const 
+{ 
+	return mMin;
+}
+
+
+const Vector3& AxisAlignedBox3::Max() const 
+{ 
+	return mMax;
+}
+
+
+void AxisAlignedBox3::Enlarge (const Vector3 &v) 
+{
+	mMax += v;
+	mMin -= v;
+}
+
+
+void AxisAlignedBox3::EnlargeToMinSize()
+{
+	const float epsMin = 1e-7f;
+	const float epsAdd = 1e-6f;
+	const float epsMul = 1.000005f;
+	float dir = mMax.x - mMin.x;
+
+	assert(dir >= 0.f);
+
+	if (dir < epsMin) 
+	{
+		if (mMax.x > 0) 
+		{
+			mMax.x *= epsMul;
+			mMax.x += epsAdd;
+		}
+		else 
+		{
+			mMin.x *= epsMul;
+			mMin.x -= epsAdd;
+		}
+		
+		assert(mMin.x < mMax.x);
+	}
+
+	dir = mMax.y - mMin.y;
+	assert(dir >= 0.f);
+	
+	if (dir < epsMin) 
+	{
+		if (mMax.y > 0) 
+		{
+			mMax.y *= epsMul;
+			mMax.y += epsAdd;
+		}
+		else 
+		{
+			mMin.y *= epsMul;
+			mMin.y -= epsAdd;
+		}
+		assert(mMin.y < mMax.y);
+	}
+	
+	dir = mMax.z - mMin.z;
+	assert(dir >= 0.f);
+	
+	if (dir < epsMin) 
+	{
+		if (mMax.z > 0) 
+		{
+			mMax.z *= epsMul;
+			mMax.z += epsAdd;
+		}
+		else 
+		{
+			mMin.z *= epsMul;
+			mMin.z -= epsAdd;
+		}
+		
+		assert(mMin.z < mMax.z);
+	}
+}
+
+
+void AxisAlignedBox3::SetMin(const Vector3 &v) 
+{
+	mMin = v;
+}
+
+
+void AxisAlignedBox3::SetMax(const Vector3 &v) 
+{
+	mMax = v;
+}
+
+
+void AxisAlignedBox3::SetMin(int axis, const float value) 
+{
+	mMin[axis] = value;
+}
+
+
+void AxisAlignedBox3::SetMax(int axis, const float value) 
+{
+	mMax[axis] = value;
+}
+
+
+// Decrease box by given splitting plane
+void AxisAlignedBox3::Reduce(int axis, int right, float value) 
+{
+	if ((value >=mMin[axis]) && (value <= mMax[axis]))
+	{
+		if (right)
+			mMin[axis] = value;
+		else
+			mMax[axis] = value;
+	}
+}
+
+
+Vector3 AxisAlignedBox3::Size() const 
+{ 
+	return mMax - mMin; 
+}
+
+
+Vector3 AxisAlignedBox3::GetRandomPoint() const
+{
+	Vector3 size = Size();
+
+	return GetRandomPoint(Vector3(RandomValue(0.0f, 1.0f),
+                                  RandomValue(0.0f, 1.0f),
+								  RandomValue(0.0f, 1.0f)));
+}
+
+
+Vector3 AxisAlignedBox3::GetRandomPoint(const Vector3 &r) const
+{
+	return mMin + Size()*r;
+}
+
+
+bool AxisAlignedBox3::Intersects(const Vector3 &lStart, 
+								 const Vector3 &lEnd) const
+{
+	float st, et, fst = 0, fet = 1;
+	float const *bmin = &mMin.x;
+	float const *bmax = &mMax.x;
+	float const *si = &lStart.x;
+	float const *ei = &lEnd.x;
+
+	for (int i = 0; i < 3; ++ i) 
+	{
+		if (*si < *ei) 
+		{
+			if (*si > *bmax || *ei < *bmin)
+				return false;
+
+			const float di = *ei - *si;
+
+			st = (*si < *bmin)? (*bmin - *si) / di : 0;
+			et = (*ei > *bmax)? (*bmax - *si) / di : 1;
+		}
+		else 
+		{
+			if (*ei > *bmax || *si < *bmin)
+				return false;
+
+			const float di = *ei - *si;
+
+			st = (*si > *bmax)? (*bmax - *si) / di : 0;
+			et = (*ei < *bmin)? (*bmin - *si) / di : 1;
+		}
+
+		if (st > fst) fst = st;
+		if (et < fet) fet = et;
+		if (fet < fst)
+			return false;
+
+		++ bmin; ++ bmax;
+		++ si; ++ ei;
+	}
+
+	//*time = fst;
+	return true;
+}
+
+//}
+
