Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/LBBC/LBBCSampleConfigFile.h
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/LBBC/LBBCSampleConfigFile.h	(revision 700)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/LBBC/LBBCSampleConfigFile.h	(revision 709)
@@ -78,4 +78,8 @@
 	unsigned int getBillboardCloudIndirectTextureAtlasSize();
 
+	unsigned int getBillboardCloudGroups();
+
+	bool getBillboardCloudGroupedBillboards();
+
 };
 
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/LBBC/LBBCManager.h
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/LBBC/LBBCManager.h	(revision 700)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/LBBC/LBBCManager.h	(revision 709)
@@ -46,4 +46,6 @@
 	void generateBillboardCloud();
 
+	void saveBillboardCloudGrouped();
+
 	void saveBillboardCloudSplitted();
 
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/BBC/BBCBillboardCloudUVMapper.h
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/BBC/BBCBillboardCloudUVMapper.h	(revision 700)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/BBC/BBCBillboardCloudUVMapper.h	(revision 709)
@@ -10,7 +10,7 @@
 class BillboardCloudUVMapper {
   protected:
-    IMG::Bsp mBsp;
+	std::vector<IMG::Bsp*> mBspList;
 
-    IMG::ClusterList mClusterList;
+	std::vector<IMG::ClusterList*> mClusterLists;
 
     unsigned short int mTextureWidth;
@@ -44,9 +44,31 @@
     unsigned short int getTextureHeight();
 
-    void BillboardCloudUVMapper::generateTextureAtlasTextureCoords(bool mergeBillboards); 
+    void generateTextureAtlasTextureCoords(bool mergeBillboards, bool groupedBillboards = false, unsigned int numberGroups = 1);
+
+	void addTextureAtlasTextureCoords(bool mergeBillboards, bool groupedBillboards, unsigned int numGeneratedBillboardClouds, unsigned int iBillboardGroup);
 
     void setBillboardCloud(BillboardCloud *billboardCloud);
+    
+	BillboardCloud* getBillboardCloud();
 
-    BillboardCloud* getBillboardCloud();
+	void addTextureInBsp(unsigned int iBillboardGroup, unsigned int iBillboard);
+
+	void addBsp(IMG::Bsp *bsp);
+
+	IMG::Bsp* getBsp(unsigned int iBsp);
+
+	void removeBsp(unsigned int iBsp);
+
+	void addClusterList(IMG::ClusterList *clusterList);
+
+	IMG::ClusterList* getClusterList(unsigned int iClusterList);
+
+	void removeClusterList(unsigned int iClusterList);
+
+	void clear();
+
+	unsigned int getNumClusterLists();
+
+	unsigned int getNumBsp();
 
     BillboardCloudUVMapper();
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/BBC/BBCBillboardGroup.h
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/BBC/BBCBillboardGroup.h	(revision 700)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/BBC/BBCBillboardGroup.h	(revision 709)
@@ -2,7 +2,5 @@
 #define _BILLBOARDGROUP_H
 
-
-#include <vector>
-using namespace std;
+#include <BBCPrerequisites.h>
 
 namespace BBC {
@@ -10,10 +8,12 @@
 class BillboardGroup {
   protected:
-    vector<int> mBillboardHandleList;
+	std::vector<unsigned int> mBillboardHandleList;
 
   public:
-    int getBillboardHandle();
+    unsigned int getBillboardHandle(unsigned int iBillboard);
 
-    void setBillboardHandle();
+    void addBillboardHandle(unsigned int iBillboardHandle);
+
+	unsigned int getNumBillboards();
 
 };
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/BBC/BBCBillboardCloud.h
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/BBC/BBCBillboardCloud.h	(revision 700)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/BBC/BBCBillboardCloud.h	(revision 709)
@@ -6,6 +6,4 @@
 #include <BBCEntityCluster.h>
 #include <BBCEntity.h>
-
-#include <vector>
 
 namespace BBC {
@@ -19,11 +17,12 @@
 
   protected:
-    vector<Billboard*> mBillboardList;
-
+	  std::vector<Billboard*> mBillboardList;
+	  
+	  std::vector<BillboardGroup*> mBillboardGroupList;
 
   public:
-    vector<Billboard*>* getBillboardList();
+	std::vector<Billboard*>* getBillboardList();
 
-    void setBillboardList(vector<Billboard*> &value);
+	void setBillboardList(std::vector<Billboard*> &value);
 
     void addBillboard(Billboard* value);
@@ -36,4 +35,16 @@
 
 	void generateBillboardCloud(bool mergeBillboards);
+
+	void initializeBillboardCloudGroups(unsigned int numberGroups);
+
+	void generateBillboardCloudGroups();
+
+	unsigned int getNumBillboardGroups();
+
+	BillboardGroup* getBillboardGroup(unsigned int iBillboardGroup);
+
+	void addBillboardGroup(BillboardGroup *value); 
+
+	void removeBillboardGroup(unsigned int value);
 
   protected:
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/IMG/IMGClusterList.h
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/IMG/IMGClusterList.h	(revision 700)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/include/IMG/IMGClusterList.h	(revision 709)
@@ -20,5 +20,5 @@
 
     //return the pointer to the list of voxels
-    inline int GetSize() const { return list.size(); }
+    inline unsigned int GetSize() const { return list.size(); }
 
     //return the number of elements of list
Index: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/scripts/IBRBillboardCloudTreeGeneratorCommandLine.vcproj
===================================================================
--- GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/scripts/IBRBillboardCloudTreeGeneratorCommandLine.vcproj	(revision 698)
+++ GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/scripts/IBRBillboardCloudTreeGeneratorCommandLine.vcproj	(revision 709)
@@ -82,5 +82,5 @@
 				Name="VCLinkerTool"
 				AdditionalDependencies="odbc32.lib kernel32.lib odbccp32.lib IBRBillboardCloudTreeGenerator.lib OgreMain.lib"
-				OutputFile="$(OutDir)/IBRBillboardCloudGeneratorCmd.exe"
+				OutputFile="$(OutDir)/IBRBillboardCloudTreeGeneratorCmd.exe"
 				LinkIncremental="1"
 				AdditionalLibraryDirectories="../bin/$(ConfigurationName);$(OGRE_PATH)/OgreMain/lib/$(ConfigurationName)"
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 709)
@@ -4,13 +4,18 @@
 namespace BBC {
 
-int BillboardGroup::getBillboardHandle() 
+unsigned int BillboardGroup::getBillboardHandle(unsigned int iBillboard) 
 {
-	return 0;
+	return mBillboardHandleList[iBillboard];
 }
 
-void BillboardGroup::setBillboardHandle() 
+void BillboardGroup::addBillboardHandle(unsigned int iBillboardHandle) 
 {
+	mBillboardHandleList.push_back(iBillboardHandle);
 }
 
+unsigned int BillboardGroup::getNumBillboards()
+{
+	return mBillboardHandleList.size();
+}
 
 }
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 709)
@@ -4,5 +4,7 @@
 namespace IMG {
 
-Bsp::~Bsp() {
+Bsp::~Bsp() 
+{
+	delete root;
 }
 
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 709)
@@ -33,5 +33,5 @@
 
             // Invalid option
-            cout<<"Invalid option "<<tmp<<endl;
+			std::cout<<"Invalid option "<<tmp<<std::endl;
 
         }
@@ -64,5 +64,5 @@
 void help()
 {
-	cout<<"Please specify the parameter: -cfg sample.cfg"<<endl;
+	std::cout<<"Please specify the parameter: -cfg sample.cfg"<<std::endl;
 }
 
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 709)
@@ -67,5 +67,4 @@
 			//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) && 
