Index: /GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj	(revision 734)
+++ /GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj	(revision 752)
@@ -20,5 +20,5 @@
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\support;..\support\devil\include;..\support\zlib\include;..\include..\support;&quot;..\include  ..\support&quot;;..\include;&quot;$(QTDIR)\include\QtCore&quot;;&quot;$(CG_INC_PATH)&quot;;&quot;$(QTDIR)\include&quot;;&quot;$(QTDIR)\include\QtOpenGl&quot;;&quot;$(QTDIR)\include\QtGui&quot;;&quot;$(GTPDIR)\NonGTP\Zlib\include&quot;;..\..\..\..\..\..\NonGTP\Xerces;..\..\..\..\..\..\NonGTP\Devil\include"
+				AdditionalIncludeDirectories="..\support;..\support\devil\include;..\support\zlib\include;..\include..\support;&quot;..\include  ..\support&quot;;..\include;&quot;$(QTDIR)\include\QtCore&quot;;&quot;$(CG_INC_PATH)&quot;;&quot;$(QTDIR)\include&quot;;&quot;$(QTDIR)\include\QtOpenGl&quot;;&quot;$(QTDIR)\include\QtGui&quot;;&quot;$(GTPDIR)\NonGTP\Zlib\include&quot;;..\..\..\..\..\..\NonGTP\Xerces;..\..\..\..\..\..\NonGTP\Devil\include;..\src"
 				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
 				MinimalRebuild="TRUE"
@@ -250,4 +250,16 @@
 			</File>
 			<File
+				RelativePath="..\src\ply.h">
+			</File>
+			<File
+				RelativePath="..\src\plyfile.c">
+			</File>
+			<File
+				RelativePath="..\src\PlyParser.cpp">
+			</File>
+			<File
+				RelativePath="..\src\PlyParser.h">
+			</File>
+			<File
 				RelativePath="..\src\Polygon3.cpp">
 			</File>
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 746)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 752)
@@ -18,5 +18,4 @@
 {
 public:
-	//bool operator() (HierarchyNode *v1, HierarchyNode *v2) const
 	bool operator() (T v1, T v2) const
 	{
@@ -39,13 +38,12 @@
 
 // pvs penalty can be different from pvs size
-inline float EvalPvsPenalty(const int pvs, const int lower, const int upper)
+inline static float EvalPvsPenalty(const int pvs, const int lower, const int upper)
 {
 	// clamp to minmax values
-#if HAS_TO_BE_REDONE
 	if (pvs < lower)
 		return (float)lower;
 	if (pvs > upper)
 		return (float)upper;
-#endif
+
 	return (float)pvs;
 }
@@ -70,5 +68,5 @@
 
 /// Fast computation of merged pvs size
-int ComputeMergedPvsSize(const ObjectPvs &pvs1, const ObjectPvs &pvs2)
+static int ComputeMergedPvsSize(const ObjectPvs &pvs1, const ObjectPvs &pvs2)
 {
 	// add first pvs
@@ -99,5 +97,6 @@
 
 // computet render cost of merge
-float ViewCellsTree::ComputeMergedPvsCost(const ObjectPvs &pvs1, const ObjectPvs &pvs2) const
+float ViewCellsTree::ComputeMergedPvsCost(const ObjectPvs &pvs1, 
+										  const ObjectPvs &pvs2) const
 {
 	float renderCost = 0;
@@ -143,5 +142,7 @@
 mParent(NULL),
 mMergeCost(0),
-mIsActive(false)
+mIsActive(false),
+mPvsSize(0),
+mPvsSizeValid(false)
 {
 }
@@ -156,5 +157,7 @@
 mMergeCost(0),
 mIsActive(false),
-mLastUpdated(sLastUpdated)
+mLastUpdated(sLastUpdated),
+mPvsSize(0),
+mPvsSizeValid(false)
 {
 }
@@ -165,4 +168,5 @@
 	return mPvs;
 }
+
 
 ObjectPvs &ViewCell::GetPvs()
@@ -205,4 +209,16 @@
 {
 	mArea = area;
+}
+
+
+void ViewCell::SetColor(const RgbColor &color) 
+{
+	mColor = color;
+}
+
+
+RgbColor ViewCell::GetColor() const 
+{
+	return mColor;
 }
 
@@ -367,5 +383,9 @@
 mUseAreaForPvs(false),
 mViewCellsManager(vcm),
-mIsCompressed(false)
+#if 0
+mViewCellsStorage(PVS_IN_INTERIORS)
+#else
+mViewCellsStorage(PVS_IN_LEAVES)
+#endif
 {
 	environment->GetBoolValue("ViewCells.Visualization.exportMergedViewCells", mExportMergedViewCells);
@@ -393,4 +413,5 @@
 float ViewCellsTree::GetMemUsage() const
 {
+	// TODO
 	return 0;
 		/*(sizeof(ViewCellsTree) +
@@ -513,10 +534,9 @@
 	// we start with the current view cells from the view cell manager. 
 	// The active view cells will change with subsequent merges
-	Debug << "here2" << endl; Debug.flush();
+	
 	// todo: should rather take initial view cells
     ViewCellContainer &activeViewCells = mViewCellsManager->GetViewCells();
-	//ViewCellContainer activeViewCells;
-	
-	Debug << "here2.6" << endl; Debug.flush();
+	
+	
 	ViewCell::NewMail();
 
@@ -704,5 +724,9 @@
 		Debug << "setting root of the merge history" << endl;
 		mRoot = activeViewCells[0];
-		Debug << "rootvc volume: " << mRoot->GetVolume() << endl;
+		Debug << "volume of the root view cell: " << mRoot->GetVolume() << " " << mViewCellsManager->GetViewSpaceBox().GetVolume() << endl;
+	}
+	else
+	{
+		Debug << "big error, root is NULL" << endl;
 	}
 	
@@ -803,5 +827,5 @@
 			swap(viewCells[i], viewCells.back());
 		
-		// mail view cell as it has not been merged
+		// mail view cell that it has not been merged
 		viewCells[i]->Mail();
 
@@ -814,4 +838,5 @@
 	// merged in the mean time
 	ViewCellContainer::const_iterator ait, ait_end = mMergedViewCells.end();
+
 	for (ait = mMergedViewCells.begin(); ait != ait_end; ++ ait)
 	{
@@ -825,4 +850,5 @@
 	}
 
+	// dispose old merged view cells
 	mMergedViewCells.clear();
 
@@ -836,4 +862,5 @@
 		const int lower = mViewCellsManager->GetMinPvsSize();
 		const int upper = mViewCellsManager->GetMaxPvsSize();
+
 		const float penalty = EvalPvsPenalty((*vit)->GetPvs().GetSize(), lower, upper);
 		
@@ -905,4 +932,5 @@
 	if (!vc) return NULL;
 
+	// set to the new parent view cell
 	l->SetParent(vc);
 	r->SetParent(vc);
@@ -932,7 +960,26 @@
 	pvsDiff = vc->GetPvs().GetSize() - pvs1 - pvs2;
 
+
+
+	//Ždon't store intermediate pvs
+	if (mViewCellsStorage == PVS_IN_LEAVES)
+	{
+		l->mPvsSize = l->GetPvs().GetSize(); 
+		l->mPvsSizeValid = true;
+		
+		if (!l->IsLeaf())
+			l->GetPvs().Clear();
+		
+		r->mPvsSize = r->GetPvs().GetSize(); 
+		r->mPvsSizeValid = true;
+		
+		if (!r->IsLeaf())
+			r->GetPvs().Clear();
+	
+}
+
+
 	return vc;
 }
-
 
 
@@ -1189,6 +1236,8 @@
 	if (1)
 	{
-		const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
-		return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
+		const float penalty = 
+			EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
+		return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) / 
+			(float)mNumActiveViewCells;
 	}
 
@@ -1233,4 +1282,5 @@
 bool ViewCellsTree::ValidateMergeCandidate(MergeCandidate &mc) const
 {
+	// propagate up so we have only the active view cells
 	while (mc.mLeftViewCell->mParent)
 	{
@@ -1243,4 +1293,6 @@
 	}
 
+	// this view cell was already merged
+	//return mc.mLeftViewCell && (mc.mLeftViewCell != mc.mRightViewCell);
 	return mc.mLeftViewCell != mc.mRightViewCell;
 }
@@ -1250,12 +1302,9 @@
 {
 	//-- compute pvs difference
-	const float newPvs = 
-#if 1 // not valid if not using const cost per object!!
-		ComputeMergedPvsSize(mc.mLeftViewCell->GetPvs(), 
-							 mc.mRightViewCell->GetPvs());
-#else
-		ComputeMergedPvsCost(mc.mLeftViewCell->GetPvs(), 
-							 mc.mRightViewCell->GetPvs());
-#endif
+	int newPvs;
+	if (1) // not valid if not using const cost per object!!
+		newPvs = ComputeMergedPvsSize(mc.mLeftViewCell->GetPvs(), mc.mRightViewCell->GetPvs());
+	else
+		newPvs = (int)ComputeMergedPvsCost(mc.mLeftViewCell->GetPvs(), mc.mRightViewCell->GetPvs());
 
 	const float newPenalty = EvalPvsPenalty(newPvs,
@@ -1305,12 +1354,23 @@
 }
 
-void ViewCellsTree::CompressViewCellsPvs()
-{
-	if (!mIsCompressed)
-	{
-		mIsCompressed = true;
+
+void ViewCellsTree::SetViewCellsStorage(int stype)
+{
+	if (mViewCellsStorage == stype)
+		return;
+
+	// TODO
+	switch (stype)
+	{
+	case COMPRESSED:
 		CompressViewCellsPvs(mRoot);
-	}
-}
+		break;
+	default:
+		break;
+	}
+
+	mViewCellsStorage = stype;
+}
+
 
 void ViewCellsTree::CompressViewCellsPvs(ViewCell *root)
@@ -1344,7 +1404,9 @@
 	const float vol = box.GetVolume();
 
+	const int rootPvs = GetPvsSize(mRoot);
+
 	Debug << "vsb volume: " << vol << endl;
 	Debug << "root volume: " << mRoot->GetVolume() << endl;
-	Debug << "root pvs: " << mRoot->GetPvs().GetSize() << endl;
+	Debug << "root pvs: " << rootPvs << endl;
 
 	int totalPvs;
@@ -1352,10 +1414,11 @@
 
 	float deviation = 0;
-	totalPvs = (int)mRoot->GetPvs().GetSize();
-	totalRenderCost = avgRenderCost = expectedCost = (float)mRoot->GetPvs().GetSize();
+	totalPvs = rootPvs;
+	totalRenderCost = avgRenderCost = expectedCost = (float)rootPvs;
 
 	ofstream stats;
 	stats.open(mergeStats.c_str());
 
+	//-- first view cell
 	stats 
 		<< "#Pass\n" << 0 << endl
@@ -1364,5 +1427,5 @@
         << "#RenderCostDecrease\n" << 0 << endl // TODO
 		<< "#TotalRenderCost\n" << totalRenderCost << endl
-		<< "#CurrentPvs\n" << mRoot->GetPvs().GetSize() << endl
+		<< "#CurrentPvs\n" << rootPvs << endl
 		<< "#ExpectedCost\n" << expectedCost << endl
 		<< "#AvgRenderCost\n" << avgRenderCost << endl
@@ -1383,5 +1446,5 @@
 			ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
 			
-			const int parentPvs = interior->GetPvs().GetSize();
+			const int parentPvs = GetPvsSize(interior);
 			const float parentCost = (float)parentPvs * interior->GetVolume();
 			float childCost = 0;
@@ -1394,6 +1457,7 @@
 			for (it = interior->mChildren.begin(); it != it_end; ++ it)
 			{
-				childCost += (float)(*it)->GetPvs().GetSize() * (*it)->GetVolume();
-				childPvs += (*it)->GetPvs().GetSize();
+				int pvsSize = GetPvsSize(*it);
+				childCost += (float) pvsSize * (*it)->GetVolume();
+				childPvs += pvsSize;
 
 				tqueue.push(*it);
@@ -1416,5 +1480,5 @@
 				<< "#RenderCostDecrease\n" << costDecr << endl // TODO
 				<< "#TotalRenderCost\n" << totalRenderCost << endl
-				<< "#CurrentPvs\n" << vc->GetPvs().GetSize() << endl
+				<< "#CurrentPvs\n" << parentPvs << endl
 				<< "#ExpectedCost\n" << expectedCost << endl
 				<< "#AvgRenderCost\n" << avgRenderCost << endl
@@ -1432,30 +1496,4 @@
 
 
-#if 0
-float ViewCellsTree::ComputeVolume(ViewCell *vc)
-{
-	if (vc->IsLeaf())
-	{
-		return vc->GetVolume();
-	}
-	else
-	{
-		ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
-
-		ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
-
-		float volume = 0;
-
-		for (it = interior->mChildren.begin(); it != it_end; ++ it)
-		{
-			volume += ComputeVolume(*it);	
-		}
-
-		interior->SetVolume(volume);
-		return volume;
-	}
-}
-#endif
-
 void ViewCellsTree::SetRoot(ViewCell *root)
 {
@@ -1558,19 +1596,19 @@
 	}
 
-	int dummy = interior->GetPvs().GetSize();
+	/*int dummy = interior->GetPvs().GetSize();
 
 	for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
 	{
 		dummy += (*cit)->GetPvs().GetSize();
-	}
-
-}
-
-
+	}*/
+
+}
+
+// TODO
 void ViewCellsTree::GetPvs(ViewCell *vc, ObjectPvs &pvs) const
 {
 	Intersectable::NewMail();
 
-	if (!mIsCompressed)
+	if (mViewCellsStorage == PVS_IN_INTERIORS)
 		pvs = vc->GetPvs();
 
@@ -1612,13 +1650,62 @@
 int ViewCellsTree::GetPvsSize(ViewCell *vc) const
 {
+	int pvsSize = 0;
+
+	if (vc->IsLeaf())
+	{
+		pvsSize = vc->GetPvs().GetSize();
+	}
+	
+
 	Intersectable::NewMail();
 
-	if (!mIsCompressed)
-		return vc->GetPvs().GetSize();
-
-
-	////////////////////////777
+	//////////////////////////
+	switch (mViewCellsStorage)
+	{
+	case PVS_IN_LEAVES: //-- store pvs only in leaves
+		{			
+			if (vc->mPvsSizeValid)
+			{
+				pvsSize = vc->mPvsSize;
+				break;
+			}
+	
+			//-- if no valid pvs size stored as a scalar=> compute new pvs size
+			ViewCellContainer leaves;
+			CollectLeaves(vc, leaves);
+
+			ViewCellContainer::const_iterator it, it_end = leaves.end();
+
+			Intersectable::NewMail();
+
+			// sum different intersectables
+			for (it = leaves.begin(); it != it_end; ++ it)
+			{
+				ObjectPvsMap::iterator oit, oit_end = (*it)->GetPvs().mEntries.end();
+
+				// mail all from first pvs
+				for (oit = (*it)->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
+				{
+					Intersectable *intersect = (*oit).first;
+
+					if (!intersect->Mailed())
+					{
+						++ pvsSize;
+						intersect->Mail();					
+					}
+				}
+			}
+
+			break;
+		}
+	case COMPRESSED:
+		{
+			////////////////////////
 	//-- compressed pvs
 
+			if (vc->mPvsSizeValid)
+				return vc->mPvsSize;
+
+			// if no pvs size stored: compute
 	int pvsSize = 0;
 	ViewCell *root = vc;
@@ -1653,7 +1740,12 @@
 		}
 	}
+			break;
+		}
+	case PVS_IN_INTERIORS:
+	default:Debug << "in interiors: " << vc->mPvsSize << " $$ " << vc->GetPvs().GetSize() << endl;
+		pvsSize = vc->GetPvs().GetSize();		
+	}
 
 	return pvsSize;  
-
 }
 
@@ -1672,6 +1764,8 @@
 	int pvsSize = 0;
 	// only count leaves for uncompressed method for fairness
-	if (mIsCompressed || vc->IsLeaf())
+	if ((mViewCellsStorage == PVS_IN_INTERIORS) || vc->IsLeaf())
+	{
 		pvsSize = vc->GetPvs().GetSize();
+	}
 
 	if (!vc->IsLeaf())
@@ -1691,7 +1785,7 @@
 
 
-bool ViewCellsTree::IsCompressed() const
-{
-	return mIsCompressed;
+int ViewCellsTree::ViewCellsStorage() const
+{
+	return mViewCellsStorage;
 }
 
@@ -1845,9 +1939,4 @@
 	if (!vc->GetValid())
 		++ vcStat.invalid;
-
-	/*ViewCellsContainer leaves;
-	CollectLeaves(vc, leaves);
-
-	vcStat.leaves = (int)leaves.size();*/
 }
 
@@ -1969,4 +2058,5 @@
 void ViewCellsTree::SetActiveSetToLeaves()
 {
+	// todo
 }
 
@@ -2026,4 +2116,5 @@
 bool MergeCandidate::IsValid() const
 {
+	// if one has a parent, it was already merged
 	return !(mLeftViewCell->mParent || mRightViewCell->mParent);
 }
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.cpp	(revision 726)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.cpp	(revision 752)
@@ -100,7 +100,8 @@
   string element(lname.LocalForm());
   
+  // only create new mesh instance if define mechanism was not used
   if (element == "Shape")
     EndShape();
-  if (1)
+
   if (element == "Transform")
 	  EndTransform();
@@ -138,4 +139,7 @@
 
 	const int len = attributes.getLength();
+    Matrix4x4 *rotm = NULL;
+	Matrix4x4 *scalem = NULL;
+	Matrix4x4 *translm = NULL;
     
 	for (int i = 0; i < len; ++ i) 
@@ -153,6 +157,5 @@
 			if (sscanf(ptr, "%f %f %f %f", &axis.x, &axis.y, &axis.z, &angle) == 4)
 			{
-				Matrix4x4 rot = RotationAxisMatrix(axis, angle);
-				currentTransform *= rot;
+				rotm = new Matrix4x4(RotationAxisMatrix(axis, angle));
 			}
 		}
@@ -163,11 +166,30 @@
 			if (sscanf(ptr, "%f %f %f %f", &transl.x, &transl.y, &transl.z) == 3)
 			{
-				Matrix4x4 tm = TranslationMatrix(transl);
-
-				currentTransform *= tm;
+				translm = new Matrix4x4(TranslationMatrix(transl));
 			}
 		}
+		else if (attrName == "scale")
+		{
+			Vector3 scale;
+
+			if (sscanf(ptr, "%f %f %f %f", &scale.x, &scale.y, &scale.z) == 3)
+			{
+				scalem = new Matrix4x4(ScaleMatrix(scale.x, scale.y, scale.z));
+			}
+		}
+		// todo: scale orientation
 	}
 	
+	if (scalem)
+		currentTransform *= (*scalem);
+	if (rotm)
+		currentTransform *= (*rotm);
+	if (translm)
+		currentTransform *= (*translm);
+
+	DEL_PTR(scalem);
+	DEL_PTR(rotm);
+	DEL_PTR(translm);
+
 	mTransformations.push(currentTransform);
 }
