Ignore:
Timestamp:
03/31/06 17:29:32 (18 years ago)
Author:
igarcia
Message:
 
File:
1 edited

Legend:

Unmodified
Added
Removed
  • GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKMeansClusterGenerator.cpp

    r699 r721  
    1  
    2 #include "LBBCKMeansClusterGenerator.h" 
     1#include <LBBCKMeansClusterGenerator.h> 
    32 
    43namespace LBBC { 
    54 
     5void KMeansClusterGenerator::setAlpha(float value) 
     6{ 
     7        mAlpha = value; 
     8} 
     9 
     10float KMeansClusterGenerator::getAlpha() 
     11{ 
     12        return mAlpha; 
     13} 
     14 
     15void KMeansClusterGenerator::setNumIterations(unsigned int value) 
     16{ 
     17        mNumIterations = value; 
     18} 
     19 
     20unsigned int KMeansClusterGenerator::getNumIterations() 
     21{ 
     22        return mNumIterations; 
     23} 
     24 
     25unsigned int KMeansClusterGenerator::findBestBillboard(Leaf *leaf) 
     26{ 
     27        float minError = FLT_MAX; 
     28        unsigned int iMinErrorBillboard = 0; 
     29         
     30        Ogre::Vector3 normalLeaf = leaf->getLeafNormal(); 
     31        Ogre::Vector3 positionLeaf = leaf->getPosition();                
     32         
     33        for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++) 
     34        { 
     35                BBC::BillboardPtr billboard = mBillboardCloud->getBillboard(iBillboard); 
     36                BillboardKMeansClusterData *billboardClusterData = (BillboardKMeansClusterData*)billboard->getBillboardClusterData().get(); 
     37                Ogre::Vector3 normalBillboard = billboardClusterData->getNormal();                       
     38 
     39                float d = (normalBillboard.dotProduct(positionLeaf) +  billboardClusterData->getD()); 
     40                float cosine = normalBillboard.dotProduct(normalLeaf); 
     41                float error = (d*d) + ( 1 - cosine * cosine ) * mAlpha; 
     42 
     43                if (error < minError) 
     44                { 
     45                        minError = error; 
     46                        iMinErrorBillboard = billboard->getBillboardHandle(); 
     47                }                                
     48        } 
     49        return iMinErrorBillboard; 
     50} 
     51 
     52void KMeansClusterGenerator::assignLeafBillboard(Leaf *leaf, BBC::BillboardPtr billboard) 
     53{ 
     54        BillboardKMeansClusterData *billboardClusterData = (BillboardKMeansClusterData*)billboard->getBillboardClusterData().get();                      
     55        BBC::EntityClusterPtr entityCluster = billboardClusterData->getEntityCluster(); 
     56 
     57        BBC::EntityClusterDataPtr entityClusterData = BBC::EntityClusterDataPtr( (BBC::EntityClusterData*) new LeafKMeansClusterData() ); 
     58        entityClusterData->setEntity(leaf); 
     59        entityCluster->addEntityClusterData(entityClusterData); 
     60} 
     61 
     62void KMeansClusterGenerator::splitLeafDistribution() 
     63{ 
     64        for (unsigned int iLeaf = 0; iLeaf < mEntityDistribution->getNumEntities(); iLeaf++) 
     65        { 
     66                Leaf *leaf = (Leaf*)mEntityDistribution->getEntity(iLeaf).get(); 
     67                unsigned int iMinErrorBillboard = findBestBillboard(leaf); 
     68 
     69                BBC::BillboardPtr billboardMinError = mBillboardCloud->getBillboard(iMinErrorBillboard); 
     70                assignLeafBillboard(leaf,billboardMinError); 
     71        } 
     72} 
     73 
     74void KMeansClusterGenerator::recomputeBillboard(BBC::BillboardPtr billboard) 
     75{ 
     76        Ogre::Matrix3 nmii = Ogre::Matrix3::ZERO; 
     77        Ogre::Matrix3 nmiiSum = Ogre::Matrix3::ZERO; 
     78        Ogre::Matrix3 miiSum = Ogre::Matrix3::ZERO; 
     79        Ogre::Matrix3 mii = Ogre::Matrix3::ZERO;         
     80        Ogre::Matrix3 mijSum = Ogre::Matrix3::ZERO; 
     81        Ogre::Matrix3 mij = Ogre::Matrix3::ZERO;  
     82        Ogre::Vector3 lastY = Ogre::Vector3::ZERO; 
     83        Ogre::Vector3 piSum = Ogre::Vector3::ZERO; 
     84        Ogre::Vector3 normSum = Ogre::Vector3::ZERO; 
     85 
     86        BillboardKMeansClusterData *billboardClusterData = (BillboardKMeansClusterData*)billboard->getBillboardClusterData().get();                      
     87        BBC::EntityClusterPtr entityCluster = billboardClusterData->getEntityCluster(); 
     88 
     89        for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++) 
     90        { 
     91                Leaf* leaf = (Leaf*)entityCluster->getEntityClusterData(iLeaf)->getEntity().get(); 
     92                Ogre::Vector3 pi = leaf->getPosition();  
     93                Ogre::Vector3 norm2 = leaf->getLeafNormal();     
     94                piSum = piSum + pi * (1.0 / (float)entityCluster->getNumEntitiesClusterData()); 
     95                         
     96                mii[0][0] = pi.x * pi.x; 
     97                mii[0][1] = pi.x * pi.y; 
     98                mii[0][2] = pi.x * pi.z; 
     99                mii[1][0] = pi.y * pi.x; 
     100                mii[1][1] = pi.y * pi.y; 
     101                mii[1][2] = pi.y * pi.z; 
     102                mii[2][0] = pi.z * pi.x; 
     103                mii[2][1] = pi.z * pi.y; 
     104                mii[2][2] = pi.z * pi.z;         
     105                nmii[0][0] = norm2.x * norm2.x; 
     106                nmii[0][1] = norm2.x * norm2.y; 
     107                nmii[0][2] = norm2.x * norm2.z; 
     108                nmii[1][0] = norm2.y * norm2.x; 
     109                nmii[1][1] = norm2.y * norm2.y; 
     110                nmii[1][2] = norm2.y * norm2.z; 
     111                nmii[2][0] = norm2.z * norm2.x; 
     112                nmii[2][1] = norm2.z * norm2.y; 
     113                nmii[2][2] = norm2.z * norm2.z;  
     114                 
     115                nmiiSum = nmiiSum + ( nmii * (1.0 / (float)entityCluster->getNumEntitiesClusterData())); 
     116 
     117                miiSum = miiSum + ( mii * (1.0 / (float)entityCluster->getNumEntitiesClusterData())); 
     118 
     119                // Generate the initial value for the iterative method as the average... 
     120                Ogre::Vector3 norm = leaf->getLeafNormal(); 
     121                lastY = lastY + norm; 
     122 
     123                // Generate the sum normal of all the leaves associated to the plane... 
     124                normSum = normSum + norm; 
     125        } 
     126         
     127        mijSum[0][0] = piSum.x * piSum.x; 
     128        mijSum[0][1] = piSum.x * piSum.y; 
     129        mijSum[0][2] = piSum.x * piSum.z; 
     130        mijSum[1][0] = piSum.y * piSum.x; 
     131        mijSum[1][1] = piSum.y * piSum.y; 
     132        mijSum[1][2] = piSum.y * piSum.z; 
     133        mijSum[2][0] = piSum.z * piSum.x; 
     134        mijSum[2][1] = piSum.z * piSum.y; 
     135        mijSum[2][2] = piSum.z * piSum.z;        
     136 
     137        Ogre::Matrix3 mA = miiSum - mijSum; 
     138        mA = mA - (mAlpha * nmiiSum); 
     139        mA = mA.Inverse(); 
     140 
     141        lastY.normalise(); 
     142        normSum.normalise(); 
     143 
     144        // Apply the iterative approach 
     145        Ogre::Vector3 currY; 
     146        currY = mA * lastY; 
     147        currY.normalise(); 
     148 
     149        for(unsigned int icount = 0; icount < 100; icount++) 
     150        { 
     151                lastY = currY; 
     152                currY = mA * lastY; 
     153                currY.normalise(); 
     154        } 
     155 
     156        // Generate the d parameter... 
     157        float sumD = 0; 
     158        for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++) 
     159        { 
     160                Leaf* leaf = (Leaf*)entityCluster->getEntityClusterData(iLeaf)->getEntity().get(); 
     161                Ogre::Vector3 pi = leaf->getPosition();  
     162                sumD = sumD + pi.dotProduct(currY); 
     163        } 
     164 
     165        sumD = - sumD / (float)entityCluster->getNumEntitiesClusterData(); 
     166 
     167        billboardClusterData->setNormal(currY); 
     168        billboardClusterData->setD(sumD); 
     169} 
     170 
     171void KMeansClusterGenerator::recomputeBillboardCloud() 
     172{ 
     173        for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++) 
     174        { 
     175                BBC::BillboardPtr billboard = mBillboardCloud->getBillboard(iBillboard); 
     176                recomputeBillboard(billboard); 
     177        } 
     178} 
     179 
     180void KMeansClusterGenerator::iterativeRecomputeBillboardCloud() 
     181{ 
     182        for (unsigned int iIteration = 0; iIteration < mNumIterations; iIteration++) 
     183        { 
     184                recomputeBillboardCloud(); 
     185        } 
     186} 
     187 
    6188void KMeansClusterGenerator::generate()  
    7189{ 
    8  
     190        // Generate the initial random billboards and cluster the leaves with them 
     191        // 1. Create the billboards and assign an initial random orientation 
     192        initializeBillboardCloud(); 
     193        // 2. Split the leaf distribution, each leaf in the it's best candidate billboard 
     194        splitLeafDistribution(); 
     195        // 3. The billboard is recomputed in order to minimize the total error  
     196        // for the leaves of this cluster with respect to this plane. 
     197        iterativeRecomputeBillboardCloud(); 
     198        // 4. Generate each entity cluster packed entity and compute the bounding quad for each entity cluster 
     199        generateBillboardCloudBounds(); 
     200} 
     201 
     202BBC::BillboardPtr KMeansClusterGenerator::createBillboard() 
     203{ 
     204        BBC::BillboardPtr billboard = BBC::BillboardPtr( new BBC::Billboard() ); 
     205        mBillboardCloud->addBillboard(billboard); 
     206        return billboard; 
     207} 
     208 
     209void KMeansClusterGenerator::initializeBillboardClusterData(BBC::BillboardPtr billboard) 
     210{ 
     211        BBC::BillboardClusterDataPtr billboardClusterData = BBC::BillboardClusterDataPtr( new BillboardKMeansClusterData() ); 
     212        billboard->setBillboardClusterData(billboardClusterData); 
     213        BBC::EntityClusterPtr entityCluster = BBC::EntityClusterPtr( new BBC::EntityCluster() ); 
     214        billboard->getBillboardClusterData()->setEntityCluster(entityCluster); 
     215} 
     216 
     217void KMeansClusterGenerator::generateBillboardCloudBounds() 
     218{ 
     219        for (unsigned int iBillboard = 0; iBillboard < this->getMaxNumBillboards(); iBillboard++) 
     220        { 
     221                BBC::BillboardPtr billboard = mBillboardCloud->getBillboard(iBillboard);                 
     222                BBC::EntityClusterPtr entityCluster = billboard->getBillboardClusterData()->getEntityCluster(); 
     223 
     224                if (entityCluster->getNumEntitiesClusterData() > 0) 
     225                {                                        
     226                        entityCluster->generateEntityCluster(); 
     227                        billboard->getBillboardClusterData()->generateBillboardBoundingQuad(); 
     228                } 
     229        } 
     230} 
     231 
     232void KMeansClusterGenerator::initializeRandomBillboard(BBC::BillboardPtr billboard) 
     233{ 
     234        float dMin = ((LeafDistribution*)mEntityDistribution)->getMinD(); 
     235        float dMax = ((LeafDistribution*)mEntityDistribution)->getMaxD(); 
     236 
     237        float d = Ogre::Math::RangeRandom(dMin,dMax); 
     238 
     239        //Ogre::Vector3 normalMin = ((LeafDistribution*)mEntityDistribution)->getMinNormal(); 
     240        //Ogre::Vector3 normalMax = ((LeafDistribution*)mEntityDistribution)->getMaxNormal(); 
     241        Ogre::Vector3 normal; 
     242        normal.x = Ogre::Math::RangeRandom(-1,1); // Ogre::Math::RangeRandom(normalMin.x,normalMax.x); 
     243        normal.y = Ogre::Math::RangeRandom(-1,1); // Ogre::Math::RangeRandom(normalMin.y,normalMax.y); 
     244        normal.z = Ogre::Math::RangeRandom(-1,1); // Ogre::Math::RangeRandom(normalMin.z,normalMax.z); 
     245         
     246        BillboardKMeansClusterData *mBillboardClusterData = (BillboardKMeansClusterData *)billboard->getBillboardClusterData().get(); 
     247        mBillboardClusterData->setNormal(normal); 
     248        mBillboardClusterData->setD(d); 
     249} 
     250 
     251void KMeansClusterGenerator::initializeBillboardCloud() 
     252{ 
     253        for (unsigned int iBillboard = 0; iBillboard < this->getMaxNumBillboards(); iBillboard++) 
     254        { 
     255                BBC::BillboardPtr billboard = createBillboard(); 
     256                initializeBillboardClusterData(billboard); 
     257                initializeRandomBillboard(billboard); 
     258        } 
    9259} 
    10260 
    11261void KMeansClusterGenerator::init()  
    12262{ 
    13  
    14 } 
    15  
    16 KMeansClusterGenerator::KMeansClusterGenerator() { 
    17 } 
    18  
    19 KMeansClusterGenerator::~KMeansClusterGenerator() { 
    20 } 
    21  
    22  
    23 } 
     263} 
     264 
     265KMeansClusterGenerator::KMeansClusterGenerator()  
     266{ 
     267} 
     268 
     269KMeansClusterGenerator::~KMeansClusterGenerator()  
     270{ 
     271 
     272} 
     273 
     274 
     275} 
Note: See TracChangeset for help on using the changeset viewer.