@@ -114,5 +113,4 @@
 					//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
@@ -138,5 +136,4 @@
 							//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
@@ -155,5 +152,4 @@
 								//Ogre::LogManager::getSingleton().logMessage("face stored: " + Ogre::StringConverter::toString(iF01));					
 								//Ogre::LogManager::getSingleton().logMessage("face stored: " + Ogre::StringConverter::toString(leaf->getFace(0)));
-								//cin.get();
 							}
 						}
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 709)
@@ -1,2 +1,3 @@
+
 
 #include "BBCBillboardCloudUVMapper.h"
@@ -7,11 +8,79 @@
 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);	
+BillboardCloudUVMapper::BillboardCloudUVMapper() 
+{
+}
+
+BillboardCloudUVMapper::~BillboardCloudUVMapper()
+{
+	clear(); 
+}
+
+void BillboardCloudUVMapper::initialize()
+{
+}
+
+void BillboardCloudUVMapper::clear() 
+{
+	Ogre::LogManager::getSingleton().logMessage("Init.BSP:" + Ogre::StringConverter::toString(getNumBsp()));
+
+	while (getNumBsp() > 0)
+	{
+		removeBsp(getNumBsp()-1);
+	}
+
+	Ogre::LogManager::getSingleton().logMessage("Clear.BSP:" + Ogre::StringConverter::toString(getNumBsp()));
+
+	Ogre::LogManager::getSingleton().logMessage("Init.CL:" + Ogre::StringConverter::toString(getNumClusterLists()));
+
+	//while (getNumClusterLists() > 0)
+	//{
+	//	removeBsp(getNumClusterLists()-1);
+	//}
+	mClusterLists.clear();
+
+	Ogre::LogManager::getSingleton().logMessage("Clear.CL:" + Ogre::StringConverter::toString(getNumClusterLists()));
+}
+
+unsigned int BillboardCloudUVMapper::getNumClusterLists()
+{
+	return mClusterLists.size();
+}
+
+unsigned int BillboardCloudUVMapper::getNumBsp()
+{
+	return mBspList.size();
+}
+
+void BillboardCloudUVMapper::addBsp(IMG::Bsp *bsp)
+{
+	mBspList.push_back(bsp);
+}
+
+IMG::Bsp* BillboardCloudUVMapper::getBsp(unsigned int iBsp)
+{
+	return mBspList[iBsp];
+}
+
+void BillboardCloudUVMapper::removeBsp(unsigned int iBsp)
+{
+	IMG::Bsp *bsp = mBspList[iBsp];
+	mBspList.erase(mBspList.begin() + iBsp);
+	delete bsp;
+}
+
+void BillboardCloudUVMapper::addClusterList(IMG::ClusterList *clusterList)
+{
+	mClusterLists.push_back(clusterList);
+}
+
+IMG::ClusterList* BillboardCloudUVMapper::getClusterList(unsigned int iClusterList)
+{
+	return mClusterLists[iClusterList];
+}
+
+void BillboardCloudUVMapper::removeClusterList(unsigned int iClusterList)
+{
+	//mClusterLists.erase(mClusterLists.begin() + iClusterList);
 }
 
@@ -56,10 +125,254 @@
 }
 
-void BillboardCloudUVMapper::generateTextureAtlasTextureCoords(bool mergeBillboards) 
+void BillboardCloudUVMapper::addTextureAtlasTextureCoords(bool mergeBillboards, bool groupedBillboards, unsigned int numGeneratedBillboardClouds, unsigned int iBillboardGroup)
+{
+	unsigned int iUniqueVertex = 0;
+
+	Ogre::LogManager::getSingleton().logMessage("iBBC:" + Ogre::StringConverter::toString(numGeneratedBillboardClouds) + "-" + "iBBCG:" + Ogre::StringConverter::toString(iBillboardGroup));
+
+	Ogre::LogManager::getSingleton().logMessage("SizeCLList:" + Ogre::StringConverter::toString(getClusterList(iBillboardGroup)->GetSize()) + " -- numBBC:" + Ogre::StringConverter::toString(numGeneratedBillboardClouds));
+
+	IMG::Cluster *cluster = getClusterList(iBillboardGroup)->Get(getClusterList(iBillboardGroup)->GetSize()-1);		
+	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 (groupedBillboards)
+	{
+		Ogre::LogManager::getSingleton().logMessage("DontMerge");
+		subEntity = subEntity = mBillboardCloud->getEntity()->getSubEntity(iBillboardGroup);				
+		
+		// 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;
+	}
+	else
+	{
+		if (!mergeBillboards)
+		{
+			Ogre::LogManager::getSingleton().logMessage("DontMerge");
+
+			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
+		{
+			Ogre::LogManager::getSingleton().logMessage("Merge");
+
+			subEntity = mBillboardCloud->getEntity()->getSubEntity(0);				
+			
+			// 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;
+		}
+		Ogre::LogManager::getSingleton().logMessage("EndAdd");
+	}
+}
+
+void BillboardCloudUVMapper::addTextureInBsp(unsigned int iBillboardGroup, unsigned int iBillboard)
+{
+	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 = getBsp(iBillboardGroup)->Insert(mTextureWidth,mTextureHeight,iBillboard);
+	
+	cluster.SetBspNodeBound(nodeDest->GetBound());
+	//cluster.Finish();
+	getClusterList(iBillboardGroup)->Insert(&cluster);	
+}
+
+void BillboardCloudUVMapper::generateTextureAtlasTextureCoords(bool mergeBillboards, bool groupedBillboards, unsigned int numGroups) 
 {	
+	unsigned int numBillboardGroups;
+	bool enabledTextureCoordSet = false;
+	unsigned int numGeneratedBillboardClouds = 0;
 
 	for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++)
 	{
-		Ogre::LogManager::getSingleton().logMessage("id:" + Ogre::StringConverter::toString(iBillboard));
+		Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);		
+		EntityCluster *entityCluster = billboard->getBillboardClusterData()->getEntityCluster();
+
+		if (entityCluster->getNumEntitiesClusterData() > 0)
+		{
+			if (mergeBillboards)
+			{
+				if (!enabledTextureCoordSet)
+				{
+					SubEntity *subEntity = mBillboardCloud->getEntity()->getSubEntity(0);	
+					subEntity->addTextureCoordSet(2);
+					subEntity->enableVertexColours(true);
+					enabledTextureCoordSet = true;
+				}
+			}
+			else
+			{
+				if (groupedBillboards)
+				{
+					SubEntity *subEntity = mBillboardCloud->getEntity()->getSubEntity(numGeneratedBillboardClouds);	
+					subEntity->addTextureCoordSet(2);
+					subEntity->enableVertexColours(true);
+				}
+			}
+
+			numGeneratedBillboardClouds++;
+		}
+	}
+
+	if (groupedBillboards)
+	{
+		numBillboardGroups = numGroups;
+	}
+	else
+	{
+		if (mergeBillboards)
+		{
+			numBillboardGroups = 1;
+		}
+		else // (!mergeBillboards)
+		{
+			numBillboardGroups = 1;
+		}
+	}
+	
+	unsigned int iBillboardsInGroup = 0;
+	unsigned int numberBillboardsEachGroup = numGeneratedBillboardClouds / numGroups;
+	unsigned int numberBillboardsAddedFirstGroup = numGeneratedBillboardClouds % numGroups;
+	numGeneratedBillboardClouds = 0;
+	unsigned int iBillboardGroup;
+	for (iBillboardGroup = 0; iBillboardGroup < numBillboardGroups; iBillboardGroup++)
+	{
+		
+		IMG::NodeBsp *node = new IMG::NodeBsp;
+		IMG::Bsp *bsp = new IMG::Bsp();
+		IMG::Box2d *box = new IMG::Box2d;
+		IMG::ClusterList *clusterList = new IMG::ClusterList();
+
+		box->SetBoundBox(0, 0, mTextureAtlasWidth, mTextureAtlasHeight);
+		node->SetBound(box);
+		bsp->SetRoot(node);	
+		addBsp(bsp);
+		addClusterList(clusterList);
+
+	}
+
+	iBillboardGroup = 0;
+	for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++)
+	{
+		Ogre::LogManager::getSingleton().logMessage("id:" + Ogre::StringConverter::toString(mBillboardCloud->getBillboard(iBillboard)->getBillboardHandle()));
+
 		BillboardClusterData *billboardClusterData = mBillboardCloud->getBillboard(iBillboard)->getBillboardClusterData();		
 		
@@ -72,144 +385,46 @@
 				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);				