@@ -180,10 +202,21 @@
 
 
-void
-X3dParseHandlers::EndShape()
-{
+void X3dParseHandlers::EndShape()
+{
+	// this shape is a definition => don't create mesh instance
+	if (mIsMeshDefinition) 
+{
+		mMeshDefinitions[mCurrentMeshName.c_str()] = mCurrentMesh;
+		//cout << "new definition: " << mCurrentMeshName << endl;
+		
+		return;
+	}
+
+	// each polygon is one single mesh
 	if (mLoadPolygonsAsMeshes)
 	{
-		vector<VertexIndexContainer>::const_iterator it, it_end = mCurrentVertexIndices.end();
+		
+		/*vector<VertexIndexContainer>::const_iterator it, 
+			it_end = mCurrentVertexIndices.end();
 
 		for (it = mCurrentVertexIndices.begin(); it != it_end; ++ it)
@@ -211,13 +244,55 @@
 			mCurrentNode->mGeometry.push_back(mi);
 
-		}
-
-		delete mCurrentMesh;
-		mCurrentVertices.clear();
-		mCurrentVertexIndices.clear();
+		}*/
+
+		//if (mCurrentMesh->mFaces.empty())	cout << "error!" << endl;
+
+		FaceContainer::const_iterator fit, fit_end = mCurrentMesh->mFaces.end();
+
+		cout << "m";
+		//cout << "m: " << mCurrentMesh->mFaces.size() << endl;
+		for (fit = mCurrentMesh->mFaces.begin(); fit != fit_end; ++ fit)
+		{
+			cout << "f";
+
+			Face *face = *fit;
+			// only one face per mesh
+			Mesh *mesh = new Mesh();
+			VertexIndexContainer vc;
+					
+			VertexIndexContainer::const_iterator vit, vit_end = face->mVertexIndices.end();
+			
+			int i = 0;
+			for (vit = face->mVertexIndices.begin(); vit != vit_end; ++ vit, ++ i)
+			{
+				cout << "i";
+				int index = (*vit);
+				// add vertices
+				mesh->mVertices.push_back(mCurrentMesh->mVertices[index]);
+				vc.push_back(i);
+			}
+
+			mesh->mFaces.push_back(new Face(vc));
+
+			// NOTE: should rather be written into trafo of mesh instance
+			ApplyTransformations(mTransformations, mesh);
+
+			mesh->Preprocess();
+				
+			// make an instance of this mesh
+			MeshInstance *mi = new MeshInstance(mesh);
+			mCurrentNode->mGeometry.push_back(mi);
+		}
+
+		// LEAK!! TODO: delete if not defd
+		if (!mUsingMeshDefinition)
+			delete mCurrentMesh;
+
+		//mCurrentVertices.clear();
+		//mCurrentVertexIndices.clear();
 	}
 	else
 	{ 
-		if (mCurrentMesh->mFaces.size()) 
+		if (!mCurrentMesh->mFaces.empty()) 
 		{
 			// should rather be written into the transformation
@@ -228,4 +303,5 @@
 			// make an instance of this mesh
 			MeshInstance *mi = new MeshInstance(mCurrentMesh);
+
 			mCurrentNode->mGeometry.push_back(mi);
 			// set the object id to a unique value
@@ -234,5 +310,7 @@
 		else 
 		{
+			// empty mesh => discard
 			cout<<"X";
+
 			delete mCurrentMesh;
 		}
@@ -243,48 +321,79 @@
 
 
-void
-X3dParseHandlers::StartIndexedFaceSet(
-									  AttributeList&  attributes)
+void X3dParseHandlers::StartIndexedFaceSet(AttributeList&  attributes)
 {
   int len = attributes.getLength();
+
   int i;
   VertexIndexContainer vertices;
   
-  for (i=0; i < len; i++) {
-    string attrName(StrX(attributes.getName(i)).LocalForm());
-    if (attrName == "coordIndex") {
-      StrX attrValue(attributes.getValue(i));
-      // handle coordIndex
-      vertices.clear();
-      const char *ptr = attrValue.LocalForm();
-      char *endptr;
-      while(1) {
-	int index = strtol(ptr, &endptr, 10);
-	if (ptr == endptr || index == -1) {
-	  if (vertices.size() > 2) {
-		  Face *face = new Face(vertices);
-
-		   if (!mLoadPolygonsAsMeshes)
-		   {
-			   mCurrentMesh->mFaces.push_back(face);
-		   }
-		   else
-		   // every polygon is a mesh
-		   {
-			   mCurrentVertexIndices.push_back(vertices);
-		   }
-	  }
-
-	  vertices.clear();
-	  if (ptr == endptr)
-	    break;
-	} else {
-	  vertices.push_back(index);
-	}
-	ptr = endptr;
-	  }
-    }
-  }
-}
+	mIsMeshDefinition = false;
+	mUsingMeshDefinition = false;
+	for (i = 0; i < len; ++ i) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+	  
+		// this is a definition of a mesh
+		if (attrName == "DEF")
+		{
+			mIsMeshDefinition = true;
+			StrX attrValue(attributes.getValue(i));
+			const char *ptr = attrValue.LocalForm();
+			mCurrentMeshName = ptr;
+
+			cout << "d";
+		}
+		
+		// we use an already defined mesh
+		if (attrName == "USE")
+		{
+			StrX attrValue(attributes.getValue(i));
+
+			// discard new mesh and assign defined mesh
+			DEL_PTR(mCurrentMesh);
+			const char *ptr = attrValue.LocalForm();
+
+			mCurrentMesh = mMeshDefinitions[ptr];
+			mUsingMeshDefinition = true;
+			cout << "u";
+		}
+		
+		if (attrName == "coordIndex") 
+		{
+			StrX attrValue(attributes.getValue(i));
+			// handle coordIndex
+			vertices.clear();
+			const char *ptr = attrValue.LocalForm();
+		  
+			char *endptr;
+	  
+			while (1) 
+			{
+				int index = strtol(ptr, &endptr, 10);
+				  
+				if (ptr == endptr || index == -1) 
+				{
+					if (vertices.size() > 2) 
+					{
+						Face *face = new Face(vertices);                 
+						mCurrentMesh->mFaces.push_back(face);
+					} 
+			  
+					vertices.clear();
+		  
+					if (ptr == endptr)
+						break;
+			  
+				  } 
+				  else 
+				  {
+					  vertices.push_back(index);
+				  }
+				  ptr = endptr;
+			}
+		}
+	}
+}
+
 
 void
@@ -358,12 +467,6 @@
 				vertices.push_back(v);
 			}
-			if (mLoadPolygonsAsMeshes)
-			{
-				mCurrentVertices = vertices;
-			}
-			else
-			{
-				mCurrentMesh->mVertices = vertices;
-			}
+			
+			mCurrentMesh->mVertices = vertices;
 		}
 	}
