dettagli - Amiga Magazine

dettagli - Amiga Magazine dettagli - Amiga Magazine

amigamagazine.info
from amigamagazine.info More from this publisher
08.11.2012 Views

Fig. 2 - Gli assi dello schermo. nale e sarà, quindi, necessario eseguire su esso una proie- zione prospettica dei punti tridimensionali. Come tutti hanno studiato sin dalle scuole medie, l'uso della prospettiva nel tracciamento di un'immagine fa in modo che gli oggetti più lontani, risultino più piccoli e contemporaneamente con- vergano verso il punto di fuga. Nel nostro caso, i punti non diminuiranno di dimensione, ma in base all'aumento della loro distanza convergeranno verso il punto di fuga, che corrisponde all'origine degli assi cartesiani. Questo nei computer equivale normalmente alle coordinate dello schermo XFO YFO, ossia nell'estremità in alto a sinistra, ma per migliorare l'effetto globale delle rappresentazioni tridimensionali (e il tracciamento di punti 3D è una di que- ste) conviene spesso traslare verso il centro l'origine degli assi. Inoltre, per semplificarsi la vita, è conveniente che l'osser- vatore non si trovi esattamente all'origine degli assi (0,0,0), ma sia leggermente traslato sull'asse Z di una costante che chiameremo zo@ In questo modo l'algebra risulta più sem- plice, e la proiezione viene centrata sullo schermo del computer. L'osservatore prende quindi le coordinate (O,O,zoff), dove zoff è negativo. in pratica, ogni stella (o punto) definita da tre coordinate Xp, Yp e Zp che la definiscono nello spazio 3D, per essere tracciata sullo schermo 2D, dovrà essere sottoposta a una semplice proiezione, che ricaverà due nuove coordinate Xs e Ys. Matematicamente, per una semplice similitudine fra triangoli, si ottiene nel modo che segue: Xs = (zoff * Xp) / (Zp + zoff) Ys = (zoff * Yp) / (Zp + zoff) Ora non resta che traslare le coordinate ottenute verso il centro dello schermo, sommando le due costanti di trasla- zione xoffe yo@ Per concludere, la proiezione completa di un punto 3D (Xp,Yp,Zp) in un spazio 2D (Xs, Ys) awiene quindi tramite le due seguenti formule: XS = xoff + [ (zoff * Xp) / (Zp + zoff) ] Ys = yoff + [ (zoff * Yp) / (zp + zoff) ] guaggio che più ci aggrada e cominciare a tracciare il numero di punti che desideriamo. Come già anticipato, in questa occasione abbiamo deciso di utilizzare il linguaggio assembly, per permettere anche ai possessori di macchine più lente di veder funzionare il proprio campo stellare, senza dover ricorrere a tecniche particolari di tracciamento, come per esempio il double- buffering, necessarie quando si lavora in C e specialmente in maniera system-friendly. Cominciamo quindi con il convertire le formule di proie- zione in una forma comprensibile per il nostro Arniga: Projection: ;Prende Xp e lo moltiplica per zoff m0ve.w Xp,DO muls #zoff ,DO ;Xp=Xp*zoff ;Prende Yp e lo moltiplica per zoff m0ve.w Yp,D1 muls #zoff ,D1 ;Yp=Yp*zoff ;Prende Zp e vi somma zoff m0ve.w Zp,D2 add.w #zoff,D2 ;Zp=Zp+zoff ;Se Zp è 0, evita la divisione beq SkipDivision ;Divide Xp e Yp per Zp divs D2,DO ; Xs=Xp/Zp divs D2,Dl ;Ys=Yp/Zp SkipDivision: ;Somma la traslazione a Xs e Ys add.w #xoff,DO ;Xs=Xs+xoff add.w #yoff,Dl ;Ys=Ys+yoff ;Memorizza le coordinate di schermo ;ottenute dalla proiezione m0ve.w D0,Xs m0ve.w D1,Ys rts Visto che questo compito sarà eseguito per un certo nume- ro di punti (difficilmente avremo una singola stella che va- ga nello spazio), per una serie di proiezioni, è conveniente utilizzare due tavole: la prima, composta da triplette di word, definisce i punti 3D; la seconda, costituita da coppie di word, in numero equivalente alle triplette già citate, con- tiene i risultati di ciascuna proiezione. Ipotizziamo per esempio di voler eseguire la proiezione delle coordinate di cinque stelle, definite nella tavola Tab3Q le coordinate proiettate, verranno depositate nella tavola Tab2D come si vede nel listato 1. Stampiamo i punti Dalla teoria alla pratica Fino a questo punto abbiamo lavorato esclusivamente sulle coordinate dei punti; è giunto finalmente il momento di Adesso che sappiamo come proiettare un punto 3D sullo iniziare a stamparli sullo schermo. Per il momento iniziereschermo, non resta che convertire la procedura nel lin- mo con un semplice schermo a due colori (1 bitplane) in