+				if ((iBillboardGroup == 0) && (iBillboardsInGroup < (numberBillboardsEachGroup + numberBillboardsAddedFirstGroup)))
+				{
+					Ogre::LogManager::getSingleton().logMessage("\nA");
+					Ogre::LogManager::getSingleton().logMessage("IG:" + Ogre::StringConverter::toString(iBillboardsInGroup) + " SizeCLList(" + Ogre::StringConverter::toString(iBillboardGroup) + "):" + Ogre::StringConverter::toString(getClusterList(iBillboardGroup)->GetSize()) + " -- numBBC:" + Ogre::StringConverter::toString(numGeneratedBillboardClouds));
+
+					addTextureInBsp(iBillboardGroup, iBillboard);
+
+					addTextureAtlasTextureCoords(mergeBillboards, groupedBillboards, numGeneratedBillboardClouds, iBillboardGroup);
+					iBillboardsInGroup++;
+				}
+				else
+				{
+					if ((iBillboardGroup > 0) && (iBillboardsInGroup < numberBillboardsEachGroup))
+					{
+						Ogre::LogManager::getSingleton().logMessage("\nB");
+						Ogre::LogManager::getSingleton().logMessage("IG:" + Ogre::StringConverter::toString(iBillboardsInGroup) + " SizeCLList(" + Ogre::StringConverter::toString(iBillboardGroup) + "):" + Ogre::StringConverter::toString(getClusterList(iBillboardGroup)->GetSize()) + " -- numBBC:" + Ogre::StringConverter::toString(numGeneratedBillboardClouds));
+
+						addTextureInBsp(iBillboardGroup, iBillboard);
+
+						addTextureAtlasTextureCoords(mergeBillboards, groupedBillboards, numGeneratedBillboardClouds, iBillboardGroup);
+						iBillboardsInGroup++;
+					}
+					else
+					{
+						iBillboardGroup++;
+						iBillboardsInGroup = 0;
+
+						Ogre::LogManager::getSingleton().logMessage("\nC IG:" + Ogre::StringConverter::toString(iBillboardsInGroup-1) + " SizeCLList(" + Ogre::StringConverter::toString(iBillboardGroup-1) + "):" + Ogre::StringConverter::toString(getClusterList(iBillboardGroup-1)->GetSize()));
+						Ogre::LogManager::getSingleton().logMessage("IG:" + Ogre::StringConverter::toString(iBillboardsInGroup) + " SizeCLList(" + Ogre::StringConverter::toString(iBillboardGroup) + "):" + Ogre::StringConverter::toString(getClusterList(iBillboardGroup)->GetSize()) + " -- numBBC:" + Ogre::StringConverter::toString(numGeneratedBillboardClouds));
+
+						addTextureInBsp(iBillboardGroup, iBillboard);
+
+						addTextureAtlasTextureCoords(mergeBillboards, groupedBillboards, numGeneratedBillboardClouds, iBillboardGroup);
+						iBillboardsInGroup++;
+					}
+				}
+
+				numGeneratedBillboardClouds++;
 			}
 		}
-	}
-	
-	//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++;
-		}
-	}
-	
+	}	
+	//mBsp.Print();
 }
 
@@ -224,11 +439,3 @@
 }
 
-BillboardCloudUVMapper::BillboardCloudUVMapper() 
-{
-}
-
-BillboardCloudUVMapper::~BillboardCloudUVMapper() 
-{
-}
-
-}
+}
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 709)
@@ -191,5 +191,7 @@
 }
 
-ClusterList::~ClusterList() {
+ClusterList::~ClusterList() 
+{
+	list.clear();
 }
 
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 709)
@@ -1,5 +1,4 @@
 
 #include "BBCBillboardCloud.h"
-#include "BBCBillboard.h"
 
 namespace BBC {
@@ -18,12 +17,21 @@
 	}
 
+	for (unsigned int iBillboardGroup = 0; iBillboardGroup < getNumBillboardGroups(); iBillboardGroup++)
+	{
+		BillboardGroup *billboardGroup = getBillboardGroup(iBillboardGroup);
+		delete billboardGroup;
+	}
+
 	delete mEntity;
 }
 