@@ -388,5 +491,6 @@
   }
   
-  if (element == "Coordinate") {
+  if (element == "Coordinate") 
+  {
     if (mCurrentMesh)
       StartCoordinate(attributes);
@@ -396,5 +500,5 @@
     StartMaterial(attributes);
   }
-if (1)
+  
   if (element == "Transform") {
 	  StartTransform(attributes);
@@ -599,4 +703,5 @@
 X3dViewCellsParseHandlers::EndShape()
 {
+	// currently processing no shape
 }
 
@@ -607,10 +712,14 @@
 	int len = attributes.getLength();
 	int i;
+	
 	// clear previous vertex indices
 	mCurrentVertexIndices.clear();
+
+
 	for (i=0; i < len; i++) 
 	{
 		string attrName(StrX(attributes.getName(i)).LocalForm());
 	    
+
 		if (attrName == "coordIndex") 
 		{
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 713)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 752)
@@ -90,5 +90,7 @@
   */
   int AddPvs(const Pvs<T> &pvs);
+
   /** Subtracts one pvs from another one.
+  WARNING: could contains bugs
 	  @returns new pvs size
   */
@@ -113,4 +115,8 @@
 									  float &pvsEnlargement);
   
+
+  /** Clears the pvs.
+  */
+  void Clear();
 
   /** Compute continuous PVS difference */
@@ -237,4 +243,12 @@
 }
 
+template <typename T> void Pvs<T>::Clear()
+{
+	mEntries.clear();
+	
+
+}
+
+
 template <typename T>
 PvsData<T> *Pvs<T>::Find(T sample)
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Polygon3.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Polygon3.h	(revision 750)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Polygon3.h	(revision 752)
@@ -12,5 +12,5 @@
 class Polygon3;
 class Plane3;
-class Face;
+struct Face;
 class Intersectable;
 class AxisAlignedBox3;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/UnigraphicsParser.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/UnigraphicsParser.cpp	(revision 750)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/UnigraphicsParser.cpp	(revision 752)
@@ -96,5 +96,5 @@
       cout<<"+";
       vector<Vector3> vertices;
-      vector<int> vertexIndices;
+      VertexIndexContainer vertexIndices;
 
       /* face */
@@ -133,6 +133,6 @@
       int index = (int)currentMesh->mVertices.size();
       for (i=0; i < vertices.size(); i++, index++) {
-	currentMesh->mVertices.push_back(vertices[i]);
-	vertexIndices.push_back(index);
+		currentMesh->mVertices.push_back(vertices[i]);
+		vertexIndices.push_back(index);
       }
       
@@ -184,5 +184,4 @@
   fclose(file);
   
-  
   *proot = root;
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 746)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 752)
@@ -41,8 +41,4 @@
   ViewCell *mViewCell;
 
-  //ViewCellContainer mViewCells;
-  /// aggregated pvs
-  //ObjectPvs mPvs;
-
   // input parameter is the render budget for the PrVS
   float mRenderBudget;
@@ -501,4 +497,8 @@
 	void CreateClipPlane();
 
+	virtual void UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs) = 0;
+
+
+
 	Plane3 mClipPlane;
 	bool mUseClipPlaneForViz;
@@ -633,6 +633,11 @@
 	bool ExportViewCells(const string filename);
 
+	/** Constructs merge hierarchy which corresponds to the spatial hierarchy.
+	*/
 	ViewCell *ConstructSpatialMergeTree(BspNode *root);
 
+	/** Updates the pvs in the view cells tree.
+	*/
+	void UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs);
 
 protected:
@@ -713,6 +718,8 @@
 								vector<MergeCandidate> &candidates);
 
+
 protected:
 
+	virtual void UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs) {};
 	/** Collects view cells from a hierarchy.
 	*/
@@ -778,4 +785,5 @@
 	void CollectMergeCandidates(const VssRayContainer &rays, vector<MergeCandidate> &candidates);
 
+	virtual void UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs) {};
 protected:
 
@@ -886,8 +894,16 @@
 	void ExportColor(Exporter *exporter, ViewCell *vc) const;
 
+	/** Prepare view cells for use after loading them from disc.
+	*/
 	void PrepareLoadedViewCells();
 
+	/** Constructs merge hierarchy which corresponds to the spatial hierarchy.
+	*/
 	ViewCell *ConstructSpatialMergeTree(BspNode *root);
 
+	void UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs);
+
+
+	// HACK
 	void TestFilter(const ObjectContainer &objects);
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 744)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 752)
@@ -472,6 +472,6 @@
 	
 	mSubdivisionStats 
-			<< "#ViewCells\n1\n" <<  endl
-			<< "#RenderCostDecrease\n0\n" << endl 
+			<< "#ViewCells\n1" <<  endl
+			<< "#RenderCostDecrease\n0" << endl 
 			<< "#TotalRenderCost\n" << mTotalCost << endl
 			<< "#AvgRenderCost\n" << mTotalPvsSize << endl;
@@ -578,5 +578,5 @@
 			<< "#ViewCells\n1\n" <<  endl
 			<< "#RenderCostDecrease\n0\n" << endl 
-			<< "#dummy\n0\n" << endl
+			<< "#SplitCandidateCost\n0\n" << endl
 			<< "#TotalRenderCost\n" << mTotalCost << endl
 			<< "#AvgRenderCost\n" << mTotalPvsSize << endl;
@@ -773,4 +773,9 @@
 		AddToPvs(leaf, *tData.mRays, sampCon, conSamp);
 
+		// update single pvs parameter
+		viewCell->mPvsSize = viewCell->GetPvs().GetSize(); 
+		viewCell->mPvsSizeValid = true;
+
+
 		mBspStats.contributingSamples += conSamp;
 		mBspStats.sampleContributions +=(int) sampCon;
@@ -869,5 +874,5 @@
 					<< "#ViewCells\n" << mBspStats.Leaves() << endl
 					<< "#RenderCostDecrease\n" << -costDecr << endl
-					<< "#dummy\n" << splitCandidate.GetCost() << endl
+					<< "#SplitCandidateCost\n" << splitCandidate.GetCost() << endl
 					<< "#TotalRenderCost\n" << mTotalCost << endl
 					<< "#AvgRenderCost\n" << (float)mTotalPvsSize / (float)mBspStats.Leaves() << endl;
@@ -902,4 +907,7 @@
 		float sampCon = 0.0f;
 		AddToPvs(leaf, *tData.mRays, sampCon, conSamp);
+
+		viewCell->mPvsSize = viewCell->GetPvs().GetSize();
+		viewCell->mPvsSizeValid = true;
 
 		mBspStats.contributingSamples += conSamp;
@@ -1763,14 +1771,8 @@
 		if ((pFront < 0.0) || (pBack < 0.0))
 		{
-			Debug << "vol f " << pFront << " b " << pBack << " p " << pOverall << endl;
-			Debug << "real vol f " << pFront << " b " << geomBack.GetVolume() << " p " << pOverall << endl;
-			Debug << "polys f " << geomFront.Size() << " b " << geomBack.Size() << " data " << data.mGeometry->Size() << endl;
-		}
-
-		// clamp because of possible precision issues
-		if (0)
-		{
-			if (pFront < 0)	pFront = 0;
-			if (pBack < 0) pBack = 0;
+			Debug << "ERROR in volume:\n"
+				  << "volume f :" << pFront << " b: " << pBack << " p: " << pOverall 
+				  << ", real volume f: " << pFront << " b: " << geomBack.GetVolume()
+				  << ", #polygons f: " << geomFront.Size() << " b: " << geomBack.Size() << " p: " << data.mGeometry->Size() << endl;
 		}
 	}
@@ -1795,5 +1797,16 @@
 
 	//Debug << "decrease: " << oldRenderCost - newRenderCost << endl;
-	return (oldRenderCost - newRenderCost) / mBox.GetVolume();
+	const float renderCostDecrease = (oldRenderCost - newRenderCost) / mBox.GetVolume();
+	
+
+#if 1
+	// take render cost of node into account
+	const float normalizedOldRenderCost = oldRenderCost / mBox.GetVolume();
+	//Debug << "rendercostdecr: " << 0.99f * renderCostDecrease << " old render cost: " << 0.01f * normalizedOldRenderCost << endl;
+	//return 0.5f * renderCostDecrease + 0.5f * normalizedOldRenderCost;
+	return 0.99f * renderCostDecrease + 0.01f * normalizedOldRenderCost;
+#else
+	return renderCostDecrease;
+#endif
 }
 