;Numero di stelle NUMSTARS EQU 5 ;Offset dei singoli elementi ;all'interno della tavola STAR-X EQU O STAR-Y EQU 2 STAR-Z EQU 4 STCSIZEOF EQU 6 Projection: ;Prende le due tavole e azzera il contatore moveq #O,D6 lea Tab3D,AO lea Tab2D,Al Loopl : m0ve.w STAR-X(AO,D6),DO muls #zof f ,DO ;Xp=Xp*zoff m0ve.w STAR_Y(AO,D6),Dl muls #zof f , D1 ;Yp=Yp*zoff m0ve.w STcZ(AO,D6),D2 add.w #zoff,D2 ;Zp=Zp+zoff beq SkipDivision divs D2,DO ; Xp=Xp/Zp divs D2,Dl ;Yp=Yp/Zp SkipDivision: add.w #xoff,DO ;Xs=Xs+xoff add.w #yoff ,D1 ;Ys=Ys+yoff ;~emorizza Xs e Ys nella tavola m0ve.w DO,(Al)+ m0ve.w Dl,(Al)+ ;Incrementa il contatore addq #STAR_SIZEOF,d6 ;Controlla il raggiungimento della fine ;della tavola cmp.w #STAR_SIZEOF*NUMSTARS,d6 blt Loopl rts ;X Y Z Tab3D: dc.w 2, 1,7 dc.w 1, 1,15 dc.w -2, 2,27 dc.w 1, 2,34 dc.w 1,-1,55 ; X Y Tab2D: 1 dc.w 0,O dc.w 0,O 1 dc.w 0,O dc.w 0,O dc.w 0,O Listato 1. modo da semplificare al massimo la routine di tracciamen- to dei pixel. In seguito sarà possibile potenziare la nostra procedura, per sfruttare più colori (e quindi bitplane), in modo da poter variare l'intensità dei pixel. I1 modo per costruire uno schermo tramite il Copper, è sta- to già ampiamente discusso su queste stesse pagine, e per- tanto daremo per scontato di avere uno schermo 320x256 pixel a due colori, già visualizzato e allocato a partire dalla locazione di memoria contenuta nel puntatore ScreenBuJ: Per esempio, se il nostro schermo viene allocato a partire dalla locazione $60000 (suggeriamo comunque di ricorrere alla funzione AllocMem di Exec) avremo 10.240 byte (10 kb di Chip RAM) a disposizione a partire da questo indiriz- zo, il quale sarà memorizzato in ScreenBuJ Una semplicissima routine di stampa di pixel, su uno schermo a due colori è la seguente. Essa prima stabilisce il byte dello schermo nel quale andrà stampato il punto e poi si awale di una tabella per la selezione del bit da accende- re all'interno del byte. Come la stessa routine di proiezione, anche questa procedura è altamente ottimizzabile tramite l'eliminazione delle istruzioni MUL e DN. In questa sede, per motivi di chiarezza, abbiamo preferito non utilizzare codice particolarmente ottimizzato (il quale, come noto, pregiudica la leggibilità). Prima di chiamare questa funzione (con un semplice JSR), bisogna immettere nei registri DO e D1 rispettivamente la coordinata X e Y, del pixel che intendiamo stampare, mentre in A0 va posto l'indirizzo del nostro schermo (per esempio $60000). Infine SCRW dovrà essere definito come la larghezza dello schermo su cui stampiamo (normalmente 320 pixel). SCRW EQU 320 SetPixel : m0ve.w DO,D2 and.w #7,D2 1sr.w #3,DO mulu #SCRW/8, D1 add.w D1,DO lea SP-Tab,Al m0ve.b (Al,DZ.W),Dl 0r.b Dl,(AO,DO.W) rts SP-Tab: dc.b 128,64,32,16,8,4,2,1 In questo modo, scandendo tutte le coppie di word della tavola dei punti già proiettati (Tab2D) e chiamando ogni volta la funzione SetPixel, impostando correttamente X e Y (DO e DI), sarà possibile tracciare nella posizione corrente tutte le stelle del nostro campo. Altrettanto importante è la possibilità di pulire i pixel trac- ciati ogni quadro video, prima di procedere alla stampa dei nuovi (nel caso in cui i punti cambino posizione di volta in volta). Visto che è del tutto controproducente azzerare ogni volta l'intera area di schermo (ben 10 kb!), prima di proce- dere al nuovo ciclo di proiezioni e di stampa, ma dopo l'at- tesa del tempo minimo di refresh (normalmente un quadro video), conviene eseguire un nuovo ciclo di scansione del- la tavola 2D (le coordinate proiettate) chiamando però la funzione ClearPixel, che in base alle coppie di coordinate X e Y fornite (esattamente le stesse che avevamo passato alla procedura SetPixel) provvederà a ripulire tutti i singoli punti stampati. È importante ricordare che in AO, deve sempre essere immesso l'indirizzo dello schermo, e che SCRWequivale alla larghezza dello stesso.

