www.pudn.com > 3dterrain.zip > OcTree_Terrain.cpp
// OcTree_Terrain.cpp: implementation of the OcTree_Terrain class. // ////////////////////////////////////////////////////////////////////// #include "OcTree_Terrain.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// float *OcTree_Terrain::vertex; vector*OcTree_Terrain::pasy_terrain; int OcTree_Terrain::split_x, OcTree_Terrain::split_z; int OcTree_Terrain::pocet_vrcholov=0; int OcTree_Terrain::max_pocet_vrcholov=10000; int OcTree_Terrain::max_stvorcov_v_kocke=100; CFrustum *OcTree_Terrain::Frustum=NULL; OcTree_Terrain::OcTree_Terrain() { pocet_vrcholov++; if(pocet_vrcholov%(max_pocet_vrcholov/100)==0) { char p[50]; itoa(pocet_vrcholov, p, 10); load->percenta=pocet_vrcholov/ (float)max_pocet_vrcholov; load->Update(p,load->index); } je_deleny = 0; size = 0; pocet_stvorcov = 0; center.x = 0; center.y = 0; center.z = 0; q.clear(); for(int i=0; i<8; i++) vrchol[i] = NULL; } OcTree_Terrain::OcTree_Terrain( float *vertex_, vector *pasy_terrain_, float velkost_, int split_x_, int split_z_) { vertex = vertex_; pasy_terrain = pasy_terrain_; split_x = split_x_; split_z = split_z_; je_deleny = 0; size = velkost_; pocet_stvorcov = split_x*split_z; center.x = 0; center.y = 0.5f*size; center.z = 0; { float uroven = (float)log(pocet_stvorcov/(double)max_stvorcov_v_kocke)/log(5.3f); max_pocet_vrcholov = (int)(1+pow( 5.3f, uroven) )*(uroven+1); if(max_pocet_vrcholov<100)max_pocet_vrcholov=100; } for(int i=0; i<8; i++) vrchol[i] = NULL; stvorce s; s.left = 0; s.right= split_x-1; for( s.z=0; s.z pom_q[8]; XYZ stred[8]; // stredy kociek, ktore vzniknu delenim velkej (aktualnej) kocky je_deleny = 1; // kocka je delena // vypocet stredov vsetkych mensich kociek stred[TOP_LEFT_FRONT].x = center.x - size/4; stred[TOP_LEFT_FRONT].y = center.y + size/4; stred[TOP_LEFT_FRONT].z = center.z + size/4; stred[TOP_LEFT_BACK].x = center.x - size/4; stred[TOP_LEFT_BACK].y = center.y + size/4; stred[TOP_LEFT_BACK].z = center.z - size/4; stred[TOP_RIGHT_BACK].x = center.x + size/4; stred[TOP_RIGHT_BACK].y = center.y + size/4; stred[TOP_RIGHT_BACK].z = center.z - size/4; stred[TOP_RIGHT_FRONT].x = center.x + size/4; stred[TOP_RIGHT_FRONT].y = center.y + size/4; stred[TOP_RIGHT_FRONT].z = center.z + size/4; stred[BOTTOM_LEFT_FRONT].x = center.x - size/4; stred[BOTTOM_LEFT_FRONT].y = center.y - size/4; stred[BOTTOM_LEFT_FRONT].z = center.z + size/4; stred[BOTTOM_LEFT_BACK].x = center.x - size/4; stred[BOTTOM_LEFT_BACK].y = center.y - size/4; stred[BOTTOM_LEFT_BACK].z = center.z - size/4; stred[BOTTOM_RIGHT_BACK].x = center.x + size/4; stred[BOTTOM_RIGHT_BACK].y = center.y - size/4; stred[BOTTOM_RIGHT_BACK].z = center.z - size/4; stred[BOTTOM_RIGHT_FRONT].x = center.x + size/4; stred[BOTTOM_RIGHT_FRONT].y = center.y - size/4; stred[BOTTOM_RIGHT_FRONT].z = center.z + size/4; // rozdelenie stvorcov do pomocnych pasov for(int i=0; i size = size/2; vrchol[i]->center.x = stred[i].x; vrchol[i]->center.y = stred[i].y; vrchol[i]->center.z = stred[i].z; vrchol[i]->pocet_stvorcov = Pocet_stvorcov( &pom_q[i]); vrchol[i]->q = pom_q[i]; } else // v kocke nie su stvoce, kocku nepridavame do stromu { pom_q[i].clear(); vrchol[i] = NULL; } } q.clear(); // uvolnime pamet, ktoru nepotrebujeme // rekurentne pokracujeme vo vytvarani stromu, pokial je v kocke viac ako max_stvorcov_v_kocke for( i=0; i<8; i++) { if(vrchol[i] == NULL) continue; if(vrchol[i]->pocet_stvorcov>max_stvorcov_v_kocke) vrchol[i]->Vytvor_vrchol(); } } bool OcTree_Terrain::Stvorec_v_kocke(XYZ stred, float polovicna_velkost, int x, int z) { if( Bod_v_kocke(stred, polovicna_velkost, &vertex[3*( (split_x+1)*z + x)] ) ) return 1; if( Bod_v_kocke(stred, polovicna_velkost, &vertex[3*( (split_x+1)*z + x+1)] ) ) return 1; if( Bod_v_kocke(stred, polovicna_velkost, &vertex[3*( (split_x+1)*(z+1) + x)] ) ) return 1; if( Bod_v_kocke(stred, polovicna_velkost, &vertex[3*( (split_x+1)*(z+1) + x+1)] ) ) return 1; return 0; } bool OcTree_Terrain::Bod_v_kocke(XYZ stred, float pol_velkost, float *v) { if( v[0]<(stred.x - pol_velkost) || v[0]>(stred.x + pol_velkost) ) return 0; if( v[1]<(stred.y - pol_velkost) || v[1]>(stred.y + pol_velkost) ) return 0; if( v[2]<(stred.z - pol_velkost) || v[2]>(stred.z + pol_velkost) ) return 0; return 1; } void OcTree_Terrain::Pridaj_stvorec(vector *q_p, int x, int z) { for(int i=0; i<(*q_p).size(); i++) // prehladavame vsetky skupiny stvorcov { if( z!=(*q_p)[i].z) continue; // preskakujeme skupiny s inou z suradnicou if( x >= (*q_p)[i].left && x<= (*q_p)[i].right )return; // ak je stvorec uz v kocke if( x == (*q_p)[i].left-1 ) // ak je na hranici z lava { (*q_p)[i].left--; return; } if( x == (*q_p)[i].right+1) // ak je na hranici z prava { (*q_p)[i].right++; return; } } { // inak pridame stvorec ssamostatne stvorce s; s.left = x; s.right = x; s.z = z; (*q_p).push_back(s); } } int OcTree_Terrain::Pocet_stvorcov( vector *s) { int pocet=0; for(int i=0; i< (*s).size(); i++) { pocet += (*s)[i].right - (*s)[i].left + 1; } return pocet; } void OcTree_Terrain::Nastav_pasy() { if(Frustum->CubeInFrustum( center.x, center.y, center.z, size*0.5f )) { if(je_deleny) for(int i=0; i<8; i++) { if(vrchol[i]!=NULL)vrchol[i]->Nastav_pasy(); } else Pridaj_pasy(); } } void OcTree_Terrain::Nastav_pasy2() { int stav; if(stav = Frustum->CubeInFrustum2( center.x, center.y, center.z, size*0.5f )) { if(je_deleny && stav!=2) for(int i=0; i<8; i++) { if(vrchol[i]!=NULL)vrchol[i]->Nastav_pasy2(); } else Pridaj_pasy(); } } void OcTree_Terrain::Maz_a_nastav_pasy() { for(int z=0; z =pasy_terrain[z][i].right) // ak je pridavany vacsi z oboh stran { pasy_terrain[z][i].left = left; pasy_terrain[z][i].right = right; return; } if( left>=pasy_terrain[z][i].left && right<=pasy_terrain[z][i].right) return; // ak je pridavany vo vnutry povodneho if( left<=pasy_terrain[z][i].left && right>=pasy_terrain[z][i].left-1) { // ak pridavany pridava z lavej strany pasy_terrain[z][i].left = left; return; } if( right>=pasy_terrain[z][i].right && left<=pasy_terrain[z][i].right+1) { // ak pridavany zvecsuje z pravej strany pasy_terrain[z][i].right = right; return; } } { cast_pasu p; p.left = left; p.right = right; if(pasy_terrain[z].size() == 0) { pasy_terrain[z].push_back(p); return; } pasy_terrain[z].push_back(p); // inak pridame dalsi kus stvorcov } } void OcTree_Terrain::Kresli_kocky() { int stav; glColor3f(1,1,0); if(keys['E']) stav = Frustum->CubeInFrustum2( center.x, center.y, center.z, size*0.5f ); else stav = Frustum->CubeInFrustum( center.x, center.y, center.z, size*0.5f ); // if( stav = Frustum.CubeInFrustum2( center.x, center.y, center.z, size*0.5f )) if(stav) { if(je_deleny) { if(stav==2) { glColor3f(1,0,0); Kresli_kocku(); return; } for(int i=0; i<8; i++) { if(vrchol[i]!=NULL)vrchol[i]->Kresli_kocky(); } } else Kresli_kocku(); } } void OcTree_Terrain::Kresli_kocku() { float s = size*0.5f; float x = center.x; float y = center.y; float z = center.z; glDisable(GL_TEXTURE_2D); // glColor3f(1,1,0); glBegin(GL_LINE_STRIP ); glVertex3f( x-s, y-s, z+s); glVertex3f( x+s, y-s, z+s); glVertex3f( x+s, y-s, z-s); glVertex3f( x-s, y-s, z-s); glVertex3f( x-s, y-s, z+s); glVertex3f( x-s, y+s, z+s); glVertex3f( x+s, y+s, z+s); glVertex3f( x+s, y+s, z-s); glVertex3f( x-s, y+s, z-s); glVertex3f( x-s, y+s, z+s); glEnd(); glBegin(GL_LINES ); glVertex3f( x+s, y-s, z+s); glVertex3f( x+s, y+s, z+s); glVertex3f( x+s, y-s, z-s); glVertex3f( x+s, y+s, z-s); glVertex3f( x-s, y-s, z-s); glVertex3f( x-s, y+s, z-s); glEnd(); glColor3f(1,1,1); glEnable(GL_TEXTURE_2D); } void OcTree_Terrain::Zapis_vrchol(FILE *sub) { zapis_OcTree_Terrain pom; pom.center.x = center.x; pom.center.y = center.y; pom.center.z = center.z; pom.pocet_stvorcov = pocet_stvorcov; pom.size = size; pom.zapisanych_stvorcov = q.size(); pom.vrchol = 0; for(int i=0; i<8; i++) { if(vrchol[i]!=NULL) pom.vrchol |= 1<Zapis_vrchol( sub); } } int OcTree_Terrain::Nacitaj_vrchol(FILE *sub) { zapis_OcTree_Terrain pom; if(!fread( &pom, sizeof(zapis_OcTree_Terrain), 1, sub) ) return 0; center.x = pom.center.x; center.y = pom.center.y; center.z = pom.center.z; if(pom.vrchol) je_deleny = 1; else je_deleny = 0; pocet_stvorcov = pom.pocet_stvorcov; size = pom.size; for(int i=0; i Nacitaj_vrchol( sub))return 0; } } } return 1; } void OcTree_Terrain::Save(char *meno) { FILE *sub; int poc_vrcholov = 0; Pocet_vrcholov( &poc_vrcholov); sub = fopen( meno, "wb"); fwrite( &poc_vrcholov, sizeof(int), 1, sub); // pocet vrcholov - pouzitie pre loader fwrite( &split_x, sizeof(int), 1, sub); // pocet stvorcov v smere x fwrite( &split_z, sizeof(int), 1, sub); // pocet stvorcov v smere z fwrite( &size, sizeof(float), 1, sub); // velkost plochy fwrite( &max_stvorcov_v_kocke, sizeof(int), 1, sub);// max_stvorcov_v_kocke Zapis_vrchol(sub); fclose(sub); } int OcTree_Terrain::Load(char *meno) { FILE *sub; int delenie_x, delenie_z, max_stvorcov_v_kocke_; float velkost; q.clear(); sub = fopen( meno, "rb"); if(sub == NULL) return 0; if(!fread( &max_pocet_vrcholov, sizeof(int), 1, sub) ){ fclose(sub); return 0;} if(!fread( &delenie_x, sizeof(int), 1, sub) ){ fclose(sub); return 0;} if(!fread( &delenie_z, sizeof(int), 1, sub) ){ fclose(sub); return 0;} if(!fread( &velkost, sizeof(float), 1, sub) ){ fclose(sub); return 0;} if(!fread( &max_stvorcov_v_kocke_, sizeof(int), 1, sub) ){ fclose(sub); return 0;} if( delenie_x!=split_x || delenie_z!=split_z || velkost!=size || max_stvorcov_v_kocke_!=max_stvorcov_v_kocke) { fclose(sub); return 0;} if(max_pocet_vrcholov<100)max_pocet_vrcholov=100; if(!Nacitaj_vrchol(sub)) { fclose(sub); return 0;} fclose(sub); return 1; } void OcTree_Terrain::Pocet_vrcholov(int *p) { (*p)++; if(!je_deleny)return; for( int i=0; i<8; i++) { if(vrchol[i]!=NULL) vrchol[i]->Pocet_vrcholov( p); } }