.[ ČeskéHry.cz ].
Chytrý algoritmus pro renderování 2D izom. mapy?

 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> Obecné
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
Crypton



Založen: 14. 05. 2009
Příspěvky: 306
Bydliště: The Void

PříspěvekZaslal: 18. srpen 2010, 15:13:15    Předmět: Chytrý algoritmus pro renderování 2D izom. mapy? Odpovědět s citátem

Zdravím ve spolek,

potřeboval bych poradit s jedním problémem ohledně algoritmu pro renderování isometrické mapy, která je ve tvaru diamatu (né "staggered"), protože strýček Google mi nic neporadil, a na GameDev.net mi taky nikdo neporadil...

Viz můj příspěvek:
http://www.gamedev.net/community/forums/topic.asp?topic_id=578795

Jde o to že mám algoritmus pro renderovaní té mapy napsaný, jen je až nechutně pomalý (max 15FPS), protože renderuje 9 bloků mapy najednou, a já bych potřeboval zjistit které bloky viditelné a jaké dlaždice z nich vyrenderovat.

Mapa je rozdělena na několik menších bloků (kde jeden blok má 32x32 dlaždic), které se pak načítají během hraní (v novém vlákně), no a abych pokryl celou oblast, a všechny "rohy", musím načíst ty bloky do matice 3x3 bloků, kde kamera/hráč je uprostřed, tedy v bloku m[1][1]. Mimichodem, jeden ten blok je jako malá mapa, je tak rozsáhlý že se celý nevyrenderuje na obrazovku.

Tady je ten algoritmus:
kód:

int BLOCK_WIDTH = 32; // počet dlaždic v bloku
int BLOCK_HEIGHT = 32; // počet dlaždic v bloku

POINT cameraPos = getCameraPos();

for (int i = 0; i < 3; i++)
{
   for (int j = 0; j < 3; j++)
   {
      BLOCK block = blockMatrix[i][j];
      
      POINT blockPos = getBlockDrawPos(cameraPos, block);

      int xMin = 0;
      int xMax = BLOCK_WIDTH;
      int yMin = 0;
      int yMax = BLOCK_HEIGHT;
      
      for (int y = yMin; y < yMax; y++)
      {
         for (int x = xMin; x < xMax; x++)
         {
            POINT tilePos = getTileDrawPos(blockPos);
            if (isTileOffscreen(tilePos))
               continue;
            else renderTile(block.tileMap[y][x], tilePos);
         }
      }
   }
}


Mimichodem ten algoritmus není pomalý kvůli samotnému renderování (renderTile), ale kvůli renderovacímu algoritmu, protože většinu času tráví v těch cyklech toho algoritmu (viz. nahoře).

Napadlo mě že bych to zrychlil tak že bych zjistil xMin/xMax a yMin/yMax, jenže netuším jak...

Tady je obrázek jak má dlaždice vypadá:


A tady je obrázek jak vypadá ta izom. mapa ve tvaru diamantu:


Díky za jakékoliv odpovědi. Embarassed
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Quiark



Založen: 29. 07. 2007
Příspěvky: 816
Bydliště: Chlívek 401

PříspěvekZaslal: 18. srpen 2010, 17:58:14    Předmět: Odpovědět s citátem

Tak co mě jako prvního napadlo. Možná existuje nějaké standardní řešení, ale couž.

Potřebuješ zjistit, které dlaždice kreslit a které ne. Počítám, že jeden blok kreslíš po řádcích (viz zelené šipky na obrázku), takže pro každý takový řádek je třeba zjistit, která je první dlaždice vidět a která je poslední vidět a ostatní nekreslit.

První dlaždice ke kreslení je ta, která koliduje s horním nebo pravým okrajem obrazovky (pokud se to kreslí v pořadí co ukazují zelené šipky). To se dá zjistit tak, že provedeme výpočet kolize daného pruhu (=řádku) dlaždic s daným okrajem obrazovky. Konkrétně pro kolizi s horním okrajem použijeme spodní okraj pruhu dlaždic, pro pravý okraj obrazovky pak ten horní.

Ze vzorečku na výpočet průsečíku dvou přímek dostaneme mimo souřadnic průsečíku (které nepotřebujem) taky parametr t, neboli pozici na přímce okraje pruhu dlaždic. Tento parametr, pokud máme úsečku okraje dlaždic správně vyjádřenou, nabývá hodnot 0 až 1 a z počtu dlaždic na tom pruhu jde zjistit, do které dlaždice to spadlo.

Správně vyjádřená úsečka okraje dlaždic je, když její počátek je na jednom jejím okraji a směrový vektor má délku shodnou s délkou úsečky. Pokud nevíš, co to plácám, nastuduj si parametrické vyjádření přímky/úsečky (analytická geometrie pro střední školy).



Rekapitulace pojmů:
pruh dlaždic - to vpravo
obrazovka - to červené
horní okraj pruhu dlaždic - světle modrá úsečka na obrázku vpravo
spodní okraj pruhu dlaždic - žlutá úsečka ...

EDIT: ujasnění
_________________
Mám strach
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
pet



Založen: 11. 08. 2010
Příspěvky: 10

PříspěvekZaslal: 19. srpen 2010, 09:52:49    Předmět: Časy Odpovědět s citátem

Máš někde nějaký přehled časů, kolik trávíš v jednotlivých metodách? Když říkáš, že renderTile to neovlivňuje, jak vypadají getTileDrawPos a isTileOffscreen?

Jinak určitě by šlo přeskočit vícero dlaždic v okamžiku kdy jsi už část kreslil a najdenou ti vyjde, že dlaždice vidět není - nebudou vidět ani ty další v této řádce.

Podobně by šlo vypočítat pozici první dlaždice a poslední dlaždice v řádce a otestovat v jaké poloze leží vůči obrazovce - což vlastně pěkně popsal Quiark.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Crypton



Založen: 14. 05. 2009
Příspěvky: 306
Bydliště: The Void

PříspěvekZaslal: 19. srpen 2010, 17:50:45    Předmět: Odpovědět s citátem

Quiark:

Přesně moje situace, díky moc podrobné za vysvětlení, doufám že jsi ty obrázky nedělal jen kvůli mě Laughing Jinak už jsem to jakž takž pochopil, spíš je problém to implementovat, takže bych se chtěl zeptat jestli nemáš nějaký snippet a nebo nevíš o nějakém open-source projektu kde se vykresluje ve tvaru diamantu. (Na matiku mi to teď fakt nepálí Embarassed)

Totiž, počátek kamery je v mém případě uprostřed obrazovky, a né v pravém/levém horním rohu, jak jsem si všimnul u jiných projektů, k tomu pohyb kamery je po dlaždicích a né pixelech, takže funkce getCameraPos vrací absolutní lokaci kamery v dané mapě. Ještě bych možná měl zmínit že se s kamerou nemůžu pohybovat mimo mapu, tedy rozsah pohybu kamery je taky ve tvaru diamantu.

pet:
Testoval jsem to přes AMD CodeAnalyst, podle toho jsem zjistil že se nejvíce času tráví právě v těch cyklech. Je to totiž 9216 iterací, v každé se volá getTileDrawPos, která vlastně převede vypočítá kde se má ta dlaždice vykreslit, no a pak se funkcí isTileOffscreen zjistí zdali se má ta dlaždice vykreslit, podle toho jestli se nachází mimo obrazovku či ne.

Ať už smažu jakýkoliv řádek v tom posledním cyklu (např. renderTile), pořád je to pomalé, ale když smažu celý ten algoritmus tak FPS vyskočí na 1300+, což je asi logické, ale ten rozdíl je obrovský, na to že vykresluju zajím jen dlaždice.

Jinak díky za tipy a rady, kouknu se na to až se pořádně vyspím, jsem totiž asi hodně přepracovaný a nebo totálně blbý Laughing
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Quiark



Založen: 29. 07. 2007
Příspěvky: 816
Bydliště: Chlívek 401

PříspěvekZaslal: 19. srpen 2010, 18:54:18    Předmět: Odpovědět s citátem

Nouma napsal:
Testoval jsem to přes AMD CodeAnalyst, podle toho jsem zjistil že se nejvíce času tráví právě v těch cyklech. Je to totiž 9216 iterací, v každé se volá getTileDrawPos, která vlastně převede vypočítá kde se má ta dlaždice vykreslit, no a pak se funkcí isTileOffscreen zjistí zdali se má ta dlaždice vykreslit, podle toho jestli se nachází mimo obrazovku či ne.


No to znamená, že pro každou dlaždic (kterých je hodně) se znova a znova počítá její souřadnice a jestli je vidět. To je zbytečná práce navíc - když máš jednu dlaždici, stačí pro výpočet pozice další dlaždice jen přičíst velikost jedné dlaždice. Podobně pro zjištění viditelnosti, když už víš, že jsi vyjel za obrazovku, stačí prostě tenhle řádek skončit. Tohle je jednodušší optimalizace než to moje "úplné" řešení a mohlo by stačit.

Jinak žádný kód ani linky nemám, ale ty už to máš přece implementovaný, ne?
_________________
Mám strach
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> Obecné Časy uváděny v GMT + 1 hodina
Strana 1 z 1

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna