It is used when a face comes out from the screen's visible area. By using this routine it is possible to draw only the faces's parts which are inside the screen and eliminate the ones outside.
Example: Faces to be drawed :
/\ / \ / \ / \ / \ \ / \ / \ / \ / \/
Screen :
+---------+ | | | | | | | | | | | | | | | | +---------+
Sum :
/\ / \ +/----\---+ / \ | /| \ | \| / | \ / | |\ / | | \ / | | \/ | | | +---------+
Sum with clipping :
+/----\---+ / \ | | \ | | / | \ / | |\ / | | \ / | | \/ | | | +---------+
In order to cut the parts outside the screen it is needed to take into consideration each face's line separately, to check the co-ordinates of the two points and, in case that only one point comes out from the screen, to calculate the intersections whit the screen.
In some cases it is useless to draw a line:
* both points are out of the screen
* the line is horizontal
In case that the line is horizontal it is useless to draw, here is an example:
---------- | | | | | | | | | | | | ----------
The blitter fills a memory's area starting when it finds a pixel and finishing when it finds another one. In our example the face is perfectly filled only thanks to the two vertical line.
Here is the source's code in assembler for 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 -> DON'T DRAW THE LINE bne.s Continua NO_LINEA: rts * X0 < X1 Continua: cmp.l d0,d1 bgt.s X0MinoreX1 exg.l d0,d1 exg.l d2,d3 X0MinoreX1: * CHECK OF THE LEFT SIZE tst.l d0 bpl.s NOClippingSinistro ; if d0 positive than NOClippingSinistro tst.l d1 ; d0 < 0 , d1 < 0 outside the screen bmi.s NO_LINEA ** LEFT CLIPPING 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: * CHECK OF THE RIGHT SIZE cmp.l #320,d1 ; if d1 < 320 than NoClippingDestro blt.s NoClippingDestro cmp.l #320,d0 ; d1 > 320 , d0 > 320 outside the scren bge.s NO_LINEA ** RIGHT CLIPPING 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 sub.w #320,d1 ; 320 pixel without 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: * CHECK OF THE HIGH SIZE tst.l d2 ; if d2 > 0 NoclippingAlto bpl.s NoClippingAlto tst.l d3 ; d3 < 0 , d2 < 0 outside the screen bmi.s NO_LINEA * HIGH CLIPPING 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 neg.l d2 ; d2 = d2 neg mulu.l d2,d4 ; d1 = d1 * d5 swap d4 ; d5 >> 16 add.w d4,d0 ; New Y -> X = 105 moveq #0,d2 NoClippingAlto: * CHECK OF THE LOW SIZE cmp.l #256,d3 ; if d3 < 256 NOCLIPPINGBASSO blt.s NoClippingBasso cmp.l #256,d2 ; d3 > 256, d2 >= 256 outside the screen bge.w NO_LINEA * LOW CLIPPING 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 sub.w #256,d3 ; 256 pixel without 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: * THESE ARE THE CALCULATED CO-ORDINATES * D0 = X0 * D1 = X1 * D2 = Y0 * D3 = Y1 rts
Written By: Alfredo Ornaghi e-mail: ted@intercom.it ITALY tel: