#include "BBCBillboardCloudUVMapper.h" #include "BBCBillboardCloud.h" #include "BBCEntityCluster.h" #include "BBCBillboardClusterData.h" namespace BBC { BillboardCloudUVMapper::BillboardCloudUVMapper() { } BillboardCloudUVMapper::~BillboardCloudUVMapper() { shutdown(); } void BillboardCloudUVMapper::initialize() { } void BillboardCloudUVMapper::shutdown() { while (getNumBsp() > 0) { removeBsp(getNumBsp()-1); } while (getNumClusterLists() > 0) { removeClusterList(getNumClusterLists()-1); } } 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) { IMG::ClusterList *clusterList = mClusterLists[iClusterList]; mClusterLists.erase(mClusterLists.begin() + iClusterList); delete clusterList; } 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::addTextureAtlasTextureCoords(bool mergeBillboards, bool groupedBillboards, unsigned int numGeneratedBillboards, unsigned int iBillboardGroup, unsigned int iBillboard, unsigned int iBillboardInGroup) { 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::Vector2 umax; umax[0] = (max[0] / mTextureAtlasWidth); umax[1] = (max[1] / mTextureAtlasHeight); Ogre::Vector2 umin; umin[0] = (min[0] / mTextureAtlasWidth); umin[1] = (min[1] / mTextureAtlasHeight); umin = umin * 2.0 - 1.0; umax = umax * 2.0 - 1.0; mBillboardCloud->getBillboard(iBillboard)->getBillboardClusterData()->addBillboardUVMapMax(umax); mBillboardCloud->getBillboard(iBillboard)->getBillboardClusterData()->addBillboardUVMapMin(umin); //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]) + ")"); //Ogre::LogManager::getSingleton().logMessage( // "UMax:" + Ogre::StringConverter::toString(Ogre::Vector3(umax[0], umax[1],0)) + // "\tUMin:" + Ogre::StringConverter::toString(Ogre::Vector3(umin[0], umin[1],0)) + // "\tUSize(" + Ogre::StringConverter::toString(umax[0]-umin[0]) + // "," + Ogre::StringConverter::toString(umax[1]-umin[1]) + ")"); Ogre::Vector2 texCoords01,texCoords02,texCoords03,texCoords04; // DirectX working version... texCoords03[0] = min[0] / mTextureAtlasWidth; texCoords03[1] = 1.0 - (min[1] / mTextureAtlasHeight); texCoords04[0] = max[0] / mTextureAtlasWidth; texCoords04[1] = 1.0 - (min[1] / mTextureAtlasHeight); texCoords01[0] = max[0] / mTextureAtlasWidth; texCoords01[1] = 1.0 - (max[1] / mTextureAtlasHeight); texCoords02[0] = min[0] / mTextureAtlasWidth; texCoords02[1] = 1.0 - (max[1] / mTextureAtlasHeight); //texCoords02[0] = min[0] / mTextureAtlasWidth; //texCoords02[1] = 1.0 - (min[1] / mTextureAtlasHeight); //texCoords01[0] = max[0] / mTextureAtlasWidth; //texCoords01[1] = 1.0 - (min[1] / mTextureAtlasHeight); //texCoords04[0] = max[0] / mTextureAtlasWidth; //texCoords04[1] = 1.0 - (max[1] / mTextureAtlasHeight); //texCoords03[0] = min[0] / mTextureAtlasWidth; //texCoords03[1] = 1.0 - (max[1] / mTextureAtlasHeight); if (groupedBillboards) { SubEntityPtr subEntity; unsigned int iUniqueVertex = 0; subEntity = mBillboardCloud->getEntity()->getSubEntity(numGeneratedBillboards); subEntity->addTextureCoordSet(2); subEntity->enableVertexColors(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()); } else { if (mergeBillboards) { SubEntityPtr subEntity; unsigned int iUniqueVertex = numGeneratedBillboards * 6; 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()); } } } void BillboardCloudUVMapper::addTextureInBsp(unsigned int iBillboardGroup, unsigned int iBillboard) { IMG::NodeBspPtr nodeDest; IMG::Cluster cluster; nodeDest = getBsp(iBillboardGroup)->insert(mTextureWidth,mTextureHeight,iBillboard); cluster.setBspNodeBound(nodeDest->getBound()); getClusterList(iBillboardGroup)->insert(&cluster); } void BillboardCloudUVMapper::generateTextureAtlasTextureCoords(bool mergeBillboards, bool groupedBillboards, unsigned int numGroups) { unsigned int numBillboardGroups; bool enabledTextureCoordSet = false; unsigned int numGeneratedBillboards = 0; for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++) { BillboardPtr billboard = mBillboardCloud->getBillboard(iBillboard); EntityClusterPtr entityCluster = billboard->getBillboardClusterData()->getEntityCluster(); if (entityCluster->getNumEntitiesClusterData() > 0) { if (mergeBillboards) { if (!enabledTextureCoordSet) { SubEntityPtr subEntity = mBillboardCloud->getEntity()->getSubEntity(0); subEntity->addTextureCoordSet(2); subEntity->enableVertexColors(true); enabledTextureCoordSet = true; } } numGeneratedBillboards++; } } if (groupedBillboards) { numBillboardGroups = numGroups; } else { if (mergeBillboards) { numBillboardGroups = 1; } else // (!mergeBillboards) { numBillboardGroups = 1; } } unsigned int iBillboardsInGroup = 0; unsigned int numberBillboardsEachGroup = numGeneratedBillboards / numGroups; unsigned int numberBillboardsAddedFirstGroup = numGeneratedBillboards % numGroups; numGeneratedBillboards = 0; unsigned int iBillboardGroup; for (iBillboardGroup = 0; iBillboardGroup < numBillboardGroups; iBillboardGroup++) { IMG::Bsp *bsp = new IMG::Bsp(); IMG::ClusterList *clusterList = new IMG::ClusterList(); IMG::NodeBspPtr node = IMG::NodeBspPtr(new IMG::NodeBsp); node->getBound()->setBoundBox(0, 0, mTextureAtlasWidth, mTextureAtlasHeight); 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().get(); if (billboardClusterData != NULL) { BillboardPtr billboard = mBillboardCloud->getBillboard(iBillboard); EntityClusterPtr entityCluster = billboardClusterData->getEntityCluster(); if (entityCluster->getNumEntitiesClusterData() > 0) { if ((iBillboardGroup == 0) && (iBillboardsInGroup < (numberBillboardsEachGroup + numberBillboardsAddedFirstGroup))) { addTextureInBsp(iBillboardGroup, iBillboard); addTextureAtlasTextureCoords(mergeBillboards, groupedBillboards, numGeneratedBillboards, iBillboardGroup, iBillboard, iBillboardsInGroup); iBillboardsInGroup++; } else { if ((iBillboardGroup > 0) && (iBillboardsInGroup < numberBillboardsEachGroup)) { addTextureInBsp(iBillboardGroup, iBillboard); addTextureAtlasTextureCoords(mergeBillboards, groupedBillboards, numGeneratedBillboards, iBillboardGroup, iBillboard, iBillboardsInGroup); iBillboardsInGroup++; } else { iBillboardGroup++; iBillboardsInGroup = 0; addTextureInBsp(iBillboardGroup, iBillboard); addTextureAtlasTextureCoords(mergeBillboards, groupedBillboards, numGeneratedBillboards, iBillboardGroup, iBillboard, iBillboardsInGroup); iBillboardsInGroup++; } } numGeneratedBillboards++; } } } } void BillboardCloudUVMapper::setBillboardCloud(BillboardCloud *billboardCloud) { mBillboardCloud = billboardCloud; } BillboardCloud * BillboardCloudUVMapper::getBillboardCloud() { return mBillboardCloud; } }