@@ -1871,5 +1884,6 @@
 			!geomFront.Valid() || !geomBack.Valid()))
 		{
-			Debug << "error f: " << pFront << " b: " << pBack << endl;
+			//Debug << "error f: " << pFront << " b: " << pBack << endl;
+			// high penalty for this split
 			return 99999.9f;
 		}
@@ -1887,7 +1901,7 @@
 
 	// only render cost heuristics or combined with standard deviation
-	const float penaltyOld = EvalPvsPenalty(totalPvs, lowerPvsLimit, upperPvsLimit);
-    const float penaltyFront = EvalPvsPenalty(pvsFront, lowerPvsLimit, upperPvsLimit);
-	const float penaltyBack = EvalPvsPenalty(pvsBack, lowerPvsLimit, upperPvsLimit);
+	const float penaltyOld = EvalPvsPenalty((int)totalPvs, lowerPvsLimit, upperPvsLimit);
+    const float penaltyFront = EvalPvsPenalty((int)pvsFront, lowerPvsLimit, upperPvsLimit);
+	const float penaltyBack = EvalPvsPenalty((int)pvsBack, lowerPvsLimit, upperPvsLimit);
 			
 	const float oldRenderCost = pOverall * penaltyOld;
@@ -2762,5 +2776,6 @@
 	BspNodeGeometry nodeGeom;
 	ConstructGeometry(n, nodeGeom);
-	
+	const float eps = 0.01f;
+
 	// split planes from the root to this node
 	// needed to verify that we found neighbor leaf
@@ -2799,5 +2814,5 @@
 							Polygon3::ClassifyPlane(geom->GetPolys(),
 													halfSpaces[i],
-													mEpsilon);
+													eps);
 
 						if (cf == Polygon3::FRONT_SIDE)
@@ -2818,5 +2833,5 @@
 							Polygon3::ClassifyPlane(geom->GetPolys(),
 													poly->GetSupportingPlane(),
-													mEpsilon);
+													eps);
 
 						if (cf == Polygon3::FRONT_SIDE)
@@ -2839,5 +2854,5 @@
 			const int cf = Polygon3::ClassifyPlane(nodeGeom.GetPolys(),
 												   interior->GetPlane(),
-												   mEpsilon);
+												   eps);
 			
 			BspNode *front = interior->GetFront();
@@ -2852,5 +2867,5 @@
 								mBox,
 								//0.0000001f);
-								mEpsilon);
+								eps);
 		
 			if (cf == Polygon3::BACK_SIDE)
@@ -2891,4 +2906,5 @@
 	ConstructGeometry(n, nodeGeom);
 	
+	float eps = 0.01f;
 	// split planes from the root to this node
 	// needed to verify that we found neighbor leaf
@@ -2932,5 +2948,5 @@
 			const int cf = Polygon3::ClassifyPlane(nodeGeom.GetPolys(),
 												   interior->GetPlane(),
-												   mEpsilon);
+												   eps);
 			
 			BspNode *front = interior->GetFront();
@@ -2945,5 +2961,5 @@
 								mBox,
 								//0.0000001f);
-								mEpsilon);
+								eps);
 		
 			if (cf == Polygon3::BACK_SIDE)
@@ -3164,5 +3180,5 @@
 
 	float t;
-	const float thresh = 1e-6f; // matt: change this
+	const float thresh = 1e-6f; // matt: change this to adjustable value
 	
 	while (1)
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.h	(revision 750)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.h	(revision 752)
@@ -18,11 +18,13 @@
 
 /// vertex index container
-typedef std::vector<int> VertexIndexContainer;
+typedef std::vector<short> VertexIndexContainer;
 
 
 /** Patch used as an element of the mesh */
-class Face {
+struct Face {
+
 public:
   Face(): mVertexIndices() {}
+
   Face(const int a, const int b, const int c):mVertexIndices(3) {
     mVertexIndices[0] = a;
@@ -39,5 +41,8 @@
   }
 
-  Face(const VertexIndexContainer &vertices):mVertexIndices(vertices) {}
+  Face(const VertexIndexContainer &vertices):mVertexIndices(vertices.size()) {
+	for (int i=0;  i < vertices.size(); i++)
+	  mVertexIndices[i] = vertices[i];
+  }
   
   /// list of vertex pointers
@@ -74,5 +79,14 @@
       delete mFaces[i];
   }
-
+  
+
+  void Clear() {
+	mVertices.clear();
+	mFaces.clear();
+  }
+  
+  void IndexVertices();
+  
+  void AssignRandomMaterial();
   void AddTriangle(const Triangle3 &triangle);
   void AddRectangle(const Rectangle3 &triangle);
@@ -155,5 +169,5 @@
 	return s<<"Mesh #vertices="<<(int)mVertices.size()<<" #faces="<<(int)mFaces.size();
   }
-
+  
   friend Mesh *CreateBox(const AxisAlignedBox3 &box);
 };
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 746)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 752)
@@ -1078,5 +1078,10 @@
 				 "kd_term_min_cost=",
 				 "10");
-  
+
+  RegisterOption("KdTree.Termination.maxNodes",
+				 optInt,
+				 "kd_term_max_nodes=",
+				 "200000");
+
   RegisterOption("KdTree.Termination.maxDepth",
 				 optInt,
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp	(revision 667)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp	(revision 752)
@@ -22,4 +22,5 @@
 {
   mRoot = new KdLeaf(NULL, 0);
+  environment->GetIntValue("KdTree.Termination.maxNodes", mTermMaxNodes);
   environment->GetIntValue("KdTree.Termination.maxDepth", mTermMaxDepth);
   environment->GetIntValue("KdTree.Termination.minCost", mTermMinCost);
@@ -61,13 +62,13 @@
 
   mBox.Initialize();
-  
   ObjectContainer::const_iterator mi;
   for ( mi = leaf->mObjects.begin();
 	mi != leaf->mObjects.end();
 	mi++) {
-    mBox.Include((*mi)->GetBox());
-  }
-
-  cout <<"KdTree Root Box:"<< mBox<<endl;
+	//	cout<<(*mi)->GetBox()<<endl;
+	mBox.Include((*mi)->GetBox());
+  }
+
+  cout <<"KdTree Root Box:"<<mBox<<endl;
   mRoot = Subdivide(TraversalData(leaf, mBox, 0));
 
@@ -90,27 +91,27 @@
   AxisAlignedBox3 backBox, frontBox;
 
-  
   while (!tStack.empty()) {
-
-#if 0
-    if ( GetMemUsage() > maxMemory ) {
+	//	cout<<mStat.Nodes()<<" "<<mTermMaxNodes<<endl;
+	if (mStat.Nodes() > mTermMaxNodes) {
+	  //    if ( GetMemUsage() > maxMemory ) {
       // count statistics on unprocessed leafs
       while (!tStack.empty()) {
-	EvaluateLeafStats(tStack.top());
-	tStack.pop();
+		EvaluateLeafStats(tStack.top());
+		tStack.pop();
       }
       break;
     }
-#endif
-
+	  
+	
     TraversalData data = tStack.top();
     tStack.pop();
     
     KdNode *node = SubdivideNode((KdLeaf *) data.mNode,
-				 data.mBox,
-				 backBox,
-				 frontBox
-				 );
-    if (result == NULL)
+								 data.mBox,
+								 backBox,
+								 frontBox
+								 );
+
+	if (result == NULL)
       result = node;
     
@@ -146,7 +147,7 @@
 int
 KdTree::SelectPlane(KdLeaf *leaf,
-		    const AxisAlignedBox3 &box,
-		    float &position
-		    )
+					const AxisAlignedBox3 &box,
+					float &position
+					)
 {
   int axis = -1;
@@ -164,32 +165,32 @@
       bool mOnlyDrivingAxis = false;
       if (mOnlyDrivingAxis) {
-				axis = box.Size().DrivingAxis();
-				costRatio = BestCostRatio(leaf,
-																	box,
-																	axis,
-																	position,
-																	objectsBack,
-																	objectsFront);
+		axis = box.Size().DrivingAxis();
+		costRatio = BestCostRatio(leaf,
+								  box,
+								  axis,
+								  position,
+								  objectsBack,
+								  objectsFront);
       } else {
-				costRatio = MAX_FLOAT;
-				for (int i=0; i < 3; i++) {
-					float p;
-					float r = BestCostRatio(leaf,
-																	box,
-																	i,
-																	p,
-																	objectsBack,
-																	objectsFront);
-					if (r < costRatio) {
-						costRatio = r;
-						axis = i;
-						position = p;
-					}
-				}
+		costRatio = MAX_FLOAT;
+		for (int i=0; i < 3; i++) {
+		  float p;
+		  float r = BestCostRatio(leaf,
+								  box,
+								  i,
+								  p,
+								  objectsBack,
+								  objectsFront);
+		  if (r < costRatio) {
+			costRatio = r;
+			axis = i;
+			position = p;
+		  }
+		}
       }
       
       if (costRatio > mMaxCostRatio) {
-				//	cout<<"Too big cost ratio "<<costRatio<<endl;
-				axis = -1;
+		//cout<<"Too big cost ratio "<<costRatio<<endl;
+		axis = -1;
       }
       break;
@@ -394,13 +395,13 @@
 
     splitCandidates->push_back(SortableEntry(SortableEntry::BOX_MIN,
-					     box.Min(axis),
-					     *mi)
-			       );
+											 box.Min(axis),
+											 *mi)
+							   );
     
     
     splitCandidates->push_back(SortableEntry(SortableEntry::BOX_MAX,
-					     box.Max(axis),
-					     *mi)
-			       );
+											 box.Max(axis),
+											 *mi)
+							   );
   }
   
@@ -411,11 +412,11 @@
 float
 KdTree::BestCostRatio(
-											KdLeaf *node,
-											const AxisAlignedBox3 &box,
-											const int axis,
-											float &position,
-											int &objectsBack,
-											int &objectsFront
-											)
+					  KdLeaf *node,
+					  const AxisAlignedBox3 &box,
+					  const int axis,
+					  float &position,
+					  int &objectsBack,
+					  int &objectsFront
+					  )
 {
 
@@ -472,7 +473,7 @@
       float sum;
       if (mSahUseFaces)
-				sum = intersectionsLeft*lbox.SurfaceArea() + intersectionsRight*rbox.SurfaceArea();
+		sum = intersectionsLeft*lbox.SurfaceArea() + intersectionsRight*rbox.SurfaceArea();
       else
-				sum = objectsLeft*lbox.SurfaceArea() + objectsRight*rbox.SurfaceArea();
+		sum = objectsLeft*lbox.SurfaceArea() + objectsRight*rbox.SurfaceArea();
       
       //      cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl;
@@ -480,9 +481,9 @@
       
       if (sum < minSum) {
-				minSum = sum;
-				position = (*ci).value;
-				
-				objectsBack = objectsLeft;
-				objectsFront = objectsRight;
+		minSum = sum;
+		position = (*ci).value;
+		
+		objectsBack = objectsLeft;
+		objectsFront = objectsRight;
       }
     }
@@ -530,4 +531,5 @@
   float position;
   int axis;
