Viene usato quando una faccia esce dalla zona visibile dello screen. Con questa routine e' possibile disegnare solo i pezzi del poligono interni allo screen ed eliminare quelli esterni.
Esempio:
Poligono da disegnare :
/\ / \ / \ / \ / \ \ / \ / \ / \ / \/
Schermo:
+---------+ | | | | | | | | | | | | | | | | +---------+
Somma:
/\ / \ +/----\---+ / \ | /| \ | \| / | \ / | |\ / | | \ / | | \/ | | | +---------+
Uso del clipping:
+/----\---+ / \ | | \ | | / | \ / | |\ / | | \ / | | \/ | | | +---------+
Per tagliare le parti esterne allo screen e' necessario prendere in considerazione una linea del poligono alla volta, controllare le coordinate dei 2 punti e, nel caso in cui solo un punto esca dallo screen, calcolare le intersezioni con lo screen.
Esistono alcuni casi in cui e' inutile disegnare una linea:
* entrambi i punti escono dallo screen
* la linea e' orizzontale
Se la linea e' orizzontale e' inutile disegnarla, facciamo un esempio pratico:
---------- | | | | | | | | | | | | ----------
Il blitter riempe una zona di memoria iniziando quando trova un pixel e finendo quando ne trova un altro. Nell'esempio avremo il poligono perfettamente riempito solo con le due linee verticali.
Ecco il sorgente in codice assembler 68020+
move.l #X0,d0 move.l #Y0,d2 move.l #X1,d1 move.l #Y1,d3 * START CLIPPING Clip: cmp.l d2,d3 ; se y1 = y2 -> NON DISEGNARE LINEA bne.s Continua NO_LINEA: rts * VOGLIO X0 < X1 Continua: cmp.l d0,d1 bgt.s X0MinoreX1 exg.l d0,d1 exg.l d2,d3 X0MinoreX1: * CONTROLLO LATO SINISTRO tst.l d0 bpl.s NOClippingSinistro ; se d0 positivo allora no clip. sinistro tst.l d1 ; d0 < 0 , d1 < 0 FUORI SCREEN bmi.s NO_LINEA ** CLIPPING SINISTRO ClipSinistro: moveq #0,d4 moveq #0,d5 move.w d1,d4 ; d4 = x1 sub.w d0,d4 ; d4 = x1 - x0 move.w d3,d5 ; d5 = y1 sub.w d2,d5 ; d5 = y1 - y0 swap d5 ; d5 << 16 divs.l d4,d5 ; WARNING : 68020+ ; d5 = d5 / d4 = pre ogni X, quante Y si sposta ? neg.l d0 ; d0 = d0 negato mulu.l d0,d5 ; WARNING : 68020+ ; d0 = d0 * d5 swap d5 ; d5 >> 16 add.w d5,d2 ; New Y -> X = 0 moveq #0,d0 NOClippingSinistro: * CONTROLLO LATO DESTRO cmp.l #320,d1 ; se d1 < 320 no clipping sinistro blt.s NoClippingDestro cmp.l #320,d0 ; d0 >= 320 , d1 > 320 FUORI SCREEN bge.s NO_LINEA ** CLIPPING DESTRO moveq #0,d4 moveq #0,d5 move.w d1,d4 ; d4 = x1 sub.w d0,d4 ; d4 = x1 - x0 move.w d3,d5 ; d5 = y1 sub.w d2,d5 ; d5 = y1 - y0 swap d5 ; d5 << 16 divs.l d4,d5 ; d5 = d5 / d4 = pre ogni X, quante Y si sposta ? sub.w #320,d1 ; 320 pixel senza clipping mulu.l d1,d5 ; d1 = d1 * d5 swap d5 ; d5 >> 16 sub.w d5,d3 ; New Y -> X = 105 move.w #319,d1 NoClippingDestro: * VOGLIO Y0 < Y1 cmp.l d2,d3 bgt.s Y0MinoreY1 exg.l d0,d1 exg.l d2,d3 Y0MinoreY1: * CONTROLLO IN ALTO tst.l d2 ; se d2 > 0 no clipping bpl.s NoClippingAlto tst.l d3 ; d3 < 0 , d2 < 0 FUORI SCREEN bmi.s NO_LINEA * CLIPPING ALTO moveq #0,d4 moveq #0,d5 move.w d1,d4 ; d4 = x1 sub.w d0,d4 ; d4 = x1 - x0 move.w d3,d5 ; d5 = y1 sub.w d2,d5 ; d5 = y1 - y0 swap d4 ; d4 << 16 divs.l d5,d4 ; d4 = d5 / d4 = pre ogni Y, quante X si sposta ? neg.l d2 ; d2 = d2 negato mulu.l d2,d4 ; d1 = d1 * d5 swap d4 ; d5 >> 16 add.w d4,d0 ; New Y -> X = 105 moveq #0,d2 NoClippingAlto: * CONTROLLO BASSO cmp.l #256,d3 ; se d3 < 256 NO CLIPPING BASSO blt.s NoClippingBasso cmp.l #256,d2 ; d3 > 256, d2 >= 256 FUORI SCREEN bge.w NO_LINEA * CLIPPING BASSO moveq #0,d4 moveq #0,d5 move.w d1,d4 ; d4 = x1 sub.w d0,d4 ; d4 = x1 - x0 move.w d3,d5 ; d5 = y1 sub.w d2,d5 ; d5 = y1 - y0 swap d4 ; d4 << 16 divs.l d5,d4 ; d4 = d5 / d4 = pre ogni Y, quante X si sposta ? sub.w #256,d3 ; 256 pixel senza clipping mulu.l d3,d4 ; d1 = d1 * d5 swap d4 ; d5 >> 16 sub.w d4,d1 ; New Y -> X = 105 move.w #255,d3 NoClippingBasso: * QUESTE SONO LE COORDINATE CALCOLATE !!! * D0 = X0 * D1 = X1 * D2 = Y0 * D3 = Y1 rts
Scritto da: Alfredo Ornaghi e-mail: ted@intercom.it ITALY tel: