Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SampleGenerator.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SampleGenerator.cpp	(revision 3233)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SampleGenerator.cpp	(revision 3234)
@@ -35,34 +35,32 @@
 	// this sampling scheme has the benefit that it is hierarchical 
 	int maxTries = 1000;
-	const float f_reduction = 0.9f;
+	const float f_reduction = 0.95f;
 	
 	float r[2];
 
+	// the maximal possible radius: our radius is a fraction of this radius
+	// this is used as a measure of the quality of distribution of the point samples
+	const float rmax = 2.0f * mRadius * sqrt(1.0f / (2.0f * sqrt(3.0f) * mNumSamples));
+
 	// generates poisson distribution on disc
-	// start with some threshold
-	// best case: all samples lie on the circumference of circle
+	// start with some thresholds: all samples lie on the circumference of circle
 	 
-	const float eps = 0.2f;
-	const float minDist = 2.0f * mRadius * M_PI * (1.0f - eps) / (float)mNumSamples;
+	float minDist = 2.0f * rmax;
 	float sqrMinDist = minDist * minDist;
 
+	int tries = 0;
+
 	//cout << "minDist before= " << minDist << endl;
 	Sample2 *s = (Sample2 *)samples;
 
-	int totalTries = 0;
-
 	// check if on disc
 	for (int i = 0; i < mNumSamples; ++ i)
 	{
-		int tries = 0;
-
 		// repeat until valid sample was found
 		while (1)
 		{
-			++ tries;
-			++ totalTries;
-
-			// note: should use halton, but seems somewhat broken
-			mHalton->GetNext(r);
+			// q: should we use halton or does it conflict with the poisson disc properties?
+			r[0] = RandomValue(0, 1); r[1] = RandomValue(0, 1);
+			//mHalton->GetNext(r);
 
 			// scale to -1 .. 1
@@ -99,13 +97,17 @@
 			}
 
+			++ tries;
+
 			if (tries > maxTries)
 			{
-				sqrMinDist *= f_reduction;
-				tries = 0;
+				minDist *= f_reduction;
+				sqrMinDist = minDist * minDist;
+
+				maxTries += 1000;
 			}
 		}
 	}
 
