#include #include #include #include "Foliage.h" /****************************************** PANTALLA **************************************************/ //-------------------------------------------------------------------------------------------------------------------------------- // Void constructor // Parameters --> None //-------------------------------------------------------------------------------------------------------------------------------- Foliage::Foliage(const Geometry::SubMesh *leavesSubMesh, const char *simpSeq, Geometry::CREATEVERTEXDATAFUNC vdfun, Geometry::CREATEINDEXDATAFUNC idfun): Acth(NULL), create_vertex_data_func(vdfun==NULL?Geometry::DefaultVertexDataCreator:vdfun), create_index_data_func(idfun==NULL?Geometry::DefaultIndexDataCreator:idfun), vertexdata(NULL), Leaves(NULL), MinDet(NULL) { cx = cy= cz= 0; ppio= final = -1; ReadVertices(leavesSubMesh); ReadLeafs(leavesSubMesh); if (!ReadSimpSeq(simpSeq)) exit(1); RellenoRaiz(); CalculaTexCoordsYNorms(); // esto no sé si devería haber akí indexdata->SetNumValidIndices(0); int h=0; Acth = new Activas[nHojas*8]; for ( h=0; h < nHojas; h++) { Acth[h].indice = h; if ( h != 0) { Acth[h].prev = (h-1); Acth[h-1].next = h; } } ppio = 0; final = nHojas-1; nhactivas = nHojas; } /* //-------------------------------------------------------------------------------------------------------------------------------- // Constructor with the name of a file cotaining the data //-------------------------------------------------------------------------------------------------------------------------------- Foliage::Foliage ( Arbol *Arbol1) { int h=0; MiArbol = Arbol1; Acth = new Activas[(MiArbol->nHojas)*8]; for ( h=0; h < MiArbol->nHojas; h++) { Acth[h].indice = h; if ( h != 0) { Acth[h].prev = (h-1); Acth[h-1].next = h; } } ppio = 0; final = (MiArbol->nHojas)-1; nhactivas = MiArbol->nHojas; }*/ //-------------------------------------------------------------------------------------------------------------------------------- // Destructor. We must deallocate the memory allocated for pointers to vertices and edges //-------------------------------------------------------------------------------------------------------------------------------- Foliage::~Foliage (void) { if (vertexdata) delete vertexdata; if (indexdata) delete indexdata; delete[] Leaves; delete MinDet; delete Acth; } // //-------------------------------------------------------------------------------------------------------------------------------- // Dibuja una hoja //-------------------------------------------------------------------------------------------------------------------------------- /* void Foliage::Dibuja_Hoja ( Hoja &aHoja) { float a,b,c; glBegin (GL_TRIANGLE_STRIP); glNormal3fv (aHoja.Normal); MiArbol->Vertices[aHoja.vertsLeaf[0]].GetCoordinates (a,b,c); glTexCoord2f ( 0.0, 0.0); glVertex3f (a,b,c); MiArbol->Vertices[aHoja.vertsLeaf[1]].GetCoordinates (a,b,c); glTexCoord2f ( 0.0, 1.0); glVertex3f (a,b,c); MiArbol->Vertices[aHoja.vertsLeaf[2]].GetCoordinates (a,b,c); glTexCoord2f ( 1.0, 0.0); glVertex3f (a,b,c); MiArbol->Vertices[aHoja.vertsLeaf[3]].GetCoordinates (a,b,c); glTexCoord2f ( 1.0, 1.0); glVertex3f (a,b,c); glEnd (); } //-------------------------------------------------------------------------------------------------------------------------------- // Dibujar todas las hojas activas //-------------------------------------------------------------------------------------------------------------------------------- int Foliage::DibujarHojas (float frustum[6][4], float zoom) { int hojactiva, i; glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); hojactiva = 0; glBindTexture (GL_TEXTURE_2D,texName[0]); glEnable(GL_ALPHA_TEST); if ( zoom <75.0) //if ( false) { //calculo el culling de las hojas de minimo detalle Culling (frustum); //printf ( "--------------------------->Entro en culling\n"); i= ppio; while ( i != -1) { if (MiArbol->Hojas[MiArbol->Hojas[i].raiz].visible == 1) { hojactiva ++; Dibuja_Hoja (MiArbol->Hojas[i]); } i = Acth[i].next; } } else { i= ppio; while ( i != -1) { hojactiva ++; Dibuja_Hoja (MiArbol->Hojas[i]); i=Acth[i].next; } } glDisable(GL_ALPHA_TEST); return ( hojactiva); } //-------------------------------------------------------------------------------------------------------------------------------- // Dibujar media copa del arbol // si el char c es 'f' dibuja la parte delantera // si es 'b' la parte trasera //-------------------------------------------------------------------------------------------------------------------------------- int Foliage::DibujaMediaCopa ( char c, float rva, float rvb,float rvc, float rvd, float radio) { int hojactiva, i; // int count, count2; glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); hojactiva = 0; glBindTexture (GL_TEXTURE_2D,texName[0]); glEnable(GL_ALPHA_TEST); i= ppio; if ( c == 'b') {//count = 0; while ( i != -1) { //count ++; if ( Criterio (MiArbol->Hojas[i],'p', rva,rvb,rvc,rvd, radio) == false) //esta detras del plano { hojactiva ++; Dibuja_Hoja (MiArbol->Hojas[i]); } i = Acth[i].next; } // printf ( " EN LA TRASERA chequeo %i hojas \n", count); } else {// count2 = 0; while ( i != -1) { //count2++; if ( Criterio (MiArbol->Hojas[i],'p', rva,rvb,rvc,rvd, radio) == true) //esta detras del plano { hojactiva ++; Dibuja_Hoja (MiArbol->Hojas[i]); } i = Acth[i].next; } // printf ( " EN LA DELANTERA chequeo %i hojas \n", count2); } glDisable(GL_ALPHA_TEST); // nhactivas = hojactiva; return ( hojactiva); } //------------------------------------------------------------------------------------------------------------------------- // dibuja la esfera //------------------------------------------------------------------------------------------------------------------------- void Foliage::DibujaEsfera(float r) { glPushMatrix(); glTranslated (0.0,MiArbol->cy, 0.0); glColor3f(1.0, 0.0, 0.0); glDisable(GL_LIGHTING); glLineWidth(1.2); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glutSolidSphere ( r,20, 20); glEnable(GL_LIGHTING); glColor3f ( 1.0, 1.0, 1.0); glPopMatrix(); } /****************************************** CULLING **************************************************/ //------------------------------------------------------------------------------------------------------------------------- // culling de las hojas de menor detalle //------------------------------------------------------------------------------------------------------------------------- void Foliage::Culling (float frustum[6][4]) { int i, j; i = 0; while ( MinDet[i].indice != -1) { j = MinDet[i].indice; if (LeafinFrustum ( j, frustum) == true) { // printf("dentro %i y el padre es %i\n", j, MiArbol->Hojas[MiArbol->MinDet[i].indice].parent); Leaves[j].visible = 1; } else { // printf("fuera %i\n", j); Leaves[j].visible = 0; } i++; } } //------- // si está en el frustrum --> true // sino --> false //------------ bool Foliage::LeafinFrustum ( int i, float frustum[6][4]) { float a,b,c, tmp; int j,p; Vector v; for (j =0; j<4; j++) { // MiArbol->Vertices[MiArbol->Hojas[i].vertsLeaf[j]].GetCoordinates (a,b,c); vertexdata->GetVertexCoord(Leaves[i].vertsLeaf[j],a,b,c); v[0]=a; v[1]=b; v[2]=c; v[3]=1; // el punto resultante será v = mat_aux*v; for( p = 0; p < 5; p++ ) { tmp = float(frustum[p][0] * v[0] + frustum[p][1] * v[1] + frustum[p][2] * v[2] + frustum[p][3]); if ( tmp <= -2.0 ) return false; } } return true; } /****************************************** CRITERIO **************************************************/ //--------------------------------------------------------------------------------------------------------- // es activo? //--------------------------------------------------------------------------------------------------------- bool Foliage::EsActivo ( int num) { return ( (Acth[num].prev != -1) || (Acth[num].next != -1)); } //------- // si está delante devolverá 1. Si está detrás -1 //------------ int Foliage::DondeEsta ( float x, float y, float z, float rva, float rvb,float rvc, float rvd) { // el plano sería pa x + pb y + pc z + pd = 0 float donde; int esta; donde = (rva * x) + (rvb * y) + (rvc * z) + rvd; if ( donde <0) esta = -1; //delante else if ( donde > 0) esta =1; //detrás else esta = 0; return esta; } //---------------------------- // EXPLICACION DE LOS PARAMETROS:: // ch --> criterio a aplicar: // si es p --> plano // si es d --> plano y esfera // si es e --> esfera //DEVUELVE true cuando está en la zona de interes y debe estar a maximo detalle //---------------------------- bool Foliage::Criterio ( Leaf &aLeaf, char ch, float rva, float rvb,float rvc, float rvd, float radio) { float a,b,c; // coordenadas del primero de los vertices en la hoja float d,e,f; // coords vertice 2 float g,h,i; // coords vertice 3 float j,k,l; // coords vertice 4 float dist; bool inter=false, inter2=false; float ccx, ccy, ccz; vertexdata->GetVertexCoord(aLeaf.vertsLeaf[0],a,b,c); ccx = cx; ccy = cy; ccz = cz; if ( (ch == 'p') || (ch == 'd')) { //plano siempre if (DondeEsta (a,b,c, rva,rvb,rvc,rvd) == 1) { // MiArbol->Vertices[aHoja.vertsLeaf[1]].GetCoordinates (d,e,f); vertexdata->GetVertexCoord(aLeaf.vertsLeaf[1],d,e,f); if (DondeEsta (d,e,f, rva,rvb,rvc,rvd) == 1) { // MiArbol->Vertices[aHoja.vertsLeaf[2]].GetCoordinates (g,h,i); vertexdata->GetVertexCoord(aLeaf.vertsLeaf[2],g,h,i); if (DondeEsta (g,h,i, rva,rvb,rvc,rvd) == 1) { // Vertices[aHoja.vertsLeaf[3]].GetCoordinates (j,k,l); vertexdata->GetVertexCoord(aLeaf.vertsLeaf[3],j,k,l); if (DondeEsta (j,k,l, rva,rvb,rvc,rvd) == 1) inter = true; } } } } if (( ch == 'e') || (( ch == 'd') && (inter == true))) //CRITERIO DE LA ESFERA { dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz)); if (dist > radio) { // MiArbol->Vertices[aHoja.vertsLeaf[1]].GetCoordinates (a,b,c); vertexdata->GetVertexCoord(aLeaf.vertsLeaf[1],a,b,c); dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz)); if (dist > radio) { // MiArbol->Vertices[aHoja.vertsLeaf[2]].GetCoordinates (a,b,c); vertexdata->GetVertexCoord(aLeaf.vertsLeaf[2],a,b,c); dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz)); if (dist > radio) { // MiArbol->Vertices[aHoja.vertsLeaf[3]].GetCoordinates (a,b,c); vertexdata->GetVertexCoord(aLeaf.vertsLeaf[3],a,b,c); dist =(float)sqrt ((a-ccx)*(a-ccx)+ (b-ccy)*(b-ccy)+ (c-ccz)*(c-ccz)); if (dist > radio) inter2 = true; } } } inter = inter2; } return inter; } /****************************************** RESOLUCIÓN VARIABLE **************************************************/ //----------------------------------------- // // RECORDAR!!! // NO cumple el criterio ------------> POCO DETALLE ( COLAPSAR ) // SI cumple el criterio ------------> MUCHO DETALLE ( SPLITEAR ) // // el ch se le pasa a Criterio y es allí donde se evalua // e --> esfera // p --> plano // d --> los dos criterios //------------------------------------------ int Foliage::ResolucionV (char ch, float rva, float rvb,float rvc, float rvd, float radio) { bool lista=false; int i, hpost, spli; float renvol, centroz; i = ppio; spli = -1; renvol = rad; centroz = cz; // printf (" el centro en %f y el radio es de %f\n", centroz, renvol); // fijo el máximo del plano de RV if (rvd < centroz -renvol ) rvd = (centroz -renvol ); else if (rvd > centroz +renvol ) rvd = (centroz +renvol ); // printf (" el plano está en %f\n", rvd); //para que fije el valor máximo del radio if (( ch == 'e') || ( ch == 'd')) { if (radio> renvol) radio = renvol; else if (radio <0) radio =0.0; } // printf (" el radio vale %f\n", radio); //empieza a buscar las hojas activas while ( i != -1){ hpost = Acth[i].next; //COLAPSAR if (( Criterio ( Leaves[i], ch, rva,rvb,rvc,rvd, radio )== false) && (Leaves[i].parent != -1)) { // SI ESTA FUESE LA HOJA IZQUIERDA Y LA DERECHA NO CUMPLE TAMPOCO EL CRITERIO if ((Leaves[Leaves[i].parent].childLeft == i) && ( Criterio (Leaves[Leaves[Leaves[i].parent].childRight] , ch, rva,rvb,rvc,rvd, radio )== false)) { //hay que colapsar if (EsActivo(Leaves[Leaves[i].parent].childRight) == false) lista = Forzar_Colapse (Leaves[Leaves[i].parent].childRight, hpost, ch, rva,rvb,rvc,rvd, radio); // para activarla else lista = true; } else // SI ESTA FUESE LA HOJA DERECHA Y LA IZQUIERDA NO CUMPLE TAMPOCO EL CRITERIO if ((Leaves[Leaves[i].parent].childRight == i) && ( Criterio (Leaves[Leaves[Leaves[i].parent].childLeft] , ch, rva,rvb,rvc,rvd, radio )== false)) {//hay que colapsar if (EsActivo(Leaves[Leaves[i].parent].childLeft) == false) lista = Forzar_Colapse (Leaves[Leaves[i].parent].childLeft, hpost, ch, rva,rvb,rvc,rvd, radio); // para activarla else lista = true; } //estan activas preparadas para subir un nivel en la zona de no detalle. if ( lista == true) { lista = false; ColapsaHoja ( Leaves[i].parent, hpost); } } i = hpost; } //ahora veo lo de splitear i = ppio; spli = -1; while ( i != -1){ hpost = Acth[i].next; spli = Chequea_Split (i, ch, rva,rvb,rvc,rvd, radio); if ( spli != -1) { Forzar_Split ( spli, i, hpost); spli = -1; } i = hpost; } return (1); } //-------------------------------------------------------------------------------------------------------------------------------- // Colapsa dos hojas //-------------------------------------------------------------------------------------------------------------------------------- void Foliage::ColapsaHoja ( int h, int& post) { //actualizo los punteros del ppio y del final, y post while (( ppio == Leaves[h].childLeft) || ( ppio == Leaves[h].childRight)) ppio = Acth[ppio].next; while (( final == Leaves[h].childLeft) || ( final == Leaves[h].childRight)) final = Acth[final].prev; while (( post == Leaves[h].childLeft) || ( post == Leaves[h].childRight)) post = Acth[post].next; //COLAPSAR = QUITO DOS DE ACTIVOS PONGO UNO A ACTIVO if (Acth[Leaves[h].childLeft].next != -1) Acth[Acth[Leaves[h].childLeft].next].prev = Acth[Leaves[h].childLeft].prev; if (Acth[Leaves[h].childLeft].prev != -1) Acth[Acth[Leaves[h].childLeft].prev].next = Acth[Leaves[h].childLeft].next; if (Acth[Leaves[h].childRight].next != -1) Acth[Acth[Leaves[h].childRight].next].prev = Acth[Leaves[h].childRight].prev; if (Acth[Leaves[h].childRight].prev != -1) Acth[Acth[Leaves[h].childRight].prev].next = Acth[Leaves[h].childRight].next; // desconecto a los hijos Acth[Leaves[h].childLeft].prev = -1; Acth[Leaves[h].childLeft].next = -1; Acth[Leaves[h].childRight].prev = -1; Acth[Leaves[h].childRight].next = -1; //añado al final Acth[h].prev = final; Acth[h].next = -1; Acth[final].next = h; final = h; } //-------------------------------------------------------------------------------------------------- // Forzar colapse // la hoja que paso en el parametro hoja es la que quiero que se active al final //-------------------------------------------------------------------------------------------------- bool Foliage::Forzar_Colapse(int hoja, int &hpost, char ch, float rva, float rvb,float rvc, float rvd, float radio) { int h; lista listah; bool fin; fin = false; listah.Inserta (hoja); // Inserta un dato en la lista while (listah.NDatos () != 0) { h = listah.GetCola ();//coger la cola if (Leaves[h].childLeft != -1) { if (!EsActivo (Leaves[h].childLeft )) listah.Inserta (Leaves[h].childLeft); if ( (!EsActivo (Leaves[h].childRight)) ) listah.Inserta (Leaves[h].childRight); if (EsActivo (Leaves[h].childLeft) && EsActivo (Leaves[h].childRight )) if((Criterio ( Leaves[Leaves[h].childLeft] ,ch, rva,rvb,rvc,rvd, radio )== false) && (Criterio ( Leaves[Leaves[h].childRight], ch, rva,rvb,rvc,rvd, radio ) == false)) { ColapsaHoja ( h, hpost); listah.Borra(h); } else fin = true; } else { fin = true; listah.Borra(h); } if ( fin == true ) while ( listah.NDatos () != 0) listah.BorraCola(); } return (EsActivo (hoja)); } //-------------------------------------------------------------------------------------------------------------------------------- // Splitea una hoja //-------------------------------------------------------------------------------------------------------------------------------- void Foliage::SplitHoja (int h, int &post) { // SPLITEAR: QUITO UNO, PONGO DOS if ( ppio == h) ppio = Acth[h].next; if ( final == h) final = Acth[h].prev; // 1 enlazo los hijos Acth[Leaves[h].childLeft].next = Leaves[h].childRight; Acth[Leaves[h].childRight].prev = Leaves[h].childLeft; Acth[Leaves[h].childRight].next = -1; //y desconecto al padre if ( Acth[h].prev != -1) Acth[Acth[h].prev].next = Acth[h].next; if ( Acth[h].next != -1) Acth[Acth[h].next].prev = Acth[h].prev; Acth[h].prev = -1; Acth[h].next = -1; //añado al final los hijos Acth[Leaves[h].childLeft].prev = final; Acth[final].next = Leaves[h].childLeft; final = Leaves[h].childRight; } //------------------------------------------------------------------------------------------- // chequear si tengo que splitear. Devuelve el primero de los nodos que cumple la condicion //------------------------------------------------------------------------------------------- int Foliage::Chequea_Split(int h, char ch, float rva, float rvb,float rvc, float rvd, float radio) { int nodo; nodo = -1; if (Leaves[h].childLeft != -1) { // si el hijo derecho o el izquierdo están en la zona de máximo detalle, haré que estos se activen if ( (Criterio (Leaves[Leaves[h].childLeft], ch, rva,rvb,rvc,rvd, radio ) == true) || (Criterio (Leaves[Leaves[h].childRight], ch, rva,rvb,rvc,rvd, radio ) == true)) nodo = Leaves[h].childLeft; else // si no, bajo un nivel más hasta encontrar algún descendiente que se encuentre en la zona de + detalle { nodo = Chequea_Split (Leaves[h].childLeft, ch, rva,rvb,rvc,rvd, radio); if ( nodo == -1 ) nodo = Chequea_Split (Leaves[h].childRight, ch, rva,rvb,rvc,rvd, radio); } } return (nodo); } //------------------------------------------------------------------------------------------- // fuerzo a splitear // hoja -> es el nodo que cumple la condicion // padre -> es el nodo que chequeaba de la lista de activos // hpost -> es el nodo siguiente en la lista de activos //------------------------------------------------------------------------------------------- bool Foliage::Forzar_Split(int hoja, int padre, int &hpost) { int h; lista listah; bool bien; bien = false; h = Leaves[hoja].parent; listah.Inserta (h); // Inserta un dato en la lista while ( h != padre) { h = Leaves[h].parent; listah.Inserta (h); // Inserta un dato en la lista } while (listah.NDatos () != 0) { h = listah.GetCola ();//coger el padre más alto SplitHoja(h, hpost); listah.Borra(h); } if ( listah.NDatos() == 0) bien = true; return (bien); } /****************************************** RESOLUCIÓN CONSTANTE **************************************************/ int Foliage::ResolucionC (float dist, float dmax, float dmin) { float difdist, d; int difhojas, nhojas; if (( dist > dmin) && (dist dmax) { AjusteHojas (minHojas); } else if (dist < dmin) { AjusteHojas (nHojas); } return (nhactivas); } void Foliage::AjusteHojas( int nhojas) { if ((nhojas <= nHojas) && (nhojas >= minHojas)) { if ( nhojas < nhactivas) { RCecol ( nhactivas - nhojas); } else { RCsplit (nhojas-nhactivas ); } nhactivas = nhojas; // printf ( "ajusto a %i\n", nhactivas ); } } //----------------------------------------- // // RECORDAR!!! // NO cumple el criterio ------------> POCO DETALLE ( COLAPSAR ) // SI cumple el criterio ------------> MUCHO DETALLE ( SPLITEAR ) // // el ch se le pasa a Criterio y es allí donde se evalua //------------------------------------------ /* void Foliage::RCecol ( int nhojas) { int i, hpost; i = ppio; while (( i != -1) && (nhojas>0)){ hpost = Acth[i].next; if ( MiArbol->Hojas[i].parent != -1) if ( MiArbol->Hojas[MiArbol->Hojas[i].parent].childLeft == i) {if ( EsActivo (MiArbol->Hojas[MiArbol->Hojas[i].parent].childRight ) ) { ColapsaHoja ( MiArbol->Hojas[i].parent, hpost); nhojas --; } } else {if ( EsActivo (MiArbol->Hojas[MiArbol->Hojas[i].parent].childLeft ) ) { ColapsaHoja ( MiArbol->Hojas[i].parent, hpost); nhojas --; } } i = hpost; } } */ void Foliage::RCecol ( int num) { int j, h; j = num; h = final+1; while ((h<=TotHojas) && (j>0)) { while (( ppio == Leaves[h].childLeft) || ( ppio == Leaves[h].childRight)) ppio = Acth[ppio].next; while (( final == Leaves[h].childLeft) || ( final == Leaves[h].childRight)) final = Acth[final].prev; //COLAPSAR = QUITO DOS DE ACTIVOS PONGO UNO A ACTIVO if (Acth[Leaves[h].childLeft].next != -1) Acth[Acth[Leaves[h].childLeft].next].prev = Acth[Leaves[h].childLeft].prev; if (Acth[Leaves[h].childLeft].prev != -1) Acth[Acth[Leaves[h].childLeft].prev].next = Acth[Leaves[h].childLeft].next; if (Acth[Leaves[h].childRight].next != -1) Acth[Acth[Leaves[h].childRight].next].prev = Acth[Leaves[h].childRight].prev; if (Acth[Leaves[h].childRight].prev != -1) Acth[Acth[Leaves[h].childRight].prev].next = Acth[Leaves[h].childRight].next; // desconecto a los hijos Acth[Leaves[h].childLeft].prev = -1; Acth[Leaves[h].childLeft].next = -1; Acth[Leaves[h].childRight].prev = -1; Acth[Leaves[h].childRight].next = -1; //añado al final Acth[h].prev = final; Acth[h].next = -1; Acth[final].next = h; final = h; // decremento el contador de colapsos j--; //incremento el posible siguiente colapso h++; } } /* void Foliage::RCsplit ( int nhojas) { int i, hpost; i = ppio; while (( i != -1) && (nhojas>0)){ hpost = Acth[i].next; if (MiArbol->Leaves[i].childLeft != -1){ SplitHoja(i, hpost); nhojas --; } i = hpost; } } */ int Foliage::AnteriorActivo (int h) { int i; if (ppio > h) i = -1; else { i = h--; while (EsActivo (i) == false) i--; } return (i); } int Foliage::PosteriorActivo (int h) { int i; i = h++; while ((EsActivo (i) == false) || (i> TotHojas)) i++; if (i > TotHojas) i=-1; return (i); } void Foliage::RCsplit ( int num) { int j, h, ant, post; j = num; h = final; while ((h > nHojas) && (j>0)) { ///////////// insertar a los hijos en orden segun su indice //hijo izquierdo ant = AnteriorActivo (Leaves[h].childLeft); post = PosteriorActivo (Leaves[h].childLeft); Acth[Leaves[h].childLeft].next = post; Acth[Leaves[h].childLeft].prev = ant; if (ant != -1) Acth[ant].next = Leaves[h].childLeft; else ppio = Leaves[h].childLeft; if (post != -1) Acth[post].prev = Leaves[h].childLeft; //hijo derecho ant = AnteriorActivo (Leaves[h].childRight); post = PosteriorActivo (Leaves[h].childRight); Acth[Leaves[h].childRight].next = post; Acth[Leaves[h].childRight].prev = ant; if (ant != -1) Acth[ant].next = Leaves[h].childRight; else ppio = Leaves[h].childRight; if (post != -1) Acth[post].prev = Leaves[h].childRight; // despues de insertar los hijos miro a ver cual spliteare el siguiente final = Acth[h].prev; //y desconecto al padre if ( Acth[h].prev != -1) Acth[Acth[h].prev].next = Acth[h].next; //if ( Acth[h].next != -1) // Acth[Acth[h].next].prev = Acth[h].prev; Acth[h].prev = -1; Acth[h].next = -1; // decremento el contador de colapsos j--; //incremento el posible siguiente colapso h--; } } void Foliage::ReadVertices(const Geometry::SubMesh *submesh) { int countv= int(submesh->mVertexBuffer->mVertexCount); vertexdata = create_vertex_data_func(2*countv); Leaves = new Leaf[countv*2]; indexdata = create_index_data_func(countv*2*3); // 3 indices x 2 triangulos x hoja vertexdata->Begin(); for (int i=0; iSetVertexCoord( i, submesh->mVertexBuffer->mPosition[i].x, submesh->mVertexBuffer->mPosition[i].y, submesh->mVertexBuffer->mPosition[i].z ); } vertexdata->End(); TotVerts = countv; } void Foliage::GetNormalH (Leaf &aleaf) { float onex, oney, onez; float twox, twoy, twoz; float threex, threey, threez; /* Vertices[aHoja.vertsLeaf[0]].GetCoordinates (onex, oney, onez); Vertices[aHoja.vertsLeaf[1]].GetCoordinates(twox, twoy, twoz); Vertices[aHoja.vertsLeaf[2]].GetCoordinates (threex, threey, threez);*/ vertexdata->GetVertexCoord(aleaf.vertsLeaf[0],onex,oney,onez); vertexdata->GetVertexCoord(aleaf.vertsLeaf[1],twox,twoy,twoz); vertexdata->GetVertexCoord(aleaf.vertsLeaf[2],threex,threey,threez); float v1[3]={twox-onex,twoy-oney,twoz-onez}; float v2[3]={threex-onex,threey-oney,threez-onez}; Normalize(v1,v1); Normalize(v2,v2); // aleaf.Normal[0] = (twoz-onez)*(threey-oney) - (twoy-oney)*(threez-onez); // aleaf.Normal[1] = (twox-onex)*(threez-onez) - (threex-onex)*(twoz-onez); // aleaf.Normal[2] = (threex-onex)*(twoy-oney) - (twox-onex)*(threey-oney); CrossProduct(v1,v2,aleaf.normal); } void Foliage::CrossProduct(const float *v1, const float *v2, float *res) { res[0] = v1[1]*v2[2] - v1[2]*v2[1]; res[1] = v1[2]*v2[0] - v1[0]*v2[2]; res[2] = v1[0]*v2[1] - v1[1]*v2[0]; } void Foliage::Normalize(const float *v, float *res) { float module=sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); res[0]=v[0]/module; res[1]=v[1]/module; res[2]=v[2]/module; } void Foliage::ReadLeafs(const Geometry::SubMesh *submesh) { int numtris = int(submesh->mIndexCount / 3); nHojas = numtris / 2; for (int h=0; hmIndex[h*6+0]; Leaves[h].vertsLeaf[1] = submesh->mIndex[h*6+1]; Leaves[h].vertsLeaf[2] = submesh->mIndex[h*6+2]; Leaves[h].vertsLeaf[3] = submesh->mIndex[h*6+5]; Leaves[h].visible = 0; GetNormalH ( Leaves[h]); } } /// returns the number of total leafs bool Foliage::ReadSimpSeq(const char *simpSeqFile) { FILE* fp_simpli; char linea[256]; int v0, v1, v2, v3, tn, tv1,tv2, e=0; if ((fp_simpli = fopen (simpSeqFile, "r")) == NULL) { printf ("No he podido abrir el fichero %s\n", simpSeqFile); return false; } else { tn = nHojas; while (fgets (linea, 255, fp_simpli) != NULL) { if (linea[0]<'0' || linea[0]>'9') continue; //N 446 Ver 10176 10178 10169 10171 Tv 156 154 E 2 // sscanf(linea, "%s %lu %s %lu %lu %lu %lu %s %lu %lu %s %i", // &str, &tn, &str, &v0, &v1, &v2, &v3, &str, &tv1, &tv2, &str, &e ); long int triviej00=-1, triviej01=-1; long int triviej10=-1, triviej11=-1; sscanf(linea, "%lu %lu %lu %lu & %lu %lu %lu %lu", &triviej00,&triviej01,&triviej10,&triviej11, &v0,&v1,&v2,&v3); Leaves[tn].vertsLeaf[0] = v0; Leaves[tn].vertsLeaf[1] = v1; Leaves[tn].vertsLeaf[2] = v2; Leaves[tn].vertsLeaf[3] = v3; Leaves[tn].visible = 0; GetNormalH (Leaves[tn]); tv1 = triviej00/2; tv2 = triviej10/2; Leaves[tn].childLeft= tv1; Leaves[tn].childRight= tv2; Leaves[tv1].parent = tn; Leaves[tv2].parent = tn; tn++; } } fclose(fp_simpli); TotHojas=tn; return true; } void Foliage::RellenoRaiz (void) { int i,j, k, t, cont; bool esta, fin; i=0; k=-1; cont =-1; MinDet = new Activas[nHojas*2]; while (i -1) j= Leaves[j].parent; Leaves[i].root = j; // para la estructura MinDet if ( k == -1){ k++; MinDet[k].indice = j; cont =k; } else { t = 0; esta = false; fin = false; while (( fin == false) && (esta == false)) { if ( MinDet[t].indice == j) esta = true; else t++; if (MinDet[t].indice == -1) fin = true; } if ( esta == false) //añado al final { cont++; MinDet[cont].indice = j; } } i++; } minHojas = cont; } void Foliage::CalculaTexCoordsYNorms(void) { vertexdata->Begin(); for (int i=0; iSetVertexNormal(Leaves[i].vertsLeaf[0], lanormal[0], lanormal[1], lanormal[2]); vertexdata->SetVertexTexCoord(Leaves[i].vertsLeaf[0], 0.0f, 1.0f); vertexdata->SetVertexNormal(Leaves[i].vertsLeaf[1], lanormal[0], lanormal[1], lanormal[2]); vertexdata->SetVertexTexCoord(Leaves[i].vertsLeaf[1], 0.0f, 0.0f); vertexdata->SetVertexNormal(Leaves[i].vertsLeaf[2], lanormal[0], lanormal[1], lanormal[2]); vertexdata->SetVertexTexCoord(Leaves[i].vertsLeaf[2], 1.0f, 1.0f); vertexdata->SetVertexNormal(Leaves[i].vertsLeaf[3], lanormal[0], lanormal[1], lanormal[2]); vertexdata->SetVertexTexCoord(Leaves[i].vertsLeaf[3], 1.0f, 0.0f); /* MiArbol->Vertices[aHoja.vertsLeaf[1]].GetCoordinates (a,b,c); glTexCoord2f ( 0.0, 1.0); glVertex3f (a,b,c); MiArbol->Vertices[aHoja.vertsLeaf[2]].GetCoordinates (a,b,c); glTexCoord2f ( 1.0, 0.0); glVertex3f (a,b,c); MiArbol->Vertices[aHoja.vertsLeaf[3]].GetCoordinates (a,b,c); glTexCoord2f ( 1.0, 1.0); glVertex3f (a,b,c);*/ } vertexdata->End(); } Foliage::Foliage(const Foliage *ar) { nHojas=ar->nHojas; MinDet = new Activas[nHojas*2]; // for (unsigned int i=0; iMinDet[i]; memcpy(MinDet,ar->MinDet,sizeof(Activas)*nHojas*2); TotHojas=ar->TotHojas; cx=ar->cx; cy=ar->cy; cz=ar->cz; rad=ar->rad; minHojas=ar->minHojas; TotVerts=ar->TotVerts; create_vertex_data_func=ar->create_vertex_data_func; create_index_data_func=ar->create_index_data_func; vertexdata=create_vertex_data_func(ar->vertexdata->GetNumVertices()); vertexdata->Begin(); for (unsigned int i=0; iGetNumVertices(); i++) { float va,vb,vc; ar->vertexdata->GetVertexCoord(i,va,vb,vc); vertexdata->SetVertexCoord(i,va,vb,vc); ar->vertexdata->GetVertexNormal(i,va,vb,vc); vertexdata->SetVertexNormal(i,va,vb,vc); } vertexdata->End(); indexdata=create_index_data_func(ar->indexdata->GetNumMaxIndices()); indexdata->Begin(); for (unsigned int i=0; iGetNumMaxIndices(); i++) indexdata->SetIndex(i,ar->indexdata->GetIndex(i)); indexdata->End(); Leaves=new Leaf[vertexdata->GetNumVertices()]; // for (unsigned int i=0; iGetNumVertices(); i++) // Leaves[i]=ar->Leaves[i]; memcpy(Leaves,ar->Leaves,sizeof(Leaf)*vertexdata->GetNumVertices()); // esto no sé si devería haber akí indexdata->SetNumValidIndices(0); int h=0; Acth = new Activas[nHojas*8]; for ( h=0; h < nHojas; h++) { Acth[h].indice = h; if ( h != 0) { Acth[h].prev = (h-1); Acth[h-1].next = h; } } ppio = 0; final = nHojas-1; nhactivas = nHojas; }