source: GTP/trunk/Lib/Illum/IBRBillboardCloudTrees/OGRE/src/LBBCKdTreeClusterGenerator.cpp @ 699

Revision 699, 9.5 KB checked in by igarcia, 19 years ago (diff)
Line 
1#include <LBBCKdTreeClusterGenerator.h>
2
3namespace LBBC {
4
5void KdTreeClusterGenerator::setAlpha(float value)
6{
7        mAlpha = value;
8}
9
10float KdTreeClusterGenerator::getAlpha()
11{
12        return mAlpha;
13}
14
15void KdTreeClusterGenerator::setNumIterations(unsigned int value)
16{
17        mNumIterations = value;
18}
19
20unsigned int KdTreeClusterGenerator::getNumIterations()
21{
22        return mNumIterations;
23}
24
25unsigned int KdTreeClusterGenerator::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::Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);
36                BillboardKdTreeClusterData *billboardClusterData = (BillboardKdTreeClusterData*)billboard->getBillboardClusterData();
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 KdTreeClusterGenerator::assignLeafBillboard(Leaf *leaf, BBC::Billboard *billboard)
53{
54        BillboardKdTreeClusterData *billboardClusterData = (BillboardKdTreeClusterData*)billboard->getBillboardClusterData();                   
55        BBC::EntityCluster *entityCluster = billboardClusterData->getEntityCluster();
56
57        BBC::EntityClusterData *entityClusterData = new LeafKdTreeClusterData();
58        entityClusterData->setEntity(leaf);
59        entityCluster->addEntityClusterData(entityClusterData);
60}
61
62void KdTreeClusterGenerator::splitLeafDistribution()
63{
64        for (unsigned int iLeaf = 0; iLeaf < mEntityDistribution->getNumEntities(); iLeaf++)
65        {
66                Leaf *leaf = (Leaf*)mEntityDistribution->getEntity(iLeaf);
67                unsigned int iMinErrorBillboard = findBestBillboard(leaf);
68
69                BBC::Billboard *billboardMinError = mBillboardCloud->getBillboard(iMinErrorBillboard);
70                assignLeafBillboard(leaf,billboardMinError);
71        }
72}
73
74void KdTreeClusterGenerator::recomputeBillboard(BBC::Billboard *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        BillboardKdTreeClusterData *billboardClusterData = (BillboardKdTreeClusterData*)billboard->getBillboardClusterData();                   
87        BBC::EntityCluster *entityCluster = billboardClusterData->getEntityCluster();
88
89        for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++)
90        {
91                Leaf* leaf = (Leaf*)entityCluster->getEntityClusterData(iLeaf)->getEntity();
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();
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 KdTreeClusterGenerator::recomputeBillboardCloud()
172{
173        for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++)
174        {
175                BBC::Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);
176                recomputeBillboard(billboard);
177        }
178}
179
180void KdTreeClusterGenerator::iterativeRecomputeBillboardCloud()
181{
182        for (unsigned int iIteration = 0; iIteration < mNumIterations; iIteration++)
183        {
184                recomputeBillboardCloud();
185        }
186}
187
188void KdTreeClusterGenerator::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::Billboard* KdTreeClusterGenerator::createBillboard()
203{
204        BBC::Billboard *billboard = new BBC::Billboard();
205        mBillboardCloud->addBillboard(billboard);
206        return billboard;
207}
208
209void KdTreeClusterGenerator::initializeBillboardClusterData(BBC::Billboard *billboard)
210{
211        BBC::BillboardClusterData *billboardClusterData = new BillboardKdTreeClusterData();
212        billboard->setBillboardClusterData(billboardClusterData);
213        BBC::EntityCluster *entityCluster = new BBC::EntityCluster();
214        billboard->getBillboardClusterData()->setEntityCluster(entityCluster);
215}
216
217void KdTreeClusterGenerator::generateBillboardCloudBounds()
218{
219        for (unsigned int iBillboard = 0; iBillboard < this->getMaxNumBillboards(); iBillboard++)
220        {
221                BBC::Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);         
222                BBC::EntityCluster *entityCluster = billboard->getBillboardClusterData()->getEntityCluster();
223
224                if (entityCluster->getNumEntitiesClusterData() > 0)
225                {                                       
226                        entityCluster->generateEntityCluster();
227                        billboard->getBillboardClusterData()->generateBillboardBoundingQuad();
228                }
229        }
230}
231
232void KdTreeClusterGenerator::initializeRandomBillboard(BBC::Billboard *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        BillboardKdTreeClusterData *mBillboardClusterData = (BillboardKdTreeClusterData *)billboard->getBillboardClusterData();
247        mBillboardClusterData->setNormal(normal);
248        mBillboardClusterData->setD(d);
249}
250
251void KdTreeClusterGenerator::initializeBillboardCloud()
252{
253        for (unsigned int iBillboard = 0; iBillboard < this->getMaxNumBillboards(); iBillboard++)
254        {
255                BBC::Billboard *billboard = createBillboard();
256                initializeBillboardClusterData(billboard);
257                initializeRandomBillboard(billboard);
258        }
259}
260
261void KdTreeClusterGenerator::init()
262{
263}
264
265KdTreeClusterGenerator::KdTreeClusterGenerator()
266{
267}
268
269KdTreeClusterGenerator::~KdTreeClusterGenerator()
270{
271        for (unsigned int iBillboard = 0; iBillboard < mBillboardCloud->getNumBillboards(); iBillboard++)
272        {
273                BBC::Billboard *billboard = mBillboardCloud->getBillboard(iBillboard);
274                BillboardKdTreeClusterData *billboardKdTreeClusterData = (BillboardKdTreeClusterData*)billboard->getBillboardClusterData();
275                BBC::EntityCluster *entityCluster = billboardKdTreeClusterData->getEntityCluster();
276
277                for (unsigned int iEntityClusterData = 0; iEntityClusterData < entityCluster->getNumEntitiesClusterData(); iEntityClusterData++)
278                {
279                        LeafKdTreeClusterData *entityClusterData = (LeafKdTreeClusterData*) entityCluster->getEntityClusterData(iEntityClusterData);
280                        delete entityClusterData;
281                }
282
283                delete entityCluster;
284                delete billboardKdTreeClusterData;
285        }
286}
287
288
289}
Note: See TracBrowser for help on using the repository browser.