Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudGenerator.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudGenerator.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudGenerator.cpp	(revision 699)
@@ -0,0 +1,46 @@
+
+#include <BBCBillboardCloudGenerator.h>
+#include <BBCEntity.h>
+
+namespace BBC {
+
+void BillboardCloudGenerator::setBillboardCloud(BillboardCloud *value)
+{
+	mBillboardCloud = value;
+}
+
+BillboardCloud* BillboardCloudGenerator::getBillboardCloud()
+{
+	return mBillboardCloud;
+}
+
+void BillboardCloudGenerator::generate() 
+{
+	Ogre::LogManager::getSingleton().logMessage("BillboardCloudGenerator::generate method not implemented.");
+}
+
+void BillboardCloudGenerator::init() 
+{
+}
+
+void BillboardCloudGenerator::setMaxNumBillboards(unsigned int value)
+{
+	mMaxNumBillboards = value;
+}
+
+unsigned int BillboardCloudGenerator::getMaxNumBillboards()
+{
+	return mMaxNumBillboards;
+}
+
+void BillboardCloudGenerator::setDistribution(EntityDistribution *value) 
+{
+	mEntityDistribution = value;
+}
+
+EntityDistribution* BillboardCloudGenerator::getDistribution() 
+{
+	return mEntityDistribution;
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCXmlSerializer.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCXmlSerializer.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCXmlSerializer.cpp	(revision 699)
@@ -0,0 +1,60 @@
+
+#include "BBCXmlSerializer.h"
+
+namespace BBC {
+
+XmlSerializer::XmlSerializer() {
+	mLoaded = false;
+}
+
+XmlSerializer::~XmlSerializer() {
+	if (mLoaded)
+	{
+		delete mFile;
+		mLoaded = false;
+	}
+}
+
+TiXmlDocument* XmlSerializer::load(Ogre::String filename) 
+{
+	mFilename = filename;
+	if (!mLoaded)
+	{
+		mFile = new TiXmlDocument(filename.c_str());
+		mLoaded = true;
+	}
+	else
+	{
+		delete mFile;
+		mFile = new TiXmlDocument(filename.c_str());
+	}
+	mFilename = filename;
+	mFile->LoadFile();
+	return mFile;
+}
+
+void XmlSerializer::save() {
+	if (mLoaded && (mFilename != ""))
+	{ 
+		Ogre::LogManager::getSingleton().logMessage("Filename:" + mFilename);
+		mFile->SaveFile(mFilename.c_str());
+	}
+}
+
+TiXmlDocument* XmlSerializer::create(Ogre::String filename)
+{	
+	if (!mLoaded)
+	{
+		mFile = new TiXmlDocument(filename.c_str());
+		mLoaded = true;
+	}
+	else
+	{
+		delete mFile;
+		mFile = new TiXmlDocument(filename.c_str());
+	}
+	mFilename = filename;
+	return mFile;
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGCluster2d.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGCluster2d.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGCluster2d.cpp	(revision 699)
@@ -0,0 +1,113 @@
+
+#include "IMGCluster2d.h"
+#include "IMGCluster.h"
+
+namespace IMG {
+
+//* Create a 2d polygon from a polygon 3d. The projecte polygon is belong the dominant normal.
+//			
+//	 
+int Cluster2d::Create2d(Cluster * cluster, int type, int type_vertexs) {
+	if (!cluster) return false;
+	
+	int axis = cluster->AxisProjected();
+	Ogre::Vector3 *vertexs3d;
+	std::vector<Ogre::Vector3> vertexs3d_;
+	int num_vertexs = 4;
+	
+	//printf("\nDins Create cluster2d axisproj: %d ", axis);
+	
+	
+	
+	switch(type)
+	{
+		//case 0:	vertexs3d = poly->GetVector3s(); break;
+		case 0:	vertexs3d_ = *cluster->GetVector3sVector(); break;		
+		//case 1: vertexs3d = poly->GetVector3sTex(); break;
+	}
+	/*
+	if (type_vertexs) num_vertexs = 3;
+	else num_vertexs = 4;
+	*/
+	this->cluster = cluster;
+	
+	//Vector2 * vertexs2d = new Vector2[4];
+	// GametoolsError -- Isma 17/08/2005
+	//vertexs = new Vector2[4];
+	//vertexs = new Vector2[vertexs3d_.size()];
+	
+	//normal = new Vector2;
+	normal = new Ogre::Vector3;
+	Ogre::Vector3 *normal3d = cluster->GetPlane()->GetNormal();
+	Ogre::Box bound;
+	
+	
+	switch(axis)
+	{
+		case (0):
+			for (int i = 0; i < vertexs3d_.size(); i++)
+			{	
+				// GametoolsError -- Isma 17/08/2005
+				//vertexs[i].x = vertexs3d_[i].z;
+				//vertexs[i].y = vertexs3d_[i].y;
+				//vertexs2_vector.push_back(vertexs[i]);
+
+				//printf("Assignat 0: (%.4f, %.4f)- (%.4f, %.4f)\n", vertexs3d_[i].z, vertexs3d_[i].y, vertexs[i].x, vertexs[i].y);
+				//bound.AddBoundingVector3 (vertexs[i].x, vertexs[i].y, 0);		
+	
+			}
+			break;					
+		
+		  case (1):
+
+			
+			for (int i = 0; i < vertexs3d_.size(); i++)
+			{
+				// GametoolsError -- Isma 17/08/2005
+				//vertexs[i].x = vertexs3d_[i].x;
+				//vertexs[i].y = vertexs3d_[i].z;
+				//vertexs2_vector.push_back(vertexs[i]);
+				//printf("Assignat 1: (%.4f, %.4f)- (%.4f, %.4f)\n", vertexs3d_[i].x, vertexs3d_[i].z, vertexs[i].x, vertexs[i].y);
+				//bound.AddBoundingVector3 (vertexs[i].x, vertexs[i].y, 0);	
+			}
+			
+			break;
+
+		case(2):
+			for (int i = 0; i < vertexs3d_.size(); i++)
+			{
+				// GametoolsError -- Isma 17/08/2005
+				//vertexs[i].x = vertexs3d_[i].x;
+				//vertexs[i].y = vertexs3d_[i].y;
+				//vertexs2_vector.push_back(vertexs[i]);
+				//printf("Assignat 2: (%.4f, %.4f)- (%.4f, %.4f)\n", vertexs3d_[i].x, vertexs3d_[i].y, vertexs[i].x, vertexs[i].y);
+				//bound.AddBoundingVector3 (vertexs[i].x, vertexs[i].y, 0);	
+			}
+		
+		break;
+	}
+
+	
+	id = cluster->GetId();
+	//printf("\n\nen 2d: ");
+	//Print();
+	//printf("\n-----------------");
+	return axis;
+}
+
+void Cluster2d::Print() {
+	printf("\nPrintant cluster2d: %d", id);
+	// GametoolsError -- Isma 17/08/2005
+	//if (!vertexs) return;
+	
+	//printf("\nVector3 1 (%.4f, %.4f)  ", vertexs[0].x, vertexs[0].y);
+	//printf("\nVector3 2 (%.4f, %.4f)  ", vertexs[1].x, vertexs[1].y);
+	//printf("\nVector3 3 (%.4f, %.4f)  ", vertexs[2].x, vertexs[2].y);	
+	//printf("\nVector3 3 (%.4f, %.4f)  ", vertexs[3].x, vertexs[3].y);	
+}
+
+Cluster2d::~Cluster2d() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKMeansClusterGenerator.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKMeansClusterGenerator.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKMeansClusterGenerator.cpp	(revision 699)
@@ -0,0 +1,23 @@
+
+#include "LBBCKMeansClusterGenerator.h"
+
+namespace LBBC {
+
+void KMeansClusterGenerator::generate() 
+{
+
+}
+
+void KMeansClusterGenerator::init() 
+{
+
+}
+
+KMeansClusterGenerator::KMeansClusterGenerator() {
+}
+
+KMeansClusterGenerator::~KMeansClusterGenerator() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCOgreMeshSerializer.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCOgreMeshSerializer.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCOgreMeshSerializer.cpp	(revision 699)
@@ -0,0 +1,310 @@
+#include "BBCOgreMeshSerializer.h"
+
+namespace BBC {
+
+    UniqueVertex::UniqueVertex()
+        : position(Ogre::Vector3::ZERO), normal(Ogre::Vector3::ZERO), colour(0), nextIndex(0)
+    {
+        for (int i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; ++i)
+            uv[i] = Ogre::Vector3::ZERO;
+    }
+
+    bool UniqueVertex::operator==(const UniqueVertex& rhs) const
+    {
+        bool ret = position == rhs.position && 
+            normal == rhs.normal && 
+            colour == rhs.colour;
+        if (!ret) return ret;
+
+        for (int i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS && ret; ++i)
+        {
+            ret = ret && (uv[i] == rhs.uv[i]);
+        }
+
+        return ret;
+    }
+
+	void OgreMeshSerializer::setEntity(Entity *entity)
+	{
+		mEntity = entity;
+	}
+
+	Entity* OgreMeshSerializer::getEntity()
+	{
+		return mEntity;
+	}
+
+    OgreMeshSerializer::OgreMeshSerializer()
+    {
+    }
+
+    OgreMeshSerializer::~OgreMeshSerializer()
+    {
+    }
+
+
+	void OgreMeshSerializer::exportMesh(const Ogre::String& fileName, bool mergeSubMeshes = false, bool tangents = false)
+    {
+
+		Ogre::LogManager::getSingleton().logMessage("** Begin OGRE Mesh Export **");
+        // Derive the scene root
+
+        // Construct mesh
+        Ogre::MeshPtr pMesh = Ogre::MeshManager::getSingleton().createManual(fileName, 
+			Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+
+		mEntity->setMesh(pMesh.getPointer());
+
+		// write the data into a mesh
+		buildMesh(pMesh.getPointer(), mergeSubMeshes);
+
+        if(tangents)
+        {
+            Ogre::LogManager::getSingleton().logMessage("Calculating tangents");
+            unsigned short src, dest;
+            if (pMesh->suggestTangentVectorBuildParams(src, dest))
+            {
+                pMesh->buildTangentVectors(src, dest);
+            }
+            else
+            {
+                Ogre::LogManager::getSingleton().logMessage("Could not derive tangents parameters");
+            }
+        }
+
+		Ogre::LogManager::getSingleton().logMessage("** OGRE Mesh Export Complete **");
+    }
+ 
+	void OgreMeshSerializer::buildMesh(Ogre::Mesh* pMesh, bool mergeSubmeshes)
+	{
+		if (!mergeSubmeshes)
+		{
+			// build contents of this polymesh into ProtoSubMesh(es)
+			generateEntityAABB(pMesh);
+			
+			// export out at the end of every PolygonMesh
+			exportSubMeshes(pMesh);
+		}
+		// TODO
+		if (mergeSubmeshes)
+		{
+			// build contents of this polymesh into ProtoSubMesh(es)
+			mEntity->mergeSubEntities();
+
+			generateEntityAABB(pMesh);
+
+			// export out the combined result
+			exportSubMeshes(pMesh);
+		}		
+	}
+ 
+	void OgreMeshSerializer::generateEntityAABB(Ogre::Mesh* pMesh)
+	{
+		// Bounds calculation
+		Ogre::Real squaredRadius = 0.0f;
+        Ogre::Vector3 min, max;
+        bool first = true;
+		
+		for (unsigned int iSubEntity = 0; iSubEntity < mEntity->getNumSubEntities(); iSubEntity++)
+		{
+			for (size_t jVertex = 0; jVertex < mEntity->getSubEntity(iSubEntity)->getNumVertices(); jVertex++)
+			{
+				if (first)
+				{
+					squaredRadius = mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position.squaredLength();
+					min = max = mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position;
+					first = false;
+				}
+				else
+				{
+					size_t numVertices = (unsigned int)mEntity->getSubEntity(iSubEntity)->getNumVertices();
+					//Ogre::LogManager::getSingleton().logMessage("NumVertices:" + Ogre::StringConverter::toString(numVertices));
+					//Ogre::LogManager::getSingleton().logMessage("IDVertex:" + Ogre::StringConverter::toString(jVertex) + "--" + Ogre::StringConverter::toString(iSubEntity) + "--" + Ogre::StringConverter::toString(mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position));
+					squaredRadius = 
+						std::max(squaredRadius,mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position.squaredLength());
+					min.makeFloor(mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position);
+					max.makeCeil(mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position);
+				}
+			}
+        }
+
+		// Merge bounds
+		Ogre::AxisAlignedBox box;
+        box.setExtents(min, max);
+        box.merge(pMesh->getBounds());
+        pMesh->_setBounds(box);
+        pMesh->_setBoundingSphereRadius(
+			std::max(
+				pMesh->getBoundingSphereRadius(), 
+				Ogre::Math::Sqrt(squaredRadius)));	
+
+		Ogre::LogManager::getSingleton().logMessage("Bounds:" + Ogre::StringConverter::toString(pMesh->getBoundingSphereRadius()) + " -- Generated:" + Ogre::StringConverter::toString(pMesh->getBounds().isNull()));
+	}
+ 
+	void OgreMeshSerializer::exportSubMeshes(Ogre::Mesh* pMesh)
+	{
+		for (unsigned int iSubEntity = 0; iSubEntity < mEntity->getNumSubEntities(); iSubEntity++)
+		{
+			exportSubMesh(pMesh,mEntity->getSubEntity(iSubEntity));
+		}		
+	}
+ 
+	void OgreMeshSerializer::exportSubMesh(Ogre::Mesh* pMesh, SubEntity *subEntity)
+	{		
+        Ogre::SubMesh* sm = 0;
+        if (subEntity->getName() == "")
+        {
+            sm = pMesh->createSubMesh();
+        }
+        else
+        {
+            sm = pMesh->createSubMesh(subEntity->getName());
+        }
+        // Set material
+        sm->setMaterialName(subEntity->getMaterialName());
+        // never use shared geometry
+        sm->useSharedVertices = false;
+		sm->vertexData = new Ogre::VertexData();
+        // always do triangle list
+        sm->indexData->indexCount = subEntity->getNumFaces()*3;
+		
+		sm->vertexData->vertexCount = subEntity->getNumVertices();
+        // Determine index size
+        bool use32BitIndexes = false;
+        if (subEntity->getNumVertices() > 65536)
+        {
+            use32BitIndexes = true;
+        }
+
+        sm->indexData->indexBuffer = 
+            Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
+            use32BitIndexes ? Ogre::HardwareIndexBuffer::IT_32BIT : Ogre::HardwareIndexBuffer::IT_16BIT,
+            sm->indexData->indexCount,
+            Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
+
+        if (use32BitIndexes)
+        {
+            unsigned int* pIdx = static_cast<unsigned int*>(
+                sm->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
+                writeIndexes(pIdx,subEntity);
+                sm->indexData->indexBuffer->unlock();
+        }
+        else
+        {
+            unsigned short int* pIdx = static_cast<unsigned short int*>(
+                sm->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
+				writeIndexes(pIdx,subEntity);
+				sm->indexData->indexBuffer->unlock();
+        }
+		
+		
+        // define vertex declaration
+        unsigned buf = 0;
+        size_t offset = 0;
+		// always add position and normal
+        sm->vertexData->vertexDeclaration->addElement(buf, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
+		offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
+        sm->vertexData->vertexDeclaration->addElement(buf, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
+		offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
+
+		// Optional vertex colour
+        if(subEntity->hasVertexColours())
+        {
+            sm->vertexData->vertexDeclaration->addElement(buf, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
+			offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
+        }
+
+        // Define UVs
+        for (unsigned short uvi = 0; uvi < subEntity->getNumTexCoordSets(); uvi++)
+        {
+			Ogre::VertexElementType uvType = Ogre::VertexElement::multiplyTypeCount(Ogre::VET_FLOAT1, subEntity->getTexCoordDimensions(uvi));
+            sm->vertexData->vertexDeclaration->addElement(buf, offset, uvType, Ogre::VES_TEXTURE_COORDINATES, uvi);
+			offset += Ogre::VertexElement::getTypeSize(uvType);
+        }
+
+        // create & fill buffer(s)
+        for (unsigned short b = 0; b <= sm->vertexData->vertexDeclaration->getMaxSource(); ++b)
+        {
+            createVertexBuffer(sm->vertexData, b, subEntity->getUniqueVertices());
+        }
+	}
+ 
+    template <typename T> 
+    void OgreMeshSerializer::writeIndexes(T* buf, SubEntity *subEntity)
+    {
+        for (unsigned int i = 0;  i < subEntity->getNumFaces(); i++)
+        {			
+			Ogre::Vector3 indexes = subEntity->getFaceVerticesIDs(i);
+			unsigned int i0, i1, i2;
+			i0 = (unsigned int)indexes[0];
+			i1 = (unsigned int)indexes[1];
+			i2 = (unsigned int)indexes[2];
+            *buf++ = static_cast<T>(i0);
+			*buf++ = static_cast<T>(i1);
+			*buf++ = static_cast<T>(i2);
+        }
+    }
+
+	void OgreMeshSerializer::createVertexBuffer(Ogre::VertexData* vd, 
+		unsigned short bufIdx, UniqueVertexList *uniqueVertexList)
+    {
+		Ogre::HardwareVertexBufferSharedPtr vbuf = 
+			Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
+            	vd->vertexDeclaration->getVertexSize(bufIdx),
+            	vd->vertexCount, 
+            	Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
+        vd->vertexBufferBinding->setBinding(bufIdx, vbuf);
+        size_t vertexSize = vd->vertexDeclaration->getVertexSize(bufIdx);
+
+        char* pBase = static_cast<char*>(
+				vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
+
+		Ogre::VertexDeclaration::VertexElementList elems = 
+			vd->vertexDeclaration->findElementsBySource(bufIdx);
+		Ogre::VertexDeclaration::VertexElementList::iterator ei, eiend;
+        eiend = elems.end();
+        float* pFloat;
+        Ogre::RGBA* pRGBA;
+
+        UniqueVertexList::iterator srci = uniqueVertexList->begin();
+
+        for (size_t v = 0; v < vd->vertexCount; ++v, ++srci)
+        {
+            for (ei = elems.begin(); ei != eiend; ++ei)
+            {
+				Ogre::VertexElement& elem = *ei;
+                switch(elem.getSemantic())
+                {
+                case Ogre::VES_POSITION:
+                    elem.baseVertexPointerToElement(pBase, &pFloat);
+                    *pFloat++ = srci->position.x;
+                    *pFloat++ = srci->position.y;
+                    *pFloat++ = srci->position.z;
+                    break;
+                case Ogre::VES_NORMAL:
+                    elem.baseVertexPointerToElement(pBase, &pFloat);
+                    *pFloat++ = srci->normal.x;
+                    *pFloat++ = srci->normal.y;
+                    *pFloat++ = srci->normal.z;
+                    break;
+                case Ogre::VES_DIFFUSE:
+                    elem.baseVertexPointerToElement(pBase, &pRGBA);
+                    *pRGBA = srci->colour;
+                    break;
+                case Ogre::VES_TEXTURE_COORDINATES:
+                    elem.baseVertexPointerToElement(pBase, &pFloat);
+					for (int t = 0; t < Ogre::VertexElement::getTypeCount(elem.getType()); ++t)
+					{
+						Ogre::Real val = srci->uv[elem.getIndex()][t];
+						*pFloat++ = val;
+					}
+                    break;
+                }
+            }
+            pBase += vertexSize;
+        }
+        vbuf->unlock();
+
+    }
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKdTreeClusterGenerator.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKdTreeClusterGenerator.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKdTreeClusterGenerator.cpp	(revision 699)
@@ -0,0 +1,289 @@
+#include <LBBCKdTreeClusterGenerator.h>
+
+namespace LBBC {
+
+void KdTreeClusterGenerator::setAlpha(float value)
+{
+	mAlpha = value;
+}
+
+float KdTreeClusterGenerator::getAlpha()
+{
+	return mAlpha;
+}
+
+void KdTreeClusterGenerator::setNumIterations(unsigned int value)
+{
+	mNumIterations = value;
+}
+
+unsigned int KdTreeClusterGenerator::getNumIterations()
+{
+	return mNumIterations;
+}
+
+unsigned int KdTreeClusterGenerator::findBestBillboard(Leaf *leaf)
+{
+	float minError = FLT_MAX;
+	unsigned int iMinErrorBillboard = 0;
+	
+	Ogre::Vector3 normalLeaf = leaf->getLeafNormal();
+	Ogre::Vector3 positionLeaf = leaf->getPosition();		
+	
+	for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++)
+	{
+		BBC::Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);
+		BillboardKdTreeClusterData *billboardClusterData = (BillboardKdTreeClusterData*)billboard->getBillboardClusterData();
+		Ogre::Vector3 normalBillboard = billboardClusterData->getNormal();			
+
+		float d = (normalBillboard.dotProduct(positionLeaf) +  billboardClusterData->getD());
+		float cosine = normalBillboard.dotProduct(normalLeaf);
+		float error = (d*d) + ( 1 - cosine * cosine ) * mAlpha;
+
+		if (error < minError)
+		{
+			minError = error;
+			iMinErrorBillboard = billboard->getBillboardHandle();
+		}				
+	}
+	return iMinErrorBillboard;
+}
+
+void KdTreeClusterGenerator::assignLeafBillboard(Leaf *leaf, BBC::Billboard *billboard)
+{
+	BillboardKdTreeClusterData *billboardClusterData = (BillboardKdTreeClusterData*)billboard->getBillboardClusterData();			
+	BBC::EntityCluster *entityCluster = billboardClusterData->getEntityCluster();
+
+	BBC::EntityClusterData *entityClusterData = new LeafKdTreeClusterData();
+	entityClusterData->setEntity(leaf);
+	entityCluster->addEntityClusterData(entityClusterData);
+}
+
+void KdTreeClusterGenerator::splitLeafDistribution()
+{
+	for (unsigned int iLeaf = 0; iLeaf < mEntityDistribution->getNumEntities(); iLeaf++)
+	{
+		Leaf *leaf = (Leaf*)mEntityDistribution->getEntity(iLeaf);
+		unsigned int iMinErrorBillboard = findBestBillboard(leaf);
+
+		BBC::Billboard *billboardMinError = mBillboardCloud->getBillboard(iMinErrorBillboard);
+		assignLeafBillboard(leaf,billboardMinError);
+	}
+}
+
+void KdTreeClusterGenerator::recomputeBillboard(BBC::Billboard *billboard)
+{
+	Ogre::Matrix3 nmii = Ogre::Matrix3::ZERO;
+	Ogre::Matrix3 nmiiSum = Ogre::Matrix3::ZERO;
+	Ogre::Matrix3 miiSum = Ogre::Matrix3::ZERO;
+	Ogre::Matrix3 mii = Ogre::Matrix3::ZERO;	
+	Ogre::Matrix3 mijSum = Ogre::Matrix3::ZERO;
+	Ogre::Matrix3 mij = Ogre::Matrix3::ZERO; 
+	Ogre::Vector3 lastY = Ogre::Vector3::ZERO;
+	Ogre::Vector3 piSum = Ogre::Vector3::ZERO;
+	Ogre::Vector3 normSum = Ogre::Vector3::ZERO;
+
+	BillboardKdTreeClusterData *billboardClusterData = (BillboardKdTreeClusterData*)billboard->getBillboardClusterData();			
+	BBC::EntityCluster *entityCluster = billboardClusterData->getEntityCluster();
+
+	for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++)
+	{
+		Leaf* leaf = (Leaf*)entityCluster->getEntityClusterData(iLeaf)->getEntity();
+		Ogre::Vector3 pi = leaf->getPosition();	
+		Ogre::Vector3 norm2 = leaf->getLeafNormal();	
+		piSum = piSum + pi * (1.0 / (float)entityCluster->getNumEntitiesClusterData());
+			
+		mii[0][0] = pi.x * pi.x;
+		mii[0][1] = pi.x * pi.y;
+		mii[0][2] = pi.x * pi.z;
+		mii[1][0] = pi.y * pi.x;
+		mii[1][1] = pi.y * pi.y;
+		mii[1][2] = pi.y * pi.z;
+		mii[2][0] = pi.z * pi.x;
+		mii[2][1] = pi.z * pi.y;
+		mii[2][2] = pi.z * pi.z;	
+		nmii[0][0] = norm2.x * norm2.x;
+		nmii[0][1] = norm2.x * norm2.y;
+		nmii[0][2] = norm2.x * norm2.z;
+		nmii[1][0] = norm2.y * norm2.x;
+		nmii[1][1] = norm2.y * norm2.y;
+		nmii[1][2] = norm2.y * norm2.z;
+		nmii[2][0] = norm2.z * norm2.x;
+		nmii[2][1] = norm2.z * norm2.y;
+		nmii[2][2] = norm2.z * norm2.z;	
+		
+		nmiiSum = nmiiSum + ( nmii * (1.0 / (float)entityCluster->getNumEntitiesClusterData()));
+
+		miiSum = miiSum + ( mii * (1.0 / (float)entityCluster->getNumEntitiesClusterData()));
+
+		// Generate the initial value for the iterative method as the average...
+		Ogre::Vector3 norm = leaf->getLeafNormal();
+		lastY = lastY + norm;
+
+		// Generate the sum normal of all the leaves associated to the plane...
+		normSum = normSum + norm;
+	}
+	
+	mijSum[0][0] = piSum.x * piSum.x;
+	mijSum[0][1] = piSum.x * piSum.y;
+	mijSum[0][2] = piSum.x * piSum.z;
+	mijSum[1][0] = piSum.y * piSum.x;
+	mijSum[1][1] = piSum.y * piSum.y;
+	mijSum[1][2] = piSum.y * piSum.z;
+	mijSum[2][0] = piSum.z * piSum.x;
+	mijSum[2][1] = piSum.z * piSum.y;
+	mijSum[2][2] = piSum.z * piSum.z;	
+
+	Ogre::Matrix3 mA = miiSum - mijSum;
+	mA = mA - (mAlpha * nmiiSum);
+	mA = mA.Inverse();
+
+	lastY.normalise();
+	normSum.normalise();
+
+	// Apply the iterative approach
+	Ogre::Vector3 currY;
+	currY = mA * lastY;
+	currY.normalise();
+
+	for(unsigned int icount = 0; icount < 100; icount++)
+	{
+		lastY = currY;
+		currY = mA * lastY;
+		currY.normalise();
+	}
+
+	// Generate the d parameter...
+	float sumD = 0;
+	for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++)
+	{
+		Leaf* leaf = (Leaf*)entityCluster->getEntityClusterData(iLeaf)->getEntity();
+		Ogre::Vector3 pi = leaf->getPosition();	
+		sumD = sumD + pi.dotProduct(currY);
+	}
+
+	sumD = - sumD / (float)entityCluster->getNumEntitiesClusterData();
+
+	billboardClusterData->setNormal(currY);
+	billboardClusterData->setD(sumD);
+}
+
+void KdTreeClusterGenerator::recomputeBillboardCloud()
+{
+	for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++)
+	{
+		BBC::Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);
+		recomputeBillboard(billboard);
+	}
+}
+
+void KdTreeClusterGenerator::iterativeRecomputeBillboardCloud()
+{
+	for (unsigned int iIteration = 0; iIteration < mNumIterations; iIteration++)
+	{
+		recomputeBillboardCloud();
+	}
+}
+
+void KdTreeClusterGenerator::generate() 
+{
+	// Generate the initial random billboards and cluster the leaves with them
+	// 1. Create the billboards and assign an initial random orientation
+	initializeBillboardCloud();
+	// 2. Split the leaf distribution, each leaf in the it's best candidate billboard
+	splitLeafDistribution();
+	// 3. The billboard is recomputed in order to minimize the total error 
+	// for the leaves of this cluster with respect to this plane.
+	iterativeRecomputeBillboardCloud();
+	// 4. Generate each entity cluster packed entity and compute the bounding quad for each entity cluster
+	generateBillboardCloudBounds();
+}
+
+BBC::Billboard* KdTreeClusterGenerator::createBillboard()
+{
+	BBC::Billboard *billboard = new BBC::Billboard();
+	mBillboardCloud->addBillboard(billboard);
+	return billboard;
+}
+
+void KdTreeClusterGenerator::initializeBillboardClusterData(BBC::Billboard *billboard)
+{
+	BBC::BillboardClusterData *billboardClusterData = new BillboardKdTreeClusterData();
+	billboard->setBillboardClusterData(billboardClusterData);
+	BBC::EntityCluster *entityCluster = new BBC::EntityCluster();
+	billboard->getBillboardClusterData()->setEntityCluster(entityCluster);
+}
+
+void KdTreeClusterGenerator::generateBillboardCloudBounds()
+{
+	for (unsigned int iBillboard = 0; iBillboard < this->getMaxNumBillboards(); iBillboard++)
+	{
+		BBC::Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);		
+		BBC::EntityCluster *entityCluster = billboard->getBillboardClusterData()->getEntityCluster();
+
+		if (entityCluster->getNumEntitiesClusterData() > 0)
+		{					
+			entityCluster->generateEntityCluster();
+			billboard->getBillboardClusterData()->generateBillboardBoundingQuad();
+		}
+	}
+}
+
+void KdTreeClusterGenerator::initializeRandomBillboard(BBC::Billboard *billboard)
+{
+	float dMin = ((LeafDistribution*)mEntityDistribution)->getMinD();
+	float dMax = ((LeafDistribution*)mEntityDistribution)->getMaxD();
+
+	float d = Ogre::Math::RangeRandom(dMin,dMax);
+
+	//Ogre::Vector3 normalMin = ((LeafDistribution*)mEntityDistribution)->getMinNormal();
+	//Ogre::Vector3 normalMax = ((LeafDistribution*)mEntityDistribution)->getMaxNormal();
+	Ogre::Vector3 normal;
+	normal.x = Ogre::Math::RangeRandom(-1,1); // Ogre::Math::RangeRandom(normalMin.x,normalMax.x);
+	normal.y = Ogre::Math::RangeRandom(-1,1); // Ogre::Math::RangeRandom(normalMin.y,normalMax.y);
+	normal.z = Ogre::Math::RangeRandom(-1,1); // Ogre::Math::RangeRandom(normalMin.z,normalMax.z);
+	
+	BillboardKdTreeClusterData *mBillboardClusterData = (BillboardKdTreeClusterData *)billboard->getBillboardClusterData();
+	mBillboardClusterData->setNormal(normal);
+	mBillboardClusterData->setD(d);
+}
+
+void KdTreeClusterGenerator::initializeBillboardCloud()
+{
+	for (unsigned int iBillboard = 0; iBillboard < this->getMaxNumBillboards(); iBillboard++)
+	{
+		BBC::Billboard *billboard = createBillboard();
+		initializeBillboardClusterData(billboard);
+		initializeRandomBillboard(billboard);
+	}
+}
+
+void KdTreeClusterGenerator::init() 
+{
+}
+
+KdTreeClusterGenerator::KdTreeClusterGenerator() 
+{
+}
+
+KdTreeClusterGenerator::~KdTreeClusterGenerator() 
+{
+	for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++)
+	{
+		BBC::Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);
+		BillboardKdTreeClusterData *billboardKdTreeClusterData = (BillboardKdTreeClusterData*)billboard->getBillboardClusterData();
+		BBC::EntityCluster *entityCluster = billboardKdTreeClusterData->getEntityCluster();
+
+		for (unsigned int iEntityClusterData = 0; iEntityClusterData < entityCluster->getNumEntitiesClusterData(); iEntityClusterData++)
+		{
+			LeafKdTreeClusterData *entityClusterData = (LeafKdTreeClusterData*) entityCluster->getEntityClusterData(iEntityClusterData);
+			delete entityClusterData;
+		}
+
+		delete entityCluster;
+		delete billboardKdTreeClusterData;
+	}
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardGroup.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardGroup.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardGroup.cpp	(revision 699)
@@ -0,0 +1,16 @@
+
+#include "BBCBillboardGroup.h"
+
+namespace BBC {
+
+int BillboardGroup::getBillboardHandle() 
+{
+	return 0;
+}
+
+void BillboardGroup::setBillboardHandle() 
+{
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGPlane3.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGPlane3.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGPlane3.cpp	(revision 699)
@@ -0,0 +1,10 @@
+
+#include "IMGPlane3.h"
+
+namespace IMG {
+
+Plane3::~Plane3() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudTextureGenerator.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudTextureGenerator.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudTextureGenerator.cpp	(revision 699)
@@ -0,0 +1,7 @@
+
+#include "BBCBillboardCloudTextureGenerator.h"
+
+namespace BBC {
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGBsp.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGBsp.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGBsp.cpp	(revision 699)
@@ -0,0 +1,10 @@
+
+#include "IMGBsp.h"
+
+namespace IMG {
+
+Bsp::~Bsp() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudSerializer.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudSerializer.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudSerializer.cpp	(revision 699)
@@ -0,0 +1,27 @@
+
+#include "BBCBillboardCloudSerializer.h"
+#include "BBCBillboardCloud.h"
+
+namespace BBC {
+
+BillboardCloudSerializer::BillboardCloudSerializer() {
+}
+
+BillboardCloudSerializer::~BillboardCloudSerializer() {
+}
+
+void BillboardCloudSerializer::setBillboardCloud(BillboardCloud *value) {
+	mBillboardCloud = value;
+}
+
+BillboardCloud * BillboardCloudSerializer::getBillboardCloud() 
+{
+	return mBillboardCloud;
+}
+
+void BillboardCloudSerializer::writeBillboardCloud(TiXmlDocument *document)
+{
+	Ogre::LogManager::getSingleton().logMessage("BillboardCloudSerializer::writeBillboardCloud method not implemented.");
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntity.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntity.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntity.cpp	(revision 699)
@@ -0,0 +1,542 @@
+
+#include "BBCEntity.h"
+
+namespace BBC {
+
+Entity::Entity() 
+{
+	createSubEntity();
+}
+
+Entity::~Entity()	 
+{
+	for (unsigned int iSubEntity = 0; iSubEntity < getNumSubEntities(); iSubEntity++)
+	{
+		SubEntity *subEntity = getSubEntity(iSubEntity);
+		delete subEntity;
+	}
+}
+
+void Entity::createSubEntity()
+{
+	SubEntity *subEntity = new SubEntity();
+	mSubEntityList.push_back(subEntity);
+}
+
+void Entity::addSubEntity(SubEntity *value)
+{
+	mSubEntityList.push_back(value);
+}
+
+SubEntity* Entity::getSubEntity(unsigned int index)
+{
+	return mSubEntityList[index];
+}
+
+void Entity::removeSubEntity(unsigned int index)
+{
+	SubEntity *subEntity = mSubEntityList[index];
+	mSubEntityList.erase(mSubEntityList.begin()+index);
+	delete subEntity;
+}
+
+void Entity::setSubEntitiesDistinctVertexColours()
+{
+	for (unsigned int iSubEntity = 0; iSubEntity < mSubEntityList.size(); iSubEntity++)
+	{
+		mSubEntityList[iSubEntity]->enableVertexColours(true);
+		float fRed = Ogre::Math::RangeRandom(0.0,1.0);
+		float fGreen = Ogre::Math::RangeRandom(0.0,1.0);
+		float fBlue = Ogre::Math::RangeRandom(0.0,1.0);
+		Ogre::ColourValue subEntityColour = Ogre::ColourValue(1.0,fRed,fGreen,fBlue);
+		for (unsigned int iVertex = 0; iVertex < mSubEntityList[iSubEntity]->getNumVertices(); iVertex++)
+		{
+			mSubEntityList[iSubEntity]->setVertexColour(iVertex, subEntityColour.getAsRGBA());
+		}
+	}
+}
+
+Ogre::Mesh* Entity::getMesh() 
+{
+	return mMesh;
+}
+
+void Entity::setMesh(Ogre::Mesh *value) 
+{
+	mMesh = value;
+}
+
+unsigned int Entity::getEntityHandle() {
+	return mEntityHandle;
+}
+
+void Entity::setEntityHandle(unsigned int value) 
+{
+	mEntityHandle = value;
+}
+
+void Entity::loadMesh(bool mergeSubMeshes = false)
+{
+   Ogre::Vector3 position = Ogre::Vector3::ZERO;
+   Ogre::Quaternion orient = Ogre::Quaternion(1.0,1.0,1.0,1.0);
+   Ogre::Vector3 scale = Ogre::Vector3::ZERO;
+   unsigned int coordset = 0;
+   unsigned short dimTexCoord = 2;
+
+   getMeshPositions(position,orient,scale,mergeSubMeshes);
+   getMeshNormals(orient,scale,mergeSubMeshes);
+   getMeshVertexColours(mergeSubMeshes);
+   getMeshTexCoords(mergeSubMeshes);
+   getMeshFacesVerticesID(mergeSubMeshes);
+}
+
+void Entity::sincronizeNumSubEntities()
+{
+	if (this->getNumSubEntities() < mMesh->getNumSubMeshes())
+	{
+		while (this->getNumSubEntities() < mMesh->getNumSubMeshes())
+		{
+			this->createSubEntity();
+		}
+	}
+
+	if (this->getNumSubEntities() > mMesh->getNumSubMeshes())
+	{
+		while (this->getNumSubEntities() > mMesh->getNumSubMeshes())
+		{
+			this->removeSubEntity(this->getNumSubEntities()-1);
+		}
+	}
+}
+
+void Entity::getMeshPositions(Ogre::Vector3 position, Ogre::Quaternion orient, Ogre::Vector3 scale, bool mergeSubMeshes)
+{	
+	bool added_shared = false;
+	size_t current_offset = 0;
+	size_t shared_offset = 0;
+	size_t next_offset = 0;
+
+	unsigned int numSubMeshes = mMesh->getNumSubMeshes();
+	sincronizeNumSubEntities();
+	
+	added_shared = false;
+	for (unsigned short i = 0; i < mMesh->getNumSubMeshes(); i++)
+	{
+		Ogre::SubMesh* subMesh = mMesh->getSubMesh(i);
+		Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mMesh->sharedVertexData : subMesh->vertexData;
+
+		if ((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !added_shared))
+		{
+			if (subMesh->useSharedVertices)
+			{
+				added_shared = true;
+				shared_offset = current_offset;
+			}
+
+			const Ogre::VertexElement* positionElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
+			Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(positionElem->getSource());
+			unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
+			float* pReal;
+
+			for(size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize())
+			{
+				positionElem->baseVertexPointerToElement(vertex, &pReal);
+		        Ogre::Vector3 position(pReal[0], pReal[1], pReal[2]);
+				
+				if (!mergeSubMeshes)
+				{
+					UniqueVertex uniqueVertex;
+					uniqueVertex.position = position;
+					this->getSubEntity(i)->addUniqueVertex(uniqueVertex);				
+				}
+				else
+				{
+					UniqueVertex uniqueVertex;
+					uniqueVertex.position = position;					
+
+					this->getSubEntity(0)->addUniqueVertex(uniqueVertex);				
+				}
+			}
+			vbuf->unlock();
+			next_offset += vertexData->vertexCount;
+		}      
+	}
+    current_offset = next_offset;
+}
+
+
+void Entity::getMeshNormals(Ogre::Quaternion orient, Ogre::Vector3 scale, bool mergeSubMeshes)
+{
+	bool added_shared = false;
+	size_t current_offset = 0;
+	size_t shared_offset = 0;
+	size_t next_offset = 0;
+
+	unsigned int numSubMeshes = mMesh->getNumSubMeshes();
+	sincronizeNumSubEntities();
+	
+	added_shared = false;
+	for (unsigned short i = 0; i < mMesh->getNumSubMeshes(); i++)
+	{
+		Ogre::SubMesh* subMesh = mMesh->getSubMesh(i);
+		Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mMesh->sharedVertexData : subMesh->vertexData;
+
+		if ((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !added_shared))
+		{
+			if (subMesh->useSharedVertices)
+			{
+				added_shared = true;
+				shared_offset = current_offset;
+			}
+
+			const Ogre::VertexElement* normalElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_NORMAL);
+			Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(normalElem->getSource());
+			unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
+			float* pReal;
+
+			for(size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize())
+			{
+				normalElem->baseVertexPointerToElement(vertex, &pReal);
+		        Ogre::Vector3 normal(pReal[0], pReal[1], pReal[2]);
+
+				if (!mergeSubMeshes)
+				{
+					this->getSubEntity(i)->setNormal(j,normal);	
+				}
+				else
+				{
+					this->getSubEntity(0)->setNormal(j,normal);								
+				}
+			}
+			vbuf->unlock();
+			next_offset += vertexData->vertexCount;
+		}      
+	}
+    current_offset = next_offset;
+}
+
+void Entity::getMeshVertexColours(bool mergeSubMeshes)
+{
+	bool added_shared = false;
+	size_t current_offset = 0;
+	size_t shared_offset = 0;
+	size_t next_offset = 0;
+
+	unsigned int numSubMeshes = mMesh->getNumSubMeshes();
+	sincronizeNumSubEntities();
+	
+	added_shared = false;
+	for (unsigned short i = 0; i < mMesh->getNumSubMeshes(); i++)
+	{
+		Ogre::SubMesh* subMesh = mMesh->getSubMesh(i);
+		Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mMesh->sharedVertexData : subMesh->vertexData;
+
+		if ((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !added_shared))
+		{
+			if (subMesh->useSharedVertices)
+			{
+				added_shared = true;
+				shared_offset = current_offset;
+			}
+
+			const Ogre::VertexElement* colourElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_DIFFUSE);
+            if (colourElem)
+            {
+				//Ogre::LogManager::getSingleton().logMessage("Has vertex colours!");
+				Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(colourElem->getSource());
+				unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
+				Ogre::RGBA *pSrcRGBA;
+
+				for(size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize())
+				{
+					if (colourElem)
+					{
+						colourElem->baseVertexPointerToElement(vertex, &pSrcRGBA);
+					}
+					
+					Ogre::ColourValue colour((Ogre::RGBA)(*pSrcRGBA));
+
+					if (!mergeSubMeshes)
+					{
+						this->getSubEntity(i)->setVertexColour(j,colour.getAsRGBA());	
+					}
+					else
+					{				
+						this->getSubEntity(0)->setVertexColour(j,colour.getAsRGBA());
+					}
+				}
+				vbuf->unlock();
+				next_offset += vertexData->vertexCount;
+
+				if (!mergeSubMeshes)
+				{
+					this->getSubEntity(i)->enableVertexColours(true);
+				}
+				else
+				{
+					this->getSubEntity(0)->enableVertexColours(true);
+				}
+			}
+		}      
+	}
+    current_offset = next_offset;
+}
+
+void Entity::getMeshTexCoords(bool mergeSubMeshes)
+{	
+	bool added_shared = false;
+	size_t current_offset = 0;
+	size_t shared_offset = 0;
+	size_t next_offset = 0;
+
+	unsigned int numSubMeshes = mMesh->getNumSubMeshes();
+	sincronizeNumSubEntities();
+	
+	added_shared = false;
+	for (unsigned short i = 0; i < mMesh->getNumSubMeshes(); i++)
+	{
+		Ogre::SubMesh* subMesh = mMesh->getSubMesh(i);
+		Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mMesh->sharedVertexData : subMesh->vertexData;
+
+		if ((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !added_shared))
+		{
+			if (subMesh->useSharedVertices)
+			{
+				added_shared = true;
+				shared_offset = current_offset;
+			}
+
+			const Ogre::VertexElement* texcoordElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
+			Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(texcoordElem->getSource());
+			unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
+
+			Ogre::VertexDeclaration* decl = vertexData->vertexDeclaration;
+			Ogre::VertexBufferBinding* bind = vertexData->vertexBufferBinding;
+			Ogre::VertexBufferBinding::VertexBufferBindingMap::const_iterator b, bend;
+			bend = bind->getBindings().end();
+			// Iterate over buffers
+			for (b = bind->getBindings().begin(); b != bend; ++b)
+			{
+				const Ogre::HardwareVertexBufferSharedPtr vbuf = b->second;
+				unsigned short bufferIdx = b->first;
+				// Get all the elements that relate to this buffer
+				Ogre::VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufferIdx);
+				Ogre::VertexDeclaration::VertexElementList::iterator it, itend;
+				itend = elems.end();
+
+				// Skim over the elements to set up the general data
+				unsigned short numTextureCoords = 0;
+				std::vector<unsigned int> baseTexCoordSetIndex;
+				for (it = elems.begin(); it != itend; ++it)
+				{
+					Ogre::VertexElement& elem = *it;
+					if (elem.getSemantic() == Ogre::VES_TEXTURE_COORDINATES)
+					{
+						if (numTextureCoords == 0)
+						{
+							baseTexCoordSetIndex.push_back(0);
+							baseTexCoordSetIndex.push_back(Ogre::VertexElement::getTypeCount(elem.getType()));
+						}
+						++numTextureCoords;
+					}
+				}
+
+				// There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
+				// as a second argument. So make it float, to avoid trouble when Ogre::Real will be
+				// compiled/typedefed as double:
+				// Ogre::Real* pReal;
+				float* pReal;
+
+				unsigned int baseTexCoord = 0;
+				unsigned int texCoordSet = 0;
+				unsigned int dimBaseTexCoord = 0;
+				for (unsigned int texCoordSet = 0; texCoordSet < numTextureCoords; texCoordSet++)
+				{
+					for (unsigned int iTexCoordSet = 0; iTexCoordSet <= texCoordSet; iTexCoordSet++)
+					{
+						baseTexCoord = baseTexCoord + baseTexCoordSetIndex[iTexCoordSet];
+					}
+					unsigned short dimTexCoord = (unsigned short)baseTexCoordSetIndex[texCoordSet+1];
+					for (size_t j = 0; j < vertexData->vertexCount; j++, vertex += vbuf->getVertexSize())
+					{
+						texcoordElem->baseVertexPointerToElement(vertex, &pReal);
+						Ogre::Vector3 texcoord;
+						if (baseTexCoordSetIndex[texCoordSet+1] == 2)
+						{
+							texcoord = Ogre::Vector3(pReal[baseTexCoord + 0], pReal[baseTexCoord + 1], 0.0);
+							dimBaseTexCoord = 2;
+						}
+						else if (baseTexCoordSetIndex[texCoordSet + 1] == 3)
+						{
+							texcoord = Ogre::Vector3(pReal[baseTexCoord + 0], pReal[baseTexCoord + 1], pReal[baseTexCoord + 2]);
+							dimBaseTexCoord = 3;
+						}
+					
+						if (!mergeSubMeshes)
+						{
+							this->getSubEntity(i)->setTexCoord(j,texCoordSet,texcoord);
+						}
+						else
+						{
+							this->getSubEntity(0)->setTexCoord(j,texCoordSet,texcoord);				
+						}
+					}			
+			
+					if (!mergeSubMeshes)
+					{
+						this->getSubEntity(i)->addTextureCoordSet(dimBaseTexCoord);
+					}
+					else
+					{
+						if (i == 0)
+						{
+							this->getSubEntity(0)->addTextureCoordSet(dimBaseTexCoord);
+						}
+					}
+				}	
+			}			
+			vbuf->unlock();
+			next_offset += vertexData->vertexCount;
+		}      
+	}
+    current_offset = next_offset;
+}
+
+void Entity::getMeshFacesVerticesID(bool mergeSubMeshes)
+{
+	bool added_shared = false;
+	size_t current_offset = 0;
+	size_t shared_offset = 0;
+	size_t next_offset = 0;
+	size_t index_offset = 0;
+
+	unsigned int numSubMeshes = mMesh->getNumSubMeshes();
+	sincronizeNumSubEntities();
+
+	added_shared = false;
+
+	// Run through the submeshes again, adding the data into the arrays
+	for ( unsigned short i = 0; i < mMesh->getNumSubMeshes(); ++i)
+	{
+		Ogre::SubMesh* submesh = mMesh->getSubMesh(i);
+
+		Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mMesh->sharedVertexData : submesh->vertexData;
+
+		if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
+		{
+			if(submesh->useSharedVertices)
+			{
+				added_shared = true;
+				shared_offset = current_offset;
+			}
+			const Ogre::VertexElement* texcoordElem =
+			vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
+
+			Ogre::HardwareVertexBufferSharedPtr vbuf =
+			vertex_data->vertexBufferBinding->getBuffer(texcoordElem->getSource());
+
+			unsigned char* vertex =
+			static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
+
+			vbuf->unlock();
+			next_offset += vertex_data->vertexCount;
+		}
+
+		Ogre::IndexData* index_data = submesh->indexData;
+		size_t numTris = index_data->indexCount / 3;
+		Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
+    
+		bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
+
+		unsigned long*  pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
+		unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
+
+		size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
+
+
+		if ( use32bitindexes )
+		{
+			for ( size_t k = 0; k < numTris*3; k=k+3)
+			{
+				if (!mergeSubMeshes)
+				{
+					Ogre::Vector3 indices(k,k+1,k+2);
+					this->getSubEntity(i)->addFaceVerticesIDs(indices);				
+				}
+				else
+				{
+					Ogre::Vector3 indices = Ogre::Vector3(pLong[k] + static_cast<unsigned long>(offset),pLong[k+1] + static_cast<unsigned long>(offset),pLong[k+2] + static_cast<unsigned long>(offset));
+					this->getSubEntity(0)->addFaceVerticesIDs(indices);			
+				}			
+				index_offset++;
+			}
+		}
+		else
+		{
+			for ( size_t k = 0; k < numTris*3; k=k+3)
+			{				
+				if (!mergeSubMeshes)
+				{
+					Ogre::Vector3 indices(k,k+1,k+2);
+					this->getSubEntity(i)->addFaceVerticesIDs(indices);				
+				}
+				else
+				{
+					Ogre::Vector3 indices = Ogre::Vector3(static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset),static_cast<unsigned long>(pShort[k+1]) + static_cast<unsigned long>(offset),static_cast<unsigned long>(pShort[k+2]) + static_cast<unsigned long>(offset));
+					this->getSubEntity(0)->addFaceVerticesIDs(indices);			
+				}
+				index_offset++;
+			}	  
+		}		
+
+		ibuf->unlock();
+		current_offset = next_offset;
+	}
+}
+
+unsigned int Entity::getNumSubEntities()
+{
+	return static_cast<unsigned int>(mSubEntityList.size());
+}
+
+void Entity::mergeSubEntities()
+{
+	if (mSubEntityList.size() > 1)
+	{
+		unsigned int currentMaxNumVertices = mSubEntityList[0]->getNumVertices();
+		unsigned int iIDVertex = currentMaxNumVertices;
+		for (unsigned int iSubEntity = 1; iSubEntity < mSubEntityList.size(); iSubEntity++)
+		{
+			if (mSubEntityList[iSubEntity]->getNumTexCoordSets() == mSubEntityList[0]->getNumTexCoordSets())
+			{
+				for (unsigned int iVertex = 0; iVertex < mSubEntityList[iSubEntity]->getNumVertices(); iVertex++)
+				{
+					mSubEntityList[0]->addUniqueVertex(mSubEntityList[iSubEntity]->getUniqueVertex(iVertex));
+				}
+				
+				// Vertices IDs go from [0,NUMVERT-1] -> First new vertex should be NUMVERT...
+				for (unsigned int iFaceVerticesIDs = 0; iFaceVerticesIDs < mSubEntityList[iSubEntity]->getNumFaces(); iFaceVerticesIDs++)
+				{
+					mSubEntityList[0]->addFaceVerticesIDs(Ogre::Vector3(iIDVertex,iIDVertex+1,iIDVertex+2));				
+					iIDVertex = iIDVertex + 3;
+				}
+			}
+			else
+			{
+				Ogre::LogManager::getSingleton().logMessage("Error: The number of texture coord. sets is not the same in all the subentities...");
+			}			
+		}
+
+		for (unsigned int iSubEntity = 1; iSubEntity < mSubEntityList.size(); iSubEntity)
+		{
+			SubEntityList::iterator subEntityListIterator = mSubEntityList.begin()+iSubEntity;
+			// Gametools -- 02/03/2006
+			// BUG: If I delete the subentity other entities that reference it will lose it's data...
+			//SubEntity *subEntity = (*subEntityListIterator);
+			mSubEntityList.erase(mSubEntityList.begin()+iSubEntity);
+			//delete subEntity;
+		}
+	}
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityDistribution.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityDistribution.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityDistribution.cpp	(revision 699)
@@ -0,0 +1,26 @@
+
+#include "BBCEntityDistribution.h"
+
+namespace BBC {
+
+Entity* EntityDistribution::getEntity(unsigned unsigned int value)
+{
+	return mEntityList[value];
+}
+
+void EntityDistribution::addEntity(Entity *value)
+{
+	mEntityList.push_back(value);
+}
+
+void EntityDistribution::removeEntity(unsigned int value)
+{
+	mEntityList.erase(mEntityList.begin()+value);
+}
+
+unsigned int EntityDistribution::getNumEntities(void)
+{
+	return static_cast<unsigned int>(mEntityList.size());
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/main.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/main.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/main.cpp	(revision 699)
@@ -0,0 +1,91 @@
+#include <LBBC.h>
+#include <LBBCPrerequisites.h>
+
+struct CommandLineOptions
+{
+	Ogre::String cfg;
+};
+
+int findCommandLineOpts(int numargs, char** argv, Ogre::UnaryOptionList& unaryOptList, 
+						Ogre::BinaryOptionList& binOptList)
+{
+    int startIndex = 1;
+    for (int i = 1; i < numargs; ++i)
+    {
+		Ogre::String tmp(argv[i]);
+		if (Ogre::StringUtil::startsWith(tmp, "-"))
+        {
+			Ogre::UnaryOptionList::iterator ui = unaryOptList.find(argv[i]);
+            if(ui != unaryOptList.end())
+            {
+                ui->second = true;
+                ++startIndex;
+                continue;
+            }
+			Ogre::BinaryOptionList::iterator bi = binOptList.find(argv[i]);
+            if(bi != binOptList.end())
+            {
+                bi->second = argv[i+1];
+                startIndex += 2;
+                ++i;
+                continue;
+            }
+
+            // Invalid option
+            cout<<"Invalid option "<<tmp<<endl;
+
+        }
+    }
+    return startIndex;
+}
+
+CommandLineOptions parseArgs(int numArgs, char **args)
+{
+    CommandLineOptions opts;
+
+	Ogre::UnaryOptionList unOpt;
+	Ogre::BinaryOptionList binOpt;
+
+    binOpt["-cfg"] = "";
+    
+	int startIndex = findCommandLineOpts(numArgs, args, unOpt, binOpt);
+	Ogre::UnaryOptionList::iterator ui;
+	Ogre::BinaryOptionList::iterator bi;
+	
+    bi = binOpt.find("-cfg");
+    if (!bi->second.empty())
+    {
+		opts.cfg = bi->second;	
+    }	
+
+    return opts;
+}
+
+void help()
+{
+	cout<<"Please specify the parameter: -cfg sample.cfg"<<endl;
+}
+
+int main(int numargs, char** args)
+{	
+	/*
+	if (numargs < 2)
+    {
+        help();
+        return -1;
+    }
+    */
+
+	CommandLineOptions opts = parseArgs(numargs, args);
+
+	LBBC::Manager* manager = new LBBC::Manager();
+	LBBC::Manager::getSingleton().initialize();	
+
+	manager->runSample(Ogre::String(opts.cfg));	
+
+	LBBC::Manager::getSingleton().shutdown();
+	delete manager;	
+
+	return 0;
+}
+
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGVoxelList.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGVoxelList.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGVoxelList.cpp	(revision 699)
@@ -0,0 +1,105 @@
+
+#include "IMGVoxelList.h"
+#include "IMGVoxel.h"
+
+namespace IMG {
+
+VoxelList::VoxelList(){
+}
+
+//VoxelList(Ogre::AxisAlignedBox *);
+VoxelList::VoxelList(Ogre::Box * ){
+}
+
+//return the pointer to the list of voxels
+//bool SetBoundBox (Ogre::AxisAlignedBox *);				//set the boundbox
+bool VoxelList::SetBoundBox(Ogre::Box * ) {
+	return true;
+}
+
+//set the boundbox
+bool VoxelList::SetBoundBox(float , float , float , float , float , float ) {
+	return true;
+}
+
+//return the number of elements of list
+Voxel * VoxelList::GetVoxel(unsigned int ) {
+	return (Voxel*)0;
+}
+
+//return pointer to voxel(i)
+void VoxelList::Print() {
+}
+
+//print stats
+//bool AddPatch2Voxel(Patch *);				//add patch to voxels
+//this function also add the obspoly to voxels
+//calculate the voxel that Vector3 go into, called by AddPatch2Voxel  
+int VoxelList::CalculateVoxel(Ogre::Vector3 * ) {
+	return true;
+}
+
+//display the voxels in wireframe mode
+bool VoxelList::CreateVoxels() {
+	return true;
+}
+
+int VoxelList::Under(unsigned int ) {
+	return 0;
+}
+
+//return the under voxel, -1 if not exist
+int VoxelList::Over(unsigned int ) {
+	return 0;
+}
+
+//return the over voxel, -1 if not exist
+int VoxelList::Right(unsigned int ) {
+	return 0;
+}
+
+//return the Right voxel, -1 if not exist
+int VoxelList::Left(unsigned int ) {
+	return 0;
+}
+
+//return the Left voxel, -1 if not exist
+int VoxelList::Front(unsigned int ) {
+	return 0;
+}
+
+//return the Front voxel, -1 if not exist
+int VoxelList::Behind(unsigned int ) {
+	return 0;
+}
+
+//return the Behind voxel, -1 if not exist
+bool VoxelList::FirstX(unsigned int ) {
+	return true;
+}
+
+bool VoxelList::FirstY(unsigned int ) {
+	return true;
+}
+
+bool VoxelList::FirstZ(unsigned int ) {
+	return true;
+}
+
+bool VoxelList::LastX(unsigned int ) {
+	return true;
+}
+
+bool VoxelList::LastY(unsigned int ) {
+	return true;
+}
+
+bool VoxelList::LastZ(unsigned int ) {
+	return true;
+}
+
+VoxelList::~VoxelList() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCTimer.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCTimer.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCTimer.cpp	(revision 699)
@@ -0,0 +1,28 @@
+
+#include "BBCTimer.h"
+
+namespace BBC {
+
+void Timer::start()
+{
+	time(&mTimer);
+	mInitTime = localtime(&mTimer);
+}	
+
+void Timer::stop()
+{
+	time(&mTimer);
+	mEndTime= localtime(&mTimer);
+}
+
+void Timer::printStartTime()
+{
+	Ogre::LogManager::getSingleton().logMessage("Init " + Ogre::StringConverter::toString(mInitTime->tm_hour) + ":" + Ogre::StringConverter::toString(mInitTime->tm_min) + ":" + Ogre::StringConverter::toString(mInitTime->tm_sec));		
+}
+
+void Timer::printStopTime()
+{
+	Ogre::LogManager::getSingleton().logMessage("End " + Ogre::StringConverter::toString(mEndTime->tm_hour) + ":" + Ogre::StringConverter::toString(mEndTime->tm_min) + ":" + Ogre::StringConverter::toString(mEndTime->tm_sec));
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGNodeBsp.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGNodeBsp.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGNodeBsp.cpp	(revision 699)
@@ -0,0 +1,121 @@
+
+#include "IMGNodeBsp.h"
+
+namespace IMG {
+
+NodeBsp::NodeBsp(){
+	child[0] = NULL;
+	child[1] = NULL;
+	//bound.StartBoundingBox();
+	bound = NULL;
+	//id= NodeBsp::ID++;
+	id = -1;
+	fit = false;
+}
+
+Box2d * NodeBsp::GetBound() {
+ 
+	return bound;   
+}
+
+void NodeBsp::Print() {
+	printf("\nNode : %d, fit: %d", id, fit);
+	if (bound) bound->Print();
+	//if (plane) plane->Print();
+}
+
+//void SetPlane (Plane3 *pla) { plane = pla; }
+//Plane3 * GetPlane () { return plane; }
+NodeBsp * NodeBsp::Insert(int w, int h) {
+	//printf("\nInsert del node: :%d (%d, %d)\n", id, w,  h);
+	
+	if (this->fit == true) return NULL;
+	
+	if (this->child[0] != NULL && this->child[1] != NULL)
+	{
+		NodeBsp * new_node = child[0]->Insert (w, h);
+		
+		if (new_node) return new_node;
+		
+		return child[1]->Insert(w,h);
+	}
+	
+	if (!bound->In (w,h)) {//printf("\nNo hi quep!!!\n"); 
+				return NULL; }
+	
+	if (bound->FitPerfect(w,h)){ //printf("\nFit Perfectly: \n"); 
+				fit = true;  return this; }
+	
+	child[0] = new NodeBsp;
+	child[1] = new NodeBsp;
+	
+	int dw, dh;
+	Ogre::Vector2 min, max;
+	float width, height;
+	
+	bound->Print();
+	min = bound->GetMinimum();
+	max = bound->GetMaximum();
+	
+	width = max.x - min.x;
+	height = max.y - min.y;
+	
+	//printf("\nwidth: %.4f\n", width);
+	//printf("\nheigth: %.4f\n", height);
+	
+	dw = (int) width - w;
+	dh = (int) height - h;
+	
+	//printf("\n Valor dw: %d\n", dw);
+	//printf("\n Valor dh: %d\n", dh);
+	
+	child[0]->bound = new Box2d;
+	child[1]->bound = new Box2d;
+	
+	if (dw > dh)
+	{	
+		/*
+		child[0]->bound->SetBoundBox(	min.x			, max.y, 
+						min.x + width - 1	, min.y);		
+		child[1]->bound->SetBoundBox(	min.x + width		, max.y, 
+						max.x 			, min.y);				
+		*/
+		child[0]->bound->SetBoundBox(	min.x			, min.y, 
+						min.x + w 		, max.y);		
+						//min.x + w - 1		, max.y);		
+		//child[1]->bound->SetBoundBox(	min.x + w + 1		, min.y, 
+		child[1]->bound->SetBoundBox(	min.x + w 		, min.y, 
+						max.x 			, max.y);										
+	}
+	else
+	{		
+		//child[0]->bound->SetBoundBox(	min.x			, max.y, 
+		//				max.x 			, max.y + height - 1);
+		child[0]->bound->SetBoundBox(	min.x 			, max.y - h ,
+		//child[0]->bound->SetBoundBox(	min.x 			, max.y - h - 1 ,
+						max.x			, max.y
+						);
+						
+		//child[1]->bound->SetBoundBox(	min.x			, max.y + height, 
+		//				max.x 			, min.y);
+		child[1]->bound->SetBoundBox(	min.x			, min.y,
+						//max.x			, max.y - h -1
+						max.x			, max.y - h 
+						);
+	}
+	
+	//printf("\nImprimint child[0]: \n");
+	//child[0]->Print();
+	//printf("\nImprimint child[1]: \n");
+	//child[1]->Print();
+	
+	return child[0]->Insert (w, h);
+}
+
+unsigned int NodeBsp::ID = 0;
+
+NodeBsp::~NodeBsp() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafDistribution.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafDistribution.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafDistribution.cpp	(revision 699)
@@ -0,0 +1,58 @@
+
+#include "LBBCLeafDistribution.h"
+
+namespace LBBC {
+
+LeafDistribution::LeafDistribution() {
+}
+
+LeafDistribution::~LeafDistribution() 
+{
+	for (unsigned int iLeaf = 0; iLeaf < getNumEntities(); iLeaf++)
+	{
+		Leaf *leaf = (Leaf*)getEntity(iLeaf);
+		delete leaf;
+	}
+}
+
+void LeafDistribution::setMinD(float value)
+{
+	mMinD = value;
+}
+
+void LeafDistribution::setMaxD(float value)
+{
+	mMaxD = value;
+}
+
+float LeafDistribution::getMinD()
+{
+	return mMinD;
+}
+
+float LeafDistribution::getMaxD()
+{
+	return mMaxD;
+}
+
+void LeafDistribution::setMinNormal(Ogre::Vector3 value)
+{
+	mMinNormal = value;
+}
+
+Ogre::Vector3 LeafDistribution::getMinNormal()
+{
+	return mMinNormal;
+}
+
+void LeafDistribution::setMaxNormal(Ogre::Vector3 value)
+{
+	mMaxNormal = value;
+}
+
+Ogre::Vector3 LeafDistribution::getMaxNormal()
+{
+	return mMaxNormal;
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeaf.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeaf.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeaf.cpp	(revision 699)
@@ -0,0 +1,229 @@
+
+#include "LBBCLeaf.h"
+
+namespace LBBC {
+
+void Leaf::setPlaneD(float value) {
+	mPlaneD = value;
+}
+
+float Leaf::getPlaneD() {
+	return mPlaneD;
+}
+
+void Leaf::setPlaneNormal(Ogre::Vector3 value) {
+}
+
+Ogre::Vector3 Leaf::getPlaneNormal() {
+	return mPlaneNormal;
+}
+
+void Leaf::setPosition(Ogre::Vector3 value) {
+	mPosition = value;
+}
+
+Ogre::Vector3 Leaf::getPosition() {
+	return mPosition;
+}
+
+Ogre::Quaternion Leaf::getOrientation() {
+	return mOrientation; 
+}
+
+void Leaf::setOrientation(const Ogre::Quaternion & orientation) {
+	mOrientation = orientation;
+}
+
+void Leaf::addFaceNormal(Ogre::Vector3 value)
+{
+	mFacesNormals.push_back(value);
+}
+
+void Leaf::removeFaceNormal(unsigned int value)
+{
+	mFacesNormals.erase(mFacesNormals.begin()+value);
+}
+
+Ogre::Vector3 Leaf::getFaceNormal(unsigned int value)
+{
+	return mFacesNormals[value];
+}
+
+bool Leaf::hasFace(unsigned int value)
+{
+	bool hasFace = false;
+
+	if (mFacesEntitySet.size() > 0)
+	{
+		hasFace = mFacesEntitySet.find(value) != mFacesEntitySet.end();
+	}
+	return hasFace;
+}
+
+void Leaf::addFace(unsigned int value)
+{
+	mFacesEntitySet.insert(value);
+}
+
+void Leaf::removeFace(unsigned int value)
+{
+	mFacesEntitySet.erase(value);
+}
+
+unsigned int Leaf::getFace(unsigned int value)
+{
+	ID_FACESet::iterator itFacesEntitySet;
+	itFacesEntitySet = mFacesEntitySet.begin();
+
+	unsigned int iElem = 0;
+	while ((iElem < value) && (value < mFacesEntitySet.size()))
+	{
+		itFacesEntitySet++;
+		iElem++;
+	}	
+	return static_cast<unsigned int>(* itFacesEntitySet);
+}
+
+unsigned int Leaf::getNumFaces()
+{
+	return static_cast<unsigned int>(mFacesEntitySet.size());	
+}
+
+unsigned int Leaf::getNumLeafNormals()
+{
+	return static_cast<unsigned int>(mFacesNormals.size());
+}
+
+void Leaf::setLeafNormal(Ogre::Vector3 normal)
+{
+	mLeafNormal = normal;
+}
+
+Ogre::Vector3 Leaf::getLeafNormal()
+{
+	return mLeafNormal;
+}
+
+void Leaf::setLeafD(float leafD)
+{
+	mLeafD = leafD;
+}
+
+float Leaf::getLeafD()
+{
+	return mLeafD;
+}
+
+void Leaf::addFaceInfo(BBC::UniqueVertex v0, BBC::UniqueVertex v1, BBC::UniqueVertex v2)
+{
+	// Add vertex 0 from the first face	
+	getSubEntity(0)->addUniqueVertex(v0);					
+	
+	// Add vertex 1 from the first face
+	getSubEntity(0)->addUniqueVertex(v1);
+
+	// Add vertex 2 from the first face
+	getSubEntity(0)->addUniqueVertex(v2);
+
+	unsigned int numIndices = getSubEntity(0)->getNumFaces() * 3;
+	Ogre::Vector3 indices = Ogre::Vector3(numIndices, numIndices + 1, numIndices + 2);
+	getSubEntity(0)->addFaceVerticesIDs(indices);
+
+	Ogre::Vector3 p1 = v0.position;
+	Ogre::Vector3 p2 = v1.position;
+	Ogre::Vector3 p3 = v2.position;
+	Ogre::Vector3 v21 = p2 - p1;
+	Ogre::Vector3 v31 = p3 - p1;
+	Ogre::Vector3 normal = v21.crossProduct(v31);
+
+	//if (dotProd < 0)
+	if (normal[2] < 0)
+	{
+		normal = v31.crossProduct(v21);
+		normal.normalise();
+	}
+
+	addFaceNormal(normal);
+}
+
+void Leaf::readLeaf(TiXmlNode *leafNode)
+{
+	unsigned int id = Ogre::StringConverter::parseInt(leafNode->ToElement()->Attribute("id"));
+	setEntityHandle(id);
+
+	Ogre::Vector3 normal;
+	TiXmlNode *coord4dNode = leafNode->FirstChild("coord4d");
+	normal.x = Ogre::StringConverter::parseReal(coord4dNode->ToElement()->Attribute("nx"));
+	normal.y = Ogre::StringConverter::parseReal(coord4dNode->ToElement()->Attribute("ny"));
+	normal.z = Ogre::StringConverter::parseReal(coord4dNode->ToElement()->Attribute("nz"));
+	float d = Ogre::StringConverter::parseReal(coord4dNode->ToElement()->Attribute("d"));	
+
+	Ogre::Vector3 position;
+	TiXmlNode *positionNode = leafNode->FirstChild("position");
+	position.x = Ogre::StringConverter::parseReal(positionNode->ToElement()->Attribute("x"));
+	position.y = Ogre::StringConverter::parseReal(positionNode->ToElement()->Attribute("y"));
+	position.z = Ogre::StringConverter::parseReal(positionNode->ToElement()->Attribute("z"));	
+
+	setLeafNormal(normal);
+	setPosition(position);
+	setLeafD(d);
+
+	TiXmlNode *facesNode = leafNode->FirstChild("faces");
+	unsigned int count = Ogre::StringConverter::parseInt(facesNode->ToElement()->Attribute("count"));
+
+	for (TiXmlNode *faceNode = facesNode->FirstChild("face"); faceNode; faceNode = faceNode->NextSibling() )
+	{
+		unsigned int id = Ogre::StringConverter::parseInt(faceNode->ToElement()->Attribute("id"));
+		addFace(id);
+	}
+}
+
+void Leaf::writeLeaf(TiXmlNode *leafNode)
+{	
+	leafNode->ToElement()->SetAttribute(Ogre::String("id"),Ogre::StringConverter::toString(getEntityHandle())); 
+	
+	TiXmlNode *coord4dNode = leafNode->ToElement()->InsertEndChild(TiXmlElement(Ogre::String("coord4d").c_str()))->ToElement();
+
+	Ogre::String sNx = Ogre::StringConverter::toString(getLeafNormal().x);
+	Ogre::String sNy = Ogre::StringConverter::toString(getLeafNormal().y);
+	Ogre::String sNz = Ogre::StringConverter::toString(getLeafNormal().z);
+	Ogre::String sD = Ogre::StringConverter::toString(getLeafD());
+
+	coord4dNode->ToElement()->SetAttribute("nx", sNx.c_str());
+	coord4dNode->ToElement()->SetAttribute("ny", sNy.c_str());
+	coord4dNode->ToElement()->SetAttribute("nz", sNz.c_str());
+	coord4dNode->ToElement()->SetAttribute("d", sD.c_str());
+
+	TiXmlNode *positionNode = leafNode->ToElement()->InsertEndChild(TiXmlElement(Ogre::String("position").c_str()))->ToElement();		
+
+	Ogre::String sCoordX = Ogre::StringConverter::toString(getPosition().x);
+	Ogre::String sCoordY = Ogre::StringConverter::toString(getPosition().y);
+	Ogre::String sCoordZ = Ogre::StringConverter::toString(getPosition().z);
+
+	positionNode->ToElement()->SetAttribute(Ogre::String("x").c_str(), sCoordX.c_str());
+	positionNode->ToElement()->SetAttribute(Ogre::String("y").c_str(), sCoordY.c_str());
+	positionNode->ToElement()->SetAttribute(Ogre::String("z").c_str(), sCoordZ.c_str());
+	TiXmlNode *facesNode;
+	for (unsigned int i = 0; i < getNumFaces(); i++)
+	{
+		if (i == 0)
+		{
+			facesNode = leafNode->ToElement()->InsertEndChild(TiXmlElement(Ogre::String("faces").c_str()))->ToElement();
+
+			Ogre::String sFace = Ogre::StringConverter::toString(getNumFaces());
+			facesNode->ToElement()->SetAttribute(Ogre::String("count").c_str(), sFace.c_str());
+		}
+		
+		TiXmlNode *faceNode = facesNode->ToElement()->InsertEndChild(TiXmlElement(Ogre::String("face").c_str()))->ToElement();
+		Ogre::String sId = Ogre::StringConverter::toString(getFace(i));
+		faceNode->ToElement()->SetAttribute("id", sId.c_str());		
+	}
+}
+
+Leaf::Leaf() {
+}
+
+Leaf::~Leaf() {
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGVoxel.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGVoxel.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGVoxel.cpp	(revision 699)
@@ -0,0 +1,49 @@
+
+#include "IMGVoxel.h"
+
+namespace IMG {
+
+//Voxel(Ogre::AxisAlignedBox &box);
+Voxel::Voxel(BBox & box){
+}
+
+Voxel::Voxel(){
+}
+
+Voxel::Voxel(const Voxel & v){
+}
+
+void Voxel::Print() {
+}
+
+// Gametools -- Isma 17/08/2005
+//unsigned int GetNextPatch()	//return the id to next patch in the voxel
+//{
+//  if (index < GetSizePatchList()) return patchlistid.Get(index++);
+//  //return -1;
+//  return 0;
+//}
+// Gametools -- Isma 17/08/2005
+//unsigned int GetPatch(unsigned int i) { if (i < GetSizePatchList()) return patchlistid.Get(i); else return 0;}
+// Gametools -- Isma 17/08/2005
+//unsigned int GetPolygon(unsigned int i) { if (i < GetSizePolygonList())return polygonlistid.Get(i); else return 0; }
+// Gametools -- Isma 17/08/2005
+//unsigned int GetNextObsPoly() 	//return the id to next obspoly in the voxel
+//{
+//  if (index_obspoly < GetSizePolygonList()) return polygonlistid.Get(index_obspoly++);
+//  //return -1;
+//  return 0;
+//}
+bool Voxel::AddPatch(unsigned int id) {
+	return true;
+}
+
+//add one patch (only the id) to list_id_patch
+bool Voxel::AddPoly(unsigned int id) {
+	return true;
+}
+
+unsigned int Voxel::ID_VOXELS;
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafDistributionGenerator.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafDistributionGenerator.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafDistributionGenerator.cpp	(revision 699)
@@ -0,0 +1,290 @@
+
+#include "LBBCLeafDistributionGenerator.h"
+
+#include <BBC.h>
+
+namespace LBBC {
+
+LeafDistributionGenerator::LeafDistributionGenerator() 
+{
+	mEntity = new BBC::Entity();
+}
+
+LeafDistributionGenerator::~LeafDistributionGenerator() 
+{
+	delete mEntity;
+}
+
+void LeafDistributionGenerator::generate()
+{
+	BBC::Timer leafDistributionTimer;
+	leafDistributionTimer.start();
+	leafDistributionTimer.printStartTime();
+
+	mEntity->loadMesh(true);
+
+	unsigned int posNorm = 0;
+	unsigned int negNorm = 0;
+	
+	std::vector<Ogre::Vector3>::iterator iFaces01;
+	std::vector<Ogre::Vector3>::iterator iFaces02;
+	std::vector<Ogre::Vector2>::iterator iVertexs;
+
+	std::vector<float> vD,vNx,vNy,vNz;
+	
+	unsigned int iV101,iV201,iV301;
+	unsigned int iV102,iV202,iV302;
+	Ogre::Vector3 v101,v201,v301;
+	Ogre::Vector3 v102,v202,v302;
+		
+	for (unsigned int iF01 = 0; iF01 < mEntity->getSubEntity(0)->getNumFaces(); iF01++)
+	{
+		Ogre::Vector3 vFace01 = mEntity->getSubEntity(0)->getFaceVerticesIDs(iF01);
+
+		iV101 = vFace01[0];
+		iV201 = vFace01[1];
+		iV301 = vFace01[2];
+
+		v101 = mEntity->getSubEntity(0)->getUniqueVertex(iV101).position;
+		v201 = mEntity->getSubEntity(0)->getUniqueVertex(iV201).position;
+		v301 = mEntity->getSubEntity(0)->getUniqueVertex(iV301).position;
+
+		for (unsigned int iF02 = 0; iF02 < mEntity->getSubEntity(0)->getNumFaces(); iF02++)
+		{
+			Ogre::Vector3 vFace02 = mEntity->getSubEntity(0)->getFaceVerticesIDs(iF02);
+			iV102 = vFace02[0];
+			iV202 = vFace02[1];
+			iV302 = vFace02[2];
+
+			v102 = mEntity->getSubEntity(0)->getUniqueVertex(iV102).position;
+			v202 = mEntity->getSubEntity(0)->getUniqueVertex(iV202).position;
+			v302 = mEntity->getSubEntity(0)->getUniqueVertex(iV302).position;
+
+			
+			
+			//Ogre::LogManager::getSingleton().logMessage("face A: " + Ogre::StringConverter::toString(iF01));					
+			//Ogre::LogManager::getSingleton().logMessage("indices A:" + Ogre::StringConverter::toString(vFace01));
+			//Ogre::LogManager::getSingleton().logMessage("face B: " + Ogre::StringConverter::toString(iF02));					
+			//Ogre::LogManager::getSingleton().logMessage("indices B:" + Ogre::StringConverter::toString(vFace02));
+			//cin.get();
+
+			if ((iF01 != iF02) && 
+				(
+				((v101 == v102) && (v201 == v202)) ||
+				((v101 == v202) && (v201 == v102)) ||
+				((v101 == v102) && (v201 == v302)) ||
+				((v101 == v302) && (v201 == v102)) ||
+				((v101 == v202) && (v201 == v302)) ||
+				((v101 == v302) && (v201 == v202)) ||
+				//-----------------------------------
+				((v201 == v102) && (v301 == v202)) ||
+				((v201 == v202) && (v301 == v102)) ||
+				((v201 == v102) && (v301 == v302)) ||
+				((v201 == v302) && (v301 == v102)) ||
+				((v201 == v202) && (v301 == v302)) ||
+				((v201 == v302) && (v301 == v202)) ||
+				//-----------------------------------
+				((v101 == v102) && (v301 == v202)) ||
+				((v101 == v202) && (v301 == v102)) ||
+				((v101 == v102) && (v301 == v302)) ||
+				((v101 == v302) && (v301 == v102)) ||
+				((v101 == v202) && (v301 == v302)) ||
+				((v101 == v302) && (v301 == v202))
+				)
+				)
+			{			
+				if (mEntityDistribution->getNumEntities() == 0)
+				{	
+					// Instance new leaf
+					Leaf *leaf = new Leaf();
+					
+					leaf->setEntityHandle(mEntityDistribution->getNumEntities());
+					leaf->getSubEntity(0)->addTextureCoordSet(2);
+
+					leaf->addFace(iF01);
+					leaf->addFaceInfo(
+							mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF01).x),
+							mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF01).y),
+							mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF01).z));
+					
+					mEntityDistribution->addEntity(leaf);
+
+					//Ogre::LogManager::getSingleton().logMessage("leaf:" + Ogre::StringConverter::toString(leaf->getEntityHandle()));
+					//Ogre::LogManager::getSingleton().logMessage("indices:" + Ogre::StringConverter::toString(vFace01));
+					//Ogre::LogManager::getSingleton().logMessage("face stored: " + Ogre::StringConverter::toString(iF01));					
+					//Ogre::LogManager::getSingleton().logMessage("face stored: " + Ogre::StringConverter::toString(leaf->getFace(0)));
+					//cin.get();
+				}
+				else
+				{
+					unsigned int j = 0;
+					bool leaveFound = false;
+
+					// Check if the face is in one of the Leaf sets...
+					while ((j < mEntityDistribution->getNumEntities()) && (!leaveFound))
+					{						
+						Leaf *leaf = (Leaf *)mEntityDistribution->getEntity(j);
+						if (leaf->hasFace(iF01))
+						{
+							leaveFound = true;
+							leaf->addFace(iF02);
+							leaf->addFaceInfo(
+									mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF02).x),
+									mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF02).y),
+									mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF02).z));
+
+							//Ogre::LogManager::getSingleton().logMessage("leaf:" + Ogre::StringConverter::toString(leaf->getEntityHandle()));
+							//Ogre::LogManager::getSingleton().logMessage("indices:" + Ogre::StringConverter::toString(vFace02));
+							//Ogre::LogManager::getSingleton().logMessage("face stored: " + Ogre::StringConverter::toString(iF02));					
+							//Ogre::LogManager::getSingleton().logMessage("face stored: " + Ogre::StringConverter::toString(leaf->getFace(0)));
+							//cin.get();
+						}
+						else
+						{							
+							if (leaf->hasFace(iF02))
+							{
+								leaveFound = true;
+								leaf->addFace(iF01);
+								leaf->addFaceInfo(
+										mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF01).x),
+										mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF01).y),
+										mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF01).z));
+
+								//Ogre::LogManager::getSingleton().logMessage("leaf:" + Ogre::StringConverter::toString(leaf->getEntityHandle()));
+								//Ogre::LogManager::getSingleton().logMessage("indices:" + Ogre::StringConverter::toString(vFace01));
+								//Ogre::LogManager::getSingleton().logMessage("face stored: " + Ogre::StringConverter::toString(iF01));					
+								//Ogre::LogManager::getSingleton().logMessage("face stored: " + Ogre::StringConverter::toString(leaf->getFace(0)));
+								//cin.get();
+							}
+						}
+						j++;
+					}
+
+					if (!leaveFound)
+					{
+						// Instance new leaf
+						Leaf *leaf = new Leaf();
+						
+						leaf->setEntityHandle(mEntityDistribution->getNumEntities());
+						leaf->getSubEntity(0)->addTextureCoordSet(2);
+						leaf->addFace(iF01);
+						leaf->addFaceInfo(
+								mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF01).x),
+								mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF01).y),
+								mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(iF01).z));
+						
+						mEntityDistribution->addEntity(leaf);
+
+						//Ogre::LogManager::getSingleton().logMessage("leaf:" + Ogre::StringConverter::toString(leaf->getEntityHandle()));
+						//Ogre::LogManager::getSingleton().logMessage("indices:" + Ogre::StringConverter::toString(vFace01));
+						//Ogre::LogManager::getSingleton().logMessage("face stored: " + Ogre::StringConverter::toString(iF01));					
+						//Ogre::LogManager::getSingleton().logMessage("face stored: " + Ogre::StringConverter::toString(leaf->getFace(0)));					
+						//cin.get();
+					}
+				}
+			}						
+		}
+	}	
+
+	// Generate the average normal, leaf position, and d leaf plane parameter for each leaf...
+	for (unsigned int ileaf = 0; ileaf < mEntityDistribution->getNumEntities(); ileaf++)
+	{
+		Leaf *leaf = (Leaf*) mEntityDistribution->getEntity(ileaf);
+		leaf->setPosition(leaf->getSubEntity(0)->getUniqueVertex(0).position);
+        generateAverageLeafNormal(leaf);
+		leaf->setLeafD(-leaf->getLeafNormal().dotProduct(leaf->getPosition()));
+	}
+
+	// Compute the max and min d leaf plane parameter, and the max and min normal value...
+	float minD;
+	float maxD;
+	Ogre::Vector3 minNormal;
+	Ogre::Vector3 maxNormal;
+
+	generateNormalDThreshold(minD, maxD, minNormal, maxNormal);
+
+	((LeafDistribution*)mEntityDistribution)->setMaxD(maxD);
+	((LeafDistribution*)mEntityDistribution)->setMinD(minD);
+	((LeafDistribution*)mEntityDistribution)->setMaxNormal(maxNormal);
+	((LeafDistribution*)mEntityDistribution)->setMinNormal(minNormal);
+
+	leafDistributionTimer.stop();
+	leafDistributionTimer.printStopTime();
+}
+
+void LeafDistributionGenerator::generateNormalDThreshold(float &minD, float &maxD, Ogre::Vector3 &minNormal, Ogre::Vector3 &maxNormal)
+{
+	float dMin = FLT_MAX;
+	float dMax = -FLT_MAX;
+
+	float nXMax = -1;
+	float nYMax = -1;
+	float nZMax = -1;
+	float nYMin = 1;
+	float nXMin = 1;	 	 
+	float nZMin = 1;
+
+	for (unsigned int iD = 0; iD < mEntityDistribution->getNumEntities(); iD++)
+	{		
+		Leaf *leaf = (Leaf *)mEntityDistribution->getEntity(iD);		
+		if (leaf->getLeafD() < dMin)
+		{
+			dMin = leaf->getLeafD();
+		}
+			
+		if (leaf->getLeafD() > dMax)
+		{
+			dMax = leaf->getLeafD();
+		}
+		//--------------------	
+		if (leaf->getLeafNormal().x < nXMin)
+		{
+			nXMin = leaf->getLeafNormal().x;
+		}
+		
+		if (leaf->getLeafNormal().x > nXMax)
+		{
+			nXMax = leaf->getLeafNormal().x;
+		}
+		//--------------------
+		if (leaf->getLeafNormal().y < nYMin)
+		{
+			nYMin = leaf->getLeafNormal().y;
+		}
+		
+		if (leaf->getLeafNormal().y > nYMax)
+		{
+			nYMax = leaf->getLeafNormal().y;
+		}
+		//--------------------
+		if (leaf->getLeafNormal().z < nZMin)
+		{
+			nZMin = leaf->getLeafNormal().z;
+		}
+		
+		if (leaf->getLeafNormal().z > nZMax)
+		{
+			nZMax = leaf->getLeafNormal().z;
+		}		
+	}
+	minNormal = Ogre::Vector3(nXMin, nYMin, nZMin);
+	maxNormal = Ogre::Vector3(nXMax, nYMax, nZMax);
+	
+	minD = dMin;
+	maxD = dMax;
+}
+
+void LeafDistributionGenerator::generateAverageLeafNormal(Leaf *leaf)
+{
+	Ogre::Vector3 aVnormal(0,0,0);
+	for (unsigned int iN = 0; iN < leaf->getNumLeafNormals(); iN++)
+	{
+		aVnormal = aVnormal + leaf->getFaceNormal(iN);
+	}
+	aVnormal = aVnormal / leaf->getNumLeafNormals();
+	aVnormal.normalise();
+
+	leaf->setLeafNormal(aVnormal);
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboard.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboard.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboard.cpp	(revision 699)
@@ -0,0 +1,32 @@
+
+#include "BBCBillboard.h"
+
+namespace BBC {
+
+Billboard::Billboard() {
+}
+
+Billboard::~Billboard() {
+}
+
+unsigned int Billboard::getBillboardHandle() 
+{
+	return mBillboardHandle;
+}
+
+void Billboard::setBillboardHandle(unsigned int value) 
+{
+	mBillboardHandle = value;
+}
+
+void Billboard::setBillboardClusterData(BillboardClusterData *value)
+{
+	mBillboardClusterData = value;
+}
+
+BillboardClusterData* Billboard::getBillboardClusterData()
+{
+	return mBillboardClusterData;
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeaves.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeaves.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeaves.cpp	(revision 699)
@@ -0,0 +1,66 @@
+
+#include "LBBCLeaves.h"
+#include "LBBCLeaf.h"
+
+namespace LBBC {
+
+Leaves::Leaves() 
+{
+	mBillboardCloud = new BBC::BillboardCloud();
+	mLeafDistribution = new LeafDistribution();	
+}
+
+Leaves::~Leaves() 
+{
+	delete mBillboardCloud;
+	delete mLeafDistribution;
+}
+
+Ogre::Mesh* Leaves::getMesh() {
+	return mMesh;
+}
+
+void Leaves::setMesh(Ogre::Mesh * value) {
+	mMesh = value;
+}
+
+void Leaves::load() {
+}
+
+void Leaves::unload() {
+}
+
+void Leaves::addLeaf(const Leaf & value) {
+}
+
+void Leaves::removeLeaf(unsigned int value) {
+}
+
+void Leaves::initLeavesDistribution() {
+
+}
+
+LeafDistribution* Leaves::getDistribution()
+{
+	return mLeafDistribution;
+}
+
+void Leaves::setDistribution(LeafDistribution *leafDistribution)
+{
+	mLeafDistribution = leafDistribution;
+}
+
+void Leaves::initBillboardCloud() {
+}
+
+void Leaves::setBillboardCloud(BBC::BillboardCloud *value)
+{
+	mBillboardCloud = value;
+}
+
+BBC::BillboardCloud* Leaves::getBillboardCloud()
+{
+	return mBillboardCloud;
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudUVMapper.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudUVMapper.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloudUVMapper.cpp	(revision 699)
@@ -0,0 +1,234 @@
+
+#include "BBCBillboardCloudUVMapper.h"
+#include "BBCBillboardCloud.h"
+#include "BBCEntityCluster.h"
+#include "BBCBillboardClusterData.h"
+
+namespace BBC {
+
+void BillboardCloudUVMapper::initialize() 
+{
+	IMG::Box2d *box = new IMG::Box2d;
+	IMG::NodeBsp *node = new IMG::NodeBsp;
+	box->SetBoundBox(0, 0, mTextureAtlasWidth, mTextureAtlasHeight);
+	node->SetBound(box);
+	mBsp.SetRoot(node);	
+}
+
+void BillboardCloudUVMapper::setTextureWidth(unsigned short int width) 
+{
+	mTextureWidth = width;
+}
+
+unsigned short int BillboardCloudUVMapper::getTextureWidth() 
+{
+	return mTextureWidth;
+}
+
+void BillboardCloudUVMapper::setTextureHeight(unsigned short int height) 
+{
+	mTextureHeight = height;
+}
+
+unsigned short BillboardCloudUVMapper::getTextureHeight() 
+{
+	return mTextureHeight;
+}
+
+void BillboardCloudUVMapper::setTextureAtlasWidth(unsigned short int width) 
+{
+	mTextureAtlasWidth = width;
+}
+
+unsigned short int BillboardCloudUVMapper::getTextureAtlasWidth() 
+{
+	return mTextureAtlasWidth;
+}
+
+void BillboardCloudUVMapper::setTextureAtlasHeight(unsigned short int height) 
+{
+	mTextureAtlasHeight = height;
+}
+
+unsigned short BillboardCloudUVMapper::getTextureAtlasHeight() 
+{
+	return mTextureAtlasHeight;
+}
+
+void BillboardCloudUVMapper::generateTextureAtlasTextureCoords(bool mergeBillboards) 
+{	
+
+	for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++)
+	{
+		Ogre::LogManager::getSingleton().logMessage("id:" + Ogre::StringConverter::toString(iBillboard));
+		BillboardClusterData *billboardClusterData = mBillboardCloud->getBillboard(iBillboard)->getBillboardClusterData();		
+		
+		if (billboardClusterData != NULL)
+		{
+			Ogre::LogManager::getSingleton().logMessage("billboardData");
+			EntityCluster *entityCluster = billboardClusterData->getEntityCluster();
+			if (entityCluster->getNumEntitiesClusterData() > 0)
+			{			
+				Ogre::LogManager::getSingleton().logMessage("entityCluster");
+				
+				IMG::NodeBsp *nodeDest;
+				IMG::Cluster cluster;
+				Ogre::LogManager::getSingleton().logMessage("w:" + Ogre::StringConverter::toString(mTextureWidth));
+				Ogre::LogManager::getSingleton().logMessage("h:" + Ogre::StringConverter::toString(mTextureHeight));
+				nodeDest = mBsp.Insert(mTextureWidth,mTextureHeight,iBillboard);
+				
+				cluster.SetBspNodeBound(nodeDest->GetBound());
+				//cluster.Finish();
+				mClusterList.Insert(&cluster);				
+			}
+		}
+	}
+	
+	//mBsp.Print();		
+
+	unsigned int numGeneratedBillboardClouds = 0;
+	bool enabledTextureCoordSet = false;
+	unsigned int iUniqueVertex = 0;
+
+	for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++)
+	{							
+		Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);		
+		EntityCluster *entityCluster = billboard->getBillboardClusterData()->getEntityCluster();
+
+		if (entityCluster->getNumEntitiesClusterData() > 0)
+		{	
+			IMG::Cluster *cluster = mClusterList.Get(numGeneratedBillboardClouds);		
+			IMG::Box2d *box = cluster->GetBspNodeBound();
+			Ogre::Vector2 max = box->GetMaximum();
+			Ogre::Vector2 min = box->GetMinimum();
+			Ogre::LogManager::getSingleton().logMessage("Max:" + Ogre::StringConverter::toString(Ogre::Vector3(max[0],max[1],0)) + 
+				"\tMin:" + Ogre::StringConverter::toString(Ogre::Vector3(min[0],min[1],0)) + 
+				"\tSize(" + Ogre::StringConverter::toString(max[0]-min[0]) +
+				"," + Ogre::StringConverter::toString(max[1]-min[1]) + ")");
+
+
+			SubEntity *subEntity;												
+			
+			Ogre::Vector2 texCoords01,texCoords02,texCoords03,texCoords04;
+			texCoords01[0] = min[0] / mTextureAtlasWidth;
+			texCoords01[1] = min[1] / mTextureAtlasHeight;
+
+			texCoords02[0] = max[0] / mTextureAtlasWidth;
+			texCoords02[1] = min[1] / mTextureAtlasHeight;
+
+			texCoords03[0] = max[0] / mTextureAtlasWidth;
+			texCoords03[1] = max[1] / mTextureAtlasHeight;
+
+			texCoords04[0] = min[0] / mTextureAtlasWidth;
+			texCoords04[1] = max[1] / mTextureAtlasHeight;
+			
+			if (!mergeBillboards)
+			{
+				subEntity = mBillboardCloud->getEntity()->getSubEntity(numGeneratedBillboardClouds);
+				subEntity->addTextureCoordSet(2);
+				subEntity->enableVertexColours(true);
+				// Face A
+				//(0,0,0);
+				//(1,0,0);
+				//(1,1,0);
+
+				subEntity->setTexCoord(0, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords01[0],texCoords01[1], 0));
+				subEntity->setTexCoord(1, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords02[0],texCoords02[1], 0));
+				subEntity->setTexCoord(2, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords03[0],texCoords03[1], 0));
+
+				Ogre::ColourValue subEntityColour01 = Ogre::ColourValue(0, texCoords01[0],texCoords01[1]);
+				Ogre::ColourValue subEntityColour02 = Ogre::ColourValue(0, texCoords02[0],texCoords02[1]);
+				Ogre::ColourValue subEntityColour03 = Ogre::ColourValue(0, texCoords03[0],texCoords03[1]);
+
+				subEntity->setVertexColour(0, subEntityColour01.getAsRGBA());
+				subEntity->setVertexColour(1, subEntityColour02.getAsRGBA());
+				subEntity->setVertexColour(2, subEntityColour03.getAsRGBA());
+
+				// Face B
+				//(1,1,0);
+				//(0,1,0);
+				//(0,0,0);
+				subEntity->setTexCoord(3, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords03[0],texCoords03[1],0));
+				subEntity->setTexCoord(4, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords04[0],texCoords04[1],0));
+				subEntity->setTexCoord(5, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords01[0],texCoords01[1],0));
+
+				Ogre::ColourValue subEntityColour04 = Ogre::ColourValue(0, texCoords03[0],texCoords03[1]);
+				Ogre::ColourValue subEntityColour05 = Ogre::ColourValue(0, texCoords04[0],texCoords04[1]);
+				Ogre::ColourValue subEntityColour06 = Ogre::ColourValue(0, texCoords01[0],texCoords01[1]);
+
+				subEntity->setVertexColour(3, subEntityColour04.getAsRGBA());
+				subEntity->setVertexColour(4, subEntityColour05.getAsRGBA());
+				subEntity->setVertexColour(5, subEntityColour06.getAsRGBA());
+
+			}
+			else
+			{
+				subEntity = mBillboardCloud->getEntity()->getSubEntity(0);				
+				if (!enabledTextureCoordSet)
+				{
+					subEntity->addTextureCoordSet(2);
+					subEntity->enableVertexColours(true);
+					enabledTextureCoordSet = true;
+				}
+				
+				// Face A
+				//(0,0,0);
+				//(1,0,0);
+				//(1,1,0);
+
+				subEntity->setTexCoord(iUniqueVertex, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords01[0],texCoords01[1],0));
+				subEntity->setTexCoord(iUniqueVertex+1, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords02[0],texCoords02[1],0));
+				subEntity->setTexCoord(iUniqueVertex+2, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords03[0],texCoords03[1],0));
+
+				Ogre::ColourValue subEntityColour01 = Ogre::ColourValue(0, texCoords01[0],texCoords01[1]);
+				Ogre::ColourValue subEntityColour02 = Ogre::ColourValue(0, texCoords02[0],texCoords02[1]);
+				Ogre::ColourValue subEntityColour03 = Ogre::ColourValue(0, texCoords03[0],texCoords03[1]);
+
+				subEntity->setVertexColour(iUniqueVertex, subEntityColour01.getAsRGBA());
+				subEntity->setVertexColour(iUniqueVertex+1, subEntityColour02.getAsRGBA());
+				subEntity->setVertexColour(iUniqueVertex+2, subEntityColour03.getAsRGBA());
+
+
+				// Face B
+				//(1,1,0);
+				//(0,1,0);
+				//(0,0,0);
+				subEntity->setTexCoord(iUniqueVertex+3, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords03[0],texCoords03[1],0));
+				subEntity->setTexCoord(iUniqueVertex+4, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords04[0],texCoords04[1],0));
+				subEntity->setTexCoord(iUniqueVertex+5, subEntity->getNumTexCoordSets()-1, Ogre::Vector3(texCoords01[0],texCoords01[1],0));
+
+				Ogre::ColourValue subEntityColour04 = Ogre::ColourValue(0, texCoords03[0],texCoords03[1]);
+				Ogre::ColourValue subEntityColour05 = Ogre::ColourValue(0, texCoords04[0],texCoords04[1]);
+				Ogre::ColourValue subEntityColour06 = Ogre::ColourValue(0, texCoords01[0],texCoords01[1]);
+
+				subEntity->setVertexColour(iUniqueVertex+3, subEntityColour04.getAsRGBA());
+				subEntity->setVertexColour(iUniqueVertex+4, subEntityColour05.getAsRGBA());
+				subEntity->setVertexColour(iUniqueVertex+5, subEntityColour06.getAsRGBA());
+
+				iUniqueVertex = iUniqueVertex + 6;
+			}
+			numGeneratedBillboardClouds++;
+		}
+	}
+	
+}
+
+void BillboardCloudUVMapper::setBillboardCloud(BillboardCloud *billboardCloud) 
+{
+	mBillboardCloud = billboardCloud;
+}
+
+BillboardCloud * BillboardCloudUVMapper::getBillboardCloud() 
+{
+	return mBillboardCloud;
+}
+
+BillboardCloudUVMapper::BillboardCloudUVMapper() 
+{
+}
+
+BillboardCloudUVMapper::~BillboardCloudUVMapper() 
+{
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCBillboardKMeansClusterData.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCBillboardKMeansClusterData.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCBillboardKMeansClusterData.cpp	(revision 699)
@@ -0,0 +1,13 @@
+
+#include "LBBCBillboardKMeansClusterData.h"
+
+namespace LBBC {
+
+BillboardKMeansClusterData::BillboardKMeansClusterData() {
+}
+
+BillboardKMeansClusterData::~BillboardKMeansClusterData() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCBillboardKdTreeClusterData.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCBillboardKdTreeClusterData.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCBillboardKdTreeClusterData.cpp	(revision 699)
@@ -0,0 +1,300 @@
+
+#include "LBBCBillboardKdTreeClusterData.h"
+
+namespace LBBC {
+
+BillboardKdTreeClusterData::BillboardKdTreeClusterData() {
+}
+
+BillboardKdTreeClusterData::~BillboardKdTreeClusterData() {
+}
+
+void BillboardKdTreeClusterData::readBillboardClusterData(TiXmlNode *parentNode)
+{
+
+}
+
+void BillboardKdTreeClusterData::writeBillboardClusterData(TiXmlNode *parentNode)
+{
+	BBC::EntityCluster *entityCluster = getEntityCluster();
+	Ogre::Vector3 normal = getNormal();
+	normal.normalise();
+
+	float d = 0;
+	for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++)
+	{
+		LeafKdTreeClusterData *leafKdTreeClusterData = (LeafKdTreeClusterData*)entityCluster->getEntityClusterData(iLeaf);
+		Leaf *leaf = (Leaf*)leafKdTreeClusterData->getEntity();
+		d = d + leaf->getPosition().dotProduct(normal);
+	}	
+	d = - d / entityCluster->getNumEntitiesClusterData();
+	
+	TiXmlNode *billboardNode;
+	TiXmlNode *coord4dNode;
+	TiXmlNode *quadTopRightCornerNode;
+	TiXmlNode *quadTopLeftCornerNode;
+	TiXmlNode *quadBottomRightCornerNode;
+	TiXmlNode *quadBottomLeftCornerNode;
+	TiXmlNode *axisXNode;
+	TiXmlNode *axisYNode;
+	TiXmlNode *axisZNode;
+	TiXmlNode *leavesNode;
+	TiXmlNode *leafNode;
+	billboardNode = parentNode->ToElement()->InsertEndChild(TiXmlElement("billboard"))->ToElement();
+
+	coord4dNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("coord4d"))->ToElement();
+	Ogre::String sNX = Ogre::StringConverter::toString(normal.x);
+	coord4dNode->ToElement()->SetAttribute("nx",sNX.c_str());
+	Ogre::String sNY = Ogre::StringConverter::toString(normal.y);
+	coord4dNode->ToElement()->SetAttribute("ny",sNY.c_str());
+	Ogre::String sNZ = Ogre::StringConverter::toString(normal.z);
+	coord4dNode->ToElement()->SetAttribute("nz",sNZ.c_str());
+	Ogre::String sD = Ogre::StringConverter::toString(d);
+	coord4dNode->ToElement()->SetAttribute("d",sD.c_str());
+	
+	quadTopLeftCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("topLeft"))->ToElement();
+	Ogre::String sTLX = Ogre::StringConverter::toString(getQuadTopLeftCorner().x);
+	quadTopLeftCornerNode->ToElement()->SetAttribute("x",sTLX.c_str());
+	Ogre::String sTLY = Ogre::StringConverter::toString(getQuadTopLeftCorner().y);
+	quadTopLeftCornerNode->ToElement()->SetAttribute("y",sTLY.c_str());
+	Ogre::String sTLZ = Ogre::StringConverter::toString(getQuadTopLeftCorner().z);
+	quadTopLeftCornerNode->ToElement()->SetAttribute("z",sTLZ.c_str());	
+
+	quadTopRightCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("topRight"))->ToElement();
+	Ogre::String sTRX = Ogre::StringConverter::toString(getQuadTopRightCorner().x);
+	quadTopRightCornerNode->ToElement()->SetAttribute("x",sTRX.c_str());
+	Ogre::String sTRY = Ogre::StringConverter::toString(getQuadTopRightCorner().y);
+	quadTopRightCornerNode->ToElement()->SetAttribute("y",sTRY.c_str());
+	Ogre::String sTRZ = Ogre::StringConverter::toString(getQuadTopRightCorner().z);
+	quadTopRightCornerNode->ToElement()->SetAttribute("z",sTRZ.c_str());	
+
+	quadBottomRightCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("bottomRight"))->ToElement();
+	Ogre::String sBRX = Ogre::StringConverter::toString(getQuadBottomRightCorner().x);
+	quadBottomRightCornerNode->ToElement()->SetAttribute("x",sBRX.c_str());
+	Ogre::String sBRY = Ogre::StringConverter::toString(getQuadBottomRightCorner().y);
+	quadBottomRightCornerNode->ToElement()->SetAttribute("y",sBRY.c_str());
+	Ogre::String sBRZ = Ogre::StringConverter::toString(getQuadBottomRightCorner().z);
+	quadBottomRightCornerNode->ToElement()->SetAttribute("z",sBRZ.c_str());	
+
+	quadBottomLeftCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("bottomLeft"))->ToElement();
+	Ogre::String sBLX = Ogre::StringConverter::toString(getQuadBottomLeftCorner().x);
+	quadBottomLeftCornerNode->ToElement()->SetAttribute("x",sBLX.c_str());
+	Ogre::String sBLY = Ogre::StringConverter::toString(getQuadBottomLeftCorner().y);
+	quadBottomLeftCornerNode->ToElement()->SetAttribute("y",sBLY.c_str());
+	Ogre::String sBLZ = Ogre::StringConverter::toString(getQuadBottomLeftCorner().z);
+	quadBottomLeftCornerNode->ToElement()->SetAttribute("z",sBLZ.c_str());	
+
+	axisYNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("axisX"))->ToElement();
+	Ogre::String sAXX = Ogre::StringConverter::toString(getAxisX().x);
+	axisYNode->ToElement()->SetAttribute("x",sAXX.c_str());
+	Ogre::String sAXY = Ogre::StringConverter::toString(getAxisX().y);
+	axisYNode->ToElement()->SetAttribute("y",sAXY.c_str());
+	Ogre::String sAXZ = Ogre::StringConverter::toString(getAxisX().z);
+	axisYNode->ToElement()->SetAttribute("z",sAXZ.c_str());	
+
+	axisYNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("axisY"))->ToElement();
+	Ogre::String sAYX = Ogre::StringConverter::toString(getAxisY().x);
+	axisYNode->ToElement()->SetAttribute("x",sAYX.c_str());
+	Ogre::String sAYY = Ogre::StringConverter::toString(getAxisY().y);
+	axisYNode->ToElement()->SetAttribute("y",sAYY.c_str());
+	Ogre::String sAYZ = Ogre::StringConverter::toString(getAxisY().z);
+	axisYNode->ToElement()->SetAttribute("z",sAYZ.c_str());	
+
+	axisZNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("axisZ"))->ToElement();
+	Ogre::String sAZX = Ogre::StringConverter::toString(getAxisZ().x);
+	axisZNode->ToElement()->SetAttribute("x",sAZX.c_str());
+	Ogre::String sAZY = Ogre::StringConverter::toString(getAxisZ().y);
+	axisZNode->ToElement()->SetAttribute("y",sAZY.c_str());
+	Ogre::String sAZZ = Ogre::StringConverter::toString(getAxisZ().z);
+	axisZNode->ToElement()->SetAttribute("z",sAZZ.c_str());	
+
+	leavesNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("leaves"))->ToElement();
+	Ogre::String sLeaves = Ogre::StringConverter::toString(entityCluster->getNumEntitiesClusterData());
+	leavesNode->ToElement()->SetAttribute("count",sLeaves.c_str());
+	
+	for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++)
+	{
+		LeafKdTreeClusterData *leafKdTreeClusterData = (LeafKdTreeClusterData*)entityCluster->getEntityClusterData(iLeaf);
+		Leaf *leaf = (Leaf*)leafKdTreeClusterData->getEntity();
+		leafNode = leavesNode->ToElement()->InsertEndChild(TiXmlElement("leaf"))->ToElement();
+		Ogre::String sLeaf = Ogre::StringConverter::toString(leaf->getEntityHandle());
+		leafNode->ToElement()->SetAttribute("id",sLeaf.c_str());
+	}
+}
+
+void BillboardKdTreeClusterData::generateBillboardBoundingQuad() 
+{
+	
+	Ogre::Vector3 normal = getNormal();
+	Ogre::Vector3 planePosition;
+	float d = getD();
+
+	normal.normalise();
+
+	if ((abs(normal[0] > abs(normal[1])) && (abs(normal[0] > abs(normal[2])))))
+	{
+		planePosition[0] = -d / normal[0];
+		planePosition[1] = 0;
+		planePosition[2] = 0;
+	}
+	else if ((abs(normal[1] > abs(normal[0])) && (abs(normal[1] > abs(normal[2])))))
+	{
+		planePosition[0] = 0;
+		planePosition[1] = -d / normal[1];
+		planePosition[2] = 0;
+	}
+	else
+	{
+		planePosition[0] = 0;
+		planePosition[1] = 0;
+		planePosition[2] = -d / normal[2];
+	}
+	
+	mAxisX = normal.perpendicular();
+	mAxisX.normalise();
+	mAxisY = normal.crossProduct(mAxisX);	
+	mAxisY.normalise();
+	mAxisZ = normal;
+
+	Ogre::Matrix4 coordPlane;
+	Ogre::Matrix4 constCoord;
+	Ogre::Matrix4 invMCoordPlane;
+
+	coordPlane[0][0] = mAxisX.x;
+	coordPlane[0][1] = mAxisX.y;
+	coordPlane[0][2] = mAxisX.z;
+	coordPlane[0][3] = 0.0f;
+	coordPlane[1][0] = mAxisY.x;
+	coordPlane[1][1] = mAxisY.y;
+	coordPlane[1][2] = mAxisY.z;
+	coordPlane[1][3] = 0.0f;
+	coordPlane[2][0] = mAxisZ.x;
+	coordPlane[2][1] = mAxisZ.y;
+	coordPlane[2][2] = mAxisZ.z;
+	coordPlane[2][3] = 0.0f;
+	coordPlane[3][0] = planePosition.x;
+	coordPlane[3][1] = planePosition.y;
+	coordPlane[3][2] = planePosition.z;
+	coordPlane[3][3] = 1.0f;
+
+	invMCoordPlane = coordPlane.inverse();
+
+	constCoord[0][0] = 1.0f;
+	constCoord[0][1] = 0.0f;
+	constCoord[0][2] = 0.0f;
+	constCoord[0][3] = 0.0f;
+	constCoord[1][0] = 0.0f;
+	constCoord[1][1] = 1.0f;
+	constCoord[1][2] = 0.0f;
+	constCoord[1][3] = 0.0f;
+	constCoord[2][0] = 0.0f;
+	constCoord[2][1] = 0.0f;
+	constCoord[2][2] = 0.0f;
+	constCoord[2][3] = 0.0f;
+	constCoord[3][0] = 0.0f;
+	constCoord[3][1] = 0.0f;
+	constCoord[3][2] = 0.0f;
+	constCoord[3][3] = 1.0f;
+
+	float xMax = -FLT_MAX;
+	float xMin = FLT_MAX;
+	float yMax = -FLT_MAX;
+	float yMin = FLT_MAX;
+
+	Ogre::Vector3 vXmax;
+	Ogre::Vector3 vXmin;
+	Ogre::Vector3 vYmax;
+	Ogre::Vector3 vYmin;
+
+	BBC::EntityCluster *entityCluster = getEntityCluster();
+	BBC::Entity *entity = entityCluster->getEntity();
+
+	for (unsigned int iVertex = 0; iVertex < entity->getSubEntity(0)->getNumVertices(); iVertex++)
+	{			        
+		Ogre::Vector3 position = entity->getSubEntity(0)->getPosition(iVertex);
+		Ogre::Vector4 projPointP1d4 =  Ogre::Vector4(position.x,position.y,position.z,1.0f) * invMCoordPlane * constCoord * coordPlane;
+	
+		// The point projected in the plane
+		Ogre::Vector3 projPointP1(projPointP1d4.x,projPointP1d4.y,projPointP1d4.z);
+
+		float v1 = normal.dotProduct(planePosition);
+		float v2 = normal.dotProduct(position);
+		float t = v1 - v2;
+		projPointP1 = position + (normal * t);
+
+		float x1 = mAxisX.dotProduct(projPointP1 - planePosition);
+		float y1 = mAxisY.dotProduct(projPointP1 - planePosition);
+		float z1 = mAxisZ.dotProduct(projPointP1 - planePosition);		
+		
+		if (x1 > xMax)
+		{
+			xMax = x1;
+			vXmax = projPointP1;
+		}
+		if (x1 < xMin)
+		{
+			xMin = x1;
+			vXmin = projPointP1;
+		}
+		if (y1 > yMax)
+		{
+			yMax = y1;
+			vYmax = projPointP1;
+		}
+		if (y1 < yMin)
+		{
+			yMin = y1;
+			vYmin = projPointP1;
+		}		
+	}
+
+	Ogre::Vector3 aP;
+	Ogre::Vector3 bP;
+	Ogre::Vector3 pP;
+	Ogre::Vector3 abV;
+	Ogre::Vector3 apV;
+	Ogre::Vector3 dProdV;
+	float aLength;
+	float abLength;
+	float dist;
+	Ogre::Vector3 intersectP;
+
+	aP = vYmin;
+	bP = vYmin + mAxisX;
+	pP = vXmin;
+	abV = bP - aP;
+	apV = pP - aP;
+	dProdV = abV.crossProduct(apV);
+	aLength = dProdV.length();
+	abLength = abV.length();
+	dist = aLength / abLength;
+	mBillboardCorners[QUAD_TOP_LEFT] = pP + (mAxisY * (-dist));
+
+	aP = vYmax;
+	bP = vYmax + mAxisX;
+	pP = vXmax;
+	abV = bP - aP;
+	apV = pP - aP;
+	dProdV = abV.crossProduct(apV);
+	aLength = dProdV.length();
+	abLength = abV.length();
+	dist = aLength / abLength;
+	mBillboardCorners[QUAD_BOTTOM_RIGHT] = pP + (mAxisY * dist);
+
+	aP = vXmax;
+	bP = vXmax + mAxisY;
+	pP = vYmin;
+	abV = bP - aP;
+	apV = pP - aP;
+	dProdV = abV.crossProduct(apV);
+	aLength = dProdV.length();
+	abLength = abV.length();
+	dist = aLength / abLength;
+	mBillboardCorners[QUAD_BOTTOM_LEFT] = pP + (mAxisX * dist);
+
+	Ogre::Vector3 vDirWidth = mBillboardCorners[QUAD_BOTTOM_LEFT] - mBillboardCorners[QUAD_BOTTOM_RIGHT];
+	float distWidth = vDirWidth.length();
+	mBillboardCorners[QUAD_TOP_RIGHT] = mBillboardCorners[QUAD_TOP_LEFT] + (mAxisY * distWidth);
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGClusterList.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGClusterList.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGClusterList.cpp	(revision 699)
@@ -0,0 +1,197 @@
+
+#include "IMGClusterList.h"
+
+namespace IMG {
+
+// Gametools -- Isma 17/08/2005
+//int Cluster::CalculaPatch (Vector3 &point)
+//{
+//	//printf("\nCalculaPatch on estÃ  el vertex: (%.4f, %.4f, %.4f)", point.x, point.y, point.z);	
+//	
+//	//this->Print();
+//	
+//	int idpatch = this->CalcPatch (point);
+//	if (ObscuranceRayTracing::Config::Debug) printf("\nEl idpatch calculat Ã©s: %d", idpatch);
+//	int id = GetIdPatch(idpatch);
+//	if (ObscuranceRayTracing::Config::Debug) printf("\nEl patch real Ã©s el : %d", id);
+//	return id;
+//}
+// Gametools -- Isma 17/08/2005
+//
+//int Cluster::CalcPatch (Vector3 &point)
+//{
+//	//printf("\nDins Calcular Patch, valor de la caixa: ");
+//	//bound->Print();
+//	int x, y;
+//	//Polygon2d poly2d;
+//	//int axisproj;	
+//	Vector2 point2d;
+//	//Box box;
+//	Vector3 min, max;
+//	//Vector2 *vertexs;
+//	//int order;
+//	
+//	
+//	//vertexs = poly2d_text->GetVector3s();
+//	//vertexs = triangle2d_text->GetVector3s();
+//	
+//	//printf("\nCalc Patch ");
+//	
+//	
+//	//for (register unsigned int i = 0; i < 4; i++)
+//	//{
+//	//	box.AddBoundingVector3 (vertexs[i].x, vertexs[i].y, 0);		
+//	//}	
+//	
+//	
+//	
+//	min = bound->GetMinimum();	
+//	max = bound->GetMaximum();
+//	//box.Print();
+//	
+//	point2d = point2d.ProjectVector33d (point, axisproj);
+//	//printf("\nPoint2d: (%.4f, %.4f)", point2d.x, point2d.y);
+//	
+//	
+//	switch (axisproj)
+//	{
+//		
+//		case 1:	// 2 3
+//			// 0 1
+//				
+//			x = int ( (point2d.x - min.x) * ObscuranceRayTracing::Config::MapWidth / (max.x - min.x));
+//			y = int ( (point2d.y - min.y) * ObscuranceRayTracing::Config::MapHeight / (max.y - min.y));
+//			return x + y * ObscuranceRayTracing::Config::MapWidth;
+//		case 2:	// 0 1
+//			// 2 3
+//
+//			x = int ( (point2d.x - min.x) * ObscuranceRayTracing::Config::MapWidth / (max.x - min.x));
+//			y = int ( (point2d.y - min.y) * ObscuranceRayTracing::Config::MapHeight / (min.y - max.y));
+//			//printf("\nValor x: %d", x);
+//			//printf("\nValor y: %d", y);
+//			
+//			if (x < 0) x = -x;	//arreglo temporal si no no va bÃ©
+//			if (y < 0) y = -y;
+//			return x + y * ObscuranceRayTracing::Config::MapWidth;
+//		
+//		case 0:	// 3 2
+//			// 1 0
+//
+//			
+//			x = int ( (point2d.x - min.x) * ObscuranceRayTracing::Config::MapWidth / (min.x - max.x));
+//			y = int ( (point2d.y - min.y) * ObscuranceRayTracing::Config::MapHeight / (max.y - min.y));
+//			
+//			//printf("\nValor x: %d", x);
+//			//printf("\nValor y: %d", y);
+//			if (x < 0) x = -x;
+//			if (y < 0) y = -y;
+//			return x + y * ObscuranceRayTracing::Config::MapWidth;		
+//	}
+//	
+//	return -1;
+//}
+//
+// Gametools -- Isma 17/08/2005
+//
+//bool Cluster::CreatePatches( bool dinamic)
+//{
+//	if (ObscuranceRayTracing::Config::Debug) 
+//	{
+//		printf("\n\nCreant Patches en cluster (%d), isdinamic %d\n\n", dinamic, GetId());
+// 		printf("\nEl polygon es: ");
+//		Print();
+//		//printf("\n-----------\n ");
+//	}
+//	
+//	//if (!Inc) return false;
+//	//if (!vertexs) return false;
+//				
+//	int acum = 0;
+//	register unsigned int i = 0, j = 0;
+//	//Vector3 orig = Inc[0], valorx = Inc[1], valory = Inc[2];
+//	
+//	
+//	Vector3 orig, valorx, valory;
+//	
+//	orig = lumel_origin;
+//	valorx = lumel_x_axis;
+//	valory = lumel_y_axis;
+//	
+//	//if (ObscuranceRayTracing::Config::Debug)
+//	{
+//		printf("\nValor de origen: (%.4f, %.4f, %.4f)", lumel_origin.x, lumel_origin.y,lumel_origin.z);
+//		printf("\nValor de Ax: (%.4f, %.4f, %.4f)", lumel_x_axis.x, lumel_x_axis.y, lumel_x_axis.z);
+//		printf("\nValor de Ay: (%.4f, %.4f, %.4f)", lumel_y_axis.x, lumel_y_axis.y, lumel_y_axis.z);
+//	}
+//	
+//	Vector3 p0, p1, p2, p3;
+//	
+//	
+//	patchlistid.GetList()->reserve ( ObscuranceRayTracing::Config::MapHeight * ObscuranceRayTracing::Config::MapWidth);
+//	int cont = 0;
+//	for (; j <  ObscuranceRayTracing::Config::MapHeight; j++)
+//	{		
+//		i = 0;
+//		for (i = 0; i < ObscuranceRayTracing::Config::MapWidth; i++)
+//		{			
+//			Patch * patch = new Patch;						
+//			patch->SetCoord (i, j);
+//			//patch->SetCoord (j, i);
+//			patch->SetIdLumel(i + j + acum);
+//			patch->SetCluster (this);
+//			
+//			if (dinamic) patch->dinamic = dinamic;
+//			
+//			
+//			Patch::seqid++;			
+//						
+//			//if (ObscuranceRayTracing::Config::Debug) patch->Print(2);
+//			
+//			patchlistid.Insert(patch->GetId());	//add the id (index) to polygon's patchlistid
+//			
+//			//if (dinamic) ObscuranceRayTracing::patchlistdinamic.Insert(patch);
+//			//else ObscuranceRayTracing::patchlist.Insert(patch);
+//			
+//			ObscuranceRayTracing::patchlist_triangle.Insert(patch);
+//			//ObscuranceRayTracing::patchlist_cluster.Insert(patch);
+//			//patch->Print(2);
+//			
+//			delete patch;
+//			cont++;
+//		}
+//			
+//		acum = acum + ObscuranceRayTracing::Config::MapWidth - 1;	//el id del patch segÃŒent acum += lightmap_del_polygon->GetWidth() - 1
+//	}
+//	
+//	//if (ObscuranceRayTracing::Config::Debug) 
+//		printf("\n\nLlista de indexs de patchs del polygon: %d" , patchlistid.GetSize());
+//	return true;
+//}
+//
+
+bool ClusterList::Insert(Cluster * p) {
+	if (!p) return false;
+	//printf("\nInserting polygon");
+	//p->Print();	
+	//list.push_back(p);
+	//printf("\nInsert polygon: INsert\n");
+	list.push_back(*p);
+	//printf("\nInsert polygon: INsert fora\n");
+	return true;
+}
+
+void ClusterList::Print() {
+	printf("\n\n\nNombre de  cluster a la llista: %d --> ", list.size());
+	for (register int i = 0; i < list.size(); i ++)
+	{
+		//printf( "%d", GetPolygon(i)->GetId());
+		Get(i)->Print();
+	}
+	
+}
+
+ClusterList::~ClusterList() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGBox2d.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGBox2d.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGBox2d.cpp	(revision 699)
@@ -0,0 +1,10 @@
+
+#include "IMGBox2d.h"
+
+namespace IMG {
+
+Box2d::~Box2d() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityDistributionSerializer.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityDistributionSerializer.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityDistributionSerializer.cpp	(revision 699)
@@ -0,0 +1,26 @@
+
+#include "BBCEntityDistributionSerializer.h"
+
+namespace BBC {
+
+Entity* EntityDistributionSerializer::getEntity() {
+	return mEntity;
+}
+
+void EntityDistributionSerializer::setEntity(Entity * value) {
+	mEntity = value;
+}
+
+void EntityDistributionSerializer::generate() {
+}
+
+void EntityDistributionSerializer::init() {
+}
+
+EntityDistributionSerializer::EntityDistributionSerializer() {
+}
+
+EntityDistributionSerializer::~EntityDistributionSerializer() {
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGCluster.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGCluster.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGCluster.cpp	(revision 699)
@@ -0,0 +1,487 @@
+
+#include "IMGCluster.h"
+#include "IMGCluster2d.h"
+
+namespace IMG {
+
+Cluster::Cluster(){
+	id = Cluster::ID_CLUSTER++;
+	bound = new BBox;
+	bspnodebound = NULL;
+	//CreateVector3s();
+}
+
+Cluster & Cluster::operator =(const Cluster & p) {
+	//	printf("\nConstructor d'assignaciÃ³ de cluster");
+	// GametoolsError -- Isma 17/08/2005
+	//vertexs = p.vertexs;
+	//vertexs_vector = p.vertexs_vector;
+	//vertexs_triangle_text = p.vertexs_triangle_text;
+	uv = p.uv;
+	id = p.id;
+
+	//get the lumel_origin becaus if get Inc[0] the value is not correct	
+	
+	lumel_origin = p.lumel_origin;
+	lumel_x_axis = p.lumel_x_axis;
+	lumel_y_axis = p.lumel_y_axis;
+	
+	//patchlistid = p.patchlistid;
+	//plane = p.plane;
+	
+	axisproj = p.axisproj;
+	order = p.order;
+	triangle2d_text = p.triangle2d_text;
+	bound = p.bound;
+	normal = p.normal;
+	bspnodebound = p.bspnodebound;
+	return *this;
+}
+
+Cluster::Cluster(const Cluster & p){
+	///printf("\nConstructor per copia de cluster");
+	// GametoolsError -- Isma 17/08/2005
+	//vertexs = p.vertexs;
+	//vertexs_triangle_text = p.vertexs_triangle_text;
+	//vertexs_vector = p.vertexs_vector;
+	//printf("\nnombre de vertexs origens: %d", p.vertexs_vector.size());
+	//printf("\nnombre de vertexs copiats: %d", vertexs_vector.size());
+	uv = p.uv;
+	id = p.id;
+	
+	//get the lumel_origin becaus if get Inc[0] the value is not correct	
+	
+	lumel_origin = p.lumel_origin;
+	lumel_x_axis = p.lumel_x_axis;
+	lumel_y_axis = p.lumel_y_axis;
+	
+	//patchlistid = p.patchlistid;
+	//plane = p.plane;
+	
+	axisproj = p.axisproj;
+	order = p.order;
+	triangle2d_text = p.triangle2d_text;
+	bound = p.bound;
+	normal = p.normal;
+	bspnodebound = p.bspnodebound;
+	
+	//trianglelistid = p.trianglelistid;
+	
+}
+
+// Gametools -- Isma 17/08/2005
+//void Cluster::Insert (Triangle *t)
+//{
+//	int axis = t->AxisProjected();
+//	
+//	//printf("\nAxis: %d", axis);
+//	//t->Print();
+//	Vector3 *v = t->GetVector3s();
+//	//std::vector<Vector3> v = *t->GetVector3sVector();
+//	
+//	for (int i = 0; i < 3; i++)
+//	{
+//		//printf("\ntriangle a transformar : (%.4f, %.4f, %.4f)", v[i].x, v[i].y, v[i].z);
+//		
+//		vertexs_vector.push_back (v[i]);
+//		//bound->AddBoundingVector3 (v[i].x, v[i].y, v[i].z);
+//		/*
+//		switch (axis)
+//		{
+//			case 0: bound->AddBoundingVector3 (v[i].z, v[i].y, 0);break;
+//			case 1: bound->AddBoundingVector3 (v[i].x, v[i].z, 0);break;
+//			case 2:	bound->AddBoundingVector3 (v[i].x, v[i].y, 0);break;	
+//		}
+//		*/
+//	}
+//	
+//	plane = *t->GetPlane();
+//}
+
+void Cluster::Print() {
+	printf("\n\nCluster: %d, axisproj: %d, order: %d", id, axisproj, order);
+	//Vector3 *normal = plane.GetNormal();
+	//printf("\nPlane: (%.4f, %.4f, %.4f)", normal->x, normal->y, normal->z);
+	plane.Print();
+	printf("\nOrigin (%.4f, %.4f, %.4f) \n", lumel_origin.x, lumel_origin.y, lumel_origin.z);
+		//printf("Inc U (%.4f, %.4f, %.4f) \n", Inc[1].x, Inc[1].y, Inc[1].z);
+	printf("Inc U (%.4f, %.4f, %.4f) \n", lumel_x_axis.x, lumel_x_axis.y, lumel_x_axis.z);
+	printf("Inc V (%.4f, %.4f, %.4f) ", lumel_y_axis.x, lumel_y_axis.y, lumel_y_axis.z);
+	
+	if (bound) bound->Print();
+	if (bspnodebound) bspnodebound->Print();
+	
+	
+	/*
+	printf("\nIndex de triangles del cluster: %d -->", trianglelistid.GetSize());
+	for (register int i = 0; i < trianglelistid.GetSize(); i++)
+	{
+		printf(" %d", trianglelistid.Get(i));
+	}
+	*/
+	
+	printf("Printant els vertexs: ");
+	
+	//for (int i = 0; i < 4; i++)
+	//	printf("\nVector3s %d del cluster: (%.4f, %.4f, %.4f)", i, vertexs[i].x, vertexs[i].y, vertexs[i].z);
+	// Gametools -- Isma 17/08/2005
+	//for (int i = 0; i < vertexs_vector.size(); i++)
+	//	printf("\nVector3s %d del cluster: (%.4f, %.4f, %.4f)", i, vertexs_vector[i].x, vertexs_vector[i].y, vertexs_vector[i].z);
+
+	//printf("\nVector3s del cluster: ");
+	//for (int i = 0; i < 4; i++)
+	//{
+	//		printf("\nVector3s %d: (%.4f, %.4f, %.4f)", i, vertexs_triangle_text[i].x, vertexs_triangle_text[i].y, vertexs_triangle_text[i].z);
+	//}	
+	
+	/*
+	printf("\nCoordenades de texture dels vertes: %d -->", vertexs_vector.size());
+	
+	for (int i = 0 ; i < vertexs_vector.size(); i++)
+	{
+		Vector3 vec= vertexs_triangle_text[i];
+		
+		printf("  (%.4f, %.4f)", vec.x, vec.y);
+	}	
+	*/	
+}
+
+//* return the dominant normal axis, for calculate the 2d projection
+int Cluster::AxisProjected() {
+	
+	Ogre::Vector3 *normal = plane.GetNormal();
+	
+	if (Ogre::Math::Abs(normal->x) >= Ogre::Math::Abs(normal->y) && Ogre::Math::Abs(normal->x) >= Ogre::Math::Abs(normal->z))	return (0);		
+	if (Ogre::Math::Abs(normal->y) >= Ogre::Math::Abs(normal->x) && Ogre::Math::Abs(normal->y) >= Ogre::Math::Abs(normal->z))	return (1);
+	else										return (2);
+}
+
+// Gametools -- Isma 17/08/2005
+//bool CreatePatches(bool dinamic = false);
+// Gametools -- Isma 17/08/2005
+//Listid *GetPatchList() { return &patchlistid;}
+//Listid *GetTriangleList(){ return &trianglelistid; }
+// Gametools -- Isma 17/08/2005
+//int GetIdPatch (unsigned int i)
+//{
+//	if (i > patchlistid.GetSize()) return -1;
+//	
+//	return patchlistid.Get(i);
+//}
+// Gametools -- Isma 17/08/2005
+//int GetIdTriangle  (unsigned int i)
+//{
+//	if (i > trianglelistid.GetSize()) return -1;
+//	
+//	return trianglelistid.Get(i);
+//}
+void Cluster::Finish() {
+	printf("\nCluster::Finish()");
+	Plane3 *plane = GetPlane();
+	Ogre::Vector3 normal = *plane->GetNormal();
+	float distance = plane->GetDistance();
+	Ogre::Vector3 corner;
+	Cluster2d cluster2d;		
+	Ogre::Vector3 vertexfinal[3];
+	Ogre::Vector2 *vertexs2d;
+	int num_vertexs = 4;
+	//Box box;
+	Ogre::Vector3 min;
+	Ogre::Vector3 max;
+	float num, den;	
+	bool type = true;
+
+	printf("\n\tCreant cluster 2d");
+	axisproj = cluster2d.Create2d (this, 0, true);	
+	printf("\n\t Imprimint el que hi al del cluster");
+		
+	//this->Print();
+	//printf("\n\t Imprimint el que hi ha del cluster2d");
+	//cluster2d.Print();
+		
+	//Vector3 *v = GetVector3s();
+	//vertexs2d = cluster2d.GetVector3s();
+	std::vector<Ogre::Vector2> vector2;
+	vector2 =*cluster2d.GetVector3sVector();
+	
+		
+	// Gametools -- Isma 17/08/2005
+	//if (ObscuranceRayTracing::Config::Debug) 
+	//{
+	//	this->Print();
+	//	//poly2d->Print();
+	//	cluster2d.Print();
+	//}
+		
+	
+	bound = new BBox;
+	for (unsigned int i = 0; i < vector2.size(); i++)
+	{		
+		bound->AddBoundingVector3 (vector2[i].x, vector2[i].y, 0);		
+	}
+	
+	min = bound->GetMinimum();	
+	max = bound->GetMaximum();
+	//if (ObscuranceRayTracing::Config::Debug) 
+	{
+		printf("\nCaixa Englobant del cluster 2d\n");
+		bound->Print();
+	}
+	//-----
+
+	// Gametools -- Isma 17/08/2005
+	//if (ObscuranceRayTracing::Config::Debug) 
+	//	printf("\nAxisproject: %d\n", axisproj);
+	
+	// Gametools -- Isma 17/08/2005
+	//vertexs_triangle_text = new Vector3[num_vertexs];
+	
+	
+	Ogre::Vector3 aux (-9999,-9999,-9999);
+	//reconstruim a 3d el polygon englobant del polygon original a partir del pla
+	
+	printf("\nAxisproj: %d", axisproj);
+	// Gametools -- Isma 17/08/2005
+	/*
+	switch(axisproj)
+	{
+		case 0: 
+
+			{
+
+				vertexs_triangle_text[0].z = min.x;
+				vertexs_triangle_text[0].y = min.y;
+				vertexs_triangle_text[0].x = - (normal.y * min.y + normal.z * min.x + distance) / normal.x;
+				
+				vertexs_triangle_text[1].z = max.x;
+				vertexs_triangle_text[1].y = min.y;
+				vertexs_triangle_text[1].x = - (normal.y * min.y + normal.z * max.x + distance) / normal.x;
+				
+				vertexs_triangle_text[2].z = min.x;
+				vertexs_triangle_text[2].y = max.y;
+				vertexs_triangle_text[2].x = - (normal.y * max.y + normal.z * min.x + distance) / normal.x;
+
+				vertexs_triangle_text[3].z = max.x;
+				vertexs_triangle_text[3].y = max.y;
+				vertexs_triangle_text[3].x = - (normal.y * max.y + normal.z * max.x + distance) / normal.x;
+			
+			}
+			break;
+		case 1:
+			{
+				
+				
+				vertexs_triangle_text[0].x = min.x;
+				vertexs_triangle_text[0].z = min.y;
+				vertexs_triangle_text[0].y = - (normal.x * min.x + normal.z * min.y + distance) / normal.y;
+				
+				vertexs_triangle_text[1].x = max.x;
+				vertexs_triangle_text[1].z = min.y;
+				vertexs_triangle_text[1].y = - (normal.x * max.x + normal.z * min.y + distance) / normal.y;
+						
+				vertexs_triangle_text[3].x = max.x;
+				vertexs_triangle_text[3].z = max.y;
+				vertexs_triangle_text[3].y = - (normal.x * max.x + normal.z * max.y + distance) / normal.y;
+
+				vertexs_triangle_text[2].x = min.x;
+				vertexs_triangle_text[2].z = max.y;
+				vertexs_triangle_text[2].y = - (normal.x * min.x + normal.z * max.y + distance) / normal.y;
+				
+
+				
+			}
+			break;
+		case 2:
+
+			{				
+				
+				vertexs_triangle_text[0].x = min.x;
+				vertexs_triangle_text[0].y = min.y;
+				vertexs_triangle_text[0].z = - (normal.x * min.x + normal.y * min.y + distance) / normal.z;
+				
+				vertexs_triangle_text[1].x = max.x;
+				vertexs_triangle_text[1].y = min.y;
+				vertexs_triangle_text[1].z = - (normal.x * max.x + normal.y * min.y + distance) / normal.z;
+				
+				vertexs_triangle_text[3].x = max.x;
+				vertexs_triangle_text[3].y = max.y;
+				vertexs_triangle_text[3].z = - (normal.x * max.x + normal.y * max.y + distance) / normal.z;
+				
+				vertexs_triangle_text[2].x = min.x;
+				vertexs_triangle_text[2].y = max.y;
+				vertexs_triangle_text[2].z =  -(normal.x * min.x + normal.y * max.y + distance) / normal.z;
+			}
+			break;	
+	}
+	*/
+	
+	//triangle2d_text = new Cluster2d;
+	//triangle2d_text->Create2d (this, 1, true);
+	
+	Ogre::Vector3 v01_, v10_;
+	
+	printf("\nvertexs del cluster \n");
+
+	// Gametools -- Isma 17/08/2005
+	//for (int i = 0; i< 4; i++)
+	//	printf("%d - (%.4f, %.4f, %.4f)\n", i, vertexs_triangle_text[i].x, vertexs_triangle_text[i].y, vertexs_triangle_text[i].z);
+		
+	// Gametools -- Isma 17/08/2005	
+	//v01_ = vertexs_triangle_text[1] - vertexs_triangle_text[0];
+	//v10_ = vertexs_triangle_text[2] - vertexs_triangle_text[0];
+	
+	// Gametools -- Isma 17/08/2005
+	//lumel_origin = vertexs_triangle_text[0];
+	//lumel_x_axis = Vector3 (v01_.x / ObscuranceRayTracing::Config::MapHeight , v01_.y / ObscuranceRayTracing::Config::MapHeight, v01_.z / ObscuranceRayTracing::Config::MapHeight);
+	//lumel_y_axis = Vector3 (v10_.x / ObscuranceRayTracing::Config::MapWidth, v10_.y / ObscuranceRayTracing::Config::MapWidth, v10_.z / ObscuranceRayTracing::Config::MapWidth);
+	
+	// Gametools -- Isma 17/08/2005
+	//if (ObscuranceRayTracing::Config::Debug) 
+	//{
+	//	printf("Increment cada cop: (%.4f, %.4f, %.4f)\n", lumel_origin.x, lumel_origin.y, lumel_origin.z);			
+	//	printf("Increment cada cop:  (%.4f, %.4f, %.4f)\n", lumel_x_axis.x, lumel_x_axis.y, lumel_x_axis.z);	
+	//	printf("Increment cada cop:  (%.4f, %.4f, %.4f)\n", lumel_y_axis.x, lumel_y_axis.y, lumel_y_axis.z);	
+	//}
+	/*
+
+	Vector3 finalx, finaly, final;
+	 
+	finalx.x = lumel_origin.x + lumel_x_axis.x * ObscuranceRayTracing::Config::MapWidth;
+	finalx.y = lumel_origin.y + lumel_x_axis.y * ObscuranceRayTracing::Config::MapWidth;
+	finalx.z = lumel_origin.z + lumel_x_axis.z * ObscuranceRayTracing::Config::MapWidth;
+	 
+	finaly.x = lumel_origin.x + lumel_y_axis.x * ObscuranceRayTracing::Config::MapHeight;
+	finaly.y = lumel_origin.y + lumel_y_axis.y * ObscuranceRayTracing::Config::MapHeight;
+	finaly.z = lumel_origin.z + lumel_y_axis.z * ObscuranceRayTracing::Config::MapHeight;
+		
+	final.x = lumel_origin.x + lumel_x_axis.x * ObscuranceRayTracing::Config::MapWidth + lumel_y_axis.x * ObscuranceRayTracing::Config::MapHeight;
+	final.y = lumel_origin.y + lumel_x_axis.y * ObscuranceRayTracing::Config::MapWidth + lumel_y_axis.y * ObscuranceRayTracing::Config::MapHeight;
+	final.z = lumel_origin.z + lumel_x_axis.z * ObscuranceRayTracing::Config::MapWidth + lumel_y_axis.z * ObscuranceRayTracing::Config::MapHeight;
+	
+	vertexs = new Vector3s[4];
+	vertexs[0] = lumel_origin;
+	vertexs[1] = finalx;
+	vertexs[2] = finaly;
+	vertexs[3] = final;
+	*/	
+	/*
+	switch (axisproj)
+	{
+		case 0:
+			order = ORDER_6; break;
+		case 1:
+			order = ORDER_2; break;
+		case 2:
+			order = ORDER_0; break;
+	}
+	//order = 1;
+	if (ObscuranceRayTracing::Config::Debug) printf("\nOrder del triangle: %d", order);
+	*/
+}
+
+//* Return the increment in U (lumel increment in x). For patchs calculation 
+Ogre::Vector3 Cluster::GetIncU() {
+ 
+	return lumel_x_axis;
+}
+
+//* Return the increment in V (lumel increment in x). For patchs calculation 
+Ogre::Vector3 Cluster::GetIncV() {
+ 
+	return lumel_y_axis;
+
+}
+
+//Vector3 GetOrigin() const { if (Inc) return Inc[0]; }
+
+//* Return the origin. For patchs calculation 
+Ogre::Vector3 Cluster::GetOrigin() {
+ 
+	return lumel_origin;
+	
+}
+
+//
+//	void CreateVector3s()
+//	{ 
+//		
+//		//Vector3s = new Vector3[4];
+//		//Vector3s_triangle_text = new Vector3[4];
+//	}
+//	
+bool Cluster::PointIn(Ogre::Vector3 & point) {
+	
+	register unsigned int i = 0;
+	//Polygon2d poly2d;
+	Ogre::Vector2 point2d;
+	Ogre::Vector2 * vertexs2d;
+	Ogre::Vector3 v1, vp;
+	
+	//printf("\ndins pointin cluster");
+	
+	// Gametools -- Isma 17/08/2005
+	//if (ObscuranceRayTracing::Config::Debug) printf("\nPointin\n");
+	
+	//int axis = poly2d.CreatePoly2d (this);
+	
+	//poly2d.Print();
+	//poly2d->Print();
+	
+	// GametoolsError -- Isma 17/08/2005
+	//point2d = point2d.ProjectVector33d (point, axisproj);
+	//if (bound->intersects ( &Vector3 (point2d.x, point2d.y, 0))) return true;
+	
+	return false;
+	//point2d.Print();
+	
+	//if (poly2d_text) return poly2d_text->PointIn(point2d);
+	/*		
+	poly2d_text->Print();
+	
+	
+	
+	//vertexs2d = poly2d.GetVector3s();
+	//vertexs2d = poly2d->GetVector3s();
+	poly2d_text->GetVector3s();
+	
+	//checks if clockwise orientation
+	/**
+	v1 = vertexs[i+1] - vertexs[i];		
+	vp.x = point2d.x - vertexs[i].x;
+	vp.y = point2d.y - vertexs[i].y;
+	
+	if ((v1.x * vp.y - vp.x * v1.y) < 0)
+	**/
+	/*
+	for (; i < 3; i++)
+	{
+		v1.x = vertexs2d[i+1].x - vertexs2d[i].x;		
+		v1.y = vertexs2d[i+1].y - vertexs2d[i].y;		
+		
+		vp.x = point2d.x - vertexs2d[i].x;
+		vp.y = point2d.y - vertexs2d[i].y;
+		v1.Print();
+		vp.Print();
+		printf("\nValor del determinant: %f", (v1.x * vp.y - vp.x * v1.y));
+		if ((v1.x * vp.y - vp.x * v1.y) > 0) return false;
+		
+	}
+	printf("\nEl punt estÃ  dins\n");
+	
+	return true;*/
+}
+
+unsigned int Cluster::ID_CLUSTER = 0;
+
+// Gametools -- Isma 17/08/2005
+//Listid patchlistid;
+//Listid trianglelistid;
+int Cluster::CalcPatch(Ogre::Vector3 & point) {
+	return 0;
+}
+
+Cluster::~Cluster() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityClusterData.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityClusterData.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityClusterData.cpp	(revision 699)
@@ -0,0 +1,22 @@
+
+#include "BBCEntityClusterData.h"
+
+namespace BBC {
+
+EntityClusterData::EntityClusterData() {
+}
+
+EntityClusterData::~EntityClusterData() {
+}
+
+void EntityClusterData::setEntity(Entity *value)
+{
+	mEntity = value;
+}
+
+Entity* EntityClusterData::getEntity()
+{
+	return mEntity;
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCManager.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCManager.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCManager.cpp	(revision 699)
@@ -0,0 +1,177 @@
+
+#include "BBCManager.h"
+
+namespace BBC {
+
+template <> Manager* CSingleton<Manager>::ms_Singleton = NULL;
+
+Manager* Manager::getSingletonPtr(void)
+{
+    return ms_Singleton;
+}
+
+Manager& Manager::getSingleton(void)
+{  
+    assert( ms_Singleton );  return ( *ms_Singleton );  
+}
+
+Manager::Manager() 
+{
+   // Change it when the texture generation will be included...
+   //mOgreRoot = new Ogre::Root();
+   if (Ogre::Root::getSingletonPtr() == NULL)
+   {
+		mOgreRoot = new Ogre::Root("", "ogre.cfg", "Ogre.log");  
+		Ogre::LogManager::getSingleton().logMessage("OgreRoot created in LBBC");
+   }
+   else
+   {	
+	   mOgreRoot = Ogre::Root::getSingletonPtr();
+	   Ogre::LogManager::getSingleton().logMessage("OgreRoot assigned in LBCC");
+   }
+   
+   mDefaultHardwareBufferManager = new Ogre::DefaultHardwareBufferManager();
+   mMeshSerializer = new Ogre::MeshSerializer();
+   mXMLMeshSerializer = new Ogre::XMLMeshSerializer();
+   mMath = new Ogre::Math();
+   loadResources();   
+}
+
+void Manager::loadResources()
+{
+	// Load resource paths from config file
+	Ogre::ConfigFile cf;
+    cf.load("resources.cfg");
+    // Go through all sections & settings in the file
+	Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
+
+	Ogre::String secName, typeName, archName;
+    while (seci.hasMoreElements())
+    {
+        secName = seci.peekNextKey();
+		Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
+		Ogre::ConfigFile::SettingsMultiMap::iterator i;
+        for (i = settings->begin(); i != settings->end(); ++i)
+        {
+            typeName = i->first;
+            archName = i->second;
+			Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
+        }
+    }
+	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
+}
+
+void Manager::initRenderWindow()
+{
+    // Change it when the texture generation will be included...
+	/*
+	// Render system.
+	Ogre::LogManager::getSingleton().logMessage("Creating window...");
+	//mOgreRoot->showConfigDialog();
+	// Set parameters of render system (window size, etc.)
+	mOgreRoot->restoreConfig();
+	
+	mWnd = mOgreRoot->initialise(true);
+	mWnd->resize(512,512);
+
+	// Camera.
+	mScene = mOgreRoot->getSceneManager(Ogre::ST_GENERIC);
+	mRSys = mOgreRoot->getRenderSystem();
+	Ogre::LogManager::getSingleton().logMessage("Creating default camera...");
+	mCam = mScene->createCamera("SubMain Camera");
+	mCam->setPosition(-1, 22, 72);
+	mCam->lookAt(0, 22, 0);
+	mCam->setNearClipDistance(0.5);
+	// Viewports.
+	Ogre::LogManager::getSingleton().logMessage("Creating default viewort...");
+	mView = mWnd->addViewport(mCam);
+	mView->setBackgroundColour(Ogre::ColourValue(1.0f,1.0f,1.0f,0));
+	// All set up, activate.
+	Ogre::LogManager::getSingleton().logMessage("Setting up...");
+	//mWnd->setActive(true);
+	mWnd->setActive(false);	
+	mFrameListener = new ExampleFrameListener(mWnd,mCam,false,false);
+	mFrameListener->showDebugOverlay(false);
+	mOgreRoot->addFrameListener(mFrameListener);
+	*/
+}
+
+Manager::~Manager() 
+{
+}
+
+void Manager::shutdown()
+{
+	mOgreRoot->shutdown();
+	delete mOgreRoot;
+	delete mMeshSerializer;
+	delete mXMLMeshSerializer;
+	delete mMath;
+	// Not necessary if we have a RenderWindow...
+	delete mDefaultHardwareBufferManager;	
+	// Change it when the texture generation will be included...
+	//mWnd->destroy();
+	// Only necessary if we have a RenderWindow...
+	//delete mFrameListener;
+	//delete mScene;
+	//delete mRSys;
+	//delete mCam;
+	//delete mView;
+	//delete mWnd;
+	
+	
+}
+
+void Manager::initialize()
+{
+}
+
+Ogre::Mesh* Manager::loadMesh(Ogre::String name)
+{	
+	Ogre::MeshPtr meshPtr = Ogre::MeshManager::getSingleton().load(name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);	
+	return meshPtr.getPointer();
+}
+
+Ogre::Mesh* Manager::loadXMLMesh(Ogre::String name)
+{
+	Ogre::MeshPtr newMesh = Ogre::MeshManager::getSingleton().createManual(name.substr(0,((name.size()-1)-4)),Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+
+	Ogre::VertexElementType colourElementType;
+	if (true)
+	{
+		// DirectX Colour Format
+		colourElementType = Ogre::VET_COLOUR_ARGB;
+	}
+	else
+	{
+		// OpenGL Colour Format
+		colourElementType = Ogre::VET_COLOUR_ABGR;
+	}
+
+    mXMLMeshSerializer->importMesh(name, colourElementType, newMesh.getPointer());
+	return newMesh.getPointer();
+}
+
+void Manager::saveMesh(Ogre::String name)
+{
+	Ogre::MeshPtr meshPtr = Ogre::MeshManager::getSingleton().getByName(name);
+	mMeshSerializer->exportMesh(meshPtr.getPointer(),name);
+}
+
+void Manager::saveXMLMesh(Ogre::String name)
+{
+	Ogre::MeshPtr meshPtr = Ogre::MeshManager::getSingleton().getByName(name);
+	mXMLMeshSerializer->exportMesh(meshPtr.getPointer(),name + ".xml");
+}
+
+Ogre::MeshSerializer* Manager::getMeshSerializer(void)
+{
+	return mMeshSerializer;
+}
+
+Ogre::XMLMeshSerializer* Manager::getXMLMeshSerializer(void)
+{
+	return mXMLMeshSerializer;
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafDistributionSerializer.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafDistributionSerializer.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafDistributionSerializer.cpp	(revision 699)
@@ -0,0 +1,103 @@
+
+#include "LBBCLeafDistributionSerializer.h"
+
+namespace LBBC {
+
+LeafDistributionSerializer::LeafDistributionSerializer()
+						   : BBC::EntityDistributionSerializer()
+{
+	mEntity = new BBC::Entity();
+}
+
+LeafDistributionSerializer::~LeafDistributionSerializer() 
+{
+	delete mEntity;
+}
+
+void LeafDistributionSerializer::setLeafDistribution(LeafDistribution *value)
+{
+	mLeafDistribution = value;
+}
+
+LeafDistribution* LeafDistributionSerializer::getLeafDistribution()
+{
+	return mLeafDistribution;
+}
+
+void LeafDistributionSerializer::readLeafDistribution(TiXmlDocument *document)
+{
+	mEntity->loadMesh(true);
+	
+	TiXmlNode *parentNode = document->FirstChild("tree");
+	TiXmlNode *leavesNode = parentNode->FirstChild("leaves");
+
+	unsigned numEntities = Ogre::StringConverter::parseInt(leavesNode->ToElement()->Attribute("count"));
+	float dMin = Ogre::StringConverter::parseInt(leavesNode->ToElement()->Attribute("dMin"));
+	float dMax = Ogre::StringConverter::parseInt(leavesNode->ToElement()->Attribute("dMax"));
+	float nXMin = Ogre::StringConverter::parseInt(leavesNode->ToElement()->Attribute("nXMin"));
+	float nXMax = Ogre::StringConverter::parseInt(leavesNode->ToElement()->Attribute("nXMax"));
+	float nYMin = Ogre::StringConverter::parseInt(leavesNode->ToElement()->Attribute("nYMin"));
+	float nYMax = Ogre::StringConverter::parseInt(leavesNode->ToElement()->Attribute("nYMax"));
+	float nZMin = Ogre::StringConverter::parseInt(leavesNode->ToElement()->Attribute("nZMin"));
+	float nZMax = Ogre::StringConverter::parseInt(leavesNode->ToElement()->Attribute("nZMax"));
+
+	mLeafDistribution->setMinD(dMin);
+	mLeafDistribution->setMaxD(dMax);
+	mLeafDistribution->setMinNormal(Ogre::Vector3(nXMin,nYMin,nZMin));
+	mLeafDistribution->setMaxNormal(Ogre::Vector3(nXMax,nYMax,nZMax));
+
+	for (TiXmlNode *leafNode = leavesNode->FirstChild("leaf"); leafNode; leafNode = leafNode->NextSibling() )
+	{
+		Leaf *leaf = new Leaf();		
+		leaf->readLeaf(leafNode);				
+		addFacesInfo(leaf);
+		mLeafDistribution->addEntity(leaf);				
+	}
+}
+
+void LeafDistributionSerializer::addFacesInfo(Leaf *leaf)
+{
+	for (unsigned int iFace = 0; iFace < leaf->getNumFaces(); iFace++)
+	{		
+		leaf->addFaceInfo(
+			mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(leaf->getFace(iFace)).x),
+			mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(leaf->getFace(iFace)).y),
+			mEntity->getSubEntity(0)->getUniqueVertex(mEntity->getSubEntity(0)->getFaceVerticesIDs(leaf->getFace(iFace)).z));							
+	}
+}
+
+void LeafDistributionSerializer::writeLeafDistribution(TiXmlDocument *document)
+{
+	TiXmlNode *parentNode = document->InsertEndChild(TiXmlElement("tree"))->ToElement();
+
+	TiXmlNode *leavesNode = parentNode->ToElement()->InsertEndChild(TiXmlElement(Ogre::String("leaves").c_str()))->ToElement();
+	Ogre::String sLeaves = Ogre::StringConverter::toString(mLeafDistribution->getNumEntities());	
+	Ogre::String sDmin = Ogre::StringConverter::toString(mLeafDistribution->getMinD());
+	Ogre::String sDmax = Ogre::StringConverter::toString(mLeafDistribution->getMaxD());
+	Ogre::String sNxMin = Ogre::StringConverter::toString(mLeafDistribution->getMinNormal().x);
+	Ogre::String sNxMax = Ogre::StringConverter::toString(mLeafDistribution->getMaxNormal().x);
+	Ogre::String sNyMin = Ogre::StringConverter::toString(mLeafDistribution->getMinNormal().y);
+	Ogre::String sNyMax = Ogre::StringConverter::toString(mLeafDistribution->getMaxNormal().y);
+	Ogre::String sNzMin = Ogre::StringConverter::toString(mLeafDistribution->getMinNormal().z);
+	Ogre::String sNzMax = Ogre::StringConverter::toString(mLeafDistribution->getMaxNormal().z);
+
+	leavesNode->ToElement()->SetAttribute("count",sLeaves.c_str());
+	leavesNode->ToElement()->SetAttribute("dMin",sDmin.c_str());
+	leavesNode->ToElement()->SetAttribute("dMax",sDmax.c_str());
+	leavesNode->ToElement()->SetAttribute("nXMin",sNxMin.c_str());
+	leavesNode->ToElement()->SetAttribute("nXMax",sNxMax.c_str());
+	leavesNode->ToElement()->SetAttribute("nYMin",sNyMin.c_str());
+	leavesNode->ToElement()->SetAttribute("nYMax",sNyMax.c_str());
+	leavesNode->ToElement()->SetAttribute("nZMin",sNzMin.c_str());
+	leavesNode->ToElement()->SetAttribute("nZMax",sNzMax.c_str());
+
+	for (unsigned int k=0; k < mLeafDistribution->getNumEntities(); k++)
+	{
+		Leaf *leaf = (Leaf *)mLeafDistribution->getEntity(k);
+
+		TiXmlNode *leafNode = leavesNode->ToElement()->InsertEndChild(TiXmlElement(Ogre::String("leaf").c_str()))->ToElement();
+		leaf->writeLeaf(leafNode);	
+	}
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityCluster.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityCluster.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityCluster.cpp	(revision 699)
@@ -0,0 +1,130 @@
+
+#include <BBCEntityCluster.h>
+#include <BBCEntity.h>
+
+namespace BBC {
+
+EntityCluster::EntityCluster() 
+{
+}
+
+EntityCluster::~EntityCluster() 
+{	
+	for (unsigned int iEntityClusterData = 0; iEntityClusterData < getNumEntitiesClusterData(); iEntityClusterData++)
+	{
+		EntityClusterData *entityClusterData = getEntityClusterData(iEntityClusterData);
+		delete entityClusterData;
+	}
+	
+	delete mEntity;
+}
+
+EntityClusterData* EntityCluster::getEntityClusterData(unsigned int value)
+{
+	return mEntityClusterDataList[value];
+}
+
+unsigned int EntityCluster::getNumEntitiesClusterData()
+{
+	return static_cast<unsigned int>(mEntityClusterDataList.size());
+}
+
+void EntityCluster::addEntityClusterData(EntityClusterData *value)
+{
+	mEntityClusterDataList.push_back(value);
+}
+
+void EntityCluster::removeEntitClusterData(unsigned int value)
+{
+	mEntityClusterDataList.erase(mEntityClusterDataList.begin()+value);
+}
+
+Entity* EntityCluster::getEntity() 
+{
+	return mEntity;
+}
+
+void EntityCluster::setEntity(Entity* value) {
+	mEntity = value;
+}
+
+unsigned int EntityCluster::getBillboardHandle() {
+	return mBillboardHandle;
+}
+
+void EntityCluster::setBillboardHandle(unsigned int value) {
+	mBillboardHandle = value;
+}
+
+void EntityCluster::setEntityDistribution(EntityDistribution *value)
+{
+	mEntityDistribution = value;
+}
+
+EntityDistribution* EntityCluster::getEntityDistribution()
+{
+	return mEntityDistribution;
+}
+
+void EntityCluster::generateEntityCluster() 
+{
+	mEntity = new BBC::Entity();
+
+	mEntity->getSubEntity(0)->addTextureCoordSet(2);
+	Ogre::Vector3 indicesOffset = Ogre::Vector3::ZERO;
+
+	mEntity->getSubEntity(0)->enableVertexColours(true);
+
+	float fRed = Ogre::Math::RangeRandom(0.0,1.0);
+	float fGreen = Ogre::Math::RangeRandom(0.0,1.0);
+	float fBlue = Ogre::Math::RangeRandom(0.0,1.0);
+	Ogre::ColourValue subEntityColour = Ogre::ColourValue(1.0,fRed,fGreen,fBlue);
+
+	unsigned int offset = 0;
+	for (unsigned int iEntityClusterData = 0; iEntityClusterData < getNumEntitiesClusterData(); iEntityClusterData++)
+	{			
+		Entity *entity = getEntityClusterData(iEntityClusterData)->getEntity();
+
+		for (unsigned int iFace = 0; iFace < entity->getSubEntity(0)->getNumFaces(); iFace++)
+		{
+			UniqueVertex uniqueVertex01, uniqueVertex02, uniqueVertex03;
+			Ogre::Vector3 indices = entity->getSubEntity(0)->getFaceVerticesIDs(iFace);
+			mEntity->getSubEntity(0)->addFaceVerticesIDs(indices + indicesOffset);
+			
+			mEntity->getSubEntity(0)->enableVertexColours(entity->getSubEntity(0)->hasVertexColours());
+			
+			uniqueVertex01.position = entity->getSubEntity(0)->getUniqueVertex(indices[0]).position;
+			uniqueVertex01.normal = entity->getSubEntity(0)->getUniqueVertex(indices[0]).normal;
+			uniqueVertex01.uv[0] = entity->getSubEntity(0)->getUniqueVertex(indices[0]).uv[0];
+			if (mEntity->getSubEntity(0)->hasVertexColours())
+			{			
+                uniqueVertex01.colour = subEntityColour.getAsRGBA();
+			}
+			mEntity->getSubEntity(0)->addUniqueVertex(uniqueVertex01);
+
+			uniqueVertex02.position = entity->getSubEntity(0)->getUniqueVertex(indices[1]).position;
+			uniqueVertex02.normal = entity->getSubEntity(0)->getUniqueVertex(indices[1]).normal;
+			uniqueVertex02.uv[0] = entity->getSubEntity(0)->getUniqueVertex(indices[1]).uv[0];
+			if (mEntity->getSubEntity(0)->hasVertexColours())
+			{			
+                uniqueVertex02.colour = subEntityColour.getAsRGBA();
+			}
+			mEntity->getSubEntity(0)->addUniqueVertex(uniqueVertex02);
+
+			uniqueVertex03.position = entity->getSubEntity(0)->getUniqueVertex(indices[2]).position;
+			uniqueVertex03.normal = entity->getSubEntity(0)->getUniqueVertex(indices[2]).normal;
+			uniqueVertex03.uv[0] = entity->getSubEntity(0)->getUniqueVertex(indices[2]).uv[0];
+			if (mEntity->getSubEntity(0)->hasVertexColours())
+			{			
+                uniqueVertex03.colour = subEntityColour.getAsRGBA();
+			}
+			mEntity->getSubEntity(0)->addUniqueVertex(uniqueVertex03);	
+
+
+		}
+		offset = offset + entity->getSubEntity(0)->getNumFaces() * 3;
+		indicesOffset = Ogre::Vector3(offset, offset, offset);
+	}
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafKMeansClusterData.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafKMeansClusterData.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafKMeansClusterData.cpp	(revision 699)
@@ -0,0 +1,13 @@
+
+#include "LBBCLeafKMeansClusterData.h"
+
+namespace LBBC {
+
+LeafKMeansClusterData::LeafKMeansClusterData() {
+}
+
+LeafKMeansClusterData::~LeafKMeansClusterData() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafKdTreeClusterData.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafKdTreeClusterData.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCLeafKdTreeClusterData.cpp	(revision 699)
@@ -0,0 +1,13 @@
+
+#include "LBBCLeafKdTreeClusterData.h"
+
+namespace LBBC {
+
+LeafKdTreeClusterData::LeafKdTreeClusterData() {
+}
+
+LeafKdTreeClusterData::~LeafKdTreeClusterData() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGBBox.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGBBox.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/IMGBBox.cpp	(revision 699)
@@ -0,0 +1,10 @@
+
+#include "IMGBBox.h"
+
+namespace IMG {
+
+BBox::~BBox() {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloud.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloud.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardCloud.cpp	(revision 699)
@@ -0,0 +1,135 @@
+
+#include "BBCBillboardCloud.h"
+#include "BBCBillboard.h"
+
+namespace BBC {
+
+BillboardCloud::BillboardCloud() 
+{
+	mEntity = new Entity();
+}
+
+BillboardCloud::~BillboardCloud() 
+{
+	for (unsigned int iBillboard = 0; iBillboard < getNumBillboards(); iBillboard++)
+	{
+		Billboard *billboard = getBillboard(iBillboard);
+		delete billboard;
+	}
+
+	delete mEntity;
+}
+
+vector<Billboard*>* BillboardCloud::getBillboardList() {
+  return &mBillboardList;
+}
+void BillboardCloud::setBillboardList(vector<Billboard*> &value) {
+  mBillboardList = value;
+}
+
+unsigned int BillboardCloud::getNumBillboards()
+{
+	return (unsigned int)(mBillboardList.size());
+}
+
+void BillboardCloud::addBillboard(Billboard *value) 
+{
+	value->setBillboardHandle((unsigned int)(mBillboardList.size()));	
+	mBillboardList.push_back(value);
+}
+
+void BillboardCloud::removeBillboard(unsigned int value) 
+{
+	Billboard *billboard = mBillboardList[value];
+	mBillboardList.erase(mBillboardList.begin() + value);
+	delete billboard;
+}
+
+Billboard* BillboardCloud::getBillboard(unsigned int value) 
+{
+	return mBillboardList[value];
+}
+
+Entity* BillboardCloud::getEntity() 
+{
+	return mEntity;
+}
+
+void BillboardCloud::setEntity(Entity *value) 
+{
+	mEntity = value;
+}
+
+void BillboardCloud::generateBillboardCloud(bool mergeBillboards)
+{
+	unsigned int numGeneratedBillboardClouds = 0;
+	for (unsigned int iBillboard = 0; iBillboard < getNumBillboards(); iBillboard++)
+	{
+		Billboard *billboard = this->getBillboard(iBillboard);		
+		EntityCluster *entityCluster = billboard->getBillboardClusterData()->getEntityCluster();
+
+		if (entityCluster->getNumEntitiesClusterData() > 0)
+		{		
+			SubEntity *subEntity;			
+			if (mergeBillboards)
+			{
+				subEntity = mEntity->getSubEntity(0);
+				unsigned int offset = subEntity->getNumFaces() * 3;
+				Ogre::Vector3 indicesA = Ogre::Vector3(offset, offset + 1, offset + 2);
+				subEntity->addFaceVerticesIDs(indicesA);
+				offset = subEntity->getNumFaces()*3;
+				Ogre::Vector3 indicesB = Ogre::Vector3(offset, offset + 1, offset + 2);
+				subEntity->addFaceVerticesIDs(indicesB);
+			}
+			else
+			{				
+				// The entity has by default one subentity, if we need more
+				// we have to create them.
+				if (numGeneratedBillboardClouds > 0)
+				{
+					mEntity->createSubEntity();
+				}
+				Ogre::Vector3 indices = Ogre::Vector3(0,1,2);
+				subEntity = mEntity->getSubEntity(numGeneratedBillboardClouds);
+				subEntity->addTextureCoordSet(2);				
+				subEntity->addFaceVerticesIDs(indices);
+				subEntity->addFaceVerticesIDs(indices + Ogre::Vector3(3,3,3));
+			}
+			
+			UniqueVertex vFaceA1,vFaceA2,vFaceA3;
+			// Face A of the billboard quad
+			vFaceA1.position = billboard->getBillboardClusterData()->getQuadTopLeftCorner();
+			vFaceA1.normal = billboard->getBillboardClusterData()->getNormal();
+			vFaceA1.uv[0] = Ogre::Vector3(0,0,0);
+			vFaceA2.position = billboard->getBillboardClusterData()->getQuadTopRightCorner();
+			vFaceA2.normal = billboard->getBillboardClusterData()->getNormal();
+			vFaceA2.uv[0] = Ogre::Vector3(1,0,0);
+			vFaceA3.position = billboard->getBillboardClusterData()->getQuadBottomRightCorner();
+			vFaceA3.normal = billboard->getBillboardClusterData()->getNormal();
+			vFaceA3.uv[0] = Ogre::Vector3(1,1,0);
+
+			// Face B of the billboard quad
+			UniqueVertex vFaceB1,vFaceB2,vFaceB3;
+			vFaceB1.position = billboard->getBillboardClusterData()->getQuadBottomRightCorner();
+			vFaceB1.normal = billboard->getBillboardClusterData()->getNormal();
+			vFaceB1.uv[0] = Ogre::Vector3(1,1,0);
+			vFaceB2.position = billboard->getBillboardClusterData()->getQuadBottomLeftCorner();
+			vFaceB2.normal = billboard->getBillboardClusterData()->getNormal();
+			vFaceB2.uv[0] = Ogre::Vector3(0,1,0);
+			vFaceB3.position = billboard->getBillboardClusterData()->getQuadTopLeftCorner();
+			vFaceB3.normal = billboard->getBillboardClusterData()->getNormal();
+			vFaceB3.uv[0] = Ogre::Vector3(0,0,0);
+
+			subEntity->addUniqueVertex(vFaceA1);
+			subEntity->addUniqueVertex(vFaceA2);
+			subEntity->addUniqueVertex(vFaceA3);
+			subEntity->addUniqueVertex(vFaceB1);
+			subEntity->addUniqueVertex(vFaceB2);
+			subEntity->addUniqueVertex(vFaceB3);
+
+			numGeneratedBillboardClouds++;
+		}
+	}
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityDistributionGenerator.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityDistributionGenerator.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCEntityDistributionGenerator.cpp	(revision 699)
@@ -0,0 +1,28 @@
+
+#include "BBCEntityDistributionGenerator.h"
+
+namespace BBC {
+
+void EntityDistributionGenerator::generate() {
+}
+
+void EntityDistributionGenerator::init() {
+}
+
+Entity* EntityDistributionGenerator::getEntity() {
+	return mEntity;
+}
+
+void EntityDistributionGenerator::setEntity(Entity * value) {
+	mEntity = value;
+}
+
+void EntityDistributionGenerator::setDistribution(EntityDistribution *value) {
+	mEntityDistribution = value;
+}
+
+EntityDistribution* EntityDistributionGenerator::getDistribution() {
+	return mEntityDistribution;
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCSampleConfigFile.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCSampleConfigFile.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCSampleConfigFile.cpp	(revision 699)
@@ -0,0 +1,179 @@
+#include "LBBCSampleConfigFile.h"
+
+namespace LBBC {
+
+SampleConfigFile::SampleConfigFile()
+{
+}
+	
+SampleConfigFile::~SampleConfigFile()
+{
+}
+
+Ogre::String SampleConfigFile::getEntitySampleMeshPrefixFilename()
+{
+	return getSetting("Entity Sample Mesh Prefix Filename");
+}
+
+bool SampleConfigFile::getEntityDistributionGeneration()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Entity Distribution Generation"));
+}
+
+bool SampleConfigFile::getEntityDistributionMerged()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Entity Distribution Merged"));
+}
+
+Ogre::String SampleConfigFile::getEntityDistributionSplittedMaterialPrefixName()
+{
+	return getSetting("Entity Distribution Splitted Material Prefix Name");
+}
+
+Ogre::String SampleConfigFile::getEntityDistributionMergedMaterialPrefixName()
+{
+	return getSetting("Entity Distribution Merged Material Prefix Name");
+}
+
+Ogre::String SampleConfigFile::getEntityDistributionFolder()
+{
+	return getSetting("Entity Distribution Folder");
+}
+
+Ogre::String SampleConfigFile::getEntityDistributionXMLPrefixFilename()
+{
+	return getSetting("Entity Distribution XML Prefix Filename");
+}
+
+Ogre::String SampleConfigFile::getEntitiesFolder()
+{
+	return getSetting("Entites Folder");
+}
+
+
+Ogre::String SampleConfigFile::getEntitiesMeshPrefixFilename()
+{
+	return getSetting("Entities Mesh Prefix Filename");
+}
+
+Ogre::String SampleConfigFile::getBillboardCloudXMLPrefixFilename()
+{
+	return getSetting("Billboard Cloud XML Prefix Filename");
+}
+
+bool SampleConfigFile::getEntitySampleMeshGeneration()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Entity Sample Mesh Generation"));
+}
+
+bool SampleConfigFile::getEntityClustersGeneration()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Entity Clusters Generation"));
+}
+
+float SampleConfigFile::getEntityClustersAlpha()
+{
+	return Ogre::StringConverter::parseReal(getSetting("Entity Clusters Alpha"));
+}
+
+unsigned int SampleConfigFile::getEntityClustersMaxClusters()
+{
+	return Ogre::StringConverter::parseInt(getSetting("Entity Clusters MaxClusters"));
+}
+
+unsigned int SampleConfigFile::getEntityClustersNumIterations()
+{
+	return Ogre::StringConverter::parseInt(getSetting("Entity Clusters NumIterations"));
+}
+
+bool SampleConfigFile::getEntityClustersMergedClusters()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Entity Clusters Merged Clusters"));
+}
+
+bool SampleConfigFile::getEntityClustersSplittedClusters()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Entity Clusters Splitted Clusters"));
+}
+
+bool SampleConfigFile::getEntityDistributionSplitted()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Entity Distribution Splitted"));
+}
+
+bool SampleConfigFile::getBillboardCloudGeneration()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Billboard Cloud Generation"));
+}
+
+bool SampleConfigFile::getBillboardCloudMergedBillboards()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Billboard Cloud Merged Billboards"));
+}
+
+bool SampleConfigFile::getBillboardCloudSplittedBillboards()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Billboard Cloud Splitted Billboards"));
+}
+
+Ogre::String SampleConfigFile::getEntityClustersFolder()
+{
+	return getSetting("Entity Clusters Folder");
+}
+
+Ogre::String SampleConfigFile::getEntityClustersMeshPrefixFilename()
+{
+	return getSetting("Entity Clusters Mesh Prefix Filename");
+}
+
+Ogre::String SampleConfigFile::getEntityClustersMaterialPrefixFilename()
+{
+	return getSetting("Entity Clusters Material Prefix Filename");
+}
+
+Ogre::String SampleConfigFile::getBillboardCloudFolder()
+{
+	return getSetting("Billboard Cloud Folder");
+}
+
+Ogre::String SampleConfigFile::getBillboardCloudMeshPrefixFilename()
+{
+	return getSetting("Billboard Cloud Mesh Prefix Filename");
+}
+
+Ogre::String SampleConfigFile::getBillboardCloudMaterialPrefixFilename()
+{
+	return getSetting("Billboard Cloud Material Prefix Filename");
+}
+
+bool SampleConfigFile::getBillboardCloudDiffuseColorTextureAtlasGeneration()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Billboard Cloud Diffuse Color Texture Atlas Generation"));
+}
+
+unsigned int SampleConfigFile::getBillboardCloudDiffuseColorTextureSize()
+{
+	return Ogre::StringConverter::parseInt(getSetting("Billboard Cloud Diffuse Color Texture Size"));
+}
+
+unsigned int SampleConfigFile::getBillboardCloudDiffuseColorTextureAtlasSize()
+{
+	return Ogre::StringConverter::parseInt(getSetting("Billboard Cloud Diffuse Color Texture Atlas Size"));
+}
+
+bool SampleConfigFile::getBillboardCloudIndirectTextureAtlasGeneration()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Billboard Cloud Diffuse Color Texture Atlas Generation"));
+}
+
+unsigned int SampleConfigFile::getBillboardCloudIndirectTextureSize()
+{
+	return Ogre::StringConverter::parseInt(getSetting("Billboard Cloud Indirect Texture Size"));
+}
+
+unsigned int SampleConfigFile::getBillboardCloudIndirectTextureAtlasSize()
+{
+	return Ogre::StringConverter::parseInt(getSetting("Billboard Cloud Indirect Texture Atlas Size"));
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCSubEntity.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCSubEntity.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCSubEntity.cpp	(revision 699)
@@ -0,0 +1,238 @@
+
+#include "BBCSubEntity.h"
+
+namespace BBC {
+
+SubEntity::SubEntity() 
+{
+	mHasTangents = false;
+	mHasVertexColours = false;
+	mHasNormals = true;
+	mHasTextureCoords = true;
+}
+
+SubEntity::~SubEntity() 
+{
+}
+
+void SubEntity::setPosition(unsigned int index, Ogre::Vector3 value)
+{
+	mUniqueVertexList[index].position = value;
+}
+
+Ogre::Vector3 SubEntity::getPosition(unsigned int index)
+{
+	return mUniqueVertexList[index].position;
+}
+
+void SubEntity::setNormal(unsigned int index, Ogre::Vector3 value)
+{
+	mUniqueVertexList[index].normal = value;
+}
+
+Ogre::Vector3 SubEntity::getNormal(unsigned int index)
+{
+	return mUniqueVertexList[index].normal;
+}
+
+void SubEntity::setTexCoord(unsigned int index, unsigned int set, Ogre::Vector3 value)
+{
+	mUniqueVertexList[index].uv[set] = value;
+}
+
+Ogre::Vector3 SubEntity::getTexCoord(unsigned int index, unsigned int set, unsigned int value)
+{
+	return mUniqueVertexList[index].uv[set];
+}
+
+void SubEntity::addFaceVerticesIDs(Ogre::Vector3 value)
+{
+	mIndices.push_back(value);
+}
+
+void SubEntity::removeFaceVerticesIDs(unsigned int value)
+{
+	mIndices.erase(mIndices.begin()+value);
+}
+
+Ogre::Vector3 SubEntity::getFaceVerticesIDs(unsigned int value)
+{
+	return mIndices[value];
+}
+
+void SubEntity::enableTangents(bool value)
+{
+	mHasTangents = value;
+}
+
+bool SubEntity::hasTangents()
+{
+	return mHasTangents;
+}
+
+void SubEntity::enableNormals(bool value)
+{
+	mHasNormals = value;
+}
+
+bool SubEntity::hasNormals()
+{
+	return mHasNormals;
+}
+
+void SubEntity::enableTextureCoords(bool value)
+{
+	mHasTextureCoords = value;
+}
+
+void SubEntity::addTextureCoordSet(unsigned int numTexCoords)
+{
+	mTextureCoordSetsDimensions.push_back(numTexCoords);
+	enableTextureCoords(true);
+}
+
+unsigned int SubEntity::getNumTexCoordSets()
+{
+	return static_cast<unsigned int>(mTextureCoordSetsDimensions.size());
+}
+
+unsigned int SubEntity::getNumTexCoords()
+{
+	return static_cast<unsigned int>(mUniqueVertexList.size());
+}
+
+unsigned int SubEntity::getTexCoordDimensions(unsigned int set)
+{
+	return mTextureCoordSetsDimensions[set];
+}
+
+void SubEntity::enableVertexColours(bool value)
+{
+	mHasVertexColours = value;
+}
+
+bool SubEntity::hasVertexColours()
+{
+	return mHasVertexColours;
+}
+
+void SubEntity::setVertexColour(unsigned int index, Ogre::RGBA value)
+{
+	mUniqueVertexList[index].colour = value;
+}
+
+Ogre::RGBA SubEntity::getVertexColour(unsigned int index)
+{
+	return mUniqueVertexList[index].colour;
+}
+
+unsigned int SubEntity::getNumFaces()
+{
+	return static_cast<unsigned int>(mIndices.size());
+}
+
+unsigned int SubEntity::getNumVertices()
+{
+	return static_cast<unsigned int>(mUniqueVertexList.size());
+}
+
+Ogre::String SubEntity::getName()
+{
+	return mName;
+}
+
+void SubEntity::setName(Ogre::String value)
+{
+	mName = value;
+}
+
+Ogre::String SubEntity::getMaterialName()
+{
+	return mMaterialName;
+}
+
+void SubEntity::setMaterialName(Ogre::String value)
+{
+	mMaterialName = value;
+}
+
+
+UniqueVertexList* SubEntity::getUniqueVertices()
+{
+	return &mUniqueVertexList;
+}
+
+/*
+void SubEntity::createUniqueVertices()
+{
+	for (unsigned int i = 0; i < getNumVertices(); i++)
+	{
+		UniqueVertex uniqueVertex;
+		uniqueVertex.position = getVertex(i);
+		uniqueVertex.normal = getNormal(i);
+		for (unsigned int j = 0; j < getNumTexCoordSets(); j++)
+		{
+			uniqueVertex.uv[j] = getTexCoord(j,i);
+		}
+		
+	}
+}
+*/
+
+void SubEntity::addUniqueVertex(UniqueVertex uniqueVertex)
+{
+	mUniqueVertexList.push_back(uniqueVertex);
+}
+
+void SubEntity::removeUniqueVertex(unsigned int index)
+{
+	mUniqueVertexList.erase(mUniqueVertexList.begin() + index);
+}
+
+UniqueVertex SubEntity::getUniqueVertex(unsigned int index)
+{
+	return mUniqueVertexList[index];
+}
+
+const Ogre::AxisAlignedBox &SubEntity::getAABBox()
+{
+	return mAABBox;
+}
+
+void SubEntity::setAABBox(Ogre::AxisAlignedBox box)
+{
+	mAABBox = box;
+}
+
+void SubEntity::generateAABBox()
+{
+	// Bounds calculation
+	Ogre::Real squaredRadius = 0.0f;
+    Ogre::Vector3 min, max;
+    bool first = true;
+
+	for (size_t jVertex = 0; jVertex < this->getNumVertices(); jVertex++)
+	{
+		if (first)
+		{
+			squaredRadius = this->getUniqueVertex(jVertex).position.squaredLength();
+			min = max = this->getUniqueVertex(jVertex).position;
+			first = false;
+		}
+		else
+		{
+			size_t numVertices = (unsigned int)this->getNumVertices();
+			//Ogre::LogManager::getSingleton().logMessage("NumVertices:" + Ogre::StringConverter::toString(numVertices));
+			//Ogre::LogManager::getSingleton().logMessage("IDVertex:" + Ogre::StringConverter::toString(jVertex) + "--" + Ogre::StringConverter::toString(iSubEntity) + "--" + Ogre::StringConverter::toString(mEntity->getSubEntity(iSubEntity)->getUniqueVertex(jVertex).position));
+			squaredRadius = 
+				std::max(squaredRadius,this->getUniqueVertex(jVertex).position.squaredLength());
+			min.makeFloor(this->getUniqueVertex(jVertex).position);
+			max.makeCeil(this->getUniqueVertex(jVertex).position);
+		}
+	}
+
+	// Merge bounds
+	mAABBox.setExtents(min, max);
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardClusterData.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardClusterData.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/BBCBillboardClusterData.cpp	(revision 699)
@@ -0,0 +1,92 @@
+
+#include "BBCBillboardClusterData.h"
+
+namespace BBC {
+
+BillboardClusterData::BillboardClusterData() {
+}
+
+BillboardClusterData::~BillboardClusterData() {
+}
+
+void BillboardClusterData::setNormal(Ogre::Vector3 value)
+{
+	mNormal = value;
+}
+
+Ogre::Vector3 BillboardClusterData::getNormal()
+{
+	return mNormal;
+}
+
+void BillboardClusterData::setD(float value)
+{
+	mD = value;
+}
+
+float BillboardClusterData::getD()
+{
+	return mD;
+}
+
+void BillboardClusterData::writeBillboardClusterData(TiXmlNode *parentNode)
+{
+	Ogre::LogManager::getSingleton().logMessage("writeBillboardClusterData method not implemented.");
+}
+
+void BillboardClusterData::readBillboardClusterData(TiXmlNode *parentNode)
+{
+	Ogre::LogManager::getSingleton().logMessage("readBillboardClusterData method not implemented.");
+}
+
+void BillboardClusterData::generateBillboardBoundingQuad()
+{
+	Ogre::LogManager::getSingleton().logMessage("generateBillboardBoundingQuad method not implemented.");
+}
+
+void BillboardClusterData::setEntityCluster(EntityCluster *value) 
+{
+  mEntityCluster = value;
+}
+
+EntityCluster* BillboardClusterData::getEntityCluster() 
+{
+  return mEntityCluster;
+}
+
+Ogre::Vector3 BillboardClusterData::getQuadTopLeftCorner()
+{
+	return mBillboardCorners[QUAD_TOP_LEFT];
+}
+
+Ogre::Vector3 BillboardClusterData::getQuadTopRightCorner()
+{
+	return mBillboardCorners[QUAD_TOP_RIGHT];
+}
+
+Ogre::Vector3 BillboardClusterData::getQuadBottomLeftCorner()
+{
+	return mBillboardCorners[QUAD_BOTTOM_LEFT];
+}
+
+Ogre::Vector3 BillboardClusterData::getQuadBottomRightCorner()
+{
+	return mBillboardCorners[QUAD_BOTTOM_RIGHT];
+}
+
+Ogre::Vector3 BillboardClusterData::getAxisX()
+{
+	return mAxisX;
+}
+
+Ogre::Vector3 BillboardClusterData::getAxisY()
+{
+	return mAxisY;
+}
+
+Ogre::Vector3 BillboardClusterData::getAxisZ()
+{
+	return mAxisZ;
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKMeansClusterSerializer.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKMeansClusterSerializer.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKMeansClusterSerializer.cpp	(revision 699)
@@ -0,0 +1,16 @@
+
+#include "LBBCKMeansClusterSerializer.h"
+
+namespace LBBC {
+
+KMeansClusterSerializer::KMeansClusterSerializer() {
+}
+
+KMeansClusterSerializer::~KMeansClusterSerializer() {
+}
+
+void KMeansClusterSerializer::writeBillboardCloud(TiXmlDocument *document) {
+}
+
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKdTreeClusterSerializer.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKdTreeClusterSerializer.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKdTreeClusterSerializer.cpp	(revision 699)
@@ -0,0 +1,37 @@
+
+#include "LBBCKdTreeClusterSerializer.h"
+
+namespace LBBC {
+
+KdTreeClusterSerializer::KdTreeClusterSerializer() {
+}
+
+KdTreeClusterSerializer::~KdTreeClusterSerializer() {
+}
+
+void KdTreeClusterSerializer::writeBillboardCloud(TiXmlDocument *document)
+{
+	TiXmlNode *billboardCloudNode = document->InsertEndChild(TiXmlElement("billboardCloud"))->ToElement();
+
+	unsigned int numSerializedBillboards = 0;
+	unsigned int numSerializedEntities = 0;
+	for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++)
+	{
+		BBC::Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);
+		BBC::EntityCluster *entityCluster = billboard->getBillboardClusterData()->getEntityCluster();
+
+		// If the Billboard has Entities...
+		if (entityCluster->getNumEntitiesClusterData() > 0)
+		{
+			BillboardKdTreeClusterData *billboardKdTreeClusterData = (BillboardKdTreeClusterData*)billboard->getBillboardClusterData();
+			billboardKdTreeClusterData->writeBillboardClusterData(billboardCloudNode);	
+			numSerializedBillboards++;
+			numSerializedEntities = numSerializedEntities + entityCluster->getNumEntitiesClusterData();
+		}
+	}
+	billboardCloudNode->ToElement()->SetAttribute("count",Ogre::StringConverter::toString(numSerializedBillboards));
+	
+	Ogre::LogManager::getSingleton().logMessage("Num.Serialized Billboards:" + Ogre::StringConverter::toString(numSerializedBillboards) + " with " + Ogre::StringConverter::toString(numSerializedEntities) + " Entities");
+}
+
+}
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCManager.cpp
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCManager.cpp	(revision 699)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCManager.cpp	(revision 699)
@@ -0,0 +1,392 @@
+
+#include "LBBCManager.h"
+
+namespace LBBC {
+
+Manager::Manager() 
+	: BBC::Manager() 
+{
+	//mCf.load("lbbc.cfg");	
+	
+	mBillboardCloudSerializer = new KdTreeClusterSerializer();
+	mLeafDistributionSerializer = new LeafDistributionSerializer();
+	mLeafDistributionGenerator = new LeafDistributionGenerator();
+	mBillboardCloudGenerator = new KdTreeClusterGenerator();
+	mBillboardCloudUVMapper = new BBC::BillboardCloudUVMapper();
+	mOgreMeshSerializer = new BBC::OgreMeshSerializer();
+}
+
+Manager::~Manager() 
+{
+	// How to manage the destruction of BBC::Manager?
+	delete mBillboardCloudSerializer;
+	delete mLeafDistributionSerializer;
+	delete mLeafDistributionGenerator;
+	delete mBillboardCloudGenerator;
+	delete mBillboardCloudUVMapper;
+	delete mOgreMeshSerializer;
+	delete mLeaves;
+}
+
+SampleConfigFile* Manager::getSampleConfigFile()
+{
+	return &mSampleCf;
+}
+void Manager::runSample(Ogre::String sampleConfigFile)
+{
+	Ogre::LogManager::getSingleton().logMessage("Sample Config Filename:" + sampleConfigFile);
+
+	mSampleCf.load(sampleConfigFile);
+	mLeaves = new Leaves();
+
+	Ogre::Mesh* leavesMesh = BBC::Manager::getSingleton().loadMesh(
+								mSampleCf.getEntitiesMeshPrefixFilename() + ".mesh");	
+	
+	mLeaves->setMesh(leavesMesh);
+
+	if (mSampleCf.getEntityDistributionGeneration())
+	{
+		generateEntityDistribution();
+	}
+	else
+	{
+		loadEntityDistribution();
+	}
+	
+	if (mSampleCf.getEntityClustersGeneration())
+	{
+		generateEntityClusters();
+	}
+	if (mSampleCf.getBillboardCloudGeneration())
+	{
+		generateBillboardCloud();
+	}	
+}
+
+void Manager::createEntityDistribution()
+{
+	mLeafDistributionGenerator->setDistribution(mLeaves->getDistribution());
+	mLeafDistributionGenerator->getEntity()->setMesh(mLeaves->getMesh());	
+	mLeafDistributionGenerator->generate();
+}
+
+void Manager::saveEntityDistributionSplitted()
+{
+	BBC::Entity *entity;
+	entity = new BBC::Entity();
+
+	if (mSampleCf.getEntityDistributionSplitted() || mSampleCf.getEntityDistributionMerged())
+	{
+		BBC::EntityDistribution *entityDistribution;		
+		unsigned int numSerializedEntities = 0;
+
+		
+		entityDistribution = mLeaves->getDistribution();
+		for (unsigned int iEntity = 0; iEntity < entityDistribution->getNumEntities(); iEntity++)
+		{				
+				BBC::SubEntity *subEntity = entityDistribution->getEntity(iEntity)->getSubEntity(0);
+
+				if (iEntity == 0)
+				{
+					// Delete the default constructed subentity...
+					entity->removeSubEntity(0);
+
+					// Add our first subentity...
+					entity->addSubEntity(subEntity);					
+				}
+				else
+				{
+					entity->addSubEntity(subEntity);
+				}
+
+				entity->getSubEntity(numSerializedEntities)->setMaterialName(mSampleCf.getEntityDistributionMergedMaterialPrefixName());
+				numSerializedEntities++;			
+		}		
+
+		entity->setSubEntitiesDistinctVertexColours();
+		
+		if (mSampleCf.getEntityDistributionSplitted())
+		{
+			mOgreMeshSerializer->setEntity(entity);
+			mOgreMeshSerializer->exportMesh(mSampleCf.getEntityClustersFolder() +
+				mSampleCf.getEntityClustersMeshPrefixFilename() + "Splitted.mesh", false, false);
+			
+			mMeshSerializer->exportMesh(entity->getMesh(), mSampleCf.getEntityDistributionFolder() + mSampleCf.getEntitiesMeshPrefixFilename() + "Splitted.mesh");
+			//mXMLMeshSerializer->exportMesh(entity->getMesh(), mSampleCf.getEntityClustersFolder() + mSampleCf.getEntitiesMeshPrefixFilename() + "Splitted.mesh" + ".xml");
+		}
+	}
+
+	if (mSampleCf.getEntityDistributionMerged())
+	{
+		entity->mergeSubEntities();
+		entity->getSubEntity(0)->setMaterialName(mSampleCf.getEntityDistributionMergedMaterialPrefixName());
+	
+		mOgreMeshSerializer->setEntity(entity);
+		mOgreMeshSerializer->exportMesh(mSampleCf.getEntityClustersFolder() +
+			mSampleCf.getEntityClustersMeshPrefixFilename() + "Merged.mesh", false, false);
+		
+		mMeshSerializer->exportMesh(entity->getMesh(), mSampleCf.getEntityDistributionFolder() + mSampleCf.getEntitiesMeshPrefixFilename() + "Merged.mesh");
+		//mXMLMeshSerializer->exportMesh(entity->getMesh(), mSampleCf.getEntityClustersFolder() + mSampleCf.getEntitiesMeshPrefixFilename() + "Merged.mesh" + ".xml");
+		
+		delete entity;
+	}
+}
+
+void Manager::saveEntityDistributionXML()
+{
+	TiXmlDocument *document = mLeafDistributionSerializer->create(
+									mSampleCf.getEntityDistributionFolder() +
+									mSampleCf.getEntityDistributionXMLPrefixFilename() + ".xml");
+	mLeafDistributionSerializer->setLeafDistribution(mLeaves->getDistribution());
+	mLeafDistributionSerializer->writeLeafDistribution(document);	
+	mLeafDistributionSerializer->save();
+}
+
+void Manager::loadEntityDistribution()
+{
+	TiXmlDocument *document = mLeafDistributionSerializer->load(
+									mSampleCf.getEntityDistributionFolder() +
+									mSampleCf.getEntityDistributionXMLPrefixFilename() + ".xml");
+	mLeafDistributionSerializer->setLeafDistribution(mLeaves->getDistribution());
+	mLeafDistributionSerializer->getEntity()->setMesh(mLeaves->getMesh());
+	mLeafDistributionSerializer->readLeafDistribution(document);
+
+	BBC::Entity *entity;
+	BBC::EntityDistribution *entityDistribution;
+
+	Ogre::Mesh* leavesSplittedMesh = BBC::Manager::getSingleton().loadMesh(mSampleCf.getEntitiesMeshPrefixFilename() + "Splitted.mesh");		
+	entity = new BBC::Entity();
+	entity->setMesh(leavesSplittedMesh);
+
+	entity->loadMesh(false);
+	entityDistribution = mLeaves->getDistribution();
+
+	for (unsigned int iSubEntity = 0; iSubEntity < entity->getNumSubEntities(); iSubEntity++)
+	{	
+		BBC::Entity *entitySample;
+		BBC::SubEntity *subEntity;
+		BBC::SubEntity *subEntitySample;
+			
+		subEntity = entity->getSubEntity(iSubEntity);
+		entitySample = entityDistribution->getEntity(iSubEntity);
+		subEntitySample = entitySample->getSubEntity(0);
+		entitySample->removeSubEntity(0);				
+
+		// Add our first subentity...
+		entitySample->addSubEntity(subEntity);	
+	}
+}
+
+void Manager::generateEntityDistribution()
+{
+	if (mSampleCf.getEntityDistributionGeneration())
+	{
+		createEntityDistribution();
+		saveEntityDistributionSplitted();
+		saveEntityDistributionXML();
+	}
+}
+
+void Manager::saveBillboardCloudSplitted()
+{
+	//exportBillboardCloudMesh()	
+	mOgreMeshSerializer->setEntity(mLeaves->getBillboardCloud()->getEntity());
+	mOgreMeshSerializer->exportMesh(mSampleCf.getBillboardCloudFolder() +
+				mSampleCf.getBillboardCloudMeshPrefixFilename() + "Splitted.mesh",false, false);
+	mMeshSerializer->exportMesh(mLeaves->getBillboardCloud()->getEntity()->getMesh(), mSampleCf.getBillboardCloudFolder() + mSampleCf.getBillboardCloudMeshPrefixFilename() + "Splitted.mesh");
+}
+
+void Manager::saveBillboardCloudMerged()
+{	
+	mLeaves->getBillboardCloud()->getEntity()->getSubEntity(0)->setMaterialName(mSampleCf.getBillboardCloudMaterialPrefixFilename());
+	mOgreMeshSerializer->setEntity(mLeaves->getBillboardCloud()->getEntity());
+	mOgreMeshSerializer->exportMesh(mSampleCf.getBillboardCloudFolder() +
+				mSampleCf.getBillboardCloudMeshPrefixFilename() + "Merged.mesh", mSampleCf.getBillboardCloudMergedBillboards(), false);
+	mMeshSerializer->exportMesh(mLeaves->getBillboardCloud()->getEntity()->getMesh(), 
+				mSampleCf.getBillboardCloudFolder() + mSampleCf.getBillboardCloudMeshPrefixFilename() 				 
+
+				+ "Merged.mesh");
+}
+
+void Manager::saveBillboardCloudXML()
+{
+	//saveBillboardCloud()
+	TiXmlDocument *document2 = mBillboardCloudSerializer->create(
+									mSampleCf.getBillboardCloudFolder() + 
+									mSampleCf.getBillboardCloudXMLPrefixFilename() + ".xml");
+	mBillboardCloudSerializer->setBillboardCloud(mLeaves->getBillboardCloud());
+	mBillboardCloudSerializer->writeBillboardCloud(document2);	
+	mBillboardCloudSerializer->save();
+}
+
+void Manager::saveEntityClusters()
+{
+	BBC::BillboardClusterData *billboardClusterData;
+	BBC::EntityCluster *entityCluster;
+	unsigned int numSerializedBillboards = 0;	
+
+	if (mSampleCf.getEntityClustersSplittedClusters())
+	{
+
+		for (unsigned int iBillboard = 0; iBillboard < mLeaves->getBillboardCloud()->getNumBillboards(); iBillboard++)
+		{
+			billboardClusterData = mLeaves->getBillboardCloud()->getBillboard(iBillboard)->getBillboardClusterData();
+			entityCluster = billboardClusterData->getEntityCluster();
+			Ogre::LogManager::getSingleton().logMessage("iBillboard: " + Ogre::StringConverter::toString(iBillboard));
+			if (entityCluster->getNumEntitiesClusterData() > 0)
+			{					
+				BBC::Entity *entityClusterized = entityCluster->getEntity();
+				entityClusterized->getSubEntity(0)->setMaterialName(mSampleCf.getEntityClustersMaterialPrefixFilename());
+				mOgreMeshSerializer->setEntity(entityClusterized);
+				mOgreMeshSerializer->exportMesh(mSampleCf.getEntityDistributionFolder() +
+					mSampleCf.getEntityClustersMeshPrefixFilename() +
+					Ogre::StringConverter::toString(numSerializedBillboards) + ".mesh", !(mSampleCf.getEntityClustersSplittedClusters()), false);
+				mMeshSerializer->exportMesh(entityClusterized->getMesh(),
+					mSampleCf.getEntityClustersFolder() +
+					mSampleCf.getEntityClustersMeshPrefixFilename() +
+					Ogre::StringConverter::toString(numSerializedBillboards) + ".mesh");
+				//mXMLMeshSerializer->exportMesh(entityClusterized->getMesh(), entityClusterized->getMesh()->getName() + ".xml");
+
+				numSerializedBillboards++;
+			}
+		}
+	}
+	numSerializedBillboards = 0;
+
+if (mSampleCf.getEntityClustersMergedClusters())
+	{
+		BBC::Entity *entity;
+		entity = new BBC::Entity();
+
+		for (unsigned int iBillboard = 0; iBillboard < mLeaves->getBillboardCloud()->getNumBillboards(); iBillboard++)
+		{
+			billboardClusterData = mLeaves->getBillboardCloud()->getBillboard(iBillboard)->getBillboardClusterData();
+			entityCluster = billboardClusterData->getEntityCluster();
+
+			if (entityCluster->getNumEntitiesClusterData() > 0)
+			{			
+				BBC::Entity *entityClusterized = entityCluster->getEntity();
+				entityClusterized->getSubEntity(0)->setMaterialName(mSampleCf.getEntityClustersMaterialPrefixFilename());
+				BBC::SubEntity *subEntity = entityClusterized->getSubEntity(0);
+
+				if (numSerializedBillboards == 0)
+				{
+					// Delete the default constructed subentity...
+					entity->removeSubEntity(0);
+
+					// Add our first subentity...
+					entity->addSubEntity(subEntity);
+				}
+				else
+				{
+					entity->addSubEntity(subEntity);
+				}
+
+				numSerializedBillboards++;
+			}
+		}
+		
+		Ogre::LogManager::getSingleton().logMessage(" Mesh Generation --" + Ogre::StringConverter::toString(numSerializedBillboards));
+
+		mOgreMeshSerializer->setEntity(entity);
+		mOgreMeshSerializer->exportMesh(mSampleCf.getEntityClustersFolder() +
+			mSampleCf.getEntityClustersMeshPrefixFilename() + "Merged.mesh", false, false);
+		
+		mMeshSerializer->exportMesh(entity->getMesh(), mSampleCf.getEntityClustersFolder() + mSampleCf.getEntityClustersMeshPrefixFilename() + "Merged.mesh");
+		//mXMLMeshSerializer->exportMesh(entity->getMesh(), mSampleCf.getEntityClustersFolder() + mSampleCf.getEntityClustersMeshPrefixFilename() + "Merged.mesh" + ".xml");
+
+		delete entity;
+	}
+
+
+
+}
+
+void Manager::createEntityClusters()
+{
+	mBillboardCloudGenerator->setDistribution(mLeaves->getDistribution());
+	mBillboardCloudGenerator->setBillboardCloud(mLeaves->getBillboardCloud());
+	mBillboardCloudGenerator->setMaxNumBillboards(mSampleCf.getEntityClustersMaxClusters());
+	((KdTreeClusterGenerator*)mBillboardCloudGenerator)->setAlpha(mSampleCf.getEntityClustersAlpha());
+	((KdTreeClusterGenerator*)mBillboardCloudGenerator)->setNumIterations(mSampleCf.getEntityClustersNumIterations());
+	((KdTreeClusterGenerator*)mBillboardCloudGenerator)->generate();
+}
+
+void Manager::saveSingleEntity()
+{
+	if (mSampleCf.getEntitySampleMeshGeneration())
+	{
+		BBC::Entity *entityLeaf = mLeaves->getDistribution()->getEntity(2);
+		entityLeaf->getSubEntity(0)->setMaterialName(mSampleCf.getEntityClustersMaterialPrefixFilename());
+		mOgreMeshSerializer->setEntity(entityLeaf);
+		mOgreMeshSerializer->exportMesh(mSampleCf.getEntityDistributionFolder() +
+			mSampleCf.getEntitySampleMeshPrefixFilename(), mSampleCf.getEntityClustersMergedClusters(), false);
+		//mXMLMeshSerializer->exportMesh(entityLeaf->getMesh(), entityLeaf->getMesh()->getName() + ".xml");
+	}
+}
+
+void Manager::generateEntityClusters()
+{
+	Ogre::LogManager::getSingleton().logMessage("EntityClustersMeshPrefixName:" + mSampleCf.getEntityClustersMeshPrefixFilename());
+	createEntityClusters();
+	saveEntityClusters();
+	saveSingleEntity();	
+}
+
+void Manager::generateBillboardCloud()
+{
+	if (mSampleCf.getBillboardCloudMergedBillboards())
+	{
+		mLeaves->getBillboardCloud()->generateBillboardCloud(mSampleCf.getBillboardCloudMergedBillboards());
+		if (mSampleCf.getBillboardCloudDiffuseColorTextureAtlasGeneration())
+		{
+			mBillboardCloudUVMapper->setBillboardCloud(mLeaves->getBillboardCloud());
+			mBillboardCloudUVMapper->setTextureWidth(mSampleCf.getBillboardCloudDiffuseColorTextureSize());
+			mBillboardCloudUVMapper->setTextureHeight(mSampleCf.getBillboardCloudDiffuseColorTextureSize());
+			mBillboardCloudUVMapper->setTextureAtlasWidth(mSampleCf.getBillboardCloudDiffuseColorTextureAtlasSize());
+			mBillboardCloudUVMapper->setTextureAtlasHeight(mSampleCf.getBillboardCloudDiffuseColorTextureAtlasSize());
+			mBillboardCloudUVMapper->initialize();
+			mBillboardCloudUVMapper->generateTextureAtlasTextureCoords(mSampleCf.getBillboardCloudMergedBillboards()); 
+		}
+		saveBillboardCloudMerged();
+	}
+
+
+	if (mSampleCf.getBillboardCloudSplittedBillboards())
+	{		
+		mLeaves->getBillboardCloud()->generateBillboardCloud(!mSampleCf.getBillboardCloudSplittedBillboards());
+		if (mSampleCf.getBillboardCloudDiffuseColorTextureAtlasGeneration())
+		{
+			mBillboardCloudUVMapper->setBillboardCloud(mLeaves->getBillboardCloud());
+			mBillboardCloudUVMapper->setTextureWidth(mSampleCf.getBillboardCloudDiffuseColorTextureSize());
+			mBillboardCloudUVMapper->setTextureHeight(mSampleCf.getBillboardCloudDiffuseColorTextureSize());
+			mBillboardCloudUVMapper->setTextureAtlasWidth(mSampleCf.getBillboardCloudDiffuseColorTextureAtlasSize());
+			mBillboardCloudUVMapper->setTextureAtlasHeight(mSampleCf.getBillboardCloudDiffuseColorTextureAtlasSize());
+			mBillboardCloudUVMapper->initialize();
+			mBillboardCloudUVMapper->generateTextureAtlasTextureCoords(!mSampleCf.getBillboardCloudSplittedBillboards()); 
+		}
+		saveBillboardCloudSplitted();
+	}
+
+	saveBillboardCloudXML();
+}
+
+Leaves* Manager::getLeaves()
+{
+	return mLeaves;
+}
+
+//exportEntities()
+/*
+BBC::Entity *entityLeaves =  new BBC::Entity();
+entityLeaves->setMesh(leavesMesh);
+entityLeaves->loadMesh(true);
+entityLeaves->getSubEntity(0)->setMaterialName(mSampleCf.getEntityClustersMaterialPrefixFilename() + ".material");
+mOgreMeshSerializer->setEntity(entityLeaves);
+mOgreMeshSerializer->exportMesh(mSampleCf.getEntityDistributionFolder() + 
+	mSampleCf.getEntitySampleMeshPrefixFilename() + "New.mesh", false, false);
+mXMLMeshSerializer->exportMesh(entityLeaves->getMesh(), mSampleCf.getEntityDistributionFolder() + 
+	mSampleCf.getEntitySampleMeshPrefixFilename() + "New.mesh.xml");
+*/
+
+}