;Numero di stelle<br />

NUMSTARS EQU 5<br />

;Offset dei singoli elementi<br />

;all'interno della tavola<br />

STAR-X EQU O<br />

STAR-Y EQU 2<br />

STAR-Z EQU 4<br />

STCSIZEOF EQU 6<br />

Projection:<br />

;Prende le due tavole e azzera il contatore<br />

moveq #O,D6<br />

lea Tab3D,AO<br />

lea Tab2D,Al<br />

Loopl :<br />

m0ve.w STAR-X(AO,D6),DO<br />

muls #zof f ,DO ;Xp=Xp*zoff<br />

m0ve.w STAR_Y(AO,D6),Dl<br />

muls #zof f , D1 ;Yp=Yp*zoff<br />

m0ve.w STcZ(AO,D6),D2<br />

add.w #zoff,D2 ;Zp=Zp+zoff<br />

beq SkipDivision<br />

divs D2,DO ; Xp=Xp/Zp<br />

divs D2,Dl ;Yp=Yp/Zp<br />

SkipDivision:<br />

add.w #xoff,DO ;Xs=Xs+xoff<br />

add.w #yoff ,D1 ;Ys=Ys+yoff<br />

;~emorizza Xs e Ys nella tavola<br />

m0ve.w DO,(Al)+<br />

m0ve.w Dl,(Al)+<br />

;Incrementa il contatore<br />

addq #STAR_SIZEOF,d6<br />

;Controlla il raggiungimento della fine<br />

;della tavola<br />

cmp.w #STAR_SIZEOF*NUMSTARS,d6<br />

blt Loopl<br />

rts<br />

;X Y Z<br />

Tab3D:<br />

dc.w 2, 1,7<br />

dc.w 1, 1,15<br />

dc.w -2, 2,27<br />

dc.w 1, 2,34<br />

dc.w 1,-1,55<br />

; X Y<br />

Tab2D:<br />

1 dc.w 0,O<br />

dc.w 0,O<br />

1 dc.w 0,O<br />

dc.w 0,O<br />