-vector<Billboard*>* BillboardCloud::getBillboardList() {
-  return &mBillboardList;
-}
-void BillboardCloud::setBillboardList(vector<Billboard*> &value) {
-  mBillboardList = value;
+std::vector<Billboard*>* BillboardCloud::getBillboardList() 
+{
+	return &mBillboardList;
+}
+
+void BillboardCloud::setBillboardList(std::vector<Billboard*> &value) 
+{
+	mBillboardList = value;
 }
 
@@ -63,4 +71,10 @@
 void BillboardCloud::generateBillboardCloud(bool mergeBillboards)
 {
+	if (mEntity != NULL)
+	{
+		delete mEntity;
+		mEntity = new Entity();
+	}
+
 	unsigned int numGeneratedBillboardClouds = 0;
 	for (unsigned int iBillboard = 0; iBillboard < getNumBillboards(); iBillboard++)
@@ -92,5 +106,8 @@
 				Ogre::Vector3 indices = Ogre::Vector3(0,1,2);
 				subEntity = mEntity->getSubEntity(numGeneratedBillboardClouds);
-				subEntity->addTextureCoordSet(2);				
+				subEntity->addTextureCoordSet(2);
+
+				Ogre::LogManager::getSingleton().logMessage("BBC-SubEntity(" + Ogre::StringConverter::toString(numGeneratedBillboardClouds) + ") - Num.Tex.Coord.Sets:" + Ogre::StringConverter::toString(subEntity->getNumTexCoordSets()));
+
 				subEntity->addFaceVerticesIDs(indices);
 				subEntity->addFaceVerticesIDs(indices + Ogre::Vector3(3,3,3));
@@ -133,3 +150,198 @@
 }
 
-}
+void BillboardCloud::initializeBillboardCloudGroups(unsigned int numberGroups)
+{
+
+	Ogre::LogManager::getSingleton().logMessage("Ini.Num.Billboard Groups:" + Ogre::StringConverter::toString(getNumBillboardGroups()));
+
+	while (getNumBillboardGroups() > 0)
+	{
+		BillboardGroup *billboardGroup = getBillboardGroup(getNumBillboardGroups()-1);
+		removeBillboardGroup(getNumBillboardGroups()-1);
+	}
+
+	Ogre::LogManager::getSingleton().logMessage("Clear.Num.Billboard Groups:" + Ogre::StringConverter::toString(getNumBillboardGroups()));
+
+	unsigned int iBillboardGroup;
+	for (iBillboardGroup = 0; iBillboardGroup < numberGroups; iBillboardGroup++)
+	{
+		BillboardGroup *billboardGroup = new BillboardGroup();
+		addBillboardGroup(billboardGroup);
+	}
+
+	Ogre::LogManager::getSingleton().logMessage("New.Num.Billboard Groups:" + Ogre::StringConverter::toString(getNumBillboardGroups()));
+	std::cin.get();
+	std::cin.get();
+
+	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)
+		{
+			numGeneratedBillboardClouds++;
+		}
+	}
+
+	unsigned int numberBillboardsEachGroup = numGeneratedBillboardClouds / numberGroups;
+	unsigned int numberBillboardsAddedFirstGroup = numGeneratedBillboardClouds % numberGroups;
+
+	Ogre::LogManager::getSingleton().logMessage("Num.Billboards:" + Ogre::StringConverter::toString(numGeneratedBillboardClouds));
+	Ogre::LogManager::getSingleton().logMessage("Num.Billboards Each Group:" + Ogre::StringConverter::toString(numberBillboardsEachGroup));
+	Ogre::LogManager::getSingleton().logMessage("Num.Billboards Added First Group:" + Ogre::StringConverter::toString(numberBillboardsAddedFirstGroup));
+	
+	iBillboardGroup = 0;
+	unsigned int iBillboardsInGroup = 0;
+	for (unsigned int iBillboard = 0; iBillboard < getNumBillboards(); iBillboard++)
+	{
+		Billboard *billboard = this->getBillboard(iBillboard);		
+		EntityCluster *entityCluster = billboard->getBillboardClusterData()->getEntityCluster();
+
+		if (entityCluster->getNumEntitiesClusterData() > 0)
+		{			
+			if ((iBillboardGroup == 0) && (iBillboardsInGroup < (numberBillboardsEachGroup + numberBillboardsAddedFirstGroup)))
+			{
+				getBillboardGroup(iBillboardGroup)->addBillboardHandle(billboard->getBillboardHandle());
+				iBillboardsInGroup++;
+			}
+			else
+			{
+				if ((iBillboardGroup > 0) && (iBillboardsInGroup < numberBillboardsEachGroup))
+				{
+					getBillboardGroup(iBillboardGroup)->addBillboardHandle(billboard->getBillboardHandle());
+					iBillboardsInGroup++;
+				}
+				else
+				{
+					iBillboardGroup++;
+					iBillboardsInGroup = 0;
+
+					getBillboardGroup(iBillboardGroup)->addBillboardHandle(billboard->getBillboardHandle());
+					iBillboardsInGroup++;
+				}
+			}
+		}
+	}
+}
+
+void BillboardCloud::generateBillboardCloudGroups()
+{
+	SubEntity *subEntityGroup;
+	SubEntity *subEntity;
+	Entity *entity = new Entity();
+	unsigned int numGeneratedBillboardClouds = 0;
+
+	for (unsigned int iBillboardGroup = 0; iBillboardGroup < this->getNumBillboardGroups(); iBillboardGroup++)
+	{
+		if (iBillboardGroup > 0)
+		{
+			entity->createSubEntity();
+			Ogre::LogManager::getSingleton().logMessage("BillboardGroup:" + Ogre::StringConverter::toString(iBillboardGroup) + "--" + Ogre::StringConverter::toString(getBillboardGroup(iBillboardGroup)->getNumBillboards()));
+		}
+		
+		subEntityGroup = entity->getSubEntity(iBillboardGroup);
+
+		BillboardGroup *billboardGroup = this->getBillboardGroup(iBillboardGroup);
+
+		Ogre::LogManager::getSingleton().logMessage("BBCG-Num.Billboards:" + Ogre::StringConverter::toString(billboardGroup->getNumBillboards()));
+		std::cin.get();
+		std::cin.get();
+
+		for (unsigned int iBillboard = 0; iBillboard < billboardGroup->getNumBillboards(); iBillboard++)
+		{
+			unsigned int billboardHandle = billboardGroup->getBillboardHandle(iBillboard);
+			Billboard *billboard = this->getBillboard(billboardHandle);
+			EntityCluster *entityCluster = billboard->getBillboardClusterData()->getEntityCluster();
+
+			if (entityCluster->getNumEntitiesClusterData() > 0)
+			{
+				subEntity = mEntity->getSubEntity(numGeneratedBillboardClouds);
+
+				while (subEntityGroup->getNumTexCoordSets() < subEntity->getNumTexCoordSets())
+				{
+					subEntityGroup->addTextureCoordSet(subEntity->getTexCoordDimensions(subEntityGroup->getNumTexCoordSets()));
+				}
+
+				unsigned int offset = subEntityGroup->getNumFaces() * 3;
+				Ogre::Vector3 indicesA = Ogre::Vector3(offset, offset + 1, offset + 2);
+				subEntityGroup->addFaceVerticesIDs(indicesA);
+				offset = subEntityGroup->getNumFaces()*3;
+				Ogre::Vector3 indicesB = Ogre::Vector3(offset, offset + 1, offset + 2);
+				subEntityGroup->addFaceVerticesIDs(indicesB);
+
+				UniqueVertex vFaceA1,vFaceA2,vFaceA3;
+				// Face A of the billboard quad
+				vFaceA1.position = billboard->getBillboardClusterData()->getQuadTopLeftCorner();
+				vFaceA1.normal = billboard->getBillboardClusterData()->getNormal();
+
+				vFaceA2.position = billboard->getBillboardClusterData()->getQuadTopRightCorner();
+				vFaceA2.normal = billboard->getBillboardClusterData()->getNormal();
+				
+				vFaceA3.position = billboard->getBillboardClusterData()->getQuadBottomRightCorner();
+				vFaceA3.normal = billboard->getBillboardClusterData()->getNormal();
+				
+				// Face B of the billboard quad
+				UniqueVertex vFaceB1,vFaceB2,vFaceB3;
+				vFaceB1.position = billboard->getBillboardClusterData()->getQuadBottomRightCorner();
+				vFaceB1.normal = billboard->getBillboardClusterData()->getNormal();
+				
+				vFaceB2.position = billboard->getBillboardClusterData()->getQuadBottomLeftCorner();
+				vFaceB2.normal = billboard->getBillboardClusterData()->getNormal();
+				
+				vFaceB3.position = billboard->getBillboardClusterData()->getQuadTopLeftCorner();
+				vFaceB3.normal = billboard->getBillboardClusterData()->getNormal();
+				
+				Ogre::LogManager::getSingleton().logMessage("BBCG-SubEntity(" + Ogre::StringConverter::toString(numGeneratedBillboardClouds) + ") - Num.Tex.Coord.Sets:"+ Ogre::StringConverter::toString(subEntity->getNumTexCoordSets()));
+
+				for (unsigned int iTexCoordSet = 0; iTexCoordSet < subEntityGroup->getNumTexCoordSets(); iTexCoordSet++)
+				{					
+					vFaceA1.uv[iTexCoordSet] = subEntity->getUniqueVertex(0).uv[iTexCoordSet];
+					vFaceA2.uv[iTexCoordSet] = subEntity->getUniqueVertex(1).uv[iTexCoordSet];
+					vFaceA3.uv[iTexCoordSet] = subEntity->getUniqueVertex(2).uv[iTexCoordSet];
+					vFaceB1.uv[iTexCoordSet] = subEntity->getUniqueVertex(3).uv[iTexCoordSet];
+					vFaceB2.uv[iTexCoordSet] = subEntity->getUniqueVertex(4).uv[iTexCoordSet];
+					vFaceB3.uv[iTexCoordSet] = subEntity->getUniqueVertex(5).uv[iTexCoordSet];
+				}
+
+				subEntityGroup->addUniqueVertex(vFaceA1);
+				subEntityGroup->addUniqueVertex(vFaceA2);
+				subEntityGroup->addUniqueVertex(vFaceA3);
+				subEntityGroup->addUniqueVertex(vFaceB1);
+				subEntityGroup->addUniqueVertex(vFaceB2);
+				subEntityGroup->addUniqueVertex(vFaceB3);
+
+				numGeneratedBillboardClouds++;
+			}
+		}
+	}	
+
+	delete mEntity;
+	mEntity = entity;
+	entity->setSubEntitiesDistinctVertexColours();
+}
+
+unsigned int BillboardCloud::getNumBillboardGroups()
+{
+	return mBillboardGroupList.size();
+}
+
+BillboardGroup* BillboardCloud::getBillboardGroup(unsigned int iBillboardGroup)
+{
+	return mBillboardGroupList[iBillboardGroup];
+}
+
+void BillboardCloud::addBillboardGroup(BillboardGroup *value) 
+{
+	mBillboardGroupList.push_back(value);
+}
+
+void BillboardCloud::removeBillboardGroup(unsigned int value) 
+{
+	BillboardGroup *billboardGroup = mBillboardGroupList[value];
+	mBillboardGroupList.erase(mBillboardGroupList.begin() + value);
+	delete billboardGroup;
+}
+
+}
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 709)
@@ -177,3 +177,13 @@
 }
 
