source: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKMeansClusterGenerator.cpp @ 721

Revision 721, 9.0 KB checked in by igarcia, 19 years ago (diff)
Line 
1#include <LBBCKMeansClusterGenerator.h>
2
3namespace LBBC {
4
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
188void KMeansClusterGenerator::generate()
189{
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        }
259}
260
261void KMeansClusterGenerator::init()
262{
263}
264
265KMeansClusterGenerator::KMeansClusterGenerator()
266{
267}
268
269KMeansClusterGenerator::~KMeansClusterGenerator()
270{
271
272}
273
274
275}
Note: See TracBrowser for help on using the repository browser.