dc.w 0,O<br />

Listato 1.<br />

modo da semplificare al massimo la routine di tracciamen-<br />

to dei pixel. In seguito sarà possibile potenziare la nostra<br />

procedura, per sfruttare più colori (e quindi bitplane), in<br />

modo da poter variare l'intensità dei pixel.<br />

I1 modo per costruire uno schermo tramite il Copper, è sta-<br />

to già ampiamente discusso su queste stesse pagine, e per-<br />

tanto daremo per scontato di avere uno schermo 320x256<br />

pixel a due colori, già visualizzato e allocato a partire dalla<br />

locazione di memoria contenuta nel puntatore ScreenBuJ:<br />

Per esempio, se il nostro schermo viene allocato a partire<br />

dalla locazione $60000 (suggeriamo comunque di ricorrere<br />

alla funzione AllocMem di Exec) avremo 10.240 byte (10<br />

kb di Chip RAM) a disposizione a partire da questo indiriz-<br />

zo, il quale sarà memorizzato in ScreenBuJ<br />

Una semplicissima routine di stampa di pixel, su uno<br />

schermo a due colori è la seguente. Essa prima stabilisce il<br />

byte dello schermo nel quale andrà stampato il punto e poi<br />

si awale di una tabella per la selezione del bit da accende-<br />

re all'interno del byte. Come la stessa routine di proiezione,<br />

anche questa procedura è altamente ottimizzabile tramite<br />

l'eliminazione delle istruzioni MUL e DN. In questa sede,<br />

per motivi di chiarezza, abbiamo preferito non utilizzare<br />

codice particolarmente ottimizzato (il quale, come noto,<br />

pregiudica la leggibilità).<br />

Prima di chiamare questa funzione (con un semplice JSR),<br />

bisogna immettere nei registri DO e D1 rispettivamente la<br />

coordinata X e Y, del pixel che intendiamo stampare,<br />

mentre in A0 va posto l'indirizzo del nostro schermo (per<br />

esempio $60000). Infine SCRW dovrà essere definito come<br />

la larghezza dello schermo su cui stampiamo (normalmente<br />

320 pixel).<br />

SCRW EQU 320<br />

SetPixel :<br />

m0ve.w DO,D2<br />

and.w #7,D2<br />

1sr.w #3,DO<br />

mulu #SCRW/8, D1<br />

add.w D1,DO<br />

lea SP-Tab,Al<br />

m0ve.b (Al,DZ.W),Dl<br />

0r.b Dl,(AO,DO.W)<br />

rts<br />

SP-Tab: dc.b 128,64,32,16,8,4,2,1<br />

In questo modo, scandendo tutte le coppie di word della<br />

tavola dei punti già proiettati (Tab2D) e chiamando ogni<br />

volta la funzione SetPixel, impostando correttamente X e Y<br />

(DO e DI), sarà possibile tracciare nella posizione corrente<br />

tutte le stelle del nostro campo.<br />

Altrettanto importante è la possibilità di pulire i pixel trac-<br />

ciati ogni quadro video, prima di procedere alla stampa dei<br />

nuovi (nel caso in cui i punti cambino posizione di volta in<br />

volta). Visto che è del tutto controproducente azzerare ogni<br />

volta l'intera area di schermo (ben 10 kb!), prima di proce-<br />

dere al nuovo ciclo di proiezioni e di stampa, ma dopo l'at-<br />

tesa del tempo minimo di refresh (normalmente un quadro<br />

video), conviene eseguire un nuovo ciclo di scansione del-<br />

la tavola 2D (le coordinate proiettate) chiamando però la<br />

funzione ClearPixel, che in base alle coppie di coordinate<br />

X e Y fornite (esattamente le stesse che avevamo passato<br />

alla procedura SetPixel) provvederà a ripulire tutti i singoli<br />

punti stampati. È importante ricordare che in AO, deve<br />

sempre essere immesso l'indirizzo dello schermo, e che<br />

SCRWequivale alla larghezza dello stesso.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!