/** ******************************************************************************* @file /gui/model/guimap.cpp @brief Mapa guimap je konstruovana v TGame::initContext(..) Makro SIMPLE_SHADOWS aktivuje vykreslovani jednoduchych stinu. Makro DEBUG_SCENE vykreslovani obsahu sceny jakoby z pohledu druhe kamery. Makro SHADOWMAPPING aktivuje neoficialni shadowmapping. Makro SHOW_FPS aktivuje vypisovani informaci o rychlosti vykreslovani sceny. @author Pavel @version 0.1 ******************************************************************************/ #ifdef SHADOWMAPPING //grr, docasne reseni #include "external/extgl.h" #endif // #include "gui/model/guimap.h" // #include "common/Interface.h" #include "common/rm/rminit.h" #include "common/Log.h" #include "common/compatibility.h" // #include "gui/GUI.h" // #include "gui/contexts/Game.h" // #include "gui/engine/TextureManager.h" #include "gui/engine/MapControllers.h" #include "gui/engine/Effects.h" // #include "gui/model/reader_ase.h" #include "gui/model/hexy.h" #include "gui/model/TerrainEntity.h" // #include "gui/common/Sounds.h" #include "gui/common/BasicFonts.h" #include "gui/common/Defs.h" #include #include /*****************************************************************************/ namespace gui{ using namespace World; /** Vypis ladicich informaci o framerate. */ void FPS(){ static int T0 = 0; static int frames = 0; int T = KTime(); frames ++; float fps; static wchar_t buff[80]; if( T - T0 > 5000 ){ fps = float(frames)/(T-T0) * 1000.0f; snwprintf(buff,80,L"frames: %d time: %d milisec FPS: %f KTime=%d\n", frames, T-T0, fps, T); frames = 0; T0 = T; } glDisable(GL_LIGHTING); glColor4f(1,1,1,1); DrawText(10,SCREEN_HEIGHT-35,buff); } /*TguiMap***********************************************************************************/ //////////////////////////////////////////////////////////////////////////////////////////// // dump mapy do txt pro testy steeringu //////////////////////////////////////////////////////////////////////////////////////////// void TguiMap::dump2DMap(){ //otevri soubor FILE* f = fopen("dump2d","w"); //projdi hexy for(int i = 0; i < hexycount; i++){ THex* hhh = hexy[i]; //projdi proxyobjekty for(Tproxyobjs::iterator it = hhh->objs.begin(); it != hhh->objs.end(); it++) { (*it)->dump2D(f); } } //zavri soubor fclose(f); } //////////////////////////////////////////////////////////////////////////////////////////// // udalosti na mape //////////////////////////////////////////////////////////////////////////////////////////// void TguiMap::hexPreselect_sensor(int indx){ ((TGame*)TGUI::gui_inst->game)->preselected_hex_index = indx; ((TGame*)TGUI::gui_inst->game)->updateStatusBar(); } void TguiMap::hexClicked_sensor(int indx){ ((TGame*)TGUI::gui_inst->game)->hexClicked(indx); } void TguiMap::unitClicked_sensor(TUnit* unit){ ((TGame*)TGUI::gui_inst->game)->unitClicked(unit); } void TguiMap::buildingClicked_sensor(TBuilding* build){ ((TGame*)TGUI::gui_inst->game)->buildingClicked(build); } void TguiMap::sceneScriptFinished_sensor(){ TGame* g = ((TGame*)TGUI::gui_inst->game); g->animationFinished(); g->updateActionsPanel(); g->updateInfoPanel(); } void TguiMap::unitMoved_sensor(TStep* step){ TGame* g = ((TGame*)TGUI::gui_inst->game); //ja sem se pohnul if (g->iPlayerOnTurn == g->iGUIOwner) { g->updateVisibility(g->iGUIOwner, step); } //nepriel se pohnul else { //?? neni moc komplexni g->guiMiniMap->moveUnit(step->left_hex_id, step->hex_id); World::TVisibilityMapsContainer *visibility_maps; World::TVisibilityMap *vmap; World::VISIBILITY visibility1; World::VISIBILITY visibility2; // ((TGame*)TGUI::gui_inst->game)->getWorldVisibility(&visibility_maps); vmap = (*visibility_maps)[g->iGUIOwner]; visibility1 = vmap->getHexById(step->hex_id).getVisibility(); visibility2 = vmap->getHexById(step->left_hex_id).getVisibility(); if (visibility1 == VI_IN_SIGHT && visibility2 == VI_IN_SIGHT) { g->visibleEnemyMoved(step->hex_id); }//if if (visibility1 == VI_IN_SIGHT && visibility2 != VI_IN_SIGHT) { g->enemyAppeared(step->hex_id); }//if }//else } void TguiMap::unitRemoved_sensor(TUnit* unit){ TGame* g = ((TGame*)TGUI::gui_inst->game); if(g->selected_unit == unit) g->unitUnselected(); g->guiMiniMap->refresh(g->iGUIOwner); } void TguiMap::buildingRemoved_sensor(TBuilding* building){ TGame* g = ((TGame*)TGUI::gui_inst->game); if(g->selected_building == building) g->buildingUnselected(); g->guiMiniMap->refresh(g->iGUIOwner); } void TguiMap::visibilityAltered_sensor(TIntContainer* shown, TIntContainer* hidden, int player_id){ vs->alterVisibility(hidden, shown, player_id, 4000); } //////////////////////////////////////////////////////////////////////////////////////////// // operace na mape //////////////////////////////////////////////////////////////////////////////////////////// void TguiMap::highlightHexs(std::vector* hexes, int tag){ for (std::vector::iterator it = hexes->begin(); it != hexes->end(); it++) { int hs = hexy[(*it)]->highlightState; hs = hhtSetTag( (hs | hhHexAreaHighlight), tag); hexy[(*it)]->highlight(hs); } } void TguiMap::disableHexsHighlighting(int tag){ for(int i = 0; i < hexycount; i++){ int hs = hexy[i]->highlightState; int t = hhtGetTag( hs ); if(t == tag){ hhtSetTag(hs, 0); hs &= ~(hhHexAreaHighlight); hexy[i]->highlight(hs); } } } //////////////////////////////////////////////////////////////////////////////////////////// // brany pro data //////////////////////////////////////////////////////////////////////////////////////////// World::MAP* TguiMap::getWorldMap(){ World::MAP* m=NULL; ((TGame*)TGUI::gui_inst->game)->getWorldData(&m, NULL, NULL); return m; } World::TLivingUnitsContainer* TguiMap::getWorldLivingUnits(){ World::TLivingUnitsContainer* lu=NULL; ((TGame*)TGUI::gui_inst->game)->getWorldData(NULL, &lu, NULL); return lu; } World::TLivingBuildingsContainer* TguiMap::getWorldLivingBuildings(){ World::TLivingBuildingsContainer* lb=NULL; ((TGame*)TGUI::gui_inst->game)->getWorldData(NULL, NULL, &lb); return lb; } World::TTownsContainer* TguiMap::getWorldLivingTowns(){ World::TTownsContainer* t=NULL; ((TGame*)TGUI::gui_inst->game)->getWorldData(&t, NULL); return t; } World::TKingdomsContainer* TguiMap::getKingdoms(){ World::TKingdomsContainer* k=NULL; ((TGame*)TGUI::gui_inst->game)->getWorldData(NULL, &k); return k; } World::TWeather* TguiMap::getWorldWeather(){ World::TWeather *w=NULL; ((TGame*)TGUI::gui_inst->game)->getWorldWeather(&w); return w; } //////////////////////////////////////////////////////////////////////////////////////////// // mesta a kralovstvi //////////////////////////////////////////////////////////////////////////////////////////// int TguiMap::getTownHexOwner(int hid){ return ((TGame*)TGUI::gui_inst->game)->getTownHexOwner(hid); } void TguiMap::townOccupy(int townid, int newowner){ // World::TTownsContainer* ts = getWorldLivingTowns(); TOWN* t = NULL; P3F p3f; THex* h; // t = &((*ts)[townid]->data()); for(int i = 0; i < t->citysize; i++) { //hex&pozice h = hexy[ t->position[i] ]; hexCentre(&p3f, t->position[i]); //teren TTerrainTown* tt = (TTerrainTown*)h->getProxy(ptTerrain); //prebarvi tt->iOwner = newowner; TSparkle::installSparkle(&p3f, HEX_EDGE_LENGTH*2, HEX_EDGE_LENGTH*2); } } void TguiMap::kingdomOccupy(int kingdom, int newowner){ for(int i = 0; i < hexycount; i++) { if(hexy[i]->kingdom == kingdom) hexy[i]->owner = newowner; } } //////////////////////////////////////////////////////////////////////////////////////////// // orientace //////////////////////////////////////////////////////////////////////////////////////////// THex* TguiMap::getHex(int x, int y){ return hexy[ y*hwidth + x ]; } int TguiMap::getHexIndex(int x, int y){ return y*hwidth + x; } void TguiMap::getHexCoords(int indx, int *x, int *y){ *x = indx % hwidth; *y = indx / hwidth; } void TguiMap::getExtents(float* minx, float* maxx,float* miny,float* maxy) { *minx = 3 * net.dx * MAP_BOUND_X; *miny = net.dy * MAP_BOUND_Y; *maxy = net.dy * (hheight + 1 - MAP_BOUND_Y); *maxx = (3 * (hwidth - MAP_BOUND_X) + 0.5f) * net.dx; } int TguiMap::inWhichHex(float x, float y, int *hx, int *hy) { int A,B,C,ind; if (net.triangle(x,y,&A,&B,&C)){ if (net.owner[A] >= 0) ind = net.owner[A]; if (net.owner[B] >= 0) ind = net.owner[B]; if (net.owner[C] >= 0) ind = net.owner[C]; *hx = ind % hwidth; *hy = ind / hwidth; return 1; } else return 0; } int TguiMap::altitude(float x, float y, float *z) { int A,B,C; int hx, hy; if (net.triangle(x,y,&A,&B,&C)){ float c; P3F u,v,w; CopyV3(u.p, net.vert[B].position.p); SubV3(u.p, net.vert[A].position.p); CopyV3(v.p, net.vert[C].position.p); SubV3(v.p, net.vert[A].position.p); VectMulV3(w.p,u.p,v.p); c=-(w.x*net.vert[A].position.x+w.y*net.vert[A].position.y+w.z*net.vert[A].position.z); *z=-(w.x*x+w.y*y+c)/w.z; inWhichHex(x, y, &hx, &hy); hexy[hx+hy*hwidth]->altitudeCorection(x,y,z); //if ( hexy[hx+hy*hwidth]->isBarrier(x,y) ) return GUIMAP_BARRIER; return GUIMAP_OK; } else return GUIMAP_OUT; } int TguiMap::getGradient(float x, float y, TGrad *grad) { int A,B,C; P3F u,v; // A,B,C jsou indexy vrcholu trojuhelnika ve kterem lezi [x,y] if ( net.triangle(x, y, &A, &B, &C) ){ // u = C - A CopyV3(u.p, net.vert[C].position.p); SubV3(u.p, net.vert[A].position.p); // v = B - A CopyV3(v.p, net.vert[B].position.p); SubV3(v.p, net.vert[A].position.p); // dz = u x v VectMulV3(grad->dz.p, u.p, v.p); // dx = dz x (0, 1, 0) SETP3(grad->dx, -grad->dz.z, 0, grad->dz.x ); // dy = dz x (1, 0, 0) SETP3(grad->dy, 0, grad->dz.z, -grad->dz.y ); // spravna orientace if (grad->dx.x < 0) MulV3(grad->dx.p, (-1)); if (grad->dy.y < 0) MulV3(grad->dy.p, (-1)); if (grad->dz.z < 0) MulV3(grad->dz.p, (-1)); return 1; } else return 0; } void TguiMap::hexCentre(P3F *p3f, int index) { INDEX2D ind = net.middle(index/hwidth,index%hwidth); CopyV3(p3f->p,net.vert[ind.x+ind.y*net.bodX].position.p); } //////////////////////////////////////////////////////////////////////////////////////////// // kreslici funkce //////////////////////////////////////////////////////////////////////////////////////////// #define LINE_MAX_X_LENGTH 10.0f #define LINE_MAX_Y_LENGTH 10.0f #define LINE_ALT 1.0f void TguiMap::drawLine(float x1, float y1, float x2, float y2) { float x, y, z, t; glBegin(GL_LINE_STRIP); int segments = MAX ( (int)(myabs(x1-x2) / LINE_MAX_X_LENGTH),(int)(myabs(y1-y2) / LINE_MAX_Y_LENGTH) ); if (segments < 1) segments = 1; for (int i = 0; i < segments+1; i++){ t = i / (float)segments; x = t * x1 + (1-t) * x2; y = t * y1 + (1-t) * y2; if (altitude(x, y, &z) == GUIMAP_OUT) z = basicLineAltitude; glVertex3f(x, y, z+LINE_ALT); } glEnd(); } void TguiMap::drawCircle(float x, float y, float r, int segments) { P2F first, last; float arg; // if ( altitude(x, y, &basicLineAltitude) == GUIMAP_OUT) return; // glDisable(GL_LIGHTING); arg = 2 * float(M_PI) * (segments-1) / (float)segments; first.x = r * cos(arg) + x; first.y = r * sin(arg) + y; for (int i = 0; i < segments; i++) { arg = 2 * float(M_PI) * i / (float)segments; last.x = r * cos(arg) + x; last.y = r * sin(arg) + y; drawLine(first.x,first.y,last.x,last.y); first.x = last.x; first.y = last.y; } glEnable(GL_LIGHTING); } void TguiMap::drawFilledCircle(float x, float y, float r, int segments){ P2F last; float arg; glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glBegin(GL_POLYGON); if ( altitude(x, y, &basicLineAltitude) == GUIMAP_OUT) { glEnable(GL_LIGHTING); return; } arg = 2 * float(M_PI) * (segments-1) / (float)segments; for (int i = 0; i < segments; i++) { arg = 2 * float(M_PI) * i / (float)segments; last.x = r * cos(arg) + x; last.y = r * sin(arg) + y; float z; if (altitude(last.x, last.y, &z) == GUIMAP_OUT) z = basicLineAltitude; glVertex3f(last.x, last.y, z+LINE_ALT); } glEnd(); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); } //////////////////////////////////////////////////////////////////////////////////////////// // inicializace //////////////////////////////////////////////////////////////////////////////////////////// TguiMap::TguiMap(int _x, int _y, int _width, int _height) : TScene(_x, _y, _width, _height) { /* parametry TActiveObject */ active = AO_ACTIVE; x = _x; y = _y; width = _width; height = _height; hexy = NULL; skc = NULL; maincam = NULL; movcam = NULL; camctrl = NULL; cm = NULL; ep = NULL; setBounds(LOW_NODE_HEIGHT, HIGH_NODE_HEIGHT, 3 * HEX_EDGE_LENGTH); } void TguiMap::initModels() { int i, j, ind; //data z worldu World::MAP * map = getWorldMap(); World::TLivingUnitsContainer* luc = getWorldLivingUnits(); World::TLivingBuildingsContainer* lbc = getWorldLivingBuildings(); World::TKingdomsContainer* kds = getKingdoms(); //zamknout // zjistim z Wordu vysky a rozmery hwidth = map->width; hheight = map->height; hexycount = hwidth * hheight; // vytvoreni modelu hexu terenu + textury hexy = (PHex*)KMemAlloc(sizeof(PHex) * hexycount); net.init(*map); net.applyLevel(); net.compNormals(); //vodni vrstva TModelSceneObject **waterso = (TModelSceneObject **)KMemAlloc(sizeof(TModelSceneObject *) * hexycount); TModel **watermodel = (TModel **)KMemAlloc(sizeof(TModel *) * hexycount); for (i = 0; i < hexycount; i++){ waterso[i] = NULL; watermodel[i] = NULL; } //nasekani vody na modely for (i = 0; i < hheight; i++){ for (j = 0; j < hwidth; j++){ ind = getHexIndex(j, i);; // pridam vodu TModel *water = net.waterModel(i, j); if (water != NULL) { TModelSceneObject *so = new TModelSceneObject(water); so->transparent = true; so->iPriorityOfSelection = 0; so->selectable = false; addObject(so); so->tag2 = TAG2_TERRAINLIKE; int index = getHexIndex(j, i); waterso[index] = so; watermodel[index] = water; } } // for j } // for i net.applyTeren(); net.compNormals(); //nasekani terenu na modely a umisteni do hexu for (i = 0; i < hheight; i++){ for (j = 0; j < hwidth; j++){ ind = getHexIndex(j, i); // vytvorim model hexu podle site bodu hexy[ind] = new THex( ind, net.model(i,j), this); if ( (i < MAP_BOUND_Y) || (i >= hheight - MAP_BOUND_Y) || (j < MAP_BOUND_X) || (j >= hwidth - MAP_BOUND_X) ) hexy[ind]->selectable = false; //HRANICE //indexy sousednich hexu int N = HN(ind, hwidth); int S = HS(ind, hwidth); int NW = HNW(ind, hwidth); int NE = HNE(ind, hwidth); int SW = HSW(ind, hwidth); int SE = HSE(ind, hwidth); #define VALID(x,y) ((0<(y))&&((y) hranicini flag int border_flag = 0; if( VALID(j,i+2) && map->hexes[N]->kingdom!=map->hexes[ind]->kingdom ) border_flag |= 1; if( VALID(j+1,i+1) && map->hexes[NE]->kingdom!=map->hexes[ind]->kingdom ) border_flag |= 2; if( VALID(j+1,i-1) && map->hexes[SE]->kingdom!=map->hexes[ind]->kingdom ) border_flag |= 4; if( VALID(j,i-1) && map->hexes[S]->kingdom!=map->hexes[ind]->kingdom ) border_flag |= 8; if( VALID(j,i-1) && map->hexes[SW]->kingdom!=map->hexes[ind]->kingdom ) border_flag |= 16; if( VALID(j,i+1) && map->hexes[NW]->kingdom!=map->hexes[ind]->kingdom ) border_flag |= 32; //vlastnik a kralovstvi int kingdom = map->hexes[ind]->kingdom; hexy[ind]->kingdom = kingdom; int player; //kralostvi bud vlastni hrac, nebo nikdo if(kingdom) player = (*kds)[kingdom]->data().roleid; else player = 0; hexy[ind]->owner = player; //vytvoreni hranice hexy[ind]->border_flag = border_flag; hexy[ind]->createBorders(); // pridam model hexu do sceny addObject(hexy[ind]); hexy[ind]->tag2 = TAG2_TERRAINLIKE; hexy[ind]->waterso = waterso[ind]; hexy[ind]->watermodel = watermodel[ind]; } // for j } // for i KMemFree(waterso); KMemFree(watermodel); //umisteni stromu a jednotek for (i = 0; i < hheight; i++){ //posilani zprav do loading screen float progress = i/(float)hheight; KSendGlobalMsg(MSG_MAPLOADING_PROGRESS, ANNONYMOUS, MOD_GUI, *((PARAM*)&progress) ); for (j = 0; j < hwidth; j++) { ind = getHexIndex(j, i);; HEX *worldhex = map->hexes[ind]; // umisti modely terenu switch (worldhex->terrain) { case TT_FOREST: hexy[getHexIndex(j, i)]->addProxy( new TTerrainForest(this, j, i) ); break; case TT_DEEP_FOREST: hexy[getHexIndex(j, i)]->addProxy( new TTerrainDeepForest(this, j, i) ); break; case TT_ROCKS: hexy[getHexIndex(j, i)]->addProxy( new TTerrainRocks(this, j, i) ); break; case TT_SWAMP: hexy[getHexIndex(j, i)]->addProxy( new TTerrainSwamp(this, j, i) ); break; case TT_TOWN: hexy[getHexIndex(j, i)]->addProxy( new TTerrainTown(this, j, i) ); break; } if( worldhex->building ) { World::LIVING_BUILDING* lb = &((*lbc)[worldhex->building]->data()); TBuilding::installBuilding(this, worldhex->building, lb, ind); } //umisti modely jednotek if( worldhex->unit ) { World::LIVING_UNIT* lu = &((*luc)[worldhex->unit]->data()); TUnit::installUnit(this, worldhex->unit, lu, j, i); } } // for j } // for i // rozmery sceny rwidth = (net.ddx*net.bodX-0.01f) - (net.ddx*(net.dvenan/2)+0.01f) + 1; rheight = (net.ddy*(net.bodY-net.dvenan/2)-0.01f) - (net.ddy*(net.dvenan/2)+0.01f) + 1; //odemknout } void TguiMap::init() { /* inicializace sceny a QuadTree */ TScene::init(); setBounds(LOW_NODE_HEIGHT, HIGH_NODE_HEIGHT, 3 * HEX_EDGE_LENGTH); /* inicializace vyberu */ TSelection::initSelection(); /* inicializace control manageru */ cm = new TMapControllerManager(); /* inicializuj casticove systemy */ TEffectEngine::initEffectEngine(this, cm); /* inicializace terenu */ TTerrainEntity::initTerrains(); /* inicializace budov */ TBuilding::initBuildings(); /* inicializace jednotek */ TUnit::initUnits(); /* steering */ skc = NULL; #ifdef STEERING skc = new TSteeringKernelController(); cm->addController( skc ); #endif /* vytvor kameru */ maincam = new TMainCamera(this); debugcam = new TMainCamera(this); /* vytvori a umisti modely */ initModels(); /* vyrob strukturu pro rendering*/ TQuadNode::buildTree(); /* vyrob strukturu pro steering */ if(skc)skc->buildStructures(this); /* inicializace osvetleni */ TLightSource *sun = (TLightSource *) new TLightSource((KHANDLE)LIGHTSOURCE_SUN,(HWID)0); TScene::addLightSource(sun); SETP4(sun->p4fPosition,0.5f,0.5f,1,0); SETP4(sun->p4fAmbient,0.2f,0.2f,0.2f,1); SETP4(sun->p4fDiffuse,0.25f,0.25f,0.25f,1); SETP4(sun->p4fSpecular,0.2f,0.2f,0.2f,1); sun->iEnabled = 0; TLightSource *sun2 = (TLightSource *) new TLightSource((KHANDLE)LIGHTSOURCE_SUN,(HWID)2); TScene::addLightSource(sun2); CopyV4(sun2->p4fPosition.p, sun->p4fPosition.p); CopyV4(sun2->p4fAmbient.p, sun->p4fAmbient.p); CopyV4(sun2->p4fDiffuse.p, sun->p4fDiffuse.p); CopyV4(sun2->p4fSpecular.p, sun->p4fSpecular.p); MulV3(sun2->p4fAmbient.p, 0); MulV3(sun2->p4fDiffuse.p, 0.8f); MulV3(sun2->p4fSpecular.p, 0.8f); sun2->iEnabled = 0; TLightSource *sun3 = (TLightSource *) new TLightSource((KHANDLE)LIGHTSOURCE_SUN,(HWID)3); TScene::addLightSource(sun3); SETP4(sun3->p4fPosition,0.5f,0.5f,1,0); SETP4(sun3->p4fAmbient,0.1f,0.1f,0.2f,1); SETP4(sun3->p4fDiffuse,0.15f,0.15f,0.25f,1); SETP4(sun3->p4fSpecular,0.1f,0.1f,0.2f,1); MulV3(sun3->p4fAmbient.p, 0); MulV3(sun3->p4fDiffuse.p, 0.5f); MulV3(sun3->p4fSpecular.p, 0.5f); sun3->iEnabled = 0; /* mlha */ fog = new TSceneFog(FAR_CLIP-2*HEX_EDGE_LENGTH, FAR_CLIP, 0.1f); fog->setColor(DEFAULT_BACKGROUND_RGB, 1); /* inicializace a nastaveni hlavni kamery */ debugcam->setupPerspective(VIEW_ANGLE, ((float)width)/height, NEAR_CLIP, FAR_CLIP); debugcam->initCam(); maincam->setupPerspective(VIEW_ANGLE, ((float)width)/height, NEAR_CLIP, FAR_CLIP); maincam->initCam(); /* ovladani kamery */ cm->addController( camctrl = new TMainCameraController(cm, maincam) ); cm->addController( movcam = new TMovingCameraController( this, maincam ) ); /* nastaveni hlavni kamery */ setFocus(hwidth/2, hheight/2); /* weather controller */ World::TWeather* w = TguiMap::getWorldWeather(); wc = TWeatherController::installWeatherController(gui::TWeatherState(w->data().state)); /* zvuk */ if(TSoundInterface::si) cm->addController( new TSoundInterfaceController(maincam, TSoundInterface::si) ); /* prehravac udalosti */ cm->addController(ep = new TEventPlayer(this)); /* odkryvac mapy */ cm->addController(vs = new TVisibilityScheduler(this)); } void TguiMap::done() { int i; /* smaz kameru */ delete maincam; if(debugcam)delete debugcam; /* zrus svetlo */ /* zrus snih */ /* zrus mlhu */ /* zrus scene graf */ TScene::destroyScene(); /* zrus modely */ for (i = 0; i < hexycount; i++){ //smaz hex delete hexy[i]; } /* uvolni sit */ net.done(); /* zrus vesak na hexy */ KMemFree(hexy); /* zrus vesak na jednotky a budovy*/ guimap_units.clear(); guimap_buildings.clear(); /* zrus knihovnu jednotek */ TUnit::freeUnits(); /* zrus knihovnu budov */ TBuilding::freeBuildings(); /* zrus generatory terenu */ TTerrainEntity::freeTerrains(); /* zrus casticove systemy */ TEffectEngine::destroyEffectEngine(); /* zrus cm a VSECHNY kontrolery*/ delete cm; /* vzrus vyber */ TSelection::destroySelection(); } //////////////////////////////////////////////////////////////////////////////////////////// // vykresleni & vstup //////////////////////////////////////////////////////////////////////////////////////////// void drawCam(TCamera* cam) { TFrustum fr; cam->getFrustum(&fr); glLineWidth(8); glBegin(GL_LINE_STRIP); glColor4f(1,0,1,1); TVector c(fr.pos); TVector lt(c+(TVector(fr.up)+TVector(fr.dir)+TVector(fr.left))*200); TVector rt(c+(TVector(fr.up)+TVector(fr.dir)+TVector(fr.right))*200); TVector lb(c+(TVector(fr.down)+TVector(fr.dir)+TVector(fr.left))*200); TVector rb(c+(TVector(fr.down)+TVector(fr.dir)+TVector(fr.right))*200); glVertex3f(c.x, c.y, c.z); glVertex3f(lt.x, lt.y, lt.z); glVertex3f(rt.x, rt.y, rt.z); glVertex3f(c.x, c.y, c.z); glVertex3f(rt.x, rt.y, rt.z); glVertex3f(rb.x, rb.y, rb.z); glVertex3f(c.x, c.y, c.z); glVertex3f(rb.x, rb.y, rb.z); glVertex3f(lb.x, lb.y, lb.z); glVertex3f(c.x, c.y, c.z); glVertex3f(lb.x, lb.y, lb.z); glVertex3f(lt.x, lt.y, lt.z); glEnd(); glLineWidth(1); } void dbgCam(TCamera* cam) { static wchar_t buff[80]; glDisable(GL_LIGHTING); glColor4f(1,1,1,1); snwprintf(buff, 80, L"pos %.1f %.1f %.1f", cam->p4fPos.x, cam->p4fPos.y, cam->p4fPos.z); DrawText(600,SCREEN_HEIGHT-35,buff); snwprintf(buff, 80, L"dir %.1f %.1f %.1f", cam->p4fDir.x, cam->p4fDir.y, cam->p4fDir.z); DrawText(600,SCREEN_HEIGHT-55,buff); snwprintf(buff, 80, L" up %.1f %.1f %.1f", cam->p4fUp.x, cam->p4fUp.y, cam->p4fUp.z); DrawText(600,SCREEN_HEIGHT-75,buff); } //=== neoficialni podpora shadow mappingu === #ifdef SHADOWMAPPING //Textura HWTID shadowMapTexture = 0; int shadowMapSize; //Matice MX4 lightProjectionMatrix; MX4 cameraProjectionMatrix; float white[]={1.0f,1.0f,1.0f,1}; float black[]={0.0f,0.0f,0.0f,1}; float grey[] ={0.2f,0.2f,0.2f,1}; void TguiMap::initShadowMapping() { //Initialise extgl if(extgl_Initialize()!=0) { printf("Unable to Initialise extgl\n"); } //Check for necessary extensions if(!extgl_Extensions.ARB_depth_texture || !extgl_Extensions.ARB_shadow) { printf("I require ARB_depth_texture and ARB_shadow extensionsn\n"); } // shadowMapSize = 512; //Load identity modelview glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //Shading states glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Depth states glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); //We use glScale when drawing the scene glEnable(GL_NORMALIZE); //Create the shadow map texture if(shadowMapTexture == 0) glGenTextures(1, &shadowMapTexture); glBindTexture(GL_TEXTURE_2D, shadowMapTexture); glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadowMapSize, shadowMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); //Use the color as the ambient and diffuse material glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); //White specular material color, shininess 16 glMaterialfv(GL_FRONT, GL_SPECULAR, white); glMaterialf(GL_FRONT, GL_SHININESS, 16.0f); //---- Calculate & save matrices ---- glPushMatrix(); //camproj glLoadIdentity(); gluPerspective(maincam->fViewAngle,maincam->fRatio,maincam->fNear,maincam->fFar); glGetFloatv(GL_MODELVIEW_MATRIX, cameraProjectionMatrix); //lightproj glLoadIdentity(); gluPerspective(VIEW_ANGLE, 1.0f, NEAR_CLIP, FAR_CLIP); glGetFloatv(GL_MODELVIEW_MATRIX, lightProjectionMatrix); glPopMatrix(); } void TguiMap::drawObject() { TFrustum fr; MX4 lightViewMatrix; MX4 cameraViewMatrix; maincam->getFrustum(&fr); fog->apply(); //uloz matice glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); //camproj glLoadIdentity(); gluLookAt(maincam->p4fPos.x,maincam->p4fPos.y,maincam->p4fPos.z, maincam->p4fDir.x+maincam->p4fPos.x,maincam->p4fDir.y+maincam->p4fPos.y,maincam->p4fDir.z+maincam->p4fPos.z, maincam->p4fUp.x,maincam->p4fUp.y,maincam->p4fUp.z); glGetFloatv(GL_MODELVIEW_MATRIX, cameraViewMatrix); //pozice kamery->pozice svetla P4F lightPosition; SETV4(lightPosition.p, maincam->p4fPos.x, maincam->p4fPos.y, maincam->p4fPos.z, 1); lightPosition.z+=800; //smer nahoru //svetlo glLoadIdentity(); gluLookAt(lightPosition.x+maincam->p4fDir.x, lightPosition.y+maincam->p4fDir.y, lightPosition.z, lightPosition.x+maincam->p4fDir.x, lightPosition.y+maincam->p4fDir.y, 0, 0,1,0); glGetFloatv(GL_MODELVIEW_MATRIX, lightViewMatrix); //1st pass - Z pohledu svetla //--------------------------- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadMatrixf(lightProjectionMatrix); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(lightViewMatrix); // viewport velikosti depth textury glViewport(0, 0, shadowMapSize, shadowMapSize); // stavy glEnable( GL_FOG ); glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); glShadeModel(GL_FLAT); glColorMask(0, 0, 0, 0); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); TQuadNode::drawObject(&fr); // Okopiruj vieport do depth textury glBindTexture(GL_TEXTURE_2D, shadowMapTexture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, shadowMapSize, shadowMapSize); // obnov stavy glCullFace(GL_BACK); glShadeModel(GL_SMOOTH); glColorMask(1, 1, 1, 1); //2nd pass - Z pohledu kamery //--------------------------- glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadMatrixf(cameraProjectionMatrix); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(cameraViewMatrix); // vlastnosti glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glDepthFunc(GL_LEQUAL); glViewport(x,SCREEN_HEIGHT-height-y,width,height); // nastav tmave svetlo glLightfv(GL_LIGHT0, GL_POSITION, lightPosition.p); glLightfv(GL_LIGHT0, GL_AMBIENT, grey); glLightfv(GL_LIGHT0, GL_DIFFUSE, grey); glLightfv(GL_LIGHT0, GL_SPECULAR, black); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); TQuadNode::drawObject(&fr); //3rd pass //--------- // nastav jasne svetlo glLightfv(GL_LIGHT0, GL_DIFFUSE, white); glLightfv(GL_LIGHT0, GL_SPECULAR, white); // vyrob matici z pohledu do textury static MX4 biasMatrix; SetMX4(biasMatrix, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0, 0.5f, 0.5f, 0.5f, 1.0f); MX4 textureMatrix; MX4 tmp; MulMatrixMX4(tmp,lightProjectionMatrix, biasMatrix); MulMatrixMX4(textureMatrix,lightViewMatrix,tmp); float fff; TransposeMX4(textureMatrix, fff); // nastav generovani glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv(GL_S, GL_EYE_PLANE, textureMatrix); glEnable(GL_TEXTURE_GEN_S); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv(GL_T, GL_EYE_PLANE, textureMatrix+4); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv(GL_R, GL_EYE_PLANE, textureMatrix+8); glEnable(GL_TEXTURE_GEN_R); glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv(GL_Q, GL_EYE_PLANE, textureMatrix+12); glEnable(GL_TEXTURE_GEN_Q); // pripoj depth texturu glBindTexture(GL_TEXTURE_2D, shadowMapTexture); glEnable(GL_TEXTURE_2D); // porovnavani v depthbufferu proti texture glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); // porovnavaci operace glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); // vysledek porovnavani glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); // zakaz vykreslovani podle alpha kanalu glAlphaFunc(GL_GEQUAL, 0.99f); glEnable(GL_ALPHA_TEST); TQuadNode::drawObject(&fr); //vypni generovani textur glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_GEN_R); glDisable(GL_TEXTURE_GEN_Q); glFinish(); //obnov stavy glDisable(GL_LIGHTING); glDisable(GL_ALPHA_TEST); glDisable(GL_CULL_FACE); glDisable( GL_FOG ); //obnov matice glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); //obnov viewport glViewport(0,0,SCREEN_WIDTH,SCREEN_HEIGHT); //ostatni cm->updateControlers(KTime()); dbgCam(maincam); #ifdef SHOW_FPS FPS(); #endif } #else //=== oficialni podpora jednoduchych stinu === #ifdef SIMPLE_SHADOWS void TguiMap::initShadowMapping() { } void TguiMap::drawObject() { if (active == AO_PASIVE) return; setupScene(); glEnable( GL_STENCIL_TEST ); glEnable( GL_CULL_FACE ); glEnable( GL_FOG ); fog->apply(); #ifdef DEBUG_SCENE TFrustum fr; maincam->setCam(); setupLights(); debugcam->getFrustum(&fr); TQuadNode::drawObject(&fr); //vykresli debug kameru drawCam(debugcam); #else //prvni pruchod drawScene(maincam); #endif #ifdef DEBUG_STEERING if(skc)skc->draw(); #endif //druhy pruchod - stinovy zbuffer TSimpleShadow::drawSecondPassShadows(); glDisable( GL_FOG ); //treti pruchod - stiny TSimpleShadow::drawThirdPassShadows(); TSimpleShadow::shadows.clear(); glDisable( GL_CULL_FACE ); glDisable( GL_STENCIL_TEST ); resetScene(); //update kontroleru cm->updateControlers(KTime()); #ifdef SHOW_FPS FPS(); #endif } //=== oficialni nepodpora stinu === #else void TguiMap::initShadowMapping() { } //optimalizovana verze pro jednoduche vykreslovani void TguiMap::drawObject() { if (active == AO_PASIVE) return; //--------------- //matice glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); //vlastnosti glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glDepthFunc(GL_LEQUAL); glEnable( GL_CULL_FACE ); glEnable( GL_FOG ); //vyrez active objectu glViewport(x,SCREEN_HEIGHT-height-y,width,height); //--------------- fog->apply(); TFrustum f; maincam->setCam(); setupLights(); maincam->getFrustum(&f); TQuadNode::drawObject(&f); //--------------- //cela obrazovka glViewport(0,0,SCREEN_WIDTH,SCREEN_HEIGHT); //vlastnosti glDisable( GL_FOG ); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); glDepthFunc(GL_ALWAYS); glDisable( GL_CULL_FACE ); //matice glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); //--------------- //update kontroleru cm->updateControlers(KTime()); #ifdef SHOW_FPS FPS(); #endif } #endif//ifdef simple shadows #endif//ifdef shadowmapping int TguiMap::workInput(INPUT *input) { TButton::workInput(input); if CLICKED(this) onClick(input); onMouseOver(input); //update vstupu cm->updateInput(input); if (input->type != INPUT_NO) cm->updateControlers(KTime()); return 0; } inline void TguiMap::onMouseOver(INPUT *input) { TSceneObject *mso = NULL; TRay ray; float t; static TSceneObject *msoold=NULL; TFrustum fr; // if (TaoKernel::aoKernel->cursor->wait) { TSelection::sel->preunselect(); delHelp(); return; } //nad mapou if ((AO_MOUSEOVERME) && (!TaoKernel::aoKernel->ao_worked)) { CopyV4toV3(ray.start.p, maincam->p4fPos.p); maincam->getFrustum(&fr); CopyV3(ray.dir.p, fr.dir.p); MulV3(fr.down.p, ((input->mousepos.y-y-height/2.0f)/(height/2.0f)) ); MulV3(fr.right.p, ((input->mousepos.x-x-width/2.0f)/(width/2.0f)) ); AddV3(ray.dir.p, fr.down.p); AddV3(ray.dir.p, fr.right.p); NormalizeV3(ray.dir.p); if (Collision(&ray, &t, &mso)) { mso->onMouseOver(); } else { TSelection::sel->preunselect(); delHelp(); } } //mimo else { TSelection::sel->preunselect(); delHelp(); } } inline void TguiMap::onClick(INPUT *input) { // printf("TguiMap::onClick\n");//!!DBG!! TSceneObject *mso = NULL; TRay ray; float t; static TSceneObject *msoold=NULL; TFrustum fr; // if AO_MOUSEOVERME { // printf("TguiMap::onClick.AO_MOUSEOVERME\n");//!!DBG!! CopyV4toV3(ray.start.p, maincam->p4fPos.p); maincam->getFrustum(&fr); CopyV3(ray.dir.p, fr.dir.p); MulV3(fr.down.p, ((input->mousepos.y-y-height/2.0f)/(height/2.0f)) ); MulV3(fr.right.p, ((input->mousepos.x-x-width/2.0f)/(width/2.0f)) ); AddV3(ray.dir.p, fr.down.p); AddV3(ray.dir.p, fr.right.p); NormalizeV3(ray.dir.p); if (Collision(&ray, &t, &mso)){ // printf("TguiMap::onClick.Collision\n");//!!DBG!! if (mso) mso->onClick(); } } } //////////////////////////////////////////////////////////////////////////////////////////// // controll manager //////////////////////////////////////////////////////////////////////////////////////////// TMapControllerManager* TguiMap::getCM(){ return cm; } //////////////////////////////////////////////////////////////////////////////////////////// // kamera //////////////////////////////////////////////////////////////////////////////////////////// TCamera* TguiMap::getCam(){ return maincam; } void TguiMap::freeFlight(){ movcam->freeFlight(); } void TguiMap::cancelFreeFlight(){ movcam->cancelFreeFlight(); } int TguiMap::focus(float x, float y){ P3F f; f.x=x; f.y=y; altitude(x, y, &(f.z) ); // return movcam->focusTo(&f, 1); } int TguiMap::setFocus(int x, int y) { if ( (x < 0) || (y < 0) || (x >= hwidth) || (y >= hheight) ) return 0; // P3F p3f; hexCentre(&p3f, getHexIndex(x, y)); maincam->setCentre(p3f.x, p3f.y); // return 1; } int TguiMap::setFocus(int indx){ int x,y; getHexCoords(indx, &x, &y); return setFocus(x, y); } void TguiMap::syncDbgCam(){ //debugcam <= maincam; MX4 mx4; maincam->getPositionMX4(mx4); debugcam->setPositionMX4(mx4); } //////////////////////////////////////////////////////////////////////////////////////////// // viditelnost //////////////////////////////////////////////////////////////////////////////////////////// void TguiMap::updateHex(int hindex, World::VISIBILITY visibility) { int x, y; bool border = false; getHexCoords(hindex, &x, &y); if ((x < MAP_BOUND_X) || (y < MAP_BOUND_Y) || (x >= hwidth - MAP_BOUND_X) || (y >= hheight - MAP_BOUND_Y) ) { hexy[hindex]->setFade( FADE_2 ); } else { switch (visibility) { case VI_IN_SIGHT: hexy[hindex]->setFade( FADE_0 ); break; case VI_SEEN: hexy[hindex]->setFade( FADE_1 ); break; case VI_NEVER_SEEN: hexy[hindex]->setFade( FADE_3 ); break; } } } void TguiMap::updateVisibility(int playerid) { int x, y; int index; World::TVisibilityMapsContainer *visibility_maps; World::TVisibilityMap *vmap; World::VISIBILITY visibility; ((TGame*)TGUI::gui_inst->game)->getWorldVisibility(&visibility_maps); vmap = (*visibility_maps)[playerid]; for (x = 0; x < hwidth; x++) { for (y = 0; y < hheight; y++) { visibility = vmap->getHexAt(x, y).getVisibility(); index = getHexIndex(x, y); updateHex(index, visibility); }//for }//for } void TguiMap::updateVisibility(int playerid, TIntContainer *shown, TIntContainer *hidden) { TIntContainer::iterator it; World::TVisibilityMapsContainer *visibility_maps; World::TVisibilityMap *vmap; ((TGame*)TGUI::gui_inst->game)->getWorldVisibility(&visibility_maps); vmap = (*visibility_maps)[playerid]; if(hidden){ it = hidden->begin(); while ( it != hidden->end() ) { updateHex((*it), VI_SEEN); // history = &vmap->getHexById((*it)).getHistory(); // newVirtualBuilding((*it), history->data().building); it++; }//while } if(shown) { it = shown->begin(); while ( it != shown->end() ) { // deleteVirtualBuilding((*it)); updateHex((*it), VI_IN_SIGHT); it++; }//while } } void TguiMap::reinstalObject(TSceneObject *so) { int hx, hy; P3F pos; so->getPosition(&pos); if (inWhichHex(pos.x, pos.y, &hx, &hy)) { so->tag = getHexIndex(hx, hy); } TScene::reinstalObject(so); } void TguiMap::addObject(TSceneObject *so) { int hx, hy; P3F pos; so->getPosition(&pos); if (inWhichHex(pos.x, pos.y, &hx, &hy)) { so->tag = getHexIndex(hx, hy); } TScene::addObject(so); } int TguiMap::getFadeFromTag(int tag, int tag2) { int _fade; if ((tag >= 0) && (tag < hexycount)) { _fade = hexy[tag]->fade; if (_fade >= FADE_3) return FADE_4; if (_fade == FADE_0) return FADE_0; if (tag2 == TAG2_UNITLIKE) return FADE_4; return _fade; } return FADE_0; } }//namespace /******************************************************************************/