+
   
   while (1) {
@@ -538,25 +540,25 @@
 
       if (entp[axis] <= position) {
-				if (extp[axis] <= position) {
-					node = in->mBack;
-					// cases N1,N2,N3,P5,Z2,Z3
-					continue;
-				} else {
-					// case N4
-					node = in->mBack;
-					farChild = in->mFront;
-				}
+		if (extp[axis] <= position) {
+		  node = in->mBack;
+		  // cases N1,N2,N3,P5,Z2,Z3
+		  continue;
+		} else {
+		  // case N4
+		  node = in->mBack;
+		  farChild = in->mFront;
+		}
       }
       else {
-				if (position <= extp[axis]) {
-					node = in->mFront;
-					// cases P1,P2,P3,N5,Z1
-					continue;
-				} else {
-					node = in->mFront;
-					farChild = in->mBack;
-					// case P4
-				}
-			}
+		if (position <= extp[axis]) {
+		  node = in->mFront;
+		  // cases P1,P2,P3,N5,Z1
+		  continue;
+		} else {
+		  node = in->mFront;
+		  farChild = in->mBack;
+		  // case P4
+		}
+	  }
       // $$ modification 3.5.2004 - hints from Kamil Ghais
       // case N4 or P4
@@ -565,42 +567,42 @@
       extp = ray.GetLoc() + ray.GetDir()*tdist;
       maxt = tdist;
-		} else {
-			// compute intersection with all objects in this leaf
-			KdLeaf *leaf = (KdLeaf *) node;
-			if (ray.mFlags & Ray::STORE_KDLEAVES)
-				ray.kdLeaves.push_back(leaf);
-			
-			ObjectContainer::const_iterator mi;
-			for ( mi = leaf->mObjects.begin();
-						mi != leaf->mObjects.end();
-						mi++) {
-				Intersectable *object = *mi;
-				if (!object->Mailed() ) {
-					object->Mail();
-					if (ray.mFlags & Ray::STORE_TESTED_OBJECTS)
-						ray.testedObjects.push_back(object);
-					hits += object->CastRay(ray);
-				}
-			}
-			
-			if (hits && ray.GetType() == Ray::LOCAL_RAY)
-				if (ray.intersections[0].mT <= maxt)
-					break;
-			
-			// get the next node from the stack
-			if (tStack.empty())
-				break;
-			
-			entp = extp;
-			mint = maxt;
-			if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f)
-				break;
-			
-			RayTraversalData &s  = tStack.top();
-			node = s.mNode;
-			extp = s.mExitPoint;
-			maxt = s.mMaxT;
-			tStack.pop();
+	} else {
+	  // compute intersection with all objects in this leaf
+	  KdLeaf *leaf = (KdLeaf *) node;
+	  if (ray.mFlags & Ray::STORE_KDLEAVES)
+		ray.kdLeaves.push_back(leaf);
+	  
+	  ObjectContainer::const_iterator mi;
+	  for ( mi = leaf->mObjects.begin();
+			mi != leaf->mObjects.end();
+			mi++) {
+		Intersectable *object = *mi;
+		if (!object->Mailed() ) {
+		  object->Mail();
+		  if (ray.mFlags & Ray::STORE_TESTED_OBJECTS)
+			ray.testedObjects.push_back(object);
+		  hits += object->CastRay(ray);
 		}
+	  }
+	  
+	  if (hits && ray.GetType() == Ray::LOCAL_RAY)
+		if (ray.intersections[0].mT <= maxt)
+		  break;
+	  
+	  // get the next node from the stack
+	  if (tStack.empty())
+		break;
+	  
+	  entp = extp;
+	  mint = maxt;
+	  if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f)
+		break;
+	  
+	  RayTraversalData &s  = tStack.top();
+	  node = s.mNode;
+	  extp = s.mExitPoint;
+	  maxt = s.mMaxT;
+	  tStack.pop();
+	}
   }
   return hits;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h	(revision 746)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h	(revision 752)
