3. Vseobecne ciary

   Viete, co je to linearny interpolator ? Pekne odborne to znie, vsak ? (Pre niektorych mozno aj odporne...) A pritom sa nejedna o nic ineho, ako spojenie dvoch bodov "vzdusnou" ciarou. Pokial mate na papieri zadane dva body (A a B), po ruke pravitko a nejake zapisovacie zariadenie (to ako ceruzku), tak nie je ziadny problem - prelozite pravitko cez obidva body a nakreslite ciaru.
   Avsak tato jednoduchost razom pominie, ked to chcete naprogramovat do pocitaca. V tom pripade ciara medzi bodmi A a B vznikne tak, ze vykreslite postupne vsetky body nachadzajuce sa na spojnici bodov A a B. Ale ako vypocitat, ktore body to vlastne mame vykreslit ?
   V romke ZX Spektra, medzi obsluznymi rutinkami prikazu DRAW, sa nachadza takyto linearny interpolator, ktory dokaze vypocitat suradnice bodov, ktore treba vykreslit na spojnici dvoch zadanych bodov. Rutinka tohto interpolatora sa nachadza na adrese #24B7 a samotny vypocet suradnic bodov robi pomerne efektivne, takze keby sme ju doplnili nasou rutinkou "bod" z minulej casti a spravili nejake kozmeticke upravy pri odovzdavani parametrov, ziskali by sme velmi rychlu a efektivnu rutinku na kreslenie vseobecnych ciar. A problem mame vyrieseny a mozeme to pre dnesok zabalit...

   Dufam, ze ste moje predchadzajuce slova nezobrali celkom vazne. Teda nie ze by neboli pravdive, to nie, ale... Spravne tusite, ze este ani zdaleka nie je koniec tejto casti. Skusim vam do hlavy nasadit takeho malickeho chrobaka. Vo vyssie spominanej rutinke sa vzdy najprv pocitaju suradnice bodu, a potom z tychto suradnic sa pocita adresa vo videoramke a maska bodu a nakoniec sa podla tejto adresy a masky vykresli samotny bod. Nedalo by sa ten linearny interpolator upravit nejak tak, aby nepocital suradnice bodov, ale priamo adresu a masku ? Potom by sme mohli vyuzit to minule spomenute sialene 7 taktove vykreslenie bodu jedinou instrukciou...
   Podme si situaciu trosku rozanalyzovat. Interpolator pocita jednotlive body tak, ze v kazdom kroku svojej cinnosti vezme bod vypocitany v minulom kroku a urcitymi matematickymi postupmi urci v akej polohe voci nemu sa nachadza dalsi vykreslovany bod - ci je nad nim, pod nim, vedla neho vpravo, vlavo, pripadne kombinacia tychto poloh (vpravo nad nim, vlavo pod nim, atd...). Dajme tomu, ze pozname adresu a masku pre bod vypocitany v minulom kroku a ideme urcovat adresu a masku pre dalsi bod na zaklade informacii ktore nam poskytne interpolator.
   Ak sa novy bod nachadza sikmo od stareho, mozno vypocet jeho polohy rozlozit na dva vypocty typu hore-dole, nalavo-napravo. Vypocet v pripade ak sa novy bod nachadza presne pod povodnym uz mame hotovy - je to presne nasa uz dobre znama rutinka "dole". Vypocet do strany (nalavo alebo napravo) sa spravi jednoducho rotaciou masky pre bajt a ak nahodou rotacia "pretecie" (nahoda je blbec) tak sa este adresa zmeni o jednotku. Nech HL je adresa a A je maska:

left rlca  right rrca  
 jr nc,llll       jr nc,rrrr 
 dec  inc 
