source: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/leaves/foliage.cpp @ 1019

Revision 1019, 32.1 KB checked in by gumbau, 18 years ago (diff)

Improved Foliage class

Line 
1#include <stdio.h>
2#include <string.h>
3#include <math.h>
4
5#include "Foliage.h"
6
7
8/******************************************   PANTALLA **************************************************/
9//--------------------------------------------------------------------------------------------------------------------------------
10// Void constructor
11// Parameters --> None
12//--------------------------------------------------------------------------------------------------------------------------------
13Foliage::Foliage(const Geometry::SubMesh *leavesSubMesh, const char *simpSeq, Geometry::CREATEVERTEXDATAFUNC vdfun, Geometry::CREATEINDEXDATAFUNC idfun):
14Acth(NULL),
15create_vertex_data_func(vdfun==NULL?Geometry::DefaultVertexDataCreator:vdfun),
16create_index_data_func(idfun==NULL?Geometry::DefaultIndexDataCreator:idfun),
17vertexdata(NULL), Leaves(NULL), MinDet(NULL)
18{
19        cx = cy= cz= 0;
20        ppio= final = -1;
21
22        ReadVertices(leavesSubMesh);
23        ReadLeafs(leavesSubMesh);
24        if (!ReadSimpSeq(simpSeq)) exit(1);
25        RellenoRaiz();
26        CalculaTexCoordsYNorms();
27
28
29        // esto no sé si devería haber akí
30        indexdata->SetNumValidIndices(0);
31
32        int h=0;
33
34
35        Acth  = new Activas[nHojas*8];
36
37        for ( h=0; h < nHojas; h++) {
38
39                Acth[h].indice = h;
40                if ( h != 0)
41                {
42                        Acth[h].prev = (h-1);
43                        Acth[h-1].next = h;
44                }
45
46        }
47                               
48        ppio = 0;
49        final = nHojas-1;
50        nhactivas = nHojas;
51
52}
53
54/*
55//--------------------------------------------------------------------------------------------------------------------------------
56// Constructor with the name of a file cotaining the data
57//--------------------------------------------------------------------------------------------------------------------------------
58Foliage::Foliage ( Arbol *Arbol1)
59{
60        int h=0;
61
62
63        MiArbol = Arbol1;
64
65        Acth  = new Activas[(MiArbol->nHojas)*8];
66
67        for ( h=0; h < MiArbol->nHojas; h++) {
68
69                Acth[h].indice = h;
70                if ( h != 0)
71                {
72                        Acth[h].prev = (h-1);
73                        Acth[h-1].next = h;
74                }
75
76        }
77                               
78        ppio = 0;
79        final = (MiArbol->nHojas)-1;
80        nhactivas = MiArbol->nHojas;
81
82
83
84}*/
85
86//--------------------------------------------------------------------------------------------------------------------------------
87// Destructor. We must deallocate the memory allocated for pointers to vertices and edges
88//--------------------------------------------------------------------------------------------------------------------------------
89Foliage::~Foliage (void)
90{
91        if (vertexdata) delete vertexdata;
92        if (indexdata) delete indexdata;
93        delete[] Leaves;
94        delete MinDet;
95        delete Acth;
96}
97//
98
99//--------------------------------------------------------------------------------------------------------------------------------
100// Dibuja una hoja
101//--------------------------------------------------------------------------------------------------------------------------------
102                                /*
103void Foliage::Dibuja_Hoja ( Hoja &aHoja)
104{
105       
106        float a,b,c;
107
108        glBegin (GL_TRIANGLE_STRIP);
109                glNormal3fv (aHoja.Normal);
110                MiArbol->Vertices[aHoja.vertsLeaf[0]].GetCoordinates (a,b,c);
111                glTexCoord2f ( 0.0, 0.0);
112
113                glVertex3f (a,b,c);
114
115                MiArbol->Vertices[aHoja.vertsLeaf[1]].GetCoordinates (a,b,c);
116                glTexCoord2f ( 0.0, 1.0);
117                glVertex3f (a,b,c);
118       
119                MiArbol->Vertices[aHoja.vertsLeaf[2]].GetCoordinates (a,b,c);
120                glTexCoord2f ( 1.0, 0.0);
121                glVertex3f (a,b,c);
122
123                MiArbol->Vertices[aHoja.vertsLeaf[3]].GetCoordinates (a,b,c);
124                glTexCoord2f ( 1.0, 1.0);
125                glVertex3f (a,b,c);
126
127        glEnd ();
128
129}
130
131
132//--------------------------------------------------------------------------------------------------------------------------------
133// Dibujar todas las hojas activas
134//--------------------------------------------------------------------------------------------------------------------------------
135                               
136int Foliage::DibujarHojas (float frustum[6][4], float zoom)
137{
138        int hojactiva, i;
139
140
141        glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
142
143        hojactiva = 0;
144        glBindTexture (GL_TEXTURE_2D,texName[0]);
145        glEnable(GL_ALPHA_TEST);
146
147        if ( zoom <75.0)
148        //if ( false)
149        {
150                //calculo el culling de las hojas de minimo detalle
151                Culling (frustum);
152                //printf ( "--------------------------->Entro en culling\n");
153
154                i= ppio;
155                while ( i != -1)
156                {
157                        if (MiArbol->Hojas[MiArbol->Hojas[i].raiz].visible == 1)
158                        {
159                                hojactiva ++;
160                                Dibuja_Hoja (MiArbol->Hojas[i]);
161                        }
162                        i = Acth[i].next;
163                }
164        }
165        else
166        {
167                i= ppio;
168        while ( i != -1)
169                {
170                        hojactiva ++;
171                        Dibuja_Hoja (MiArbol->Hojas[i]);
172                        i=Acth[i].next;
173                }
174
175        }
176
177
178
179        glDisable(GL_ALPHA_TEST);
180
181        return ( hojactiva);
182
183}
184
185//--------------------------------------------------------------------------------------------------------------------------------
186// Dibujar media copa del arbol
187// si el char c es 'f' dibuja la parte delantera
188// si es 'b' la parte trasera
189//--------------------------------------------------------------------------------------------------------------------------------
190                               
191int Foliage::DibujaMediaCopa (  char c, float rva, float rvb,float rvc, float rvd, float radio)
192{
193        int hojactiva, i;
194//      int count, count2;
195
196        glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
197
198        hojactiva = 0;
199        glBindTexture (GL_TEXTURE_2D,texName[0]);
200        glEnable(GL_ALPHA_TEST);
201
202        i= ppio;
203        if ( c == 'b')
204        {//count = 0;
205        while ( i != -1)
206        {  //count ++;
207                        if ( Criterio (MiArbol->Hojas[i],'p', rva,rvb,rvc,rvd, radio) == false) //esta detras del plano
208                {
209                        hojactiva ++;
210                        Dibuja_Hoja (MiArbol->Hojas[i]);
211                        }
212                i = Acth[i].next;
213
214        }
215//      printf ( " EN LA TRASERA chequeo %i hojas \n", count);
216        }
217        else
218        {// count2 = 0;
219
220                while ( i != -1)
221                { //count2++;
222                        if ( Criterio (MiArbol->Hojas[i],'p', rva,rvb,rvc,rvd, radio) == true) //esta detras del plano
223                {
224                        hojactiva ++;
225                        Dibuja_Hoja (MiArbol->Hojas[i]);
226                        }
227                i = Acth[i].next;
228        }
229                //      printf ( " EN LA DELANTERA chequeo %i hojas \n", count2);
230
231        }
232        glDisable(GL_ALPHA_TEST);
233
234//      nhactivas = hojactiva;
235
236
237        return ( hojactiva);
238
239
240
241}
242
243
244
245//-------------------------------------------------------------------------------------------------------------------------
246// dibuja la esfera
247//-------------------------------------------------------------------------------------------------------------------------
248
249void Foliage::DibujaEsfera(float r)
250{
251
252        glPushMatrix();
253                glTranslated (0.0,MiArbol->cy, 0.0);
254                glColor3f(1.0, 0.0, 0.0);
255                glDisable(GL_LIGHTING);
256                glLineWidth(1.2);
257                glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
258                glutSolidSphere ( r,20, 20);
259                glEnable(GL_LIGHTING);
260                glColor3f ( 1.0, 1.0, 1.0);
261        glPopMatrix();
262
263}
264
265/******************************************   CULLING **************************************************/
266//-------------------------------------------------------------------------------------------------------------------------
267// culling de las hojas de menor detalle
268//-------------------------------------------------------------------------------------------------------------------------
269
270void Foliage::Culling (float frustum[6][4])
271{
272        int i, j;
273
274        i = 0;
275        while ( MinDet[i].indice != -1)
276        {
277                j = MinDet[i].indice;
278                if (LeafinFrustum ( j, frustum) == true) {
279                //      printf("dentro %i y el padre es %i\n", j, MiArbol->Hojas[MiArbol->MinDet[i].indice].parent);
280                        Leaves[j].visible = 1;
281                }
282                else 
283                {
284                //      printf("fuera %i\n", j);
285                        Leaves[j].visible = 0;
286                }
287
288                i++;
289        }
290
291}
292
293
294//-------
295// si está en el frustrum --> true
296//      sino --> false
297//------------
298
299
300bool Foliage::LeafinFrustum ( int i, float frustum[6][4])
301{
302        float a,b,c, tmp;
303        int j,p;
304        Vector v;
305
306        for (j =0; j<4; j++)
307        {
308//              MiArbol->Vertices[MiArbol->Hojas[i].vertsLeaf[j]].GetCoordinates (a,b,c);
309                vertexdata->GetVertexCoord(Leaves[i].vertsLeaf[j],a,b,c);
310                v[0]=a; v[1]=b; v[2]=c; v[3]=1;
311
312                //  el punto resultante será
313                v = mat_aux*v;
314
315                for( p = 0; p < 5; p++ )
316                { tmp = float(frustum[p][0] * v[0] + frustum[p][1] * v[1] + frustum[p][2] * v[2] + frustum[p][3]);
317                  if ( tmp <= -2.0 )  return false;
318                }
319        }
320
321
322        return true;
323
324}
325
326
327/******************************************   CRITERIO **************************************************/
328
329
330
331//---------------------------------------------------------------------------------------------------------
332// es activo?
333//---------------------------------------------------------------------------------------------------------
334
335bool Foliage::EsActivo (  int num)
336{
337        return ( (Acth[num].prev != -1) || (Acth[num].next != -1));
338}
339
340
341
342
343//-------
344// si está delante devolverá 1. Si está detrás -1
345//------------
346
347int Foliage::DondeEsta (  float x, float y, float z, float rva, float rvb,float rvc, float rvd)
348{
349        // el plano sería pa x + pb y + pc z + pd = 0
350        float donde;
351        int   esta;
352
353        donde = (rva * x) + (rvb * y) + (rvc * z) + rvd;
354       
355        if ( donde <0) esta = -1;  //delante
356         else if ( donde > 0) esta =1; //detrás
357                        else esta = 0;
358
359                        return esta;
360
361}
362
363
364
365//----------------------------
366// EXPLICACION DE LOS PARAMETROS::
367// ch --> criterio a aplicar:
368//                      si es p --> plano
369//                      si es d --> plano y esfera
370//                      si es e --> esfera
371//DEVUELVE true cuando está en la zona de interes y debe estar a maximo detalle
372//----------------------------
373
374
375bool Foliage::Criterio ( Leaf &aLeaf,  char ch, float rva, float rvb,float rvc, float rvd, float radio)
376{
377        float a,b,c; // coordenadas del primero de los vertices en la hoja
378        float d,e,f; // coords vertice 2
379        float g,h,i; // coords vertice 3
380        float j,k,l; // coords vertice 4
381        float dist;
382        bool inter=false, inter2=false;
383        float ccx, ccy, ccz;
384
385        vertexdata->GetVertexCoord(aLeaf.vertsLeaf[0],a,b,c);
386
387        ccx = cx;
388        ccy = cy;
389        ccz = cz;
390
391        if ( (ch == 'p') || (ch == 'd'))
392        {
393        //plano siempre
394        if (DondeEsta (a,b,c, rva,rvb,rvc,rvd) == 1)
395        {
396//              MiArbol->Vertices[aHoja.vertsLeaf[1]].GetCoordinates (d,e,f);
397                vertexdata->GetVertexCoord(aLeaf.vertsLeaf[1],d,e,f);
398                if (DondeEsta (d,e,f, rva,rvb,rvc,rvd) == 1)
399                {
400//                      MiArbol->Vertices[aHoja.vertsLeaf[2]].GetCoordinates (g,h,i);
401                        vertexdata->GetVertexCoord(aLeaf.vertsLeaf[2],g,h,i);
402                        if (DondeEsta (g,h,i, rva,rvb,rvc,rvd) == 1)
403                        {
404//                              Vertices[aHoja.vertsLeaf[3]].GetCoordinates (j,k,l);
405                                vertexdata->GetVertexCoord(aLeaf.vertsLeaf[3],j,k,l);
406                                if (DondeEsta (j,k,l, rva,rvb,rvc,rvd) == 1) inter = true;
407                        }
408                }
409
410        }
411       
412
413        }
414       
415               
416        if (( ch == 'e') || (( ch == 'd') && (inter == true))) //CRITERIO DE LA ESFERA
417        {
418       
419        dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz));
420        if (dist >  radio)
421
422        {
423//              MiArbol->Vertices[aHoja.vertsLeaf[1]].GetCoordinates (a,b,c);
424                vertexdata->GetVertexCoord(aLeaf.vertsLeaf[1],a,b,c);
425                dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz));
426
427                if (dist >  radio)
428                {
429//                      MiArbol->Vertices[aHoja.vertsLeaf[2]].GetCoordinates (a,b,c);
430                        vertexdata->GetVertexCoord(aLeaf.vertsLeaf[2],a,b,c);
431                        dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz));
432
433                        if (dist >  radio)
434                        {
435//                              MiArbol->Vertices[aHoja.vertsLeaf[3]].GetCoordinates (a,b,c);
436                                vertexdata->GetVertexCoord(aLeaf.vertsLeaf[3],a,b,c);
437                                dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz));
438
439                                if (dist >  radio) inter2 = true;
440                        }
441                }
442        }
443                inter =  inter2;
444        }
445
446
447        return inter;
448}
449
450
451
452
453
454/******************************************   RESOLUCIÓN VARIABLE **************************************************/
455
456//-----------------------------------------
457//
458//      RECORDAR!!!
459//              NO cumple el criterio ------------>  POCO  DETALLE ( COLAPSAR )
460//              SI cumple el criterio ------------>  MUCHO DETALLE ( SPLITEAR )
461//
462// el ch se le pasa a Criterio y es allí donde se evalua
463//          e --> esfera
464//      p --> plano
465//      d --> los dos criterios
466//------------------------------------------
467
468int Foliage::ResolucionV (char ch, float rva, float rvb,float rvc, float rvd, float radio)
469{
470        bool lista=false;
471    int i, hpost, spli;
472        float renvol, centroz;
473       
474        i = ppio;
475        spli = -1;
476
477        renvol = rad;
478        centroz = cz;
479//      printf (" el centro en %f y el radio es de %f\n", centroz, renvol);
480
481// fijo el máximo del plano de RV
482
483        if (rvd < centroz -renvol )
484                  rvd = (centroz -renvol );
485        else if (rvd > centroz +renvol )
486                  rvd = (centroz +renvol );
487
488//      printf (" el plano está en %f\n", rvd);
489
490
491        //para que fije el valor máximo del radio
492
493        if  (( ch == 'e') || ( ch == 'd'))
494        {       if (radio> renvol)      radio = renvol;
495                else if (radio <0)  radio =0.0;
496        }
497
498//      printf (" el radio vale %f\n", radio);
499       
500        //empieza a buscar las hojas activas
501
502        while ( i != -1){
503               
504                hpost = Acth[i].next;
505
506                //COLAPSAR
507
508                if (( Criterio ( Leaves[i], ch, rva,rvb,rvc,rvd, radio )== false) && (Leaves[i].parent != -1))
509                {
510                        // SI ESTA FUESE LA HOJA IZQUIERDA Y LA DERECHA NO CUMPLE TAMPOCO EL CRITERIO
511                        if ((Leaves[Leaves[i].parent].childLeft == i) &&
512                                ( Criterio (Leaves[Leaves[Leaves[i].parent].childRight] , ch, rva,rvb,rvc,rvd, radio )== false))
513                        {       //hay que colapsar
514                                if (EsActivo(Leaves[Leaves[i].parent].childRight) == false)
515                                        lista = Forzar_Colapse (Leaves[Leaves[i].parent].childRight, hpost, ch, rva,rvb,rvc,rvd, radio); // para activarla
516                                else lista = true;
517                                                                       
518                        }
519                        else
520                        // SI ESTA FUESE LA HOJA DERECHA Y LA IZQUIERDA NO CUMPLE TAMPOCO EL CRITERIO
521                        if ((Leaves[Leaves[i].parent].childRight == i) &&
522                                ( Criterio (Leaves[Leaves[Leaves[i].parent].childLeft] , ch, rva,rvb,rvc,rvd, radio )== false))
523                        {//hay que colapsar
524                                if (EsActivo(Leaves[Leaves[i].parent].childLeft) == false)
525                                         lista = Forzar_Colapse (Leaves[Leaves[i].parent].childLeft, hpost,  ch, rva,rvb,rvc,rvd, radio); // para activarla
526                                else  lista = true;
527                                       
528                        }
529                       
530                         //estan activas preparadas para subir un nivel en la zona de no detalle.
531                       
532                        if ( lista == true)
533                        {
534                                lista = false;
535                               
536                                        ColapsaHoja ( Leaves[i].parent, hpost);
537                        }
538                                       
539                }
540        i = hpost;
541
542        }
543       
544        //ahora veo lo de splitear
545        i = ppio;
546        spli = -1;
547
548        while ( i != -1){
549                hpost = Acth[i].next;
550                spli = Chequea_Split (i, ch, rva,rvb,rvc,rvd, radio);
551                        if ( spli != -1)
552                                {       Forzar_Split ( spli, i, hpost);
553                                        spli = -1;
554                                }
555                        i = hpost;
556        }
557
558        return (1);
559               
560}
561
562//--------------------------------------------------------------------------------------------------------------------------------
563// Colapsa dos hojas
564//--------------------------------------------------------------------------------------------------------------------------------
565                               
566void Foliage::ColapsaHoja (  int h,   int& post)
567{
568
569        //actualizo los punteros del ppio y del final, y post
570        while (( ppio == Leaves[h].childLeft) || ( ppio == Leaves[h].childRight))
571                ppio = Acth[ppio].next;
572        while (( final == Leaves[h].childLeft) || ( final == Leaves[h].childRight))
573                 final = Acth[final].prev;
574
575        while (( post == Leaves[h].childLeft) || ( post == Leaves[h].childRight))
576                 post = Acth[post].next;
577
578
579
580        //COLAPSAR = QUITO DOS DE ACTIVOS PONGO UNO A ACTIVO
581
582        if (Acth[Leaves[h].childLeft].next != -1)
583                Acth[Acth[Leaves[h].childLeft].next].prev = Acth[Leaves[h].childLeft].prev;
584        if (Acth[Leaves[h].childLeft].prev != -1)
585                Acth[Acth[Leaves[h].childLeft].prev].next = Acth[Leaves[h].childLeft].next;
586
587        if (Acth[Leaves[h].childRight].next != -1)
588                Acth[Acth[Leaves[h].childRight].next].prev = Acth[Leaves[h].childRight].prev;
589        if (Acth[Leaves[h].childRight].prev != -1)
590                Acth[Acth[Leaves[h].childRight].prev].next = Acth[Leaves[h].childRight].next;
591
592       
593        //  desconecto a los hijos
594        Acth[Leaves[h].childLeft].prev = -1;
595        Acth[Leaves[h].childLeft].next = -1;
596        Acth[Leaves[h].childRight].prev = -1;
597        Acth[Leaves[h].childRight].next = -1;
598
599        //añado al final
600        Acth[h].prev = final;
601        Acth[h].next = -1;
602        Acth[final].next = h;
603        final = h;
604
605       
606}
607
608
609
610
611//--------------------------------------------------------------------------------------------------
612// Forzar colapse
613// la hoja que paso en el parametro hoja es la que quiero que se active al final
614//--------------------------------------------------------------------------------------------------
615
616
617bool Foliage::Forzar_Colapse(int hoja,  int &hpost,  char ch, float rva, float rvb,float rvc, float rvd, float radio)
618{
619       
620        int h;
621        lista <int> listah;
622        bool fin;
623
624        fin = false;
625        listah.Inserta (hoja); // Inserta un dato en la lista
626
627        while  (listah.NDatos () != 0)
628        {
629               
630                h = listah.GetCola ();//coger la cola
631                if (Leaves[h].childLeft != -1)
632
633                { if (!EsActivo (Leaves[h].childLeft ))
634                        listah.Inserta (Leaves[h].childLeft);
635                       
636                  if ( (!EsActivo (Leaves[h].childRight)) )     
637                        listah.Inserta (Leaves[h].childRight);
638               
639                  if (EsActivo (Leaves[h].childLeft) && EsActivo (Leaves[h].childRight ))
640                          if((Criterio ( Leaves[Leaves[h].childLeft] ,ch, rva,rvb,rvc,rvd, radio )== false) &&
641                                  (Criterio ( Leaves[Leaves[h].childRight], ch, rva,rvb,rvc,rvd, radio ) == false))
642                        {
643                        ColapsaHoja ( h, hpost);
644                                listah.Borra(h);
645                        }
646                          else fin = true;
647                }
648                else
649                {  fin = true;
650                   listah.Borra(h);
651                }
652
653                if ( fin == true )
654                        while ( listah.NDatos () != 0)
655                                listah.BorraCola();
656       
657        }
658
659        return (EsActivo (hoja));
660               
661}
662
663
664//--------------------------------------------------------------------------------------------------------------------------------
665// Splitea una hoja
666//--------------------------------------------------------------------------------------------------------------------------------
667                               
668void Foliage::SplitHoja (int h, int &post)
669{
670
671        // SPLITEAR: QUITO UNO, PONGO DOS
672       
673        if ( ppio == h) ppio = Acth[h].next;
674        if ( final == h) final = Acth[h].prev;
675
676        // 1 enlazo los hijos
677        Acth[Leaves[h].childLeft].next = Leaves[h].childRight;
678        Acth[Leaves[h].childRight].prev = Leaves[h].childLeft;
679        Acth[Leaves[h].childRight].next = -1;
680
681        //y desconecto al padre
682        if ( Acth[h].prev != -1)
683                Acth[Acth[h].prev].next = Acth[h].next;
684        if ( Acth[h].next != -1)
685                Acth[Acth[h].next].prev = Acth[h].prev;
686        Acth[h].prev = -1;
687        Acth[h].next = -1;
688       
689        //añado al final los hijos
690        Acth[Leaves[h].childLeft].prev = final;
691        Acth[final].next = Leaves[h].childLeft;
692        final = Leaves[h].childRight;
693
694}
695
696
697
698
699//-------------------------------------------------------------------------------------------
700// chequear si tengo que splitear. Devuelve el primero de los nodos que cumple la condicion
701//-------------------------------------------------------------------------------------------
702
703int Foliage::Chequea_Split(int h,  char ch, float rva, float rvb,float rvc, float rvd, float radio)
704{
705       
706        int  nodo;
707       
708
709        nodo = -1;
710
711        if (Leaves[h].childLeft != -1)
712
713        {  // si el hijo derecho o el izquierdo están en la zona de máximo detalle, haré que estos se activen   
714                  if ( (Criterio (Leaves[Leaves[h].childLeft],  ch, rva,rvb,rvc,rvd, radio ) == true) ||
715                          (Criterio (Leaves[Leaves[h].childRight], ch, rva,rvb,rvc,rvd, radio ) == true))
716                       
717                                nodo = Leaves[h].childLeft;
718                       
719                        else // si no, bajo un nivel más hasta encontrar algún descendiente que se encuentre en la zona de + detalle
720                        {
721                                nodo = Chequea_Split (Leaves[h].childLeft,  ch, rva,rvb,rvc,rvd, radio);
722                                if ( nodo == -1 ) nodo = Chequea_Split (Leaves[h].childRight, ch, rva,rvb,rvc,rvd, radio);
723                        }
724                                 
725                }
726               
727        return (nodo);
728               
729}
730
731//-------------------------------------------------------------------------------------------
732// fuerzo a splitear
733// hoja -> es el nodo que cumple la condicion
734// padre -> es el nodo que chequeaba de la lista de activos
735// hpost -> es el nodo siguiente en la lista de activos
736//-------------------------------------------------------------------------------------------
737
738bool Foliage::Forzar_Split(int hoja, int padre, int &hpost)
739{
740       
741        int h;
742        lista <int> listah;
743        bool bien;
744
745        bien = false;
746        h = Leaves[hoja].parent;
747        listah.Inserta (h); // Inserta un dato en la lista
748
749        while ( h != padre)
750        {
751                h = Leaves[h].parent;
752                listah.Inserta (h); // Inserta un dato en la lista
753        }
754
755
756        while  (listah.NDatos () != 0)
757        {
758                h = listah.GetCola ();//coger el padre más alto
759                SplitHoja(h, hpost);
760                listah.Borra(h);
761       
762        }
763
764        if ( listah.NDatos() == 0)
765                bien = true;
766        return (bien);
767               
768}               
769
770
771
772
773/******************************************   RESOLUCIÓN CONSTANTE **************************************************/
774
775
776int Foliage::ResolucionC (float dist, float dmax, float dmin)
777{
778
779        float difdist,  d;
780        int difhojas, nhojas;
781
782        if (( dist > dmin) && (dist <dmax))
783        {
784                difdist = dmax - dmin;
785                difhojas = nHojas - minHojas;
786
787                d = dist - dmin;
788
789                //regla de 3
790
791                nhojas = int(abs(d*difhojas /difdist));
792
793                AjusteHojas ((nHojas)-nhojas);
794
795        }
796        else if (dist > dmax) {
797                AjusteHojas (minHojas);
798        }
799        else if (dist < dmin) {
800                AjusteHojas (nHojas);
801        }
802               
803        return (nhactivas);
804}
805
806
807
808void Foliage::AjusteHojas( int nhojas)
809{
810        if ((nhojas <= nHojas) && (nhojas >= minHojas))
811        {
812                if ( nhojas < nhactivas) {
813                        RCecol ( nhactivas - nhojas);
814                }
815                else  {
816                         RCsplit (nhojas-nhactivas );
817                }
818
819                nhactivas = nhojas;
820        //      printf ( "ajusto a %i\n", nhactivas );
821
822        }
823
824}
825
826//-----------------------------------------
827//
828//      RECORDAR!!!
829//              NO cumple el criterio ------------>  POCO  DETALLE ( COLAPSAR )
830//              SI cumple el criterio ------------>  MUCHO DETALLE ( SPLITEAR )
831//
832// el ch se le pasa a Criterio y es allí donde se evalua
833//------------------------------------------
834
835/*
836void Foliage::RCecol (  int nhojas)
837{
838        int i, hpost;
839
840        i = ppio;
841       
842        while (( i != -1) && (nhojas>0)){
843                hpost = Acth[i].next;
844
845                        if ( MiArbol->Hojas[i].parent != -1)
846                                if ( MiArbol->Hojas[MiArbol->Hojas[i].parent].childLeft == i)
847                                {if ( EsActivo (MiArbol->Hojas[MiArbol->Hojas[i].parent].childRight ) )
848                                {
849                                        ColapsaHoja ( MiArbol->Hojas[i].parent, hpost);
850                                        nhojas --; }
851                                }
852                                else
853                                {if ( EsActivo (MiArbol->Hojas[MiArbol->Hojas[i].parent].childLeft ) )
854                                {
855                                        ColapsaHoja ( MiArbol->Hojas[i].parent, hpost);
856                                        nhojas --; }
857                                }
858
859
860                i = hpost;
861               
862        }
863}
864*/
865
866void Foliage::RCecol ( int num)
867{
868
869        int  j, h;
870
871        j = num;
872        h = final+1;
873                while ((h<=TotHojas) && (j>0))
874                {
875                        while (( ppio == Leaves[h].childLeft) || ( ppio == Leaves[h].childRight))
876                                ppio = Acth[ppio].next;
877
878                        while (( final == Leaves[h].childLeft) || ( final == Leaves[h].childRight))
879                                final = Acth[final].prev;
880
881
882                        //COLAPSAR = QUITO DOS DE ACTIVOS PONGO UNO A ACTIVO
883
884                        if (Acth[Leaves[h].childLeft].next != -1)
885                                Acth[Acth[Leaves[h].childLeft].next].prev = Acth[Leaves[h].childLeft].prev;
886                        if (Acth[Leaves[h].childLeft].prev != -1)
887                                Acth[Acth[Leaves[h].childLeft].prev].next = Acth[Leaves[h].childLeft].next;
888
889                        if (Acth[Leaves[h].childRight].next != -1)
890                                Acth[Acth[Leaves[h].childRight].next].prev = Acth[Leaves[h].childRight].prev;
891                        if (Acth[Leaves[h].childRight].prev != -1)
892                                Acth[Acth[Leaves[h].childRight].prev].next = Acth[Leaves[h].childRight].next;
893
894       
895                        //  desconecto a los hijos
896                        Acth[Leaves[h].childLeft].prev = -1;
897                        Acth[Leaves[h].childLeft].next = -1;
898                        Acth[Leaves[h].childRight].prev = -1;
899                        Acth[Leaves[h].childRight].next = -1;
900
901                        //añado al final
902                        Acth[h].prev = final;
903                        Acth[h].next = -1;
904                        Acth[final].next = h;
905                        final = h;
906
907
908                        // decremento el contador de colapsos
909                        j--;
910                        //incremento el posible siguiente colapso
911                        h++;
912
913
914                }
915
916}
917
918/*
919void Foliage::RCsplit (  int nhojas)
920{
921        int i, hpost;
922
923        i = ppio;
924       
925        while (( i != -1) && (nhojas>0)){
926                hpost = Acth[i].next;
927
928                if (MiArbol->Leaves[i].childLeft != -1){
929                                        SplitHoja(i, hpost);
930                                        nhojas --;
931
932                }
933               
934                i = hpost;
935
936        }
937}
938*/
939
940int Foliage::AnteriorActivo (int h)
941{
942        int i;
943
944       
945        if (ppio > h)  i = -1;
946        else
947        {
948                i = h--;
949       
950                while (EsActivo (i) == false)   
951                        i--;
952        }
953
954        return (i);
955}
956
957int Foliage::PosteriorActivo (int h)
958{       int i;
959
960        i = h++;
961       
962        while ((EsActivo (i) == false) || (i> TotHojas))
963                i++;
964
965        if (i > TotHojas) i=-1;
966
967
968        return (i);
969}
970
971void Foliage::RCsplit ( int num)
972{
973
974        int  j, h, ant, post;
975
976        j = num;
977        h = final;
978        while ((h > nHojas) &&  (j>0))
979        {
980
981                ///////////// insertar a los hijos en orden segun su indice
982                //hijo izquierdo
983                ant = AnteriorActivo (Leaves[h].childLeft);
984                post = PosteriorActivo (Leaves[h].childLeft);
985
986
987                Acth[Leaves[h].childLeft].next = post;
988                Acth[Leaves[h].childLeft].prev = ant;
989                if (ant != -1) Acth[ant].next = Leaves[h].childLeft;
990                        else ppio = Leaves[h].childLeft;
991                if (post != -1) Acth[post].prev = Leaves[h].childLeft;
992
993               
994                //hijo derecho
995                ant = AnteriorActivo (Leaves[h].childRight);
996                post = PosteriorActivo (Leaves[h].childRight);
997
998
999                Acth[Leaves[h].childRight].next = post;
1000                Acth[Leaves[h].childRight].prev = ant;
1001                if (ant != -1)  Acth[ant].next = Leaves[h].childRight;
1002                                else ppio = Leaves[h].childRight;
1003                if (post != -1) Acth[post].prev = Leaves[h].childRight;
1004
1005
1006                // despues de insertar los hijos miro a ver cual spliteare el siguiente
1007                final = Acth[h].prev;
1008               
1009                //y desconecto al padre
1010                if ( Acth[h].prev != -1)
1011                        Acth[Acth[h].prev].next = Acth[h].next;
1012                //if ( Acth[h].next != -1)
1013                //      Acth[Acth[h].next].prev = Acth[h].prev;
1014                Acth[h].prev = -1;
1015                Acth[h].next = -1;
1016       
1017                // decremento el contador de colapsos
1018                j--;
1019                //incremento el posible siguiente colapso
1020                h--;
1021
1022
1023        }
1024
1025
1026 }
1027
1028void Foliage::ReadVertices(const Geometry::SubMesh *submesh)
1029{
1030        int countv= int(submesh->mVertexBuffer->mVertexCount);
1031        vertexdata = create_vertex_data_func(2*countv);
1032        Leaves = new Leaf[countv*2];
1033        indexdata = create_index_data_func(countv*2*3); // 3 indices x 2 triangulos x hoja
1034       
1035        vertexdata->Begin();
1036        for (int i=0; i<countv; i++)
1037        {
1038                vertexdata->SetVertexCoord( i,  submesh->mVertexBuffer->mPosition[i].x,
1039                                                                                submesh->mVertexBuffer->mPosition[i].y,
1040                                                                                submesh->mVertexBuffer->mPosition[i].z );
1041        }
1042        vertexdata->End();
1043
1044        TotVerts = countv;
1045}
1046
1047
1048void Foliage::GetNormalH (Leaf &aleaf)
1049{
1050
1051        float onex, oney, onez;
1052        float twox, twoy, twoz;
1053        float threex, threey, threez;
1054
1055/*      Vertices[aHoja.vertsLeaf[0]].GetCoordinates (onex, oney, onez);
1056        Vertices[aHoja.vertsLeaf[1]].GetCoordinates(twox, twoy, twoz);
1057        Vertices[aHoja.vertsLeaf[2]].GetCoordinates (threex, threey, threez);*/
1058
1059        vertexdata->GetVertexCoord(aleaf.vertsLeaf[0],onex,oney,onez);
1060        vertexdata->GetVertexCoord(aleaf.vertsLeaf[1],twox,twoy,twoz);
1061        vertexdata->GetVertexCoord(aleaf.vertsLeaf[2],threex,threey,threez);
1062
1063        float v1[3]={twox-onex,twoy-oney,twoz-onez};
1064        float v2[3]={threex-onex,threey-oney,threez-onez};
1065
1066        Normalize(v1,v1);
1067        Normalize(v2,v2);
1068       
1069//      aleaf.Normal[0] = (twoz-onez)*(threey-oney) - (twoy-oney)*(threez-onez);
1070//      aleaf.Normal[1] = (twox-onex)*(threez-onez) - (threex-onex)*(twoz-onez);
1071//      aleaf.Normal[2] = (threex-onex)*(twoy-oney) - (twox-onex)*(threey-oney);
1072
1073        CrossProduct(v1,v2,aleaf.normal);
1074       
1075}
1076
1077void Foliage::CrossProduct(const float *v1, const float *v2, float *res)
1078{
1079        res[0] = v1[1]*v2[2] - v1[2]*v2[1];
1080        res[1] = v1[2]*v2[0] - v1[0]*v2[2];
1081        res[2] = v1[0]*v2[1] - v1[1]*v2[0];
1082}
1083
1084void Foliage::Normalize(const float *v, float *res)
1085{
1086        float module=sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
1087        res[0]=v[0]/module;
1088        res[1]=v[1]/module;
1089        res[2]=v[2]/module;
1090}
1091
1092void Foliage::ReadLeafs(const Geometry::SubMesh *submesh)
1093{
1094        int numtris = int(submesh->mIndexCount / 3);
1095        nHojas =  numtris / 2;
1096        for (int h=0; h<nHojas; h++)
1097        {
1098                Leaves[h].vertsLeaf[0] = submesh->mIndex[h*6+0];
1099                Leaves[h].vertsLeaf[1] = submesh->mIndex[h*6+1];
1100                Leaves[h].vertsLeaf[2] = submesh->mIndex[h*6+2];
1101                Leaves[h].vertsLeaf[3] = submesh->mIndex[h*6+5];
1102                Leaves[h].visible = 0;
1103
1104                GetNormalH ( Leaves[h]);
1105        }
1106}
1107
1108/// returns the number of total leafs
1109bool Foliage::ReadSimpSeq(const char *simpSeqFile)
1110{
1111        FILE* fp_simpli;
1112        char linea[256];
1113        int v0, v1, v2, v3, tn, tv1,tv2, e=0;
1114
1115        if ((fp_simpli = fopen (simpSeqFile, "r")) == NULL)
1116        {
1117                printf ("No he podido abrir el fichero %s\n", simpSeqFile);
1118                return false;
1119        }
1120        else
1121        {
1122                tn = nHojas;
1123                while (fgets (linea, 255, fp_simpli) != NULL)
1124                {
1125                        if (linea[0]<'0' || linea[0]>'9')
1126                                continue;
1127               
1128                        //N 446 Ver 10176 10178 10169 10171  Tv 156 154 E 2
1129
1130//                      sscanf(linea, "%s %lu %s %lu %lu  %lu %lu %s %lu %lu %s %i",
1131//                              &str, &tn, &str, &v0, &v1, &v2, &v3, &str, &tv1, &tv2, &str, &e );
1132                        long int triviej00=-1, triviej01=-1;
1133                        long int triviej10=-1, triviej11=-1;
1134                        sscanf(linea, "%lu %lu %lu %lu & %lu %lu %lu %lu", &triviej00,&triviej01,&triviej10,&triviej11, &v0,&v1,&v2,&v3);
1135
1136                        Leaves[tn].vertsLeaf[0] = v0;
1137                        Leaves[tn].vertsLeaf[1] = v1;
1138                        Leaves[tn].vertsLeaf[2] = v2;
1139                        Leaves[tn].vertsLeaf[3] = v3;
1140
1141                        Leaves[tn].visible = 0;
1142
1143                        GetNormalH  (Leaves[tn]);
1144
1145                        tv1 = triviej00/2;
1146                        tv2 = triviej10/2;
1147
1148                        Leaves[tn].childLeft= tv1;
1149                        Leaves[tn].childRight= tv2;
1150
1151                        Leaves[tv1].parent = tn;
1152                        Leaves[tv2].parent = tn;               
1153
1154                        tn++;
1155                }
1156
1157        }
1158
1159        fclose(fp_simpli);
1160
1161        TotHojas=tn;
1162               
1163        return true;
1164}
1165
1166void Foliage::RellenoRaiz (void)
1167{
1168        int i,j, k, t, cont;
1169        bool esta, fin;
1170
1171        i=0;
1172        k=-1;
1173        cont =-1;
1174
1175        MinDet  = new Activas[nHojas*2];
1176       
1177        while (i<TotHojas)
1178        {
1179                j=i;
1180                while (Leaves[j].parent > -1) j= Leaves[j].parent;
1181                Leaves[i].root = j;
1182
1183
1184                // para la estructura MinDet
1185                if ( k == -1){
1186                        k++;
1187                        MinDet[k].indice = j;
1188                        cont =k;
1189                }
1190                else
1191                {
1192                        t = 0;
1193                        esta = false;
1194                        fin = false;
1195
1196                        while (( fin == false) && (esta == false))
1197                        {       if ( MinDet[t].indice == j) esta = true;
1198                                        else t++;
1199                                if (MinDet[t].indice == -1) fin = true;
1200                        }
1201
1202                        if ( esta == false) //añado al final
1203                        {
1204                                cont++;
1205                                MinDet[cont].indice = j;
1206                        }
1207                }
1208
1209        i++;
1210        }       
1211
1212        minHojas = cont;
1213
1214}
1215
1216void Foliage::CalculaTexCoordsYNorms(void)
1217{       
1218        vertexdata->Begin();
1219        for (int i=0; i<nHojas; i++)
1220        {       
1221                const float* lanormal = Leaves[i].normal;
1222                vertexdata->SetVertexNormal(Leaves[i].vertsLeaf[0], lanormal[0], lanormal[1], lanormal[2]);
1223                vertexdata->SetVertexTexCoord(Leaves[i].vertsLeaf[0], 0.0f, 1.0f);
1224
1225                vertexdata->SetVertexNormal(Leaves[i].vertsLeaf[1], lanormal[0], lanormal[1], lanormal[2]);
1226                vertexdata->SetVertexTexCoord(Leaves[i].vertsLeaf[1], 0.0f, 0.0f);
1227
1228                vertexdata->SetVertexNormal(Leaves[i].vertsLeaf[2], lanormal[0], lanormal[1], lanormal[2]);
1229                vertexdata->SetVertexTexCoord(Leaves[i].vertsLeaf[2], 1.0f, 1.0f);
1230
1231                vertexdata->SetVertexNormal(Leaves[i].vertsLeaf[3], lanormal[0], lanormal[1], lanormal[2]);
1232                vertexdata->SetVertexTexCoord(Leaves[i].vertsLeaf[3], 1.0f, 0.0f);
1233
1234
1235/*              MiArbol->Vertices[aHoja.vertsLeaf[1]].GetCoordinates (a,b,c);
1236                glTexCoord2f ( 0.0, 1.0);
1237                glVertex3f (a,b,c);
1238       
1239                MiArbol->Vertices[aHoja.vertsLeaf[2]].GetCoordinates (a,b,c);
1240                glTexCoord2f ( 1.0, 0.0);
1241                glVertex3f (a,b,c);
1242
1243                MiArbol->Vertices[aHoja.vertsLeaf[3]].GetCoordinates (a,b,c);
1244                glTexCoord2f ( 1.0, 1.0);
1245                glVertex3f (a,b,c);*/
1246        }
1247        vertexdata->End();
1248}
1249
1250Foliage::Foliage(const Foliage *ar)
1251{
1252        nHojas=ar->nHojas;
1253        MinDet  = new Activas[nHojas*2];
1254//      for (unsigned int i=0; i<nHojas*2; i++)
1255//              MinDet[i]=ar->MinDet[i];
1256        memcpy(MinDet,ar->MinDet,sizeof(Activas)*nHojas*2);
1257        TotHojas=ar->TotHojas;
1258        cx=ar->cx;
1259        cy=ar->cy;
1260        cz=ar->cz;
1261        rad=ar->rad;
1262        minHojas=ar->minHojas;
1263        TotVerts=ar->TotVerts;
1264
1265        create_vertex_data_func=ar->create_vertex_data_func;
1266        create_index_data_func=ar->create_index_data_func;
1267        vertexdata=create_vertex_data_func(ar->vertexdata->GetNumVertices());
1268        vertexdata->Begin();
1269        for (unsigned int i=0; i<vertexdata->GetNumVertices(); i++)
1270        {
1271                float va,vb,vc;
1272                ar->vertexdata->GetVertexCoord(i,va,vb,vc);
1273                vertexdata->SetVertexCoord(i,va,vb,vc);
1274                ar->vertexdata->GetVertexNormal(i,va,vb,vc);
1275                vertexdata->SetVertexNormal(i,va,vb,vc);
1276        }
1277        vertexdata->End();
1278        indexdata=create_index_data_func(ar->indexdata->GetNumMaxIndices());
1279        indexdata->Begin();
1280        for (unsigned int i=0; i<indexdata->GetNumMaxIndices(); i++)
1281                indexdata->SetIndex(i,ar->indexdata->GetIndex(i));
1282        indexdata->End();
1283
1284        Leaves=new Leaf[vertexdata->GetNumVertices()];
1285//      for (unsigned int i=0; i<vertexdata->GetNumVertices(); i++)
1286//              Leaves[i]=ar->Leaves[i];
1287        memcpy(Leaves,ar->Leaves,sizeof(Leaf)*vertexdata->GetNumVertices());
1288
1289        // esto no sé si devería haber akí
1290        indexdata->SetNumValidIndices(0);
1291
1292        int h=0;
1293
1294        Acth  = new Activas[nHojas*8];
1295
1296        for ( h=0; h < nHojas; h++) {
1297
1298                Acth[h].indice = h;
1299                if ( h != 0)
1300                {
1301                        Acth[h].prev = (h-1);
1302                        Acth[h-1].next = h;
1303                }
1304
1305        }
1306                               
1307        ppio = 0;
1308        final = nHojas-1;
1309        nhactivas = nHojas;
1310
1311}
Note: See TracBrowser for help on using the repository browser.