@@ -90,4 +90,12 @@
 class ViewCell: public MeshInstance
 {
+	friend class ViewCellsTree;
+	friend class ViewCellsManager;
+	friend class VspBspViewCellsManager;
+	friend class BspViewCellsManager;
+	friend class VspBspTree;
+	friend class BspTree;
+
+
 public:
 	ViewCell();
@@ -104,6 +112,9 @@
 	*/
 	const ObjectPvs &GetPvs() const;
+
 	ObjectPvs &GetPvs();
 
+	/** Type of view cells.
+	*/
 	int Type() const;
 
@@ -151,13 +162,11 @@
 	float GetRenderCost() const;
 
-  /** set color for visiualizations */
-  void SetColor(const RgbColor &color) {
-	mColor = color;
-  }
-
-  /** get color for visualuzations */
-  RgbColor GetColor() const {
-	return mColor;
-  }
+	/** set color for visiualizations.
+	*/
+	void SetColor(const RgbColor &color);
+
+	/** get color for visualuzations.
+	*/
+    RgbColor GetColor() const;
 
   
@@ -173,6 +182,6 @@
 	virtual bool IsLeaf() const = 0;
 
-  static bool SmallerPvs(const ViewCell *a,
-						 const ViewCell *b) {
+	static bool SmallerPvs(const ViewCell *a, const ViewCell *b) 
+	{
 	return a->GetPvs().GetSize() < b->GetPvs().GetSize();
   }
@@ -205,4 +214,5 @@
 	bool IsActive() const;
 
+
 	// last mail id -> warning not thread safe!
 	// both mailId and mailbox should be unique for each thread!!!
@@ -228,4 +238,10 @@
 	/** color used for consistent visualization */
 	RgbColor mColor;
+
+	
+	/// pvs size, used for lazy pvs computation
+	int mPvsSize;
+	bool mPvsSizeValid;
+
 };
 
@@ -233,4 +249,5 @@
 class ViewCellInterior: public ViewCell
 {
+	friend class ViewCellsManager;
 public:
 	ViewCellInterior();
@@ -292,4 +309,6 @@
 {
 	friend class ViewCellsManager;
+
+
 public:
 	ViewCellsTree(ViewCellsManager *vcm);
@@ -355,11 +374,14 @@
 	float GetMemoryCost(ViewCell *vc) const;
 
-	/** Compresses the pvs of the view cells from the root.
-	*/
-	void CompressViewCellsPvs();
+	/** Sets method of storage for view cells.
+	*/
+	void SetViewCellsStorage(int type);
+
+	/** pvs storage methods */
+	enum {PVS_IN_INTERIORS, COMPRESSED, PVS_IN_LEAVES};
 
 	/** If view cells in this tree have compressed pvs.
 	*/
-	bool IsCompressed() const;
+	int ViewCellsStorage() const;
 
 	/** Returns active view cell that is in the path of this view cell.
@@ -485,5 +507,5 @@
 
 	/// if the view cell tree hold compressed pvs
-	bool mIsCompressed;
+	int mViewCellsStorage;
 
 	ViewCellsManager *mViewCellsManager;
@@ -494,5 +516,6 @@
 
 	
-		
+	/** intermediate container of merged view cells.
+*/
 	ViewCellContainer mMergedViewCells;
 	
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 750)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 752)
@@ -19,4 +19,6 @@
 static void AddGeometry(SceneGraph *scene)
 {
+	scene->mRoot->UpdateBox();
+
 	AxisAlignedBox3 sceneBox = scene->GetBox();
 
@@ -131,19 +133,25 @@
 Preprocessor::~Preprocessor()
 {
-  Debug<<"Deleting view cells manager...\n";
+  cout << "cleaning up" << endl;
+
+  cout << "Deleting view cells manager ... \n";
   DEL_PTR(mViewCellsManager);
-  Debug<<"done.\n";
-  Debug<<"Deleting bsp tree...\n";
+  cout << "done.\n";
+
+  cout << "Deleting bsp tree ... \n";
   DEL_PTR(mBspTree);
-  Debug<<"done.\n";
-  Debug<<"Deleting kd tree...\n";
+  cout << "done.\n";
+
+  cout<<"Deleting kd tree...\n";
   DEL_PTR(mKdTree);
-  Debug<<"done.\n";
-  Debug<<"Deleting vspkd tree...\n";
+  cout<<"done.\n";
+  
+  cout<<"Deleting vspkd tree...\n";
   DEL_PTR(mVspKdTree);
-  Debug<<"done.\n";
-  Debug<<"Deleting vspbsp tree...\n";
+  cout<<"done.\n";
+
+  cout<<"Deleting vspbsp tree...\n";
   DEL_PTR(mVspBspTree);
-  Debug<<"done.\n";
+  cout<<"done.\n";
 }
 
@@ -213,16 +221,18 @@
 	
 
-	if (result) {
-	  // HACK 
-	mSceneGraph->mRoot->UpdateBox();
-	AddGeometry(mSceneGraph);
+	if (result) 
+		{
+		// HACK 
+		//AddGeometry(mSceneGraph);
 	  mSceneGraph->AssignObjectIds();
+		
 	  int intersectables, faces;
 	  mSceneGraph->GetStatistics(intersectables, faces);
+
 	  cout<<filename<<" parsed successfully."<<endl;
 	  cout<<"#NUM_OBJECTS (Total numner of objects)\n"<<intersectables<<endl;
 	  cout<<"#NUM_FACES (Total numner of faces)\n"<<faces<<endl;
 	  mSceneGraph->CollectObjects(&mObjects);
-	  //mSceneGraph->mRoot->UpdateBox();
+	  mSceneGraph->mRoot->UpdateBox();
 
 	 /* Exporter *exporter = Exporter::GetExporter("testload.x3d");
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.cpp	(revision 746)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.cpp	(revision 752)
@@ -67,4 +67,5 @@
 	}
 	break;
+	
   default:
 	result = Preprocessor::GenerateRays(number, sampleType, rays);
@@ -80,6 +81,10 @@
 						  )
 {
-  for (int i=0; i < rays.size(); i++)
+  for (int i=0; i < rays.size(); i++) {
 	CastRay(rays[i].mOrigin, rays[i].mDirection, rays[i].mPdf, vssRays);
+	if (i % 10000 == 0)
+	  cout<<".";
+  }
+  cout<<endl;
 }
 
@@ -298,5 +303,5 @@
   exporter->SetFilled();
   // $$JB temporarily do not export the scene
-  if (1)
+  if (0)
 	exporter->ExportScene(mSceneGraph->mRoot);
   exporter->SetWireframe();
@@ -435,5 +440,5 @@
 {
   // compute rendering error
-  if (renderer) {
+  if (renderer && renderer->mPvsStatFrames) {
 	//	emit EvalPvsStat();
 	//	QMutex mutex;
@@ -504,4 +509,5 @@
 	SimpleRayContainer rays;
 
+	cout<<"Generating initial rays..."<<endl;
 	GenerateRays(mInitialSamples/4, SPATIAL_BOX_BASED_DISTRIBUTION, rays);
 	GenerateRays(mInitialSamples/4, OBJECT_BASED_DISTRIBUTION, rays);
@@ -509,4 +515,5 @@
 	GenerateRays(mInitialSamples/4, OBJECT_DIRECTION_BASED_DISTRIBUTION, rays);
 	
+	cout<<"Casting initial rays..."<<endl;
 	CastRays(rays, mVssRays);
 
@@ -536,7 +543,8 @@
   if (mUseViewcells) {
 
+	cout<<"Computing sample contributions..."<<endl;
 	// evaluate contributions of the intitial rays
 	mViewCellsManager->ComputeSampleContributions(mVssRays, true, false);
-	
+	cout<<"done.\n";
 	
 	mStats <<
@@ -559,5 +567,6 @@
 	Debug<<"Valid viewcells before set validity: "<<mViewCellsManager->CountValidViewcells()<<endl;
 	// cull viewcells with PVS > median (0.5f)
-	mViewCellsManager->SetValidityPercentage(0, 0.5f); 
+	//mViewCellsManager->SetValidityPercentage(0, 0.5f); 
+	mViewCellsManager->SetValidityPercentage(0, 1.0f); 
 	Debug<<"Valid viewcells after set validity: "<<mViewCellsManager->CountValidViewcells()<<endl;
 	
@@ -571,5 +580,5 @@
   
   /// compute view cell contribution of rays if view cells manager already constructed
-  mViewCellsManager->ComputeSampleContributions(mVssRays, true, false);
+  //  mViewCellsManager->ComputeSampleContributions(mVssRays, true, false);
 
   if (mUseImportanceSampling) {
@@ -651,11 +660,19 @@
 		if (mDirectionalSampling)
 		  rayType = DIRECTION_BASED_DISTRIBUTION;
-	  
+
+	  cout<<"Generating rays..."<<endl;
+
 	  GenerateRays(mRssSamplesPerPass, rayType, rays);
+	  cout<<"done."<<endl;
+
+	  cout<<"Casting rays..."<<endl;
 	  CastRays(rays, vssRays);
+	  cout<<"done."<<endl;
 	  castRays += rays.size();
 	  if (mUseViewcells) {
 		/// compute view cell contribution of rays
+		cout<<"Computing sample contributions..."<<endl;
 		mViewCellsManager->ComputeSampleContributions(vssRays, true, false);
+		cout<<"done."<<endl;
 	  }
 	  	
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h	(revision 512)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h	(revision 752)
@@ -221,11 +221,11 @@
 
     bool operator<(
-		   const TraversalData &b) const {
+				   const TraversalData &b) const {
       KdLeaf *leafa = (KdLeaf *) mNode;
       KdLeaf *leafb = (KdLeaf *) b.mNode;
       return 
-	leafa->mObjects.size()*mBox.SurfaceArea()
-	<
-	leafb->mObjects.size()*b.mBox.SurfaceArea();
+		leafa->mObjects.size()*mBox.SurfaceArea()
+		<
+		leafb->mObjects.size()*b.mBox.SurfaceArea();
     }
 
@@ -514,5 +514,5 @@
 
 
-
+  int mTermMaxNodes;
   float mSplitBorder;
   int mTermMaxDepth;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/PlyParser.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/PlyParser.h	(revision 749)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/PlyParser.h	(revision 752)
@@ -17,5 +17,9 @@
 
   bool ParseFile(const string filename, ViewCellsManager &viewCells) { return false; }
-  
+
+  bool
+  ParseSingleFile(const string filename,
+				  SceneGraphNode *root);
+	
 };
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/PlyParser.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/PlyParser.cpp	(revision 749)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/PlyParser.cpp	(revision 752)
@@ -2,4 +2,5 @@
 using namespace std;
 #include <ply.h>
+#include <stdio.h>
 
 #include "PlyParser.h"
@@ -9,6 +10,8 @@
 
 
-
-
+// int facesPerMesh = 100000000;
+int facesPerMesh = 30;
+bool useRandomMaterial = false;
+bool indexVertices = true;
 
 /* user's vertex and face definitions for a polygonal object */
@@ -33,4 +36,5 @@
 };
 
+
 PlyProperty vert_props[] = { /* list of property information for a vertex */
   {"x", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex,x), 0, 0, 0, 0},
@@ -47,38 +51,30 @@
 static PlyFace **flist;
 
+
 bool
-PlyParser::ParseFile(const string filename,
-					 SceneGraphNode **root,
-					 const bool loadPolygonsAsMeshes)
+PlyParser::ParseSingleFile(const string filename,
+						   SceneGraphNode *root)
 {
-
-  /* user's vertex and face definitions for a polygonal object */
+  /*** the PLY object ***/
+  int nverts;
+  Vertex **vlist;
+  PlyOtherElems *other_elements = NULL;
+  PlyOtherProp *vert_other;
+  int nelems;
+  char **elist;
+  int num_comments;
+  char **comments;
+  int num_obj_info;
+  char **obj_info;
+  int file_type;
   
-
-
-typedef double Matrix[4][4];
-
-/*** the PLY object ***/
-
- int nverts;
- Vertex **vlist;
- PlyOtherElems *other_elements = NULL;
- PlyOtherProp *vert_other;
- int nelems;
- char **elist;
- int num_comments;
- char **comments;
- int num_obj_info;
- char **obj_info;
- int file_type;
- 
- int i,j;
- PlyFile *ply;
- int nprops;
- int num_elems;
- PlyProperty **plist;
- char *elem_name;
- float version;
- 
+  int i,j;
+  PlyFile *ply;
+  int nprops;
+  int num_elems;
+  PlyProperty **plist;
+  char *elem_name;
+  float version;
+  
  
   /*** Read in the original PLY object ***/
@@ -169,48 +165,128 @@
  ply_close (ply);
 
-
-
-
- *root = new SceneGraphNode;
- SceneGraphNode *currentNode = *root;
-
-
- cerr<<"Baking faces into eshes"<<endl;
+ SceneGraphNode *currentNode = root;
+
+ cerr<<"Baking faces into meshes"<<endl;
+
  // bake the faces into meshes
- Mesh *mesh = NULL;
- int facesPerMesh = 100;
+ Mesh meshProxy;
+ // only one face per mesh
+ VertexContainer vertices;
+
  for (i = 0; i < nfaces; i++) {
    if (i % facesPerMesh == 0) {
-	 if (mesh) {
-		 mesh->Preprocess;
-		 // make an instance of this mesh
-		 MeshInstance *mi = new MeshInstance(mesh);
-		 currentNode->mGeometry.push_back(mi);
-	   }
-	   mesh = new Mesh();
+	 if (meshProxy.mFaces.size()) {
+
+	   if (indexVertices)
+		 meshProxy.IndexVertices();
+	   
+	   Mesh *mesh = new Mesh(meshProxy.mVertices.size(),
+							 meshProxy.mFaces.size());
+	   
+	   
+	   //	   cout<<"C="<<mesh->mVertices.capacity();
+	   mesh->mVertices = meshProxy.mVertices;
+	   //	   cout<<" NC="<<mesh->mVertices.capacity()<<" S="<<mesh->mVertices.size()<<endl;
+	   
+	   mesh->mFaces = meshProxy.mFaces;
+	   
+	   if (useRandomMaterial)
+		 mesh->AssignRandomMaterial();
+
+	   mesh->Preprocess();
+	   // make an instance of this mesh
+	   MeshInstance *mi = new MeshInstance(mesh);
+	   currentNode->mGeometry.push_back(mi);
 	 }
+
+	 meshProxy.Clear();
+   }
 		 
-	 // only one face per mesh
-	 VertexIndexContainer vc;
-	 
-	 // add vertices
-	 for (int k  = 0; k < flist[i]->nverts; k++) {
-	   Vertex *v = vlist[flist[i]->verts[k]];
-	   vc.push_back(mesh->mVertices.size());
-	   mesh->mVertices.push_back(Vector3(v->x, v->y, v->z));
-	 }
-	 
-	 mesh->mFaces.push_back(new Face(vc));
+   // only one face per mesh
+   VertexIndexContainer vc;
+   
+   // add vertices
+   for (int k  = 0; k < flist[i]->nverts; k++) {
+	 Vertex *v = vlist[flist[i]->verts[k]];
+	 vc.push_back(meshProxy.mVertices.size());
+	 meshProxy.mVertices.push_back(Vector3(v->x, v->y, v->z));
+   }
+   
+   meshProxy.mFaces.push_back(new Face(vc));
  }
  
+ if (meshProxy.mFaces.size()) {
+
+   if (indexVertices)
+	 meshProxy.IndexVertices();
+
+   Mesh *mesh = new Mesh(meshProxy.mVertices.size(),
+						 meshProxy.mFaces.size());
+
+   mesh->mVertices = meshProxy.mVertices;
+   
+   mesh->mFaces = meshProxy.mFaces;
+   
+   if (useRandomMaterial)
+	 mesh->AssignRandomMaterial();
+   
+   mesh->Preprocess();
+   // make an instance of this mesh
+   MeshInstance *mi = new MeshInstance(mesh);
+   currentNode->mGeometry.push_back(mi);
+ }
+
+ // make sure that no face gets deleted by the destructor!
+ meshProxy.Clear();
+
  for (i=0; i < nverts; i++)
    free(vlist[i]);
+
  free(vlist);
 
  for (i=0; i < nfaces; i++)
    free(flist[i]);
+
  free(flist);
-
+ 
  
  return true;
+
+
 }
+
+bool
+PlyParser::ParseFile(const string filename,
+					 SceneGraphNode **root,
+					 const bool loadPolygonsAsMeshes)
+{
+  vector<string> filelist;
+  
+  if (strstr(filename.c_str(), ".plb")) {
+	// parse the filelist
+	FILE *f = fopen(filename.c_str(), "rt");
+	char s[64];
+	if (!f) {
+	  cerr<<"Cannot open .plb file"<<endl;
+	  exit(1);
+	}
+	while (fgets(s,64,f)) {
+	  // remove nl
+	  s[strlen(s)-1] = 0;
+	  filelist.push_back(s);
+	}
+	fclose(f);
+
+  } else
+	filelist.push_back(filename);
+
+  *root = new SceneGraphNode;
+
+  for (int i=0; i < filelist.size(); i++) {
+	if (!ParseSingleFile(filelist[i], *root)) {
+	  cerr<<"Ply parse error. Quiting ...\n";
+	  exit(1);
+	}
+  }
+  return true;
+}
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 750)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 752)
@@ -332,4 +332,6 @@
 	cout << "view cell construction: casting " << mInitialSamples << " initial samples ... ";
 
+	long startTime = GetTime();
+
 	//-- construction rays => we use uniform samples for this
 	CastPassSamples(mInitialSamples, 
@@ -341,13 +343,23 @@
 	
 	// construct view cells
-	const int numInitialSamples = 
-		ConstructSubdivision(preprocessor->mObjects, initialSamples);
+	ConstructSubdivision(preprocessor->mObjects, initialSamples);
 
 	// initial samples count for overall samples ...
-	numSamples += numInitialSamples;
+	numSamples += mInitialSamples;
 
 	// rays can be passed or deleted
 	disposeRays(initialSamples, outRays);
-	
+
+	cout << "time needed for initial construction: "
+		 << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
+
+	Debug << "time needed for initial construction: "
+		  << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
+
+
+	// take post processing time
+	startTime = GetTime();
+
+
 	// testing the view cell filter functionality	
 	if (0) TestFilter(preprocessor->mObjects);
@@ -421,4 +433,5 @@
 		cout << "total samples: " << numSamples << endl;
 	}
+
 	
 
@@ -457,4 +470,10 @@
 	PostProcess(preprocessor->mObjects, postProcessSamples);
 
+	cout << "time needed for  post processing (merge) step: "
+		 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
+
+	Debug << "time needed for  post processing (merge) step: "
+		 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
+
 	// only for debugging purpose
 	if (TEST_EMPTY_VIEW_CELLS)
@@ -481,8 +500,4 @@
 	}
 
-	// needed to fix empty view cells
-    //SetValidity(0, 99999999999);
-
-
 	// evaluation of the paritition, i.e., a number of new samples are cast
 	if (mEvaluateViewCells)
@@ -491,50 +506,10 @@
 	}
 	
-	if (0)
-	{
-		ViewCellContainer leaves;
-		mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
-		mViewCellsTree->ResetPvs();
-		VssRayContainer dummyRays;
-		CastPassSamples(mInitialSamples, mSamplingType, dummyRays);
-	
-		//ComputeSampleContributions(initialSamples, true, false);
-		ComputeSampleContributions(dummyRays, true, false);
-
-		ViewCellContainer::const_iterator it, it_end = leaves.end();
-
-		for (it = leaves.begin(); it != it_end; ++ it)
-		{
-			mViewCellsTree->PropagatePvs(*it);
-		}
-
-		mViewCellsTree->ExportStats("dummy.log");
-	}
-
 	return numSamples;
 }
 
 
-void ComputeMinMaxRenderCost(float &minRenderCost,
-							 float &maxRenderCost, 
-							 const ViewCellContainer &viewCells)
-{
-	minRenderCost = 1e20f;
-	maxRenderCost = -1;
-
-	ViewCellContainer::const_iterator it, it_end = viewCells.end();
-
-	for (it = viewCells.begin(); it != it_end; ++ it)
-	{
-		const float renderCost = (float)(*it)->GetPvs().GetSize() * (*it)->GetVolume();
-		if (renderCost > maxRenderCost)
-			maxRenderCost = renderCost;
-		else if (renderCost < minRenderCost)
-			minRenderCost = renderCost;
-	}
-}
-
-
-void ViewCellsManager::EvalViewCellHistogram(const string filename, const int nViewCells)
+void ViewCellsManager::EvalViewCellHistogram(const string filename, 
+											 const int nViewCells)
 {
 	std::ofstream outstream;
@@ -554,5 +529,5 @@
 	Debug << "histogram minrc: " << minRenderCost << " maxrc: " << maxRenderCost << endl;
 
-	const int intervals = min(10000, (int)viewCells.size());
+	const int intervals = min(50, (int)viewCells.size());
 
 	const float range = maxRenderCost - minRenderCost;
@@ -634,11 +609,17 @@
 	maxPvsSize = viewCells.back()->GetPvs().GetSize();
 	
+	minPvsSize = 0;
+	maxPvsSize = 1200;
+
 	Debug << "histogram minpvssize: " << minPvsSize << " maxpvssize: " << maxPvsSize << endl;
 
-	const int intervals = min(10000, (int)viewCells.size());
+	const int intervals = min(20, (int)viewCells.size());
 	const int range = maxPvsSize - minPvsSize;
 	int stepSize = range / intervals;
 
+	
 	if (!stepSize) stepSize = 1;
+Debug << "stepsize: " << stepSize << endl;
+	cout << "stepsize: " << stepSize << endl;
 
 	const float totalRenderCost = mViewCellsTree->GetRoot()->GetRenderCost();
@@ -756,5 +737,6 @@
 		castSamples += samplesPerPass;
 
-		cout << "computing sample contributions of " << (int)evaluationSamples.size() << " samples " << endl;
+		cout << "computing sample contributions of " << (int)evaluationSamples.size() 
+			 << " samples " << endl;
 
 		ComputeSampleContributions(evaluationSamples, true, false);
@@ -762,10 +744,8 @@
 		cout << "compute new statistics ... ";
 
-		ViewCellContainer::const_iterator it, it_end = leaves.end();
-
-		for (it = leaves.begin(); it != it_end; ++ it)
-		{
-			mViewCellsTree->PropagatePvs(*it);
-		}
+		// propagate pvs or pvs size information
+		ObjectPvs pvs;
+		UpdatePvsForEvaluation(mViewCellsTree->GetRoot(), pvs);
+
 
 		// output stats
@@ -819,5 +799,5 @@
 		}
 #else
-		for (int pass = histoPasses; pass < numLeaves; pass += histoPasses)
+		for (int pass = histoPasses; pass <= numLeaves; pass += histoPasses)
 		{
 			cout << "computing histogram for " << pass << " view cells" << endl;
@@ -830,5 +810,5 @@
 
 			//////////////////////////////////////////
-            // --evaluate histogram for pvs size
+            //-- evaluate histogram for pvs size
 
 			cout << "computing pvs histogram for " << pass << " view cells" << endl;
@@ -892,5 +872,6 @@
 	{
 	case PER_OBJECT:
-		return 1;
+		//cout << "perobject" << endl;
+		return 1.0f;
 	
 	case PER_TRIANGLE:
@@ -906,9 +887,10 @@
 		}
 	default:
-		return 1;
+		cout << "default" << endl;
+		return 1.0f;
 	}
 
 	// should not come here
-	return 0;
+	return 0.0f;
 }
 
@@ -1355,12 +1337,14 @@
 }
 
-
+// fast way of merging 2 view cells
 ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCell *left, ViewCell *right) const
 {
 	// generate parent view cell
-	ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
-
+	ViewCellInterior *vc = new ViewCellInterior();
+
+	vc->GetPvs().Clear();
 	vc->GetPvs() = left->GetPvs();
-	// merge pvs
+
+	// merge pvs of right cell
 	vc->GetPvs().Merge(right->GetPvs());
 
@@ -1380,4 +1364,8 @@
 	vc->mChildren.push_back(right);
 
+	// update pvs size
+	vc->mPvsSize = vc->GetPvs().GetSize();
+	vc->mPvsSizeValid = true;
+
 	return vc;
 }
@@ -1386,5 +1374,5 @@
 ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCellContainer &children) const
 {
-	ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
+	ViewCellInterior *vc = new ViewCellInterior();
 
 	ViewCellContainer::const_iterator it, it_end = children.end();
@@ -1395,5 +1383,4 @@
 		vc->GetPvs().Merge((*it)->GetPvs());
 		vc->mChildren.push_back(*it);
-		//vc->SetupChildLink(*it);
 	}
 
@@ -1755,13 +1742,4 @@
 float ViewCellsManager::GetRendercost(ViewCell *viewCell) const
 {
-	const ObjectPvs &pvs = viewCell->GetPvs();
-
-	ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
-
-	for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
-	{
-		
-	}
-
 	return mViewCellsTree->GetPvsSize(viewCell);
 }
@@ -2022,6 +2000,12 @@
 	{
 		cout << "constructing spatial merge tree" << endl;
+
 		// create spatial merge hierarchy
-		mViewCellsTree->SetRoot(ConstructSpatialMergeTree(mBspTree->GetRoot()));
+		ViewCell *root = ConstructSpatialMergeTree(mBspTree->GetRoot());
+		mViewCellsTree->SetRoot(root);
+
+		// compute pvs
+		ObjectPvs pvs;
+		UpdatePvsForEvaluation(root, pvs);
 	}
 
@@ -2037,8 +2021,8 @@
 	cout << "finished" << endl;
 	cout << "merged view cells in "
-		 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
+		 << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
 
 	Debug << "Postprocessing: Merged view cells in "
-		<< TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
+		<< TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl << endl;
 	
 
@@ -2076,5 +2060,5 @@
 	}
 
-	if (1) // export merged view cells
+	if (1) // export merged view cells using pvs color coding
 	{
 		mColorCode = 1;
@@ -2087,5 +2071,6 @@
 		{
 			//exporter->SetWireframe();
-			
+			//exporter->SetForcedMaterial(RandomMaterial());
+
 			if (mExportGeometry)
 				exporter->ExportGeometry(objects);
@@ -2629,11 +2614,10 @@
 ViewCell *BspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
 {
+	// terminate recursion
 	if (root->IsLeaf())
 	{
-		ViewCell *viewCell = dynamic_cast<BspLeaf *>(root)->GetViewCell();
-
-		viewCell->SetMergeCost(0.0f);
-
-		return viewCell;
+		BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
+		leaf->GetViewCell()->SetMergeCost(0.0f);
+		return leaf->GetViewCell();
 	}
 	
@@ -2641,8 +2625,6 @@
 	ViewCellInterior *viewCellInterior = new ViewCellInterior();
 		
+	// evaluate merge cost for priority traversal
 	float mergeCost = 1.0f / (float)root->mTimeStamp;
-	//Debug << "timestamp: " << root->mTimeStamp;
-	//Debug << "merge cost: " << mergeCost << endl;
-
 	viewCellInterior->SetMergeCost(mergeCost);
 
@@ -2652,23 +2634,98 @@
 	BspNode *back = interior->GetBack();
 
-	// recursivly compute child hierarchies
+
+	//-- recursivly compute child hierarchies
 	ViewCell *backVc = ConstructSpatialMergeTree(back);
 	ViewCell *frontVc = ConstructSpatialMergeTree(front);
 
+
+	viewCellInterior->SetupChildLink(backVc);
 	viewCellInterior->SetupChildLink(frontVc);
-	viewCellInterior->SetupChildLink(backVc);
-
+
+	volume += backVc->GetVolume();
+	volume += frontVc->GetVolume();	
+
+	viewCellInterior->SetVolume(volume);
+
+	return viewCellInterior;
+}
+
+
+void BspViewCellsManager::UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs)
+{
+	// terminate traversal
+	if (root->IsLeaf())
+	{
+		pvs = root->GetPvs();
+
+		root->mPvsSize = pvs.GetSize();
+		root->mPvsSizeValid = true;
+
+		return;
+	}
+
+	ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
+	ViewCellContainer::const_iterator vit, vit_end = interior->mChildren.end();
+
+	vector<ObjectPvs> pvsList;
+	
+	
+	for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit)
+	{
+		ObjectPvs objPvs;
+		
+		//-- recursivly compute child pvss
+		UpdatePvsForEvaluation(*vit, objPvs);
+
+		// store pvs in vector
+		pvsList.push_back(objPvs);
+	}
+
+#if 1
+	Intersectable::NewMail();
+
+	//-- faster way of computing pvs:
+	//   construct merged pvs by adding 
+	//   and only those of the next pvs which were not mailed.
+	//   note: sumpdf is not correct!!
+	vector<ObjectPvs>::iterator oit = pvsList.begin();
+
+	for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ oit)
+	{
+		
+        ObjectPvsMap::iterator pit, pit_end = (*oit).mEntries.end();
+	
+		for (pit = (*oit).mEntries.begin(); pit != pit_end; ++ pit)
+		{
+			
+			Intersectable *intersect = (*pit).first;
+
+			if (!intersect->Mailed())
+			{
+				pvs.AddSample(intersect, (*pit).second.mSumPdf);
+				intersect->Mail();
+			}
+		}
+	}
+
+	// store pvs in this node
+	if (mViewCellsTree->ViewCellsStorage() == ViewCellsTree::PVS_IN_INTERIORS)
+	{
+		interior->mPvs = pvs;
+	}
+	
+	// set new pvs size
+	interior->mPvsSize = pvs.GetSize();
+	interior->mPvsSizeValid = true;
+
+#else
+	// really merge cells: slow put sumpdf is correct
+	ViewCellInterior *viewCellInterior = new ViewCellInterior();
 
 	viewCellInterior->GetPvs().Merge(backVc->GetPvs());
 	viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
-
-	volume += backVc->GetVolume();
-	volume += frontVc->GetVolume();	
-
-	viewCellInterior->SetVolume(volume);
-
-	return viewCellInterior;
-}
-
+#endif
+
+}
 
 /************************************************************************/
@@ -2819,5 +2876,5 @@
 
 			ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
-			// output PVS of view cell
+			// -- output PVS of view cell
 			for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
 			{
@@ -3448,4 +3505,5 @@
 	if (SAMPLE_AFTER_SUBDIVISION)
 		ComputeSampleContributions(savedRays, true, false);
+
 	cout << "finished" << endl;
 
@@ -3489,4 +3547,8 @@
 		ViewCell *root = ConstructSpatialMergeTree(mVspBspTree->GetRoot());
 		mViewCellsTree->SetRoot(root);
+
+		// compute pvs
+		ObjectPvs pvs;
+		UpdatePvsForEvaluation(root, pvs);
 	}
 