+unsigned int SampleConfigFile::getBillboardCloudGroups()
+{
+	return Ogre::StringConverter::parseInt(getSetting("Billboard Cloud Groups"));
 }
+
+bool SampleConfigFile::getBillboardCloudGroupedBillboards()
+{
+	return Ogre::StringConverter::parseBool(getSetting("Billboard Cloud Grouped Billboards"));
+}
+
+}
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 709)
@@ -91,4 +91,5 @@
 	enableTextureCoords(true);
 }
+
 
 unsigned int SubEntity::getNumTexCoordSets()
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 709)
@@ -188,23 +188,59 @@
 }
 
+void Manager::saveBillboardCloudGrouped()
+{
+	for (unsigned int iSubEntity = 0; iSubEntity < mLeaves->getBillboardCloud()->getEntity()->getNumSubEntities(); iSubEntity++)
+	{
+		BBC::SubEntity *subEntity = mLeaves->getBillboardCloud()->getEntity()->getSubEntity(iSubEntity);
+		subEntity->setMaterialName(mSampleCf.getBillboardCloudMaterialPrefixFilename());
+	}
+	mOgreMeshSerializer->setEntity(mLeaves->getBillboardCloud()->getEntity());
+   
+	Ogre::LogManager::getSingleton().logMessage("Num.SubEntities:" + Ogre::StringConverter::toString(mLeaves->getBillboardCloud()->getEntity()->getNumSubEntities()));
+	mOgreMeshSerializer->exportMesh(mSampleCf.getBillboardCloudFolder() +
+				mSampleCf.getBillboardCloudMeshPrefixFilename() + "Grouped.mesh",false, false);
+	mMeshSerializer->exportMesh(mLeaves->getBillboardCloud()->getEntity()->getMesh(), mSampleCf.getBillboardCloudFolder() + mSampleCf.getBillboardCloudMeshPrefixFilename() + "Grouped.mesh");
+	mXMLMeshSerializer->exportMesh(mLeaves->getBillboardCloud()->getEntity()->getMesh(), mSampleCf.getBillboardCloudFolder() + mSampleCf.getBillboardCloudMeshPrefixFilename() + "Grouped.mesh.xml");
+}
+
+
 void Manager::saveBillboardCloudSplitted()