llll ...  rrrr ...  

   Ale co v pripade, ked je novy bod nad povodnym ? Urcite by nebol problem napisat rutinku "hore" ktora by bola v podstate analogicka s rutinou "dole", ale ja vam ponukam ine, ovela zaujimavejsie riesenie: akonahle by sa vyskytla potreba pri kresleni ciary pouzit rutinku "hore", tak jednoducho navzajom vymenime suradnice oboch krajnych bodov a namiesto "hore" budeme potrebovat len "dole". Logicky sme spravili to, ze problem posunu adresy hore sme previedli na problem posunu adresy dole. Fyzicky sme vlastne spravili akurat to, ze interpolator bude kreslit ciaru vzdy zhora nadol.
   Nasa rutinka interpolatora sa vola "line" a na vstupe ocakava suradnice dvoch bodov v registroch BC a DE: prvy bod X=C,Y=B a druhy X=E,Y=D. Rutinka si najprv prehodi suradnice bodov tak, aby ciaru kreslila vzdy zhora nadol, potom si zisti, ci bude kreslit ciaru zlava doprava alebo zprava dolava a podla toho si nastavi rotaciu masky a pripadny inkrement/dekrement adresy. Potom si podla predpocitanej tabulky z minulej casti vypocita adresu a masku prveho vykreslovaneho bodu, este sa rozhodne ci sa bude viackrat posuvat do strany alebo dole (ludsky povedane, ci ciara bude "vodorovnejsia" alebo "zvislejsia") a nakoniec sa priamo vrhne na vypocet a vykreslovanie vsetkych bodov leziacich na spojnici medzi dvomi zadanymi bodmi na vstupe.
   Ako obvykle, rutinka "run" ukazuje priklad pouzitia interpolatora a rutinka "over" urcuje sposob vykreslovania ciary (OVER 0 alebo OVER 1).

tabbod #6000 
   
run call mkbod 
 ld bc,#00 
 ld de,#bfff 
 call line 
 ld bc,#1525 
 ld de,#2343 
 call line 
 ld bc,#8142 
 ld de,#4767 
 jp line 
   
mkbod ... (ako minule) 
dole ... (ako minule) 
   
over rrca  
 sbc a,a 
 and #18 
 xor #b6 
 ld (lnov1),a 
 ld (lnov2),a 
 ld (bodset),a 
 ret  
   
line ld a,d 
 cp 
 jr nc,lnxch 
 ld d,b 
 ld b,a 
 ld a,e 
 ld e,c 
 ld c,a 
lnxch ld a,c 
 cp 
 sbc a,a 
 and #08 
 ld l,#2d 
 jr z,#01 
 dec 
 inc 
 ld (rot1+1),a 
 ld (rot2+1),a 
 ld a,l 
 ld (deci1),a 
 ld (deci2),a 
   
 ld a,d 
 sub 
 ld d,a 
 ld a,e 
 sub 
 ld e,a 
 jr nc,#03 
 neg  
 ld e,a 
   
hitab >tabbod 
lnbod ld h,hitab+3 
 ld l,c 
 ld c,(hl) 
 dec 
 ld a,(hl) 
 dec 
 ld l,b 
 or (hl) 
 dec 
 ld h,(hl) 
 ld l,a 
   
 ld a,e 
 cp 
 jr nc,lnaaa 
   
 ld b,d 
 inc 
 ld a,e 
 sub 
 ld e,a 
 xor 
 xor 
 rra  
   
lnn1 ex af,af 
 ld a,c 
lnov1 xor (hl) 
 ld (hl),a 
 inc 
 ld a,h 
 and #07 
 jr z,dolu1 
hore1 ex af,af 
 add a,e 
 jr nc,ln11 
rot1 rrc 
 jr c,deci1 
 djnz lnn1 
 ret  
   
deci1 dec 
 djnz lnn1 
 ret  
   
ln11 add a,d 
 djnz lnn1 
 ret  
   
dolu1 ld a,#20 
 add a,l 
 ld l,a 
 jr c,hore1 
 ld a,#f8 
 add a,h 
 ld h,a 
 jp hore1 
   
lnaaa ld b,e 
 inc 
 ld a,e 
 sub 
 ld d,a 
 xor 
 xor 
 rra  
 ex af,af 
 jr hore2 
   
lnn2 ex af,af 
 inc 
 ld a,h 
 and #07 
 jr z,dole2 
hore2 ld a,c 
lnov2 xor (hl) 
 ld (hl),a 
rot2 rrc 
 jr c,deci2 
 ex af,af 
 sub 
 jr c,ln22 
 djnz lnn2 
 ret  
   
deci2 dec 
 ex af,af 
 sub 
 jr c,ln22 
 djnz lnn2 
 ret  
   
ln22 add a,e 
 ex af,af 
 djnz hore2 
 ret  
   
dole2 ld a,#20 
 add a,l 
 ld l,a 
 jr c,hore2 
 ld a,#f8 
 add a,h 
 ld h,a 
 jp hore2 

   Nabuduce si ukazeme, ako nakreslit bod rychlejsie ako za jeden jediny takt hodin procesora !

Vas Busy.

Nazad / back , predchadzajuca a dalsia lekcia