-	cout << "minDist after= " << sqrt(sqrMinDist) << " #tries: " << totalTries << endl;
+	cout << "minDist after= " << (float)minDist / mNumSamples<< " #tries: " << tries << endl;
 }
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/gzstream.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/gzstream.h	(revision 3234)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/gzstream.h	(revision 3234)
@@ -0,0 +1,146 @@
+// ============================================================================
+// gzstream, C++ iostream classes wrapping the zlib compression library.
+// Copyright (C) 2001  Deepak Bandyopadhyay, Lutz Kettner
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// ============================================================================
+//
+// File          : gzstream.h
+// Revision      : $Revision: 1.1 $
+// Revision_date : $Date: 2004/02/16 14:46:00 $
+// Author(s)     : Deepak Bandyopadhyay, Lutz Kettner
+// 
+// Standard streambuf implementation following Nicolai Josuttis, "The 
+// Standard C++ Library".
+// ============================================================================
+
+#ifndef GZSTREAM_H
+#define GZSTREAM_H 1
+
+#include <zlib.h>
+
+// standard C++ with new header file names and std:: namespace
+#include <iostream>
+#include <fstream>
+
+#ifdef GZSTREAM_NAMESPACE
+namespace GZSTREAM_NAMESPACE {
+#endif
+
+// ----------------------------------------------------------------------------
+// Internal classes to implement gzstream. See below for user classes.
+// ----------------------------------------------------------------------------
+
+   // size of data buff
+#define gzbufferSize  303   
+
+
+
+#define STREAMBUF std::streambuf 
+#define ISTREAM std::istream
+#define OSTREAM std::ostream
+
+//#define STREAMBUF streambuf 
+//#define ISTREAM istream
+//#define OSTREAM ostream
+
+class gzstreambuf : public STREAMBUF {
+
+private:
+    // totals 512 bytes under g++ for igzstream at the end.
+
+    gzFile           file;               // file handle for compressed file
+    char             buffer[gzbufferSize]; // data buffer
+    char             opened;             // open/close state of stream
+    int              mode;               // I/O mode
+
+    int flush_buffer();
+public:
+    gzstreambuf() : opened(0) {
+        setp( buffer, buffer + (gzbufferSize-1));
+        setg( buffer + 4,     // beginning of putback area
+              buffer + 4,     // read position
+              buffer + 4);    // end position      
+        // ASSERT: both input & output capabilities will not be used together
+    }
+    int is_open() const { return opened; }
+    gzstreambuf* open( const char* name, int open_mode);
+    gzstreambuf* close();
+    ~gzstreambuf() { close(); }
+  
+    virtual int     overflow( int c = EOF);
+    virtual int     underflow();
+    virtual int     sync();
+
+};
+
+class gzstreambase : virtual public std::ios {
+
+protected:
+    gzstreambuf buf;
+public:
+  gzstreambase() { init(&buf); }
+  gzstreambase( const char* name, int open_mode);
+  ~gzstreambase();
+  void open( const char* name, int open_mode);
+  void close();
+  gzstreambuf* rdbuf() { return &buf; }
+  int is_open() const { return buf.is_open(); }
+};
+
+// ----------------------------------------------------------------------------
+// User classes. Use igzstream and ogzstream analogously to ifstream and
+// ofstream respectively. They read and write files based on the gz* 
+// function interface of the zlib. Files are compatible with gzip compression.
+// ----------------------------------------------------------------------------
+
+  
+
+  class igzstream : public gzstreambase, public ISTREAM {
+  
+  public:
+    igzstream() : gzstreambase(), ISTREAM( &buf )  {} 
+    
+    igzstream( const char* name, int open_mode = std::ios::in)
+      : gzstreambase( name, open_mode), ISTREAM( &buf) {}
+    
+    gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
+    
+    void open( const char* name, int open_mode = std::ios::in) {
+      gzstreambase::open( name, open_mode);
+    }
+  };
+  
+class ogzstream : public gzstreambase, public OSTREAM {
+  
+public:
+  ogzstream() : OSTREAM( &buf) {}
+  ogzstream( const char* name, int mode = std::ios::out)
+    : gzstreambase( name, mode), OSTREAM( &buf) {}  
+  gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
+  void open( const char* name, int open_mode = std::ios::out) {
+    gzstreambase::open( name, open_mode);
+  }
+  
+};
+
+#ifdef GZSTREAM_NAMESPACE
+} // namespace GZSTREAM_NAMESPACE
+#endif
+
+#endif // GZSTREAM_H
+// ============================================================================
+// EOF //
+
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/ObjConverter.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/ObjConverter.cpp	(revision 3234)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/ObjConverter.cpp	(revision 3234)
@@ -0,0 +1,483 @@
+#include "ObjConverter.h"
+#include "SimpleTri.h"
+#include "SimpleVec.h"
+#include "gzstream.h"
+#include <iostream>
+
+
+using namespace std;
+
+//#define USE_TEXTURE
+
+
+static void LoadIndices(char *str, 
+						const VertexArray &vertices, 
+						const VertexArray &normals, 
+						const vector<pair<float, float> > &texcoords,
+						VertexArray &faceVertices,
+						VertexArray &faceNormals,
+						vector<Texcoord> &faceTexcoords
+						)
+{
+	vector<string> triples;
+
+	char *next_token;
+
+	// extract the triples of the form v/t/n v/t/n ...
+	char *pch = strtok_s(str + 1, " ", &next_token);
+
+	while (pch)
+	{
+		string s(pch);
+		//s += "\n",
+		triples.push_back(s);
+		
+		pch = strtok_s(NULL, " ", &next_token);	  
+	}
+
+	vector<int> indices;
+	vector<int> nIndices;
+	vector<int> tIndices;
+
+	char seps[] = " /\t\n";
+
+	for (size_t i = 0; i < triples.size(); ++ i)
+	{
+		static int dummy = 0;
+
+		size_t found;
+		found = triples[i].find_first_of(seps);
+		size_t prevfound = 0;
+		// vertex, normal, texture indices
+		string str = triples[i].substr(prevfound, found);
+
+		int index = (int)strtol(str.c_str(), NULL, 10) - 1;
+
+		int tIndex = index;
+		int nIndex = index;	
+		
+		prevfound = found;
+		found = triples[i].find_first_of(seps, found + 1);  
+
+		if (found != string::npos)
+		{
+			str = triples[i].substr(prevfound, found);
+
+			int idx = (int)strtol(str.c_str(), NULL, 10) - 1;
+			if (idx > 0) tIndex = idx;
+		}
+
+		if ((found + 1) < triples[i].size())
+		{
+			str = triples[i].substr(found + 1);
+
+			int idx = (int)strtol(str.c_str(), NULL, 10) - 1;
+			if (idx > 0) nIndex = idx;
+		}
+
+		// store indices
+		if (index >= 0)
+		{
+			indices.push_back(index);
+			nIndices.push_back(nIndex);
+			tIndices.push_back(tIndex);
+		}
+
+		// new triangle found
+		if (indices.size() > 2)
+		{
+			// change orientation of faces?
+#if 1
+			int idx1 = 0;
+			int idx2 = (int)indices.size() - 2;
+			int idx3 = (int)indices.size() - 1;
+#else
+			int idx3 = 0;
+			int idx2 = (int)indices.size() - 2;
+			int idx1 = (int)indices.size() - 1;
+#endif
+			faceVertices.push_back(vertices[indices[idx1]]);
+			faceVertices.push_back(vertices[indices[idx2]]);
+			faceVertices.push_back(vertices[indices[idx3]]);
+
+
+			if (!normals.empty())
+			{
+				//if (dummy < 3) cout << nIndices[idx1] << " " << nIndices[idx2] << " " << nIndices[idx3] << endl;
+				faceNormals.push_back(normals[nIndices[idx1]]);
+				faceNormals.push_back(normals[nIndices[idx2]]);
+				faceNormals.push_back(normals[nIndices[idx3]]);
+			}
+			else
+			{
+				// no face normals? => create normals
+				const SimpleTri tri(vertices[indices[idx1]],
+					                vertices[indices[idx2]], 
+									vertices[indices[idx3]]);
+				const SimpleVec n = tri.GetNormal();
+
+				faceNormals.push_back(n);
+				faceNormals.push_back(n);
+				faceNormals.push_back(n);
+			}
+
+			++ dummy;
+			if (!texcoords.empty())
+			{
+				faceTexcoords.push_back(texcoords[tIndices[idx1]]);
+				faceTexcoords.push_back(texcoords[tIndices[idx2]]);
+				faceTexcoords.push_back(texcoords[tIndices[idx3]]);
+			}
+		}
+	}
+}
+
+
+ObjConverter::ObjConverter()
+{}
+
+
+ObjConverter::~ObjConverter()
+{
+	for (size_t i = 0; i < mGeometry.size(); ++ i)
+	{
+		delete [] mGeometry[i]->mVertices;
+		delete [] mGeometry[i]->mNormals;
+		delete [] mGeometry[i]->mTexcoords;
+
+		delete mGeometry[i];
+	}
+	
+	mGeometry.clear();
+}
+
+
+void ObjConverter::LoadShape(const VertexArray &faceVertices,
+							 const VertexArray &faceNormals,
+							 const vector<Texcoord> &faceTexcoords)
+{
+	int numElements = (int)faceVertices.size();
+	Geometry *geom = new Geometry();
+
+	// convert the triangles to geometry
+	geom->mVertices = new SimpleVec[numElements];
+	geom->mNormals = new SimpleVec[numElements];
+	geom->mTexcoords = new Texcoord[numElements];
+
+	geom->mVertexCount = numElements;
+	geom->mTexcoordCount = (int)faceTexcoords.size();
+
+	cout << "number of vertices=" << numElements << endl;
+
+	for (int i = 0; i < numElements; ++ i)
+	{
+#if 0
+		// convert to our camera system: change y and z
+		geom->mVertices[i].x = faceVertices[i].x;
+		geom->mVertices[i].y = -faceVertices[i].z;
+		geom->mVertices[i].z = faceVertices[i].y;
+	
+		geom->mNormals[i].x = faceNormals[i].x;
+		geom->mNormals[i].y = -faceNormals[i].z;
+		geom->mNormals[i].z = faceNormals[i].y;
+
+#else
+		geom->mVertices[i].x = faceVertices[i].x;
+		geom->mVertices[i].y = faceVertices[i].y;
+		geom->mVertices[i].z = faceVertices[i].z;
+	
+		geom->mNormals[i].x = faceNormals[i].x;
+		geom->mNormals[i].y = faceNormals[i].y;
+		geom->mNormals[i].z = faceNormals[i].z;
+
+#endif
+
+		if (i < geom->mTexcoordCount)
+		{
+			geom->mTexcoords[i].first = faceTexcoords[i].first;
+			geom->mTexcoords[i].second = faceTexcoords[i].second;
+		}
+	}
+
+	mGeometry.push_back(geom);
+}
+
+
+bool ObjConverter::Convert(const string &filename, const std::string &outputFilename)
+{
+	mNumShapes = 0;
+	
+	for (size_t i = 0; i < mGeometry.size(); ++ i)
+	{
+		delete [] mGeometry[i]->mVertices;
+		delete [] mGeometry[i]->mNormals;
+		delete [] mGeometry[i]->mTexcoords;
+
+		delete mGeometry[i];
+	}
+	
+	mGeometry.clear();
+
+	if (!ReadFile(filename))
+	{
+		cerr << "could not read file" << endl;
+		return false;
+	}
+
+	if (!WriteFile(outputFilename))
+	{
+		cerr << "could not write file" << endl;
+		return false;
+	}
+
+
+	return true;
+}
+
+
+bool ObjConverter::ReadFile(const string &filename) 
+{
+	FILE *file;
+
+	if ((file = fopen(filename.c_str(), "r")) == NULL)
+	{	
+		return false;
+	}
+	
+	VertexArray faceVertices; 
+	VertexArray faceNormals;
+	vector<Texcoord> faceTexcoords;
+
+	VertexArray vertices; 
+	VertexArray normals;
+	vector<Texcoord> texcoords;
+
+	vector<int> indices;
+
+	int line = 0;
+	const int len = 10000;
+	char str[len];
+
+	while (fgets(str, len, file) != NULL)
+	{
+		switch (str[0])
+		{
+		case 'v': // vertex or normal
+			{
+				float x, y, z;
+
+				switch (str[1]) 
+				{
+				case 'n' :
+					sscanf(str + 2, "%f %f %f", &x, &y, &z);
+					normals.push_back(SimpleVec(x, y, z));
+					break;
+				case 't':
+					sscanf(str + 2, "%f %f", &x, &y);
+					texcoords.push_back(pair<float, float>(x, y));
+					break;
+				default:
+					sscanf(str + 1, "%f %f %f", &x, &y, &z);
+					//const float scale = 5e-3f;
+					const float scale = 1.0f;
+					vertices.push_back(SimpleVec(x * scale, y * scale, z* scale));
+					//cout <<"v " << x << " " << y << " "<< z << " ";
+				}
+				break;
+			}
+		case 'f': 
+			{
+				//////////
+				//-- indices in the current line
+
+				LoadIndices(str, 
+					        vertices, normals, texcoords, 
+					        faceVertices, faceNormals, faceTexcoords);
+
+				if (0 &&
+					(((line % 1000) == 999) && !faceVertices.empty()))
+				{
+					++ mNumShapes;
+
+					LoadShape(faceVertices, faceNormals, faceTexcoords);
+
+					faceVertices.clear();
+					faceNormals.clear();
+					faceTexcoords.clear();
+				}
+
+				break;
+			}   // end face
+		case 'g': // load a new shape
+			{/*
+				if (!faceVertices.empty())
+				{
+					++ mNumShapes;
+
+					LoadShape(faceVertices, faceNormals, faceTexcoords);
+
+					faceVertices.clear();
+					faceNormals.clear();
+					faceTexcoords.clear();
+				}*/
+			}
+			break;
+		default:
+			// throw away line
+			break;
+		}
+
+		++ line;
+	}
+
+	if (!faceVertices.empty())
+	{
+		++ mNumShapes;
+
+		LoadShape(faceVertices, faceNormals, faceTexcoords);
+
+		faceVertices.clear();
+		faceNormals.clear();
+		faceTexcoords.clear();
+	}
+
+	fclose(file);
+	
+	return true;
+}
+
+
+void ObjConverter::WriteGeometry(ogzstream &str, Geometry *geom)
+{
+	int vertexCount = geom->mVertexCount;
+	str.write(reinterpret_cast<char *>(&vertexCount), sizeof(int));
+  
+	str.write(reinterpret_cast<char *>(geom->mVertices), sizeof(SimpleVec) * vertexCount);
+	str.write(reinterpret_cast<char *>(geom->mNormals), sizeof(SimpleVec) * vertexCount);
+
+	int texCoordCount = geom->mTexcoordCount;
+	str.write(reinterpret_cast<char *>(&texCoordCount), sizeof(int));
+
+	if (texCoordCount)
+		str.write(reinterpret_cast<char *>(geom->mTexcoords), sizeof(float) * texCoordCount * 2);
+	
+
+	///////
+	//-- texture
+
+#ifdef USE_TEXTURE
+	int texId = 0;
+#else
+	int texId = -1;
+#endif
+
+	str.write(reinterpret_cast<char *>(&texId), sizeof(int));
+
+	bool alphaTestEnabled = false;
+	//bool cullFaceEnabled = false;
+	bool cullFaceEnabled = true;
+
+	str.write(reinterpret_cast<char *>(&alphaTestEnabled), sizeof(bool));
+	str.write(reinterpret_cast<char *>(&cullFaceEnabled), sizeof(bool));
+
+	// material
+	bool hasMaterial = true;
+	//bool hasMaterial = false;
+	str.write(reinterpret_cast<char *>(&hasMaterial), sizeof(bool));
+	
+	if (hasMaterial)
+	{
+		SimpleVec ambient, diffuse, spec, emm;
+
+		ambient.x = ambient.y = ambient.z = 0.2f;
+		//diffuse.x = diffuse.y = diffuse.z = 1.0f;
+		diffuse.x = 0.7f; diffuse.y = 0.5f; diffuse.z = 0.2f;
+		spec.x    = spec.y    = spec.z    =  .0f;
+		emm = spec;
+
+		// only write rgb part of the material
+		str.write(reinterpret_cast<char *>(&ambient), sizeof(SimpleVec));
+		str.write(reinterpret_cast<char *>(&diffuse), sizeof(SimpleVec));
+		str.write(reinterpret_cast<char *>(&spec), sizeof(SimpleVec));
+		str.write(reinterpret_cast<char *>(&emm), sizeof(SimpleVec));
+	}
+}
+
+
+bool ObjConverter::WriteFile(const string &filename)
+{
+	ogzstream ofile(filename.c_str());
+
+	if (!ofile.is_open())
+		return false;
+	
+
+	/////////
+	//-- write textures
+
+#ifdef USE_TEXTURE
+	int textureCount = 1;
+#else
+	int textureCount = 0;
+#endif
+	ofile.write(reinterpret_cast<char *>(&textureCount), sizeof(int));
+
+	if (textureCount > 0)
+	{
+		// hack
+		const string texName("wood.jpg");
+
+		int texnameSize = (int)texName.length() + 1;
+		ofile.write(reinterpret_cast<char *>(&texnameSize), sizeof(int));
+
+		ofile.write(texName.c_str(), sizeof(char) * texnameSize);
+
+		int boundS = 1, boundT = 1;
+
+		ofile.write(reinterpret_cast<char *>(&boundS), sizeof(int));
+		ofile.write(reinterpret_cast<char *>(&boundT), sizeof(int));
+	}
+
+
+	///////////
+	//-- write shapes
+
+	ofile.write(reinterpret_cast<char *>(&mNumShapes), sizeof(int));
+
+	vector<Geometry *>::const_iterator it, it_end = mGeometry.end();
+
+	for (it = mGeometry.begin(); it != it_end; ++ it)
+	{
+		WriteGeometry(ofile, *it);
+	}
+
+
+	int entityCount = 1;
+	ofile.write(reinterpret_cast<char *>(&entityCount), sizeof(int));
+
+
+	//////////
+	//-- write single scene entity
+
+	// no transformation
+	bool hasTrafo = false;
+	ofile.write(reinterpret_cast<char *>(&hasTrafo), sizeof(bool));
+
+	// a dummy lod
+	int numLODs = 1;
+	ofile.write(reinterpret_cast<char *>(&numLODs), sizeof(int));
+
+	float dist = 0;
+	ofile.write(reinterpret_cast<char *>(&dist), sizeof(float));
+
+	ofile.write(reinterpret_cast<char *>(&mNumShapes), sizeof(int));
+
+	// all shapes belong to this scene entity
+	for (int i = 0; i < mNumShapes; ++ i)
+	{
+		int shapeId = i;
+		ofile.write(reinterpret_cast<char *>(&shapeId), sizeof(int));
+	}
+
+	return true;
+}
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/main.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/main.cpp	(revision 3234)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/main.cpp	(revision 3234)
@@ -0,0 +1,29 @@
+#include "ObjConverter.h"
+#include <iostream>
+#include <time.h>
+
+using namespace std;
+
+static string model_path("data/city/model/");
+
+int main(int argc, char* argv[])
+{
+	int returnCode = 0;
+
+	ObjConverter converter;
+
+	cout << "converting obj to dem format" << endl;
+
+	if (!converter.Convert(model_path + argv[1], model_path + argv[2]))
+	{
+		cerr << "conversion failed" << endl;
+
+		std::cin.get();
+		exit(0);
+	}
+	//std::cin.get();
+	cout << "conversion successful" << endl;
+
+	return 0;
+}
+
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/ObjConverter.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/ObjConverter.h	(revision 3234)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/ObjConverter.h	(revision 3234)
@@ -0,0 +1,64 @@
+#ifndef _OBJCONVERTER_H
+#define _OBJCONVERTER_H
+
+#include "SimpleVec.h"
+#include <string>
+#include <vector>
+
+/*struct SimpleVec
+{
+	SimpleVec() {}
+	SimpleVec(float _x, float _y, float _z): x(_x), y(_y), z(_z) {}
+
+	float x, y, z;
+};*/
+
+typedef std::vector<SimpleVec> VertexArray;
+typedef std::pair<float, float> Texcoord;
+
+class ogzstream;
+
+/** Converts obj format into objects readable by our format
+*/
+class ObjConverter
+{
+public:
+
+	ObjConverter();
+
+	bool Convert(const std::string &inputFilename, 
+		         const std::string &outputFilename);
+	// const std::string textureFilename) const;
+
+	~ObjConverter();
+
+protected:
+
+	struct Geometry
+	{
+		SimpleVec *mVertices;
+		SimpleVec *mNormals;
+		Texcoord *mTexcoords;
+
+		int mVertexCount;
+		int mTexcoordCount;
+	};
+
+	void LoadShape(const VertexArray &faceVertices,
+		           const VertexArray &faceNormals,
+				   const std::vector<Texcoord> &faceTexcoords);
+
+	void WriteGeometry(ogzstream &str, Geometry *geom);
+
+	bool ReadFile(const std::string &inputFilename);
+	bool WriteFile(const std::string &outputFilename);
+
+
+	std::vector<Geometry *> mGeometry;
+
+	int mNumShapes;
+};
+
+
+
+#endif
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleVec.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleVec.cpp	(revision 3234)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleVec.cpp	(revision 3234)
@@ -0,0 +1,103 @@
+#include "SimpleVec.h"
+#include <float.h>
+
+
+
+// Given min a vector to minimize and a candidate vector, replace
+// elements of min whose corresponding elements in Candidate are
+// smaller.  This function is used for finding objects' bounds,
+// among other things.
+void Minimize(SimpleVec &min, const SimpleVec &Candidate)
+{
+	if (Candidate.x < min.x)
+		min.x = Candidate.x;
+	if (Candidate.y < min.y)
+		min.y = Candidate.y;
+	if (Candidate.z < min.z)
+		min.z = Candidate.z;
+}
+
+// Given min a vector to minimize and a candidate vector, replace
+// elements of min whose corresponding elements in Candidate are
+// larger.  This function is used for finding objects' bounds,
+// among other things.
+void Maximize(SimpleVec &max, const SimpleVec &Candidate)
+{
+	if (Candidate.x > max.x)
+		max.x = Candidate.x;
+	if (Candidate.y > max.y)
+		max.y = Candidate.y;
+	if (Candidate.z > max.z)
+		max.z = Candidate.z;
+}
+
+// Project the vector onto the YZ, XZ, or XY plane depending on which.
+// which      Coordinate plane to project onto
+// 0          YZ
+// 1          XZ
+// 2          XY
+// This function is used by the polygon intersection code.
+
+void SimpleVec::ExtractVerts(float *px, float *py, int which) const
+{
+	switch (which) {
+	case 0:
+		*px = y;
+		*py = z;
+		break;
+	case 1:
+		*px = x;
+		*py = z;
+		break;
+	case 2:
+		*px = x;
+		*py = y;
+		break;
+	}
+}
+
+// returns the axis, where the vector has the largest value
+int
+SimpleVec::DrivingAxis(void) const
+{
+	int axis = 0;
+	float val = fabs(x);
+
+	if (fabs(y) > val) {
+		val = fabs(y);
+		axis = 1;
+	}
+
+	if (fabs(z) > val)
+		axis = 2;
+
+	return axis;
+}
+
+
+// returns the axis, where the vector has the smallest value
+int SimpleVec::TinyAxis(void) const
+{
+	int axis = 0;
+	float val = fabs(x);
+
+	if (fabs(y) < val) {
+		val = fabs(y);
+		axis = 1;
+	}
+
+	if (fabs(z) < val)
+		axis = 2;
+
+	return axis;
+}
+
+
+bool SimpleVec::CheckValidity() const
+{
+#ifdef _WIN32
+	return !(_isnan(x) || _isnan(y) || _isnan(z));
+#else
+	return !(isnan(x) || isnan(y) || isnan(z));
+#endif  
+}
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleTri.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleTri.cpp	(revision 3234)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleTri.cpp	(revision 3234)
@@ -0,0 +1,41 @@
+#include "SimpleTri.h"
+
+
+using namespace std;
+
+
+SimpleTri::SimpleTri(const SimpleVec &a, const SimpleVec &b, const SimpleVec &c) 
+{
+	Init(a, b, c);
+}
+
+
+void SimpleTri::Init(const SimpleVec &a, const SimpleVec &b, const SimpleVec &c) 
+{
+	mVertices[0] = a;
+	mVertices[1] = b;
+	mVertices[2] = c;
+}
+
+
+SimpleVec SimpleTri::GetNormal() const 
+{
+	const SimpleVec v1 = mVertices[0] - mVertices[1];
+	const SimpleVec v2 = mVertices[2] - mVertices[1];
+
+	return Normalize(CrossProd(v2, v1));
+}
+
+
+SimpleVec SimpleTri::GetWorldCenter() const 
+{
+	return (mVertices[0] + mVertices[1] + mVertices[2]) / 3.0f;
+}
+
+
+float SimpleTri::GetArea() const 
+{
+	SimpleVec v1 = mVertices[0] - mVertices[1], v2=mVertices[2] - mVertices[1];
+	return 0.5f * Magnitude(CrossProd(v2, v1));
+}
+
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleVec.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleVec.h	(revision 3234)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleVec.h	(revision 3234)
@@ -0,0 +1,489 @@
+#ifndef _SimpleVec_h__
+#define _SimpleVec_h__
+
+
+#include <math.h>
+#include <vector>
+#include <iostream>
+
+
+/** Vector class.
+*/
+class SimpleVec
+{
+public:
+
+	///////////
+	//-- members;
+
+	float x; 
+	float y;
+	float z;
+
+
+	/////////////////////////
+
+	void  SetX(float q) { x = q; }
+	void  SetY(float q) { y = q; }
+	void  SetZ(float q) { z = q; }
+
+	float GetX() const { return x; }
+	float GetY() const { return y; }
+	float GetZ() const { return z; }
+
+
+	//////////////
+	//-- constructors
+
+	SimpleVec() { }
+
+	SimpleVec(float x, float y, float z): x(x), y(y), z(z)
+	{}
+
+	explicit SimpleVec(float v): x(v), y(v), z(v){}
+	/** Copy constructor.
+	*/
+	SimpleVec(const SimpleVec &v): x(v.x), y(v.y), z(v.z)
+	{}
+
+	// Functions to get at the std::vector components
+	float& operator[] (const int inx) 
+	{
+		return (&x)[inx];
+	}
+
+	operator const float*() const 
+	{ 
+		return (const float*) this; 
+	}
+
+	const float &operator[] (const int inx) const 
+	{
+		return *(&x + inx);
+	}
+
+	void ExtractVerts(float *px, float *py, int which) const;
+  
+	void SetValue(float a, float b, float c)
+	{  
+		x = a; y = b; z = c; 
+	}
+
+	void SetValue(float a) 
+	{ 
+		x = y = z = a; 
+	}
+ 
+	
+	/** Returns the axis, where the std::vector has the largest value.
+	*/
+	int DrivingAxis(void) const;
+	/** returns the axis, where the std::vector has the smallest value
+	*/
+	int TinyAxis(void) const;
+	/** Returns largest component in this vector
+	*/
+	inline float MaxComponent(void) const 
+	{
+		return (x > y) ? ( (x > z) ? x : z) : ( (y > z) ? y : z);
+	}
+	/** Returns copy of this vector where all components are positiv.
+	*/
+	inline SimpleVec Abs(void) const 
+	{
+		return SimpleVec(fabs(x), fabs(y), fabs(z));
+	}
+	/** normalizes the std::vector of unit size corresponding to given std::vector
+	*/
+	inline void Normalize();
+	/** Returns false if this std::vector has a nan component.
+	*/
+	bool CheckValidity() const;
+	/**
+	Find a right handed coordinate system with (*this) being
+	the z-axis. For a right-handed system, U x V = (*this) holds.
+	This implementation is here to avoid inconsistence and confusion
+	when construction coordinate systems using ArbitraryNormal():
+	In fact:
+	V = ArbitraryNormal(N);
+	U = CrossProd(V,N);
+	constructs a right-handed coordinate system as well, BUT:
+	1) bugs can be introduced if one mistakenly constructs a 
+	left handed sytems e.g. by doing
+	U = ArbitraryNormal(N);
+	V = CrossProd(U,N);
+	2) this implementation gives non-negative base vectors
+	for (*this)==(0,0,1) |  (0,1,0) | (1,0,0), which is
+	good for debugging and is not the case with the implementation
+	using ArbitraryNormal()
+
+	===> Using ArbitraryNormal() for constructing coord systems 
+	is obsoleted by this method (<JK> 12/20/03).   
+	*/
+	void RightHandedBase(SimpleVec& U, SimpleVec& V) const;
+	
+	
+	// Unary operators
+
+	SimpleVec operator+ () const;
+	SimpleVec operator- () const;
+
+	// Assignment operators
+	
+	SimpleVec& operator+= (const SimpleVec &A);
+	SimpleVec& operator-= (const SimpleVec &A);
+	SimpleVec& operator*= (const SimpleVec &A);
+	SimpleVec& operator*= (float A);
+	SimpleVec& operator/= (float A);
+
+	static inline SimpleVec UNIT_X() { return SimpleVec(1, 0, 0); }
+	static inline SimpleVec UNIT_Y() { return SimpleVec(0, 1, 0); }
+	static inline SimpleVec UNIT_Z() { return SimpleVec(0, 0, 1); }
+	static inline SimpleVec ZERO() { return SimpleVec(0, 0, 0); }
+
+
+	//////////
+	//-- friends
+	
+	/**
+	===> Using ArbitraryNormal() for constructing coord systems 
+	===> is obsoleted by RightHandedBase() method (<JK> 12/20/03).   
+
+	Return an arbitrary normal to `v'.
+	In fact it tries v x (0,0,1) an if the result is too small,
+	it definitely does v x (0,1,0). It will always work for
+	non-degenareted std::vector and is much faster than to use
+	TangentVectors.
+
+	@param v(in) The std::vector we want to find normal for.
+	@return The normal std::vector to v.
+	*/
+	friend inline SimpleVec ArbitraryNormal(const SimpleVec &v); 
+
+	/// Transforms a std::vector to the global coordinate frame.
+	/**
+	Given a local coordinate frame (U,V,N) (i.e. U,V,N are 
+	the x,y,z axes of the local coordinate system) and
+	a std::vector 'loc' in the local coordiante system, this
+	function returns a the coordinates of the same std::vector
+	in global frame (i.e. frame (1,0,0), (0,1,0), (0,0,1).
+	*/
+	friend inline SimpleVec ToGlobalFrame(const SimpleVec& loc,
+		                                const SimpleVec& U,
+										const SimpleVec& V,
+										const SimpleVec& N);
+
+	/// Transforms a std::vector to a local coordinate frame.
+	/**
+	Given a local coordinate frame (U,V,N) (i.e. U,V,N are 
+	the x,y,z axes of the local coordinate system) and
+	a std::vector 'loc' in the global coordiante system, this
+	function returns a the coordinates of the same std::vector
+	in the local frame.
+	*/
+	friend inline SimpleVec ToLocalFrame(const SimpleVec& loc,
+                                	   const SimpleVec& U,
+									   const SimpleVec& V,
+									   const SimpleVec& N);
+
+	/// the magnitude=size of the std::vector
+	friend inline float Magnitude(const SimpleVec &v);
+	/// the squared magnitude of the std::vector .. for efficiency in some cases
+	friend inline float SqrMagnitude(const SimpleVec &v);
+	/// Magnitude(v1-v2)
+	friend inline float Distance(const SimpleVec &v1, const SimpleVec &v2);
+	/// SqrMagnitude(v1-v2)
+	friend inline float SqrDistance(const SimpleVec &v1, const SimpleVec &v2);
+	/// creates the std::vector of unit size corresponding to given std::vector
+	friend inline SimpleVec Normalize(const SimpleVec &A);
+	
+
+	// construct view vectors .. DirAt is the main viewing direction
+	// Viewer is the coordinates of viewer location, UpL is the std::vector.
+	friend void ViewVectors(const SimpleVec &DirAt, 
+							const SimpleVec &Viewer,
+							const SimpleVec &UpL, 
+							SimpleVec &ViewV,
+							SimpleVec &ViewU, 
+							SimpleVec &ViewN);
+
+	// Given the intersection point `P', you have available normal `N'
+	// of unit length. Let us suppose the incoming ray has direction `D'.
+	// Then we can construct such two vectors `U' and `V' that
+	// `U',`N', and `D' are coplanar, and `V' is perpendicular
+	// to the vectors `N','D', and `V'. Then 'N', 'U', and 'V' create
+	// the orthonormal base in space R3.
+	friend void TangentVectors(SimpleVec &U, SimpleVec &V, // output
+							   const SimpleVec &normal, // input
+							   const SimpleVec &dirIncoming);
+
+
+	// Binary operators
+	
+	friend inline SimpleVec operator+ (const SimpleVec &A, const SimpleVec &B);
+	friend inline SimpleVec operator- (const SimpleVec &A, const SimpleVec &B);
+	friend inline SimpleVec operator* (const SimpleVec &A, const SimpleVec &B);
+	friend inline SimpleVec operator* (const SimpleVec &A, float B);
+	friend inline SimpleVec operator* (float A, const SimpleVec &B);
+	friend inline SimpleVec operator/ (const SimpleVec &A, const SimpleVec &B);
+
+	friend inline int operator< (const SimpleVec &A, const SimpleVec &B);
+	friend inline int operator<= (const SimpleVec &A, const SimpleVec &B);
+
+	friend inline SimpleVec operator/ (const SimpleVec &A, float B);
+	friend inline int operator== (const SimpleVec &A, const SimpleVec &B);
+	friend inline float DotProd(const SimpleVec &A, const SimpleVec &B);
+	friend inline SimpleVec CrossProd (const SimpleVec &A, const SimpleVec &B);
+
+	friend std::ostream& operator<< (std::ostream &s, const SimpleVec &A);
+	friend std::istream& operator>> (std::istream &s, SimpleVec &A);
+
+	friend void Minimize(SimpleVec &min, const SimpleVec &candidate);
+	friend void Maximize(SimpleVec &max, const SimpleVec &candidate);
+
+	friend inline int EpsilonEqualV3(const SimpleVec &v1, const SimpleVec &v2, float thr);
+	friend inline int EpsilonEqualV3(const SimpleVec &v1, const SimpleVec &v2);
+};
+
+
+inline SimpleVec ArbitraryNormal(const SimpleVec &N)
+{
+	float dist2 = N.x * N.x + N.y * N.y;
+
+	if (dist2 > 0.0001f) 
+	{
+		float inv_size = 1.0f / sqrtf(dist2);
+		return SimpleVec(N.y * inv_size, -N.x * inv_size, 0); // N x (0,0,1)
+	}
+
+	float inv_size = 1.0f / sqrtf(N.z * N.z + N.x * N.x);
+	return SimpleVec(-N.z * inv_size, 0, N.x * inv_size); // N x (0,1,0)
+}
+
+
+
+inline float Magnitude(const SimpleVec &v) 
+{
+	return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
+}
+
+
+inline float SqrMagnitude(const SimpleVec &v) 
+{
+	return v.x * v.x + v.y * v.y + v.z * v.z;
+}
+
+
+inline float Distance(const SimpleVec &v1, const SimpleVec &v2)
+{
+	//return sqrtf(sqrt(v1.x - v2.x) + sqrt(v1.y - v2.y) + sqrt(v1.z - v2.z));
+	return Magnitude(v1 - v2);
+}
+
+
+inline float SqrDistance(const SimpleVec &v1, const SimpleVec &v2)
+{
+	//return sqrt(v1.x - v2.x) + sqrt(v1.y - v2.y) + sqrt(v1.z - v2.z);
+	return SqrMagnitude(v1 - v2);
+}
+
+
+inline SimpleVec Normalize(const SimpleVec &A)
+{
+	return A * (1.0f / Magnitude(A));
+}
+
+
+inline float DotProd(const SimpleVec &A, const SimpleVec &B)
+{
+	return A.x * B.x + A.y * B.y + A.z * B.z;
+}
+
+
+// angle between two vectors with respect to a surface normal in the
+// range [0 .. 2 * pi]
+inline float Angle(const SimpleVec &A, const SimpleVec &B, const SimpleVec &norm)
+{
+	SimpleVec cross = CrossProd(A, B);
+
+	float signedAngle;
+
+	if (DotProd(cross, norm) > 0)
+		signedAngle = atan2(-Magnitude(CrossProd(A, B)), DotProd(A, B));
+	else
+		signedAngle = atan2(Magnitude(CrossProd(A, B)), DotProd(A, B));
+
+	if (signedAngle < 0)
+		return 2 * 3.145f + signedAngle;
+
+	return signedAngle;
+}
+
+
+inline SimpleVec SimpleVec::operator+() const
+{
+	return *this;
+}
+
+
+inline SimpleVec SimpleVec::operator-() const
+{
+  return SimpleVec(-x, -y, -z);
+}
+
+
+inline SimpleVec &SimpleVec::operator+=(const SimpleVec &A)
+{
+	x += A.x;  y += A.y;  z += A.z;
+	return *this;
+}
+
+
+inline SimpleVec& SimpleVec::operator-=(const SimpleVec &A)
+{
+	x -= A.x;  y -= A.y;  z -= A.z;
+	
+	return *this;
+}
+
+
+inline SimpleVec& SimpleVec::operator*= (float A)
+{
+	x *= A;  y *= A;  z *= A;
+	return *this;
+}
+
+
+inline SimpleVec& SimpleVec::operator/=(float A)
+{
+	float a = 1.0f / A;
+	
+	x *= a;  y *= a;  z *= a;
+	
+	return *this;
+}
+
+
+inline SimpleVec& SimpleVec::operator*= (const SimpleVec &A)
+{
+  x *= A.x;  y *= A.y;  z *= A.z;
+  return *this;
+}
+
+
+inline SimpleVec operator+ (const SimpleVec &A, const SimpleVec &B)
+{
+	return SimpleVec(A.x + B.x, A.y + B.y, A.z + B.z);
+}
+
+
+inline SimpleVec operator- (const SimpleVec &A, const SimpleVec &B)
+{
+	return SimpleVec(A.x - B.x, A.y - B.y, A.z - B.z);
+}
+
+
+inline SimpleVec operator* (const SimpleVec &A, const SimpleVec &B)
+{
+	return SimpleVec(A.x * B.x, A.y * B.y, A.z * B.z);
+}
+
+
+inline SimpleVec operator* (const SimpleVec &A, float B)
+{
+  return SimpleVec(A.x * B, A.y * B, A.z * B);
+}
+
+
+inline SimpleVec operator* (float A, const SimpleVec &B)
+{
+	return SimpleVec(B.x * A, B.y * A, B.z * A);
+}
+
+
+inline SimpleVec operator/ (const SimpleVec &A, const SimpleVec &B)
+{
+	return SimpleVec(A.x / B.x, A.y / B.y, A.z / B.z);
+}
+
+
+inline SimpleVec operator/ (const SimpleVec &A, float B)
+{
+	float b = 1.0f / B;
+	return SimpleVec(A.x * b, A.y * b, A.z * b);
+}
+
+
+inline int operator< (const SimpleVec &A, const SimpleVec &B)
+{
+	return A.x < B.x && A.y < B.y && A.z < B.z;
+}
+
+
+inline int operator<= (const SimpleVec &A, const SimpleVec &B)
+{
+	return A.x <= B.x && A.y <= B.y && A.z <= B.z;
+}
+
+
+// Might replace floating-point == with comparisons of
+// magnitudes, if needed.
+inline int operator== (const SimpleVec &A, const SimpleVec &B)
+{ 
+	return (A.x == B.x) && (A.y == B.y) && (A.z == B.z);
+}
+
+
+inline SimpleVec CrossProd (const SimpleVec &A, const SimpleVec &B)
+{
+	return SimpleVec(A.y * B.z - A.z * B.y,
+		           A.z * B.x - A.x * B.z,
+				   A.x * B.y - A.y * B.x);
+}
+
+
+inline void SimpleVec::Normalize()
+{
+	float sqrmag = x * x + y * y + z * z;
+	
+	if (sqrmag > 0.0f)
+		(*this) *= 1.0f / sqrtf(sqrmag);
+}
+
+
+// Overload << operator for C++-style output
+inline std::ostream& operator<< (std::ostream &s, const SimpleVec &A)
+{
+	return s << "(" << A.x << ", " << A.y << ", " << A.z << ")";
+}
+
+
+// Overload >> operator for C++-style input
+inline std::istream& operator>> (std::istream &s, SimpleVec &A)
+{
+	char a;
+	// read "(x, y, z)"
+	return s >> a >> A.x >> a >> A.y >> a >> A.z >> a;
+}
+
+
+inline int EpsilonEqualV3(const SimpleVec &v1, const SimpleVec &v2, float thr)
+{
+	if (fabsf(v1.x-v2.x) > thr)
+		return false;
+	if (fabsf(v1.y-v2.y) > thr)
+		return false;
+	if (fabsf(v1.z-v2.z) > thr)
+		return false;
+	
+	return true;
+}
+
+
+inline int EpsilonEqualV3(const SimpleVec &v1, const SimpleVec &v2)
+{
+	return EpsilonEqualV3(v1, v2, 1e-6f);
+}
+
+
+#endif
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/gzstream.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/gzstream.cpp	(revision 3234)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/gzstream.cpp	(revision 3234)
@@ -0,0 +1,175 @@
+// ============================================================================
+// gzstream, C++ iostream classes wrapping the zlib compression library.
+// Copyright (C) 2001  Deepak Bandyopadhyay, Lutz Kettner
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// ============================================================================
+//
+// File          : gzstream.C
+// Revision      : $Revision: 1.1 $
+// Revision_date : $Date: 2004/02/16 14:46:00 $
+// Author(s)     : Deepak Bandyopadhyay, Lutz Kettner
+// 
+// Standard streambuf implementation following Nicolai Josuttis, "The 
+// Standard C++ Library".
+// ============================================================================
+
+#include "gzstream.h"
+#include <string.h>  // for memcpy
+
+#ifdef GZSTREAM_NAMESPACE
+namespace GZSTREAM_NAMESPACE {
+#endif
+
+// ----------------------------------------------------------------------------
+// Internal classes to implement gzstream. See header file for user classes.
+// ----------------------------------------------------------------------------
+
+// --------------------------------------
+// class gzstreambuf:
+// --------------------------------------
+
+gzstreambuf*
+gzstreambuf::open( const char* name, int open_mode) {
+  if ( is_open() )
+    return (gzstreambuf*)0;
+  mode = open_mode;
+  // no append nor read/write mode
+  if ((mode & std::ios::ate) || (mode & std::ios::app)
+      || ((mode & std::ios::in) && (mode & std::ios::out)))
+    return (gzstreambuf*)0;
+  char fmode[10];
+  char* fmodeptr = fmode;
+  if ( mode & std::ios::in)
+    *fmodeptr++ = 'r';
+  else
+    if ( mode & std::ios::out)
+      *fmodeptr++ = 'w';
+  *fmodeptr++ = 'b';
+  *fmodeptr = '\0';
+  file = gzopen( name, fmode);
+  if (file == 0)
+    return (gzstreambuf*)0;
+  opened = 1;
+  return this;
+}
+  
+gzstreambuf *
+gzstreambuf::close() {
+  if ( is_open()) {
+    sync();
+    opened = 0;
+    if ( gzclose( file) == Z_OK)
+      return this;
+  }
+  return (gzstreambuf*)0;
+}
+  
+int
+gzstreambuf::underflow() { // used for input buffer only
+  if ( gptr() && ( gptr() < egptr()))
+    return * reinterpret_cast<unsigned char *>( gptr());
+  
+  if ( ! (mode & std::ios::in) || ! opened)
+    return EOF;
+  // Josuttis' implementation of inbuf
+  int n_putback = gptr() - eback();
+  if ( n_putback > 4)
+    n_putback = 4;
+  memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
+  
+  int num = gzread( file, buffer+4, gzbufferSize-4);
+  if (num <= 0) // ERROR or EOF
+    return EOF;
+  
+  // reset buffer pointers
+  setg( buffer + (4 - n_putback),   // beginning of putback area
+	buffer + 4,                 // read position
+	buffer + 4 + num);          // end of buffer
+  
+  // return next character
+  return * reinterpret_cast<unsigned char *>( gptr());    
+}
+  
+int
+gzstreambuf::flush_buffer() {
+  // Separate the writing of the buffer from overflow() and
+  // sync() operation.
+  int w = pptr() - pbase();
+  if ( gzwrite( file, pbase(), w) != w)
+    return EOF;
+  pbump( -w);
+  return w;
+}
+  
+int
+gzstreambuf::overflow( int c) { // used for output buffer only
+  if ( ! ( mode & std::ios::out) || ! opened)
+    return EOF;
+  if (c != EOF) {
+    *pptr() = c;
+    pbump(1);
+  }
+  if ( flush_buffer() == EOF)
+    return EOF;
+  return c;
+}
+  
+int
+gzstreambuf::sync() {
+  // Changed to use flush_buffer() instead of overflow( EOF)
+  // which caused improper behavior with std::endl and flush(),
+  // bug reported by Vincent Ricard.
+  if ( pptr() && pptr() > pbase()) {
+    if ( flush_buffer() == EOF)
+      return -1;
+  }
+  return 0;
+}
+  
+  
+  // --------------------------------------
+  // class gzstreambase:
+// --------------------------------------
+
+gzstreambase::gzstreambase( const char* name, int mode)
+{
+  init( &buf);
+  open( name, mode);
+}
+  
+  gzstreambase::~gzstreambase()
+  {
+    buf.close();
+  }
+  
+  void
+  gzstreambase::open( const char* name, int open_mode) {
+    if ( ! buf.open( name, open_mode))
+      clear( rdstate() | std::ios::badbit);
+}
+
+void gzstreambase::close() {
+    if ( buf.is_open())
+        if ( ! buf.close())
+            clear( rdstate() | std::ios::badbit);
+}
+
+#ifdef GZSTREAM_NAMESPACE
+} // namespace GZSTREAM_NAMESPACE
+#endif
+
+// ============================================================================
+// EOF //
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleTri.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleTri.h	(revision 3234)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/SimpleTri.h	(revision 3234)
@@ -0,0 +1,53 @@
+#ifndef __SIMPLETRI_H
+#define __SIMPLETRI_H
+
+#include <iostream>
+#include "SimpleVec.h"
+
+
+struct SimpleTri 
+{
+	SimpleTri() {};
+	SimpleTri(const SimpleVec &a, const SimpleVec &b, const SimpleVec &c);
+
+	void Init(const SimpleVec &a, const SimpleVec &b, const SimpleVec &c);
+
+	SimpleVec GetNormal() const;
+
+	SimpleVec GetWorldCenter() const;
+
+	float GetSpatialAngle(const SimpleVec &point) const;
+
+	float GetArea() const;
+	
+	  
+	friend std::ostream& operator<< (std::ostream &s, const SimpleTri &A);
+	friend std::istream& operator>> (std::istream &s, SimpleTri &A);
+
+
+	///////////////////
+
+	/// the triangle vertices
+	SimpleVec mVertices[3];
+};
+
+
+// Overload << operator for C++-style output
+inline std::ostream&
+operator<< (std::ostream &s, const SimpleTri &A)
+{
+  return s << "(" << A.mVertices[0] << ", " << A.mVertices[1] << ", " << A.mVertices[2] << ")";
+}
+
+// Overload >> operator for C++-style input
+inline std::istream&
+operator>> (std::istream &s, SimpleTri &A)
+{
+  char a;
+  // read "(x, y, z)"
+  return s >> a >> A.mVertices[0] >> a >> A.mVertices[1] >> a >> A.mVertices[2] >> a;
+}
+
+
+#endif
+