-{
-	//exportBillboardCloudMesh()	
+{	
+	for (unsigned int iSubEntity = 0; iSubEntity < mLeaves->getBillboardCloud()->getEntity()->getNumSubEntities(); iSubEntity++)
+	{
+		BBC::SubEntity *subEntity = mLeaves->getBillboardCloud()->getEntity()->getSubEntity(iSubEntity);
+		subEntity->setMaterialName(mSampleCf.getBillboardCloudMaterialPrefixFilename());
+	}
+
 	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");
+	mXMLMeshSerializer->exportMesh(mLeaves->getBillboardCloud()->getEntity()->getMesh(), mSampleCf.getBillboardCloudFolder() + mSampleCf.getBillboardCloudMeshPrefixFilename() + "Splitted.mesh.xml");
 }
 
 void Manager::saveBillboardCloudMerged()
 {	
-	mLeaves->getBillboardCloud()->getEntity()->getSubEntity(0)->setMaterialName(mSampleCf.getBillboardCloudMaterialPrefixFilename());
+	//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");
+	//mXMLMeshSerializer->exportMesh(mLeaves->getBillboardCloud()->getEntity()->getMesh(), mSampleCf.getBillboardCloudFolder() + mSampleCf.getBillboardCloudMeshPrefixFilename() + "Merged.mesh.xml");
+	
+
+	for (unsigned int iSubEntity = 0; iSubEntity < mLeaves->getBillboardCloud()->getEntity()->getNumSubEntities(); iSubEntity++)
+	{
+		BBC::SubEntity *subEntity = mLeaves->getBillboardCloud()->getEntity()->getSubEntity(iSubEntity);
+		subEntity->setMaterialName(mSampleCf.getBillboardCloudMaterialPrefixFilename());
+	}
 	mOgreMeshSerializer->setEntity(mLeaves->getBillboardCloud()->getEntity());
+   
+	Ogre::LogManager::getSingleton().logMessage("Num.SubEntities:" + Ogre::StringConverter::toString(mLeaves->getBillboardCloud()->getEntity()->getNumSubEntities()));
 	mOgreMeshSerializer->exportMesh(mSampleCf.getBillboardCloudFolder() +
-				mSampleCf.getBillboardCloudMeshPrefixFilename() + "Merged.mesh", mSampleCf.getBillboardCloudMergedBillboards(), false);
-	mMeshSerializer->exportMesh(mLeaves->getBillboardCloud()->getEntity()->getMesh(), 
-				mSampleCf.getBillboardCloudFolder() + mSampleCf.getBillboardCloudMeshPrefixFilename() 				 
-
-				+ "Merged.mesh");
+				mSampleCf.getBillboardCloudMeshPrefixFilename() + "Merged.mesh",false, false);
+	mMeshSerializer->exportMesh(mLeaves->getBillboardCloud()->getEntity()->getMesh(), mSampleCf.getBillboardCloudFolder() + mSampleCf.getBillboardCloudMeshPrefixFilename() + "Merged.mesh");
+	mXMLMeshSerializer->exportMesh(mLeaves->getBillboardCloud()->getEntity()->getMesh(), mSampleCf.getBillboardCloudFolder() + mSampleCf.getBillboardCloudMeshPrefixFilename() + "Merged.mesh.xml");
 }
 
