Changeset 721 for GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKMeansClusterGenerator.cpp
- Timestamp:
- 03/31/06 17:29:32 (18 years ago)
- 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> 3 2 4 3 namespace LBBC { 5 4 5 void KMeansClusterGenerator::setAlpha(float value) 6 { 7 mAlpha = value; 8 } 9 10 float KMeansClusterGenerator::getAlpha() 11 { 12 return mAlpha; 13 } 14 15 void KMeansClusterGenerator::setNumIterations(unsigned int value) 16 { 17 mNumIterations = value; 18 } 19 20 unsigned int KMeansClusterGenerator::getNumIterations() 21 { 22 return mNumIterations; 23 } 24 25 unsigned 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 52 void 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 62 void 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 74 void 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 171 void 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 180 void KMeansClusterGenerator::iterativeRecomputeBillboardCloud() 181 { 182 for (unsigned int iIteration = 0; iIteration < mNumIterations; iIteration++) 183 { 184 recomputeBillboardCloud(); 185 } 186 } 187 6 188 void KMeansClusterGenerator::generate() 7 189 { 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 202 BBC::BillboardPtr KMeansClusterGenerator::createBillboard() 203 { 204 BBC::BillboardPtr billboard = BBC::BillboardPtr( new BBC::Billboard() ); 205 mBillboardCloud->addBillboard(billboard); 206 return billboard; 207 } 208 209 void 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 217 void 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 232 void 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 251 void 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 } 9 259 } 10 260 11 261 void KMeansClusterGenerator::init() 12 262 { 13 14 } 15 16 KMeansClusterGenerator::KMeansClusterGenerator() { 17 } 18 19 KMeansClusterGenerator::~KMeansClusterGenerator() { 20 } 21 22 23 } 263 } 264 265 KMeansClusterGenerator::KMeansClusterGenerator() 266 { 267 } 268 269 KMeansClusterGenerator::~KMeansClusterGenerator() 270 { 271 272 } 273 274 275 }
Note: See TracChangeset
for help on using the changeset viewer.