@@ -3494,4 +3556,6 @@
 	{
 		char mstats[100];
+		ObjectPvs pvs;
+
 		environment->GetStringValue("ViewCells.mergeStats", mstats);
 		mViewCellsTree->ExportStats(mstats);
@@ -3728,5 +3792,5 @@
 		Debug << "number of entries before compress: " << pvsEntries << endl;
 
-		mViewCellsTree->CompressViewCellsPvs();
+		mViewCellsTree->SetViewCellsStorage(ViewCellsTree::COMPRESSED);
 
 		pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
@@ -3768,20 +3832,18 @@
 ViewCell *VspBspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
 {
+	// terminate recursion
 	if (root->IsLeaf())
 	{
-		ViewCell *viewCell = dynamic_cast<BspLeaf *>(root)->GetViewCell();
-
-		viewCell->SetMergeCost(0.0f);
-
-		return viewCell;
-	}
+		BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
+		leaf->GetViewCell()->SetMergeCost(0.0f);
+		return leaf->GetViewCell();
+	}
+	
 	
 	BspInterior *interior = dynamic_cast<BspInterior *>(root);
 	ViewCellInterior *viewCellInterior = new ViewCellInterior();
 		
+	// evaluate merge cost for priority traversal
 	float mergeCost = 1.0f / (float)root->mTimeStamp;
-	//Debug << "timestamp: " << root->mTimeStamp;
-	//Debug << "merge cost: " << mergeCost << endl;
-
 	viewCellInterior->SetMergeCost(mergeCost);
 
@@ -3791,21 +3853,98 @@
 	BspNode *back = interior->GetBack();
 
-	// recursivly compute child hierarchies
+
+	ObjectPvs frontPvs, backPvs;
+
+	//-- recursivly compute child hierarchies
 	ViewCell *backVc = ConstructSpatialMergeTree(back);
 	ViewCell *frontVc = ConstructSpatialMergeTree(front);
 
+
+	viewCellInterior->SetupChildLink(backVc);
 	viewCellInterior->SetupChildLink(frontVc);
-	viewCellInterior->SetupChildLink(backVc);
-
+
+	volume += backVc->GetVolume();
+	volume += frontVc->GetVolume();	
+
+	viewCellInterior->SetVolume(volume);
+
+	return viewCellInterior;
+}
+
+
+
+void VspBspViewCellsManager::UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs)
+{
+	// terminate traversal
+	if (root->IsLeaf())
+	{
+		pvs = root->GetPvs();
+
+		root->mPvsSize = pvs.GetSize();
+		root->mPvsSizeValid = true;
+
+		return;
+	}
+	
+	ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
+	ViewCellContainer::const_iterator vit, vit_end = interior->mChildren.end();
+
+	vector<ObjectPvs> pvsList;
+	
+	
+	for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit)
+	{
+		ObjectPvs objPvs;
+		
+		//-- recursivly compute child pvss
+		UpdatePvsForEvaluation(*vit, objPvs);
+
+		// store pvs in vector
+		pvsList.push_back(objPvs);
+	}
+
+#if 1
+	Intersectable::NewMail();
+
+	//-- faster way of computing pvs:
+	//   construct merged pvs by adding 
+	//   and only those of the next pvs which were not mailed.
+	//   note: sumpdf is not correct!!
+	vector<ObjectPvs>::iterator oit = pvsList.begin();
+
+	for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ oit)
+	{
+	    ObjectPvsMap::iterator pit, pit_end = (*oit).mEntries.end();
+	
+		for (pit = (*oit).mEntries.begin(); pit != pit_end; ++ pit)
+		{
+			Intersectable *intersect = (*pit).first;
+
+			if (!intersect->Mailed())
+			{
+				pvs.AddSample(intersect, (*pit).second.mSumPdf);
+				intersect->Mail();
+			}
+		}
+	}
+
+	// store pvs in this node
+	if (mViewCellsTree->ViewCellsStorage() == ViewCellsTree::PVS_IN_INTERIORS)
+	{
+		interior->mPvs = pvs;
+	}
+	
+	// set new pvs size
+	interior->mPvsSize = pvs.GetSize();
+	interior->mPvsSizeValid = true;
+
+#else
+	// really merge cells: slow put sumpdf is correct
+	ViewCellInterior *viewCellInterior = new ViewCellInterior();
 
 	viewCellInterior->GetPvs().Merge(backVc->GetPvs());
 	viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
-
-	volume += backVc->GetVolume();
-	volume += frontVc->GetVolume();	
-
-	viewCellInterior->SetVolume(volume);
-
-	return viewCellInterior;
+#endif
+
 }
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 746)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 752)
@@ -1134,5 +1134,5 @@
   cb = new QCheckBox("Render errors", vbox);
   vbox->layout()->addWidget(cb);
-  cb->setChecked(true);
+  cb->setChecked(false);
   connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderErrors(bool)));
 
@@ -1229,5 +1229,5 @@
   mCutViewCells = false;
   mCutScene = false;
-  mRenderErrors = true;
+  mRenderErrors = false;
   mRenderFilter = true;
   mShowRenderCost = false;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/X3dParserXerces.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/X3dParserXerces.h	(revision 712)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/X3dParserXerces.h	(revision 752)
@@ -18,4 +18,15 @@
 class Material;
 class ViewCellsManager;
+
+struct ltstr
+{
+  bool operator()(const string &s1, const string &s2) const
+  {
+    return s1 < s2;
+  }
+};
+
+typedef map<string, Mesh *, ltstr> MeshDefinitions;
+typedef map<string, Material *, ltstr> MaterialDefinitions;
 
 class X3dParseHandlers : public HandlerBase
@@ -66,13 +77,20 @@
   vector<VertexIndexContainer> mCurrentVertexIndices;
   VertexContainer mCurrentVertices;
+  string mCurrentMeshName;
 
   Material *mCurrentMaterial;
+  
   bool mLoadPolygonsAsMeshes;
 
   typedef stack<Matrix4x4> TrafoStack;
 
+  bool mUsingMeshDefinition;
   // stack of accumulated transformations
   TrafoStack mTransformations;
 
+  MaterialDefinitions mMaterialDefinitions;
+  MeshDefinitions mMeshDefinitions;
+
+  bool mIsMeshDefinition;
   // Handlers for X3D
   void
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/MeshKdTree.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/MeshKdTree.cpp	(revision 469)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/MeshKdTree.cpp	(revision 752)
@@ -291,7 +291,7 @@
 int
 MeshKdTree::CastRay(
-										Ray &ray,
-										MeshInstance *instance
-										)
+					Ray &ray,
+					MeshInstance *instance
+					)
 {
   int hits = 0;
@@ -303,4 +303,5 @@
   
   AxisAlignedBox3 box = GetBox();
+
   if (!box.GetMinMaxT(ray, &mint, &maxt))
     return 0;
@@ -308,11 +309,11 @@
   if (mint < 0)
     mint = 0;
-
-
-	if (ray.GetType() == Ray::LOCAL_RAY &&
-			ray.intersections.size() && ray.intersections[0].mT < mint) {
-		return 0;
-	}
-
+  
+
+  if (ray.GetType() == Ray::LOCAL_RAY &&
+	  ray.intersections.size() && ray.intersections[0].mT < mint) {
+	return 0;
+  }
+  
   maxt += Limits::Threshold;
   
@@ -324,5 +325,5 @@
   float position;
   int axis;
-  
+
   while (1) {
     if (!node->IsLeaf()) {
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.cpp	(revision 750)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.cpp	(revision 752)
@@ -7,14 +7,58 @@
 int Intersectable::sReservedMailboxes = 1;
 
+struct SortableVertex {
+
+  Vector3 vertex;
+
+  int originalId;
+  int newId;
+  int finalPos;
+
+  SortableVertex() {}
+
+  SortableVertex(const Vector3 &v,
+				 const int id):
+	vertex(v),
+	originalId(id),
+	newId(id)
+  {}
+  
+  friend bool operator<(const SortableVertex &a,
+						const SortableVertex &b)
+  {
+	if (a.vertex.x < b.vertex.x)
+	  return true;
+	else
+	  if (a.vertex.x > b.vertex.x)
+		return false;
+	
+	if (a.vertex.y < b.vertex.y)
+	  return true;
+	else
+	  if (a.vertex.y > b.vertex.y)
+		return false;
+	
+	if (a.vertex.z < b.vertex.z)
+	  return true;
+	else
+	  //	  if (a.z > b.z)
+	  return false;
+	
+	//	return false;
+  }
+
+};
+
 void
 Mesh::Preprocess()
 {
-	Cleanup();
-	
-	mBox.Initialize();
+  Cleanup();
+	
+  mBox.Initialize();
   VertexContainer::const_iterator vi = mVertices.begin();
   for (; vi != mVertices.end(); vi++) {
     mBox.Include(*vi);
   }
+
   
   /** true if it is a watertight convex mesh */
@@ -28,10 +72,56 @@
     cout<<"KD";
     mKdTree->Construct();
-
+	
     if (mKdTree->GetRoot()->IsLeaf()) {
       cout<<"d";
       delete mKdTree;
-			mKdTree = NULL;
+	  mKdTree = NULL;
     }
+  }
+}
+
+
+void
+Mesh::IndexVertices()
+{
+  int i;
+  // check whether the vertices can be simplfied and reindexed
+  vector<SortableVertex> svertices(mVertices.size());
+
+  for (i=0; i < mVertices.size(); i++)
+	svertices[i] = SortableVertex(mVertices[i], i);
+
+  sort(svertices.begin(), svertices.end());
+
+  for (i=0; i < svertices.size() - 1; i++)
+	if (svertices[i].vertex == svertices[i+1].vertex)
+	  svertices[i+1].newId = svertices[i].newId;
+
+  // remove the same vertices
+  int k = 0;
+  mVertices[0] = svertices[0].vertex;
+  svertices[0].finalPos = 0;
+  
+  for (i=1; i < svertices.size(); i++) {
+	if (svertices[i].newId != svertices[i-1].newId)
+	  k++;
+	
+	mVertices[k] = svertices[i].vertex;
+	svertices[i].finalPos = k;
+  }
+
+  mVertices.resize(k + 1);
+  
+  vector<int> remapBuffer(svertices.size());
+  for (i = 0; i < svertices.size(); i++)
+	remapBuffer[svertices[i].originalId] = svertices[i].finalPos;
+  
+  // remap all faces
+  
+  for (int faceIndex = 0; faceIndex < mFaces.size(); faceIndex++) {
+	Face *face = mFaces[faceIndex];
+	for (int i = 0; i < face->mVertexIndices.size(); i++) {
+	  face->mVertexIndices[i] = remapBuffer[face->mVertexIndices[i]];
+	}
   }
 }
@@ -49,5 +139,4 @@
   return box;
 }
-
 
 int
@@ -251,4 +340,5 @@
     ExtractVerts(&u1, &v1, paxis );
   
+  //$$JB changed 12.4.2006 from 0 ^^
   if (0 && size <= 4) {
     // assume a convex face
@@ -463,4 +553,12 @@
 }
 
+void
+Mesh::AssignRandomMaterial()
+{
+  if (!mMaterial)
+	mMaterial = new Material;
+  *mMaterial = RandomMaterial();
+
+}
 
 