@@ -338,7 +374,28 @@
 	if (mSampleCf.getBillboardCloudMergedBillboards())
 	{
-		mLeaves->getBillboardCloud()->generateBillboardCloud(mSampleCf.getBillboardCloudMergedBillboards());
+		//mLeaves->getBillboardCloud()->generateBillboardCloud(mSampleCf.getBillboardCloudMergedBillboards());
+		//mLeaves->getBillboardCloud()->initializeBillboardCloudGroups(1);
+
+		//if (mSampleCf.getBillboardCloudDiffuseColorTextureAtlasGeneration())
+		//{
+		//	mBillboardCloudUVMapper->clear();
+		//	mBillboardCloudUVMapper->setBillboardCloud(mLeaves->getBillboardCloud());
+		//	mBillboardCloudUVMapper->setTextureWidth(mSampleCf.getBillboardCloudDiffuseColorTextureSize());
+		//	mBillboardCloudUVMapper->setTextureHeight(mSampleCf.getBillboardCloudDiffuseColorTextureSize());
+		//	mBillboardCloudUVMapper->setTextureAtlasWidth(mSampleCf.getBillboardCloudDiffuseColorTextureAtlasSize());
+		//	mBillboardCloudUVMapper->setTextureAtlasHeight(mSampleCf.getBillboardCloudDiffuseColorTextureAtlasSize());
+		//	mBillboardCloudUVMapper->initialize();
+		//	mBillboardCloudUVMapper->generateTextureAtlasTextureCoords(false, mSampleCf.getBillboardCloudGroupedBillboards(), 1); 
+		//}
+
+		//mLeaves->getBillboardCloud()->generateBillboardCloudGroups();
+		//saveBillboardCloudMerged();
+
+		mLeaves->getBillboardCloud()->generateBillboardCloud(false);
+		mLeaves->getBillboardCloud()->initializeBillboardCloudGroups(1);
+		
 		if (mSampleCf.getBillboardCloudDiffuseColorTextureAtlasGeneration())
 		{
+			mBillboardCloudUVMapper->clear();
 			mBillboardCloudUVMapper->setBillboardCloud(mLeaves->getBillboardCloud());
 			mBillboardCloudUVMapper->setTextureWidth(mSampleCf.getBillboardCloudDiffuseColorTextureSize());
@@ -347,15 +404,20 @@
 			mBillboardCloudUVMapper->setTextureAtlasHeight(mSampleCf.getBillboardCloudDiffuseColorTextureAtlasSize());
 			mBillboardCloudUVMapper->initialize();
-			mBillboardCloudUVMapper->generateTextureAtlasTextureCoords(mSampleCf.getBillboardCloudMergedBillboards()); 
-		}
+			mBillboardCloudUVMapper->generateTextureAtlasTextureCoords(false, mSampleCf.getBillboardCloudGroupedBillboards(), 1); 
+		}
+
+		mLeaves->getBillboardCloud()->generateBillboardCloudGroups();
+
 		saveBillboardCloudMerged();
 	}
 
-
-	if (mSampleCf.getBillboardCloudSplittedBillboards())
-	{		
-		mLeaves->getBillboardCloud()->generateBillboardCloud(!mSampleCf.getBillboardCloudSplittedBillboards());
+	if (mSampleCf.getBillboardCloudGroupedBillboards())
+	{				
+		mLeaves->getBillboardCloud()->generateBillboardCloud(false);
+		mLeaves->getBillboardCloud()->initializeBillboardCloudGroups(mSampleCf.getBillboardCloudGroups());
+		
 		if (mSampleCf.getBillboardCloudDiffuseColorTextureAtlasGeneration())
 		{
+			mBillboardCloudUVMapper->clear();
 			mBillboardCloudUVMapper->setBillboardCloud(mLeaves->getBillboardCloud());
 			mBillboardCloudUVMapper->setTextureWidth(mSampleCf.getBillboardCloudDiffuseColorTextureSize());
@@ -364,5 +426,25 @@
 			mBillboardCloudUVMapper->setTextureAtlasHeight(mSampleCf.getBillboardCloudDiffuseColorTextureAtlasSize());
 			mBillboardCloudUVMapper->initialize();
-			mBillboardCloudUVMapper->generateTextureAtlasTextureCoords(!mSampleCf.getBillboardCloudSplittedBillboards()); 
+			mBillboardCloudUVMapper->generateTextureAtlasTextureCoords(false, mSampleCf.getBillboardCloudGroupedBillboards(), mSampleCf.getBillboardCloudGroups()); 
+		}
+
+		mLeaves->getBillboardCloud()->generateBillboardCloudGroups();
+
+		saveBillboardCloudGrouped();
+	}
+
+	if (mSampleCf.getBillboardCloudSplittedBillboards())
+	{		
+		mLeaves->getBillboardCloud()->generateBillboardCloud(!mSampleCf.getBillboardCloudSplittedBillboards());
+		if (mSampleCf.getBillboardCloudDiffuseColorTextureAtlasGeneration())
+		{
+			mBillboardCloudUVMapper->clear();
+			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(),false); 
 		}
 		saveBillboardCloudSplitted();
@@ -377,16 +459,3 @@
 }
 
-//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");
-*/
-
-}
+}
