/******************************** * Příklad na dvourozměrné vlny * * Napsal Bulb roku 1997 * ********************************/ /* Tento zdrojový kód byl psán a testován v kompilátoru * * DJGPP v2. Nicméně jsem se snažil napsat jej tak, aby * * neobsahoval žádné systémově či kompilátorově specifické * * funkce, takže by mělo být možné jej přeložit libovolným * * kompilátorem pod podmínkou, že si pro tento kompilátor * * napíšete vlastní I/O rutiny, jejichž verze pro DJGPP v2 * * a TURBO C přikládám ve dvou variantách souboru xmisc.if */ #include<conio.h> /* testování klávesnice pomocí kbhit/getch */ #include"xmisc.if" /* Bulbovy příkladové I/O funkce */ #define IDIM 100 /* 200 / 2 (y) */ #define JDIM 160 /* 320 / 2 (x) */ #define ROWS 200 #define COLS 320 /* pozn: není to izotropní -> bude to vypadat divně */ int main(void) { fixed p[IDIM*JDIM]; /* pole okamžitých výchylek */ fixed v[IDIM*JDIM]; /* pole rychlostí (1. derivace) */ long pavg=0, vavg=0; /* proměnné pro průměrování */ #ifndef __GNUC__ /* GNU C podporuje 64-bitové integery */ long long tmp; long long psum=0, vsum=0; /* pomocné proměnné pro průměrování - DJGPP */ #else /* V ostatních případech se použije pomalejší přetypování na double */ double tmp; double psum=0, vsum=0; /* pomocné proměnné pro průměrování - TC/BC */ #endif long i=0, j=0, k=0; /* pomocné proměnné */ for(i = 0; i < IDIM*JDIM; i++) {p[i] = 0; v[i] = 0;}; /* počáteční podmínky */ while(kbhit()) getch(); x_set_mcga(); /* nastav MCGA mode (13h) */ for(i = 0, j = 32; i < 32; i++, j++) /* nastav paletu 0 - 31 */ x_mcga_set_color(i, 0, j, 63); for(i = 32, j = 1; i < 95; i++, j++) /* nastav paletu 32 - 94 */ x_mcga_set_color(i, j, 63, 63); for(i = 95; i < 161; i++) /* nastav paletu 95 - 160 */ x_mcga_set_color(i, 31, 31, 31); for(i = 161, j = 0; i < 225; i++, j++) /* nastav paletu 161 - 224 */ x_mcga_set_color(i, 0, 0, j); for(i = 225, j = 1; i < 256; i++, j++) /* nastav paletu 225 - 255 */ x_mcga_set_color(i, 0, j, 63); for(k = 0; !kbhit(); k++) { /* začátek výpočetní smyčky */ vsum = 0; /* nulování sčítacích proměnných */ psum = 0; for(i = JDIM; i < JDIM * (IDIM - 1); i += JDIM) { for(j = i + 1; j < i + JDIM - 1; j++) { v[j] += ((p[j+1] + p[j-1] + p[j-JDIM] + p[j+JDIM]) >> 2) - p[j] - (v[j] >> 6) - vavg; /* V = 1/4, D = 1/64 */ vsum += v[j]; }; }; /* tady proběhl výpočet rychlosti. Ten cyklus je tak zběsilý, * aby se to potom nemuselo násobit */ tmp = vsum / ((IDIM - 2)*(JDIM - 2)); /* výpočet průměru */ vavg = tmp; /* z důvodu správného přetypování */ for(i = JDIM; i < JDIM * (IDIM - 1); i += JDIM) { for(j = i + 1; j < i + JDIM - 1; j++) { p[j] += v[j] - pavg; psum += p[j]; }; p[i] = p[i + 1]; /* okrajové prvky */ p[j] = p[j - 1]; }; /* stejně zběsilý cyklus pro výpočet výchylek */ tmp = psum / ((IDIM - 2)*(JDIM - 2)); /* výpočet průměru */ pavg = tmp; /* z důvodu správného přetypování */ for(i = 0, j = JDIM * (IDIM - 1); i < JDIM; i++, j++) { p[i] = p[i + JDIM]; /* zapsání volných okrajů */ p[j] = p[j - JDIM]; }; if(!(k & 0x3f)) { /* v určitých periodách (64 cyklů) */ i = (k & 0x80) ? (65*JDIM) : (35*JDIM); j = (k & 0x40) ? (105) : (55); /* dopadne do místa i, j */ #define LO 45 /* kapka vody (tohle jsou pomocné konstanty - hloubka) */ #define MD 75 #define MH 90 #define HI 100 p[i - (3*JDIM) + j - 1] -= LO * 65536; /* a tohle všechno... */ p[i - (3*JDIM) + j ] -= LO * 65536; p[i - (3*JDIM) + j + 1] -= LO * 65536; p[i - (2*JDIM) + j - 2] -= LO * 65536; p[i - (2*JDIM) + j - 1] -= MD * 65536; p[i - (2*JDIM) + j ] -= MD * 65536; p[i - (2*JDIM) + j + 1] -= MD * 65536; p[i - (2*JDIM) + j + 2] -= LO * 65536; p[i - (1*JDIM) + j - 3] -= LO * 65536; p[i - (1*JDIM) + j - 2] -= MD * 65536; p[i - (1*JDIM) + j - 1] -= MH * 65536; p[i - (1*JDIM) + j ] -= HI * 65536; p[i - (1*JDIM) + j + 1] -= MH * 65536; p[i - (1*JDIM) + j + 2] -= MD * 65536; p[i - (1*JDIM) + j + 3] -= LO * 65536; p[i + j - 3] -= LO * 65536; p[i + j - 2] -= MD * 65536; p[i + j - 1] -= HI * 65536; p[i + j ] -= HI * 65536; p[i + j + 1] -= HI * 65536; p[i + j + 2] -= MD * 65536; p[i + j + 3] -= LO * 65536; p[i + (1*JDIM) + j - 3] -= LO * 65536; p[i + (1*JDIM) + j - 2] -= MD * 65536; p[i + (1*JDIM) + j - 1] -= MH * 65536; p[i + (1*JDIM) + j ] -= HI * 65536; p[i + (1*JDIM) + j + 1] -= MH * 65536; p[i + (1*JDIM) + j + 2] -= MD * 65536; p[i + (1*JDIM) + j + 3] -= LO * 65536; p[i + (2*JDIM) + j - 2] -= LO * 65536; p[i + (2*JDIM) + j - 1] -= MD * 65536; p[i + (2*JDIM) + j ] -= MD * 65536; p[i + (2*JDIM) + j + 1] -= MD * 65536; p[i + (2*JDIM) + j + 2] -= LO * 65536; p[i + (3*JDIM) + j - 1] -= LO * 65536; p[i + (3*JDIM) + j ] -= LO * 65536; p[i + (3*JDIM) + j + 1] -= LO * 65536; /* je její popis */ }; /* x_mcga_vsync(); */ /* veritcal retrace synchronizace */ /* Rozhodl jsem se tady ten příkaz nechat jenom v kometnáři. Když * * jsem to totiž odlaďoval, tak to vypadalo následovně: Při turbu * * (Pentium 2x66MHz) téměř žádný rozdíl, bez turba (Pentium * * 2x50MHz) to s vsync běželo dvakrát pomalejc, protože to těsně * * nestíhalo za 1 snímek. Mimochodem, velmi paradoxní je, že když * * jsem tenhle příklad původně napsal s rozepsaným kódem * * putpixelu, tak to fachalo pomalejc, než když jsem tento kód * * přesunul do __INLINE__ funkce! */ for(i = 0; i < IDIM*JDIM; i += JDIM) { for(j = 0; j < JDIM; j++) { x_mcga_put_pixel((i<<2) + (j<<1), x_fixtoi(p[i+j])); x_mcga_put_pixel((i<<2) + 2*JDIM + (j<<1), x_fixtoi(p[i+j])); x_mcga_put_pixel((i<<2) + (j<<1) + 1, x_fixtoi(p[i+j])); x_mcga_put_pixel((i<<2) + 2*JDIM + (j<<1) + 1, x_fixtoi(p[i+j])); }; }; }; x_set_normalmode(); /* Nastavení normálního videomódu */ getch(); /* zrušení stisknuté klávesy ze zásobníku, nezpůsobí čekání, * protože kbhit() */ return 0; } výheň