This routine is used to give a drawing priority to the faces; our object could be rotated in any way, and it will always be displayed correctly.
Removing hidden surfaces is based upon very specific algos, not very easy to implement and rarely executed with the needed speed. Removing hidden faces is divided into two parts. First one, removes the hidden faces. They are so called because they cannot be seen from observer; to find them you have just to compute the degree formed from the normal to the sourface and by the vector of the view. If this degree is between 90 and -90, the face will be visible; if the result is greater than 90 or minor than -90, the face is hidden.
To compute the normal to the surface, you have just to compute Once deleted invisible faces, you'll have to draw visible ones in a correct way. For this task two algos exist: the z-buffering and the painter algo. Both of them cannot be implemented inside a demo in a standard way, following you'll see how to implement them.
Z-buffering algo is so composed:
- From a face's coords, you have to compute Z value for every X,Y and memorize it inside a buffer - Find the Z value closer to the observer, check this value with the one contained inside the Z buffer (with the same X and Y) and if it is closer to the observer, it will replace the current value. - Now for any X,Y coordinate we have a Z value (the one nearest to the observer) and the pixel color, you just have to draw it.
Painter algo is based upon a series of checks :
1 - Extensions on X axe of two faces overlap ? If no-> end of checks, drawing priority does not matters. If yes-> check 2. 2 - Extensions on Y axe of two faces overlap ? If no-> end of controls. If yes-> check 3. 3&4 - Extend a polygon widely and you'll have a surface : the other polygon is completely on the other part ? If yes -> end of checks. If no-> check 5. 5 - Now we know faces are in the wrong position : we'll have to swap them.
These algos are very computing-demanding, and our beloved Amigas haven't a PowerPC 604/200Mhz, so I do not suggets to anyone to use one of the above algos, and to give a look to the one I do introduce.
The following is not an algo of mine but just a modification I made to make it as fast as possibkle.
We can divide the algo into two parts. The first one takes all points making a face, sums all Z values and divide the result for the number of points (Z factor).
The second part sorts faces so that much far to the observer are rendered first. So, if an objects obscures another one, we will not have any problem : we'll see our object before all the rest.
Imagine not to use this algo : objects would be rendered always with the same priority... in a wood of trees, the foremost tree must be appear before the rest (so it has to be drawn as last). With a fixed order, everything would work until we do not begin to rotate inside this wood : then priority has to be changed. This is a typical example of when to use a Z sort algo.
Warning : you do not need it always.
There are situations when you can get rid of the Z sort, saving a lot of CPU time : in these cases drawing priorities is irrilevant. We have said that you can avoid sorting with some objects : first of all they have to be CLOSED and then they have to be SIMPLE. For example, a sphere : hidden faces will never be drawn (that's important !) and drawing priority does not mind at all. Objects have to be closed : if a side would be opened, you should have to draw also hidden faces, so you should use Z sort again.
**************************** parte 1 ********************************* CalcPoints: ; Z factor move.l Dlines,a0 ; how to join faces move.l dplane,a1 ; number of punts per face and color lea Intz(pc),a2 ; Z val of all points lea BufferFace(pc),a3 ; empty buffer move.w dface,d6 ; number of faces moveq #0,d0 moveq #0,d1 LpLps: move.w (a1),d0 ; number of punts creating a face add.w #4,a1 move.w d0,d1 ; d1 = d0 subq.w #1,d0 ; d0 = -1 per dbf moveq #0,d3 SomaLp: move.w (a0),d2 ; point number add.w #4,a0 add.w d2,d2 ; * 2 (it is a word) add.w (a2,d2.w),d3 ; Z coord dbf d0,SomaLp ext.l d3 divs.w d1,d3 ; points / Z total move.w d3,(a3)+ ; factor value dbf d6,LpLps **************************** parte 2 ********************************* ; compute Z value of faces (not points) lea BufferFace(pc),a0 ; Z factor of all faces lea FacceSeq(pc),a1 ; empty buffer movea.l a0,a2 move.w dface,d4 ; number of faces move.w d4,d5 ; number of faces move.w d5,d6 ; number of faces subq.w #1,d6 ; number of faces -1 for dbf move.w d6,d7 ; number of faces -1 for dbf add.w d5,d5 ; number of faces *2 addq.w #2,d5 ; +2 because -(a1) before dec ; then we insert val in a1 add.w d5,a1 ; last val move.w #$9999,d5 ; $9999 = -26215 smallest Z value Calcs: move.w d7,d6 ; number of faces -1 per dbf moveq #2,d2 ; first face to insert (1)(2=WORD) moveq #0,d3 , starting face (0) move.w (a0)+,d0 ; Z value Calc: move.w (a0)+,d1 ; Z2 value cmp.w d0,d1 ; if Z2
OBJECT REDRAWING
Abs addresses between $100 and $200 MUST NEVER be used ! ! They are used by me in this old routine because when I have written it (1990) I had an A500 and with A500, A2000, A3000, these addresses were always empty. Now with AGA machines these addresses are in use, so I do not assure the demo will work correctly on these machines.
A lot of time, 6 years, is passed since I have written this code, I'll try to explain it as well as I can.
Display: clr.w $120.w clr.w $122.w clr.w $124.w move.l #0,a1 move.w ScrClrNow,a1 move.w #0,(a1)+ ; erase $150 move.w #$7fff,(a1)+ ; max. value in $152 move.w #0,(a1)+ ; delete $154 move.w #$7fff,(a1)+ ; max. value in $156 move.l Dlines,a6 ** this is the main routine : it is executed once per every face. lea $dff000,a6 move.l Bm2_PL1,d1 move.w dpunti,d6 ; number of points lea UltimateFace(pc),a1 ; empty buffer where to place the value ; corresponding to the faces that will be drawn ; after all the others. lea IntY1(pc),a2 ; Y lea IntX1(pc),a3 ; X lea FacceSeq(pc),a0 ; faces' sequence moveq #0,d5 move.w dface,d5 Face: move.l dplane,a5 move.l Dlines,a4 move.w (a0)+,d0 lsr.w #1,d0 subq.w #1,d0 moveq #0,d3 moveq #0,d4 cmp.w #-1,d0 beq EAddr Addr: add.w (a5),d3 add.w #4,a5 addq #1,d4 dbf d0,Addr EAddr: add.w d3,d3 add.w d3,d3 add.w d4,d4 move.w d4,$130.w bsr Againdopo dbf d5,Face tst.w $120.w bne HoHo rts ** this routine is executed only if there are faces that have to be drawn after all the others. ** This routine is executed as last. HoHo: move.w #1,$122.w move.w $124.w,d5 subq #1,d5 lea UltimateFace(pc),a1 Face2: move.l dplane,a5 move.l Dlines,a4 move.w (a1)+,d0 lsr.w #1,d0 subq.w #1,d0 moveq #0,d3 moveq #0,d4 cmp.w #-1,d0 beq EAddr2 Addr2: add.w (a5),d3 add.w #4,a5 addq #1,d4 dbf d0,Addr2 EAddr2: add.w d3,d3 add.w d3,d3 add.w d4,d4 move.w d4,$130.w bsr Againdopo dbf d5,Face2 rts againdopo: ; compute starting point for data in Lines2 movem.l a0-a3/d5,-(sp) clr.w Out lea BufferLine(pc),a1 add.w d3,a4 move.w d3,$104.w move.w 2(a5),$106.w move.w (a5),d6 move.w d6,$10e.w subq.w #1,d6 ; Places in BufferLine X,Y coords of all points making a face ; so we have it in sequence DlpLop: movem.w (a4)+,d2/d3 add.w d2,d2 add.w d3,d3 move.w (a3,d2.w),(a1)+ ; x1 move.w (a2,d2.w),(a1)+ ; y1 move.w (a3,d3.w),(a1)+ ; x2 move.w (a2,d3.w),(a1)+ ; y2 dbf d6,DlpLop ; check whether inside Priority there is 0 or 1 ; if 1 this face is drawn last. move.l DPriority,a1 move.w $130.w,d2 move.w (a1,d2.w),d2 cmp.w #1,d2 ; draw all beq Dloop2 tst.w $122.w ; if it has to draw the face bne Saltoo ; cmp.w #2,d2 ; last faces before the others. beq Ultima ; compute whether it is a line Saltoo: cmp.w #1,$10e.w ; draw just 1 line beq OnlyLine ; compute if it is an hidden face (YEAAA!!!) lea BufferLine(pc),a1 movem.w (a1),d0-d3 ; d0=x0 d1=y0 d2=x1 d3=y1 d4=x2 d5=y2 movem.w 12(a1),d4-d5 sub.w d0,d2 ; sub.w d0,d4 ; sub.w d1,d3 ;cross product of two sides sub.w d1,d5 ; muls.w d2,d5 ; muls.w d3,d4 ; tst.w $132.w bne.s blts sub.l d4,d5 bgt.s dloop2 lea $dff000,a6 bra NoFace ; hidden face ! blts: sub.l d4,d5 blt.s dloop2 lea $dff000,a6 bra NoFace ; hidden face! ** face is visible, draw it now ! Dloop2: ; now we have all face's point in BufferLine bsr CalcScr ; compute X e Y inside the screen for clipping bsr.l CalcPoits ; compute Xmax,Ymax,Xmin,Ymin bsr.l TCalcAll ; compute Xmax,Ymax,Xmin,Ymin di tutto bsr.L CalcArea ; compute size,mod.,.... bsr.l Lineeee ; draw lines bsr.l Fillare ; fill between lines bsr.l Copyarea ; compute draw lea -$58(a6),a6 ; a6 = $dff000 bsr.l Clerorno ; erase buffer I used to draw NoFace: move.w #$400,$96(a6) movem.l (sp)+,a0-a3/d5 rts Ultima: movem.l (sp)+,a0-a3/d5 move.w -2(a0),(a1)+ move.w #1,$120.w add.w #1,$124.w rts *** compute screen clipping ( max size = 320*256 ) CalcScr: move.w $10e,d6 add.w d6,d6 subq.w #1,d6 lea BufferLine(pc),a0 lea BufferLine2(pc),a1 Clip: movem.w (a0)+,d0-d1 cmp.w #0,d0 bge.s Ok0 move.w #0,(a1)+ move.w #1,Out bra.s Di1 Ok0: cmp.w #320,d0 ble.s Ok2 move.w #320,(a1)+ bra.s Di1 Ok2: move.w d0,(a1)+ Di1: cmp.w #0,d1 bge.s Ok3 move.w #0,(a1)+ bra.s Di2 Ok3: cmp.w #256,d1 ble.s Ok4 move.w #256,(a1)+ bra.s Di2 Ok4: move.w d1,(a1)+ Di2: dbf d6,Clip rts *** compute Xmax, Xmin, Ymax, Ymin of all the object TCalcAll: lea $140.w,a2 move.w ScrClrNow,a3 moveq #0,d3 move.w (a2)+,d3 cmp.w (a3)+,d3 blt TCalcPoits2 move.w d3,-2(a3) TCalcPoits2: move.w (a2)+,d3 cmp.w (a3)+,d3 bgt TCalcPoits3 move.w d3,-2(a3) TCalcPoits3: move.w (a2)+,d3 cmp.w (a3)+,d3 blt TCalcPoits4 move.w d3,-2(a3) TCalcPoits4: move.w (a2)+,d3 cmp.w (a3)+,d3 bgt TCalcPoits5 move.w d3,-2(a3) TCalcPoits5: rts *** compute SIZE and modules for blitter CalcArea: ; calcola size lea Dax(pc),a3 movem.w $140.w,d0-d3 sub.w d3,d2 ; x sub.w d1,d0 ; y lsr.w #4,d2 addq #2,d2 ; world size move.w d2,$100.w lsr.w #2,d0 addq #1,d0 ; hight screen lsl.l #8,d0 ; muls #$100,d0 add.w d2,d0 ; size $dff058 move.w d0,18(a3) ; compute screen move.l Fill,a1 move.l Bm2_pl1,a2 ; compute memory area to copy (desending method) move.w $140.w,d1 move.w d1,d3 muls #$2c,d3 muls #$78,d1 move.w $144.w,d2 lsr.w #3,d2 add.w d2,d1 add.w d2,d3 add.w d3,a1 add.l d1,a2 move.l a1,(a3) move.l a2,4(a3) move.l a2,8(a3) ; calcola moduli (metodo discendente) moveq #0,d1 move.w $100.w,d1 ; num. world to copy add.w d1,d1 ; in bytes moveq #44,d2 ; 40 byte in 320 pixel sub.w d1,d2 ; a module move.w #$78,d3 ; $78 byte sub.w d1,d3 ; d module move.w d2,12(a3) move.w d3,14(a3) move.w d3,16(a3) rts *** copy area created and place it in corresponding planes. Copyarea: ; funzione d=a+c lea $dff000,a6 move.w #$8400,$96(a6) lea Jump(pc),a1 lea Dax(pc),a3 move.w $106.w,d1 add.w d1,d1 move.w d1,d2 add.w d2,d2 add.w d2,d1 add.w d1,a1 moveq #0,d0 move.w 18(a3),d0 ; size $dff058 moveq #$28,d1 moveq #0,d2 move.l 4(a3),d2 ; $dff048 - $dff054 moveq #0,d3 move.l (a3),d3 ; $dff050 move.l #AddGriglia+[$2c*256]-2,d4 lea $40(a6),a2 lea $54(a6),a4 lea $48(a6),a5 move.l #$0b0a0002,d5 move.l #$0bfa0002,d6 move.l #$0fca0002,d7 Altola: btst #6,2(a6) bne Altola move.w 12(a3),$64(a6) move.w 12(a3),$62(a6) move.w 14(a3),$66(a6) move.w 16(a3),$60(a6) lea $50(a6),a3 lea $58(a6),a6 jmp (a1)Please note this order :
______ plane 4 | _____ plane 3 || ____ plane 2 ||| ___ plane 1 |||| 0 -> %0000 non usato 1 -> %0001 plane 1 pieno, 2-3-4 vuoti 2 -> %0010 plane 2 pieno, 1-3-4 vuoti 3 -> %0011 plane 1-2 pieni, 3-4 vuoti 4 -> %0100 plane 3 pieno, 1-2-4 vuoti . -> %....You have to copy or erase interested area. For the copy, you just have to add the screen with the face you are drawing. For the erase, you have to do a mul with the NEG face on the destination screen.
Depending on the selected colour, just ONE SINGLE routine is executed.
Jump: jmp zeros jmp unos jmp dues jmp tres jmp quattros jmp cinques jmp seis jmp settes jmp ottos jmp noves jmp diecis jmp undicis jmp dodicis jmp tredicis zeros: bsr disegnare ; disegna plane 0 add.w d1,d2 bsr cancellare ; cancella plane 1 add.w d1,d2 bsr cancellare ; cancella plane 2 rts unos: bsr cancellare ; disegna plane 0 add.w d1,d2 bsr disegnare ; disegna plane 1 add.w d1,d2 bsr cancellare ; cancella plane 2 rts dues: bsr cancellare ; cancella plane 0 add.w d1,d2 bsr cancellare ; cancella plane 1 add.w d1,d2 bsr disegnare ; disegna plane 2 rts tres: bsr disegnare add.w d1,d2 bsr disegnare add.w d1,d2 bsr cancellare rts quattros: bsr disegnare add.w d1,d2 bsr cancellare add.w d1,d2 bsr disegnare rts cinques: bsr cancellare add.w d1,d2 bsr disegnare add.w d1,d2 bsr disegnare rts seis: bsr disegnare add.w d1,d2 bsr disegnare add.w d1,d2 bsr disegnare rts settes: bsr griglia add.w d1,d2 bsr cancellare add.w d1,d2 bsr cancellare rts ottos: bsr cancellare add.w d1,d2 bsr griglia add.w d1,d2 bsr cancellare rts noves: bsr cancellare add.w d1,d2 bsr cancellare add.w d1,d2 bsr griglia rts diecis: bsr griglia add.w d1,d2 bsr griglia add.w d1,d2 bsr cancellare rts undicis: bsr griglia add.w d1,d2 bsr cancellare add.w d1,d2 bsr griglia rts dodicis: bsr cancellare add.w d1,d2 bsr griglia add.w d1,d2 bsr griglia rts tredicis: bsr griglia add.w d1,d2 bsr griglia add.w d1,d2 bsr griglia rts cancellare: ; funzione D=A(neg)*C per cancellare btst #6,-$56(a6) bne cancellare move.l d5,(a2) move.l d3,(a3) move.l d2,(a4) move.l d2,(a5) move.w d0,(a6) rts disegnare: btst #6,-$56(a6) bne disegnare move.l d6,(a2) move.l d3,(a3) move.l d2,(a4) move.l d2,(a5) move.w d0,(a6) rts Griglia: btst #6,-$56(a6) bne griglia move.l d7,(a2) ; funzione D=A(neg)*C+A*B move.l d4,-$c(a6) move.l d3,(a3) move.l d2,(a4) move.l d2,(a5) move.w d0,(a6) rts ** This routine erases the buffer Clerorno: ; zone to delete to erase the lines. btst #6,$2(a6) bne Clerorno lea Dax(pc),a3 move.l #$01000002,$40(a6) move.w 12(a3),$66(a6) move.l (a3),$54(a6) move.w 18(a3),$58(a6) rts Fillare: lea Dax(pc),a3 tst.w out beq doppld move.w 12(a3),d0 addq.w #2,d0 move.w 18(a3),d1 subq.w #1,d1 bra.s FillWait doppld: move.w 12(a3),d0 move.w 18(a3),d1 FillWait: ; zona da fillare per riempire linee btst #6,$2(a6) bne FillWait move.l #$09f00012,$40(a6) move.w d0,$64(a6) move.w d0,$66(a6) move.l (a3),$50(a6) move.l (a3),$54(a6) move.w d1,$58(a6) rts ** This routine just draws ONE SINGLE LINE with the blitter ** without using any buffer. Onlyline: bsr CalcScr ; compute screen's X and Y lea BufferLine(pc),a1 lea jump2(pc),a2 move.l BM2_PL1,a0 move.l BM2_PL1,a3 lea $dff000,a6 move.w $106.w,d1 add.w d1,d1 move.w d1,d2 add.w d2,d2 add.w d2,d1 add.w d1,a2 jmp (a2) Jump2: jmp linep0 jmp linep1 jmp linep2 jmp linep3 jmp linep4 jmp linep5 jmp linep6 Linep0: move.l #$ffff8000,d7 ; metodo TEXTURE = tutto pieno bsr Line00 move.l #$00008000,d7 ; metodo TEXTURE = vuoto = cancella linea add.w #$28,a3 bsr Line00 add.w #$28,a3 bsr Line00 bra CalcMax Linep1: move.l #$00008000,d7 bsr Line00 move.l #$ffff8000,d7 add.w #$28,a3 bsr Line00 move.l #$00008000,d7 add.w #$28,a3 bsr Line00 bra CalcMax Linep2: move.l #$00008000,d7 bsr Line00 add.w #$28,a3 bsr Line00 move.l #$ffff8000,d7 add.w #$28,a3 bsr Line00 bra CalcMax Linep3: move.l #$ffff8000,d7 bsr Line00 add.w #$28,a3 bsr Line00 add.w #$28,a3 move.l #$00008000,d7 bsr Line00 bra CalcMax Linep4: move.l #$ffff8000,d7 bsr Line00 move.l #$00008000,d7 add.w #$28,a3 bsr Line00 move.l #$ffff8000,d7 add.w #$28,a3 bsr Line00 bra CalcMax Linep5: move.l #$00008000,d7 bsr Line00 move.l #$ffff8000,d7 add.w #$28,a3 bsr Line00 add.w #$28,a3 bsr Line00 bra CalcMax Linep6: move.l #$ffff8000,d7 bsr Line00 add.w #$28,a3 bsr Line00 add.w #$28,a3 bsr Line00 bra CalcMax ** This routine draws lines using blitter Line00: movem.w (a1),d0-d3 ; coordinate x0,y0,x1,y1 ****** Insert clipping routine here. Line: cmp.w d1,d3 bne encode rts encode: move.l a3,a0 move.w #$78,d4 sub.w d0,d2 bpl.s Oct1278 neg.w d2 sub.w d1,d3 bpl.s Oct34 neg.w d3 cmp.w d2,d3 bpl.s Oct6 moveq.l #28+1,d5 bra.s Lline Oct6: exg d2,d3 moveq.l #12+1,d5 bra.s Lline Oct34: cmp.w d2,d3 bpl.s Oct3 moveq.l #20+1,d5 bra.s Lline Oct3: exg d2,d3 moveq.l #8+1,d5 bra.s Lline Oct1278:sub.w d1,d3 bpl.s Oct12 neg.w d3 cmp.w d2,d3 bpl.s Oct7 moveq.l #24+1,d5 bra.s Lline Oct7: exg d2,d3 moveq.l #4+1,d5 bra.s Lline Oct12: cmp.w d2,d3 bpl.s Oct2 moveq.l #16+1,d5 bra.s Lline Oct2: exg d2,d3 moveq.l #0+1,d5 Lline: mulu.w d4,d1 ror.l #4,d0 add.w d0,d0 add.l d1,a0 add.w d0,a0 swap d0 or.w #$bca,d0 add.w d3,d3 add.w d3,d3 add.w d2,d2 move.w d2,d1 lsl.w #5,d1 add.w #$42,d1 swap d5 move.w d0,d5 swap d5 move.w d3,d0 sub.w d2,d0 bpl waitb1 bset #6,d5 waitb1: move.w d0,d6 sub.w d2,d6 Drawl2: btst #6,2(a6) bne.s Drawl2 move.w d3,$62(a6) move.l d0,$50(a6) move.l d5,$40(a6) move.w d4,$60(a6) move.w d4,$66(a6) move.w d6,$64(a6) move.l #-1,$44(a6) move.l d7,$72(a6) move.l a0,$48(a6) move.l a0,$54(a6) move.w d1,$58(a6) rts CalcMax: ; calcola lea BufferLine2(pc),a1 lea $140.w,a2 moveq #0,d0 moveq #0,d1 moveq #0,d2 moveq #0,d3 movem.w (a1),d0-d3 cmp.w d0,d2 ble.s Less move.w d0,6(a2) move.w d2,4(a2) bra.s Great Less: move.w d0,4(a2) move.w d2,6(a2) Great: cmp.w d1,d3 ble.s Less2 move.w d1,2(a2) move.w d3,(a2) bra.s Great2 Less2: move.w d1,(a2) move.w d3,2(a2) Great2: bsr TCalcAll bra NoFace CalcPoits: ; Calcola Xmax,Xmin,Ymax,Ymin lea BufferLine2+2(pc),a2 move.w $10e.w,d6 add.w d6,d6 subq.w #1,d6 move.w d6,d7 moveq #0,d1 move.w (a2),d2 moveq #0,d3 CalcPoits4: move.w (a2),d1 cmp.w d1,d3 bgt.s CalcPoits2 move.w d1,d3 addq #4,a2 dbf d6,CalcPoits4 bra.s CalcPoitsend CalcPoits2: cmp.w d1,d2 blt.s CalcPoits3 move.w d1,d2 CalcPoits3: addq #4,a2 dbf d6,CalcPoits4 CalcPoitsend: move.w d3,$140.w move.w d2,$142.w lea BufferLine2(pc),a2 moveq #0,d0 moveq #0,d1 move.w (a2),d2 moveq #0,d3 move.w d7,d6 CalcPoit5: move.w (a2),d1 cmp.w d1,d3 bgt.s CalcPoit6 move.w d1,d3 addq #4,a2 dbf d6,CalcPoit5 move.w d3,$144.w move.w d2,$146.w rts CalcPoit6: cmp.w d1,d2 blt.s CalcPoit7 move.w d1,d2 CalcPoit7: addq #4,a2 dbf d6,CalcPoit5 move.w d3,$144.w move.w d2,$146.w rts Lineeee: lea BufferLine(pc),a5 ; sequanza delle linee da disegnare move.w $10e.w,d6 subq.w #1,d6 Linene: movem.w (a5)+,d0-d3 bsr.s SWline dbf d6,Linene rts ** Qui deve essere inserita la routine di CLIPPING SWLine: move.l Fill,a0 lea $dff000,a6 cmp.w d1,d3 bne.s Sencode ; linea orizzontale rts Sencode:bmi.s SLine0A exg.l d0,d2 exg.l d1,d3 SLine0A:addq.w #1,d3 clr.w d4 sub.w d1,d3 bge.s SLine16 neg.w d3 bra.s SLine1A SLine16:or.w #1,d4 SLine1A:sub.w d0,d2 bge.s SLine22 neg.w d2 bra.s SLine26 SLine22:or.w #2,d4 SLine26:cmp.w d3,d2 bge.s SLine2E exg.l d2,d3 bra.s SLine32 SLine2E:or.w #4,d4 SLine32:clr.w d5 ror.w #4,d0 or.w #$B00,d0 move.b d0,d5 move.b #$5A,d0 add.w d5,d5 mulu.w #$2c,d1 and.w #$FFFF,d1 add.w d5,d1 add.l a0,d1 move.b oct(pc,d4.w),d4 add.l d3,d3 SLine5C:btst #6,2(a6) bne.s SLine5C move.w d3,$62(a6) sub.w d2,d3 bge.s SLine70 or.b #$40,d4 SLine70: move.l d3,$50(a6) sub.w d2,d3 move.l #$ffff8000,$72(a6) moveq #-1,d5 move.l d5,$44(a6) moveq #44,d5 move.w d5,$60(a6) move.w d5,$66(a6) move.w d3,$64(a6) move.w d4,$42(a6) move.w d0,$40(a6) move.l d1,$48(a6) move.l d1,$54(a6) lsl.w #6,d2 add.w #$42,d2 move.w d2,$58(a6) rts ; octant codes oct: dc.b $0f,$0b,$07,$03,$1f,$17,$1b,$13By checking the source, you should have notice that CLIPPING routine is not present. This routine will be described in the next issue, so please BE CAREFULL not to draw objects that exists the screen !
Now we'll examine remaining source code parts.
jmp START org $130000 load $130000 START: ................These commands are used to make code NOT RELOCABLE, so the routine will always be loaded starting from $130000.
************************************************************************* lea $150000,a0 Clear: clr.l (a0)+ cmp.l #$180000,a0 bne clear lea $100.w,a0 dsf: clr.b (a0)+ cmp.l #$200,a0 bne dsf This loop erases memory from $150000 and $180000 and from $100 and $200 ************************************************************************* lea SphLines(pc),a0 lea Plane9(pc),a1 addiaz: add.w #96,(a0)+ cmp.l a0,a1 bne addiazThis routine just adds the two spheres together.
************************************************************************* lea AddGriglia,a0 move.w #$80,d1 ; 1/2 height gri1: moveq #10,d0 ; num. screen in long gri2: move.l #$55555555,(a0)+ move.l #$aaaaaaaa,$28(a0) ; $28=modulo-$4[1 long] dbra d0,gri2 add.l #$2c,a0 ; modulo dbra d1,gri1 ** Creates a grid for creating the dither effect. ******************************************************************************** Inter: btst #5,$dff01f beq.w Int move.w #$20,$dff09c add.w #4,ZANGLE add.w #2,YANGLE add.w #4,XANGLE move.w #1,IntOk Int: rte IntOk: dc.w 0 ** Routine in INTERRUPT $6c. That's because our object will always run at the same speed. **************************************************************************
HOW TO DRAW OBJECTS
Dpunti: dc.w 0 ;number of points Dface: dc.w 0 ; number of faces DX: dc.l 0 ; coords X DY: dc.l 0 ; coords Y DZ: dc.l 0 ; coords Z Dlines: dc.l 0 ; how to join lines Dplane: dc.l 0 ; how to color object Dpriority: dc.l 0 ; how to draw object Blkpoints=200 ; num points BlkLine=26 ; num lines per face Blkface=200 ; num faces ; cube with lines NPOINTS=76 ; num points Nface=12 ; num faces Wx: dc.w -120,120,120,-120,-120,120,120,-120 dc.w -100,100,100,35,35,-35,-35,-100 dc.w 120,120,120,120,120,120,120,120,120,120,120,120 dc.w 100,-20,-100,-100,-20,100,45,5,-45,-45,5,45 dc.w -120,-120,-120,-120,-120,-120,-120,-120,-120,-120,-120,-120,-120,-120 dc.w -120,-120,-120,-120,-120,-120,-120,-120,-120,-120,-120,-120 dc.w 0,-80,100,-100,80 dc.w 0,-80,100,-100,80 Wy: dc.w 120,120,-120,-120,120,120,-120,-120 dc.w 100,100,40,40,-100,-100,40,40 dc.w 100,100,60,60,20,20,-20,-20,-60,-60,-100,-100 dc.w 100,100,40,-40,-100,-100,45,45,10,-10,-45,-45 dc.w 60,60,40,40,-40,-40,-20,-20,0,0,-20,-20,-60,-60 dc.w 60,60,40,40,10,10,-60,-60,-40,-40,-10,-10 dc.w 120,120,120,120,120 dc.w -120,-120,-120,-120,-120 Wz: dc.w 120,120,120,120,-120,-120,-120,-120 dc.w 120,120,120,120,120,120,120,120 dc.w 100,-100,-100,40,40,-40,-40,40,40,-100,-100,100 dc.w -120,-120,-120,-120,-120,-120,-120,-120,-120,-120,-120,-120 dc.w -100,-20,-20,-80,-80,-40,-40,-50,-50,-10,-10,-20,-20,-100 dc.w 10,100,100,30,30,100,100,10,10,80,80,10 dc.w 100,-100,20,20,-100 dc.w 100,-100,20,20,-100 Lines: dc.w 0,1,1,2,2,3,3,0 dc.w 5,4,4,7,7,6,6,5 dc.w 1,5,5,6,6,2,2,1 dc.w 4,0,0,3,3,7,7,4 dc.w 4,5,5,1,1,0,0,4 dc.w 3,2,2,6,6,7,7,3 dc.w 8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,8 dc.w 16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,16 dc.w 28,29,29,30,30,31,31,32,32,33,33,28,34,35,35,36,36,37,37,38,38,39,39,34 dc.w 40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,48,48,49,49,50,50,51,51,52,52,53,53,40 dc.w 54,55,55,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63,64,64,65,65,54 dc.w 66,67,67,68,68,69,69,70,70,66 dc.w 75,74,74,73,73,72,72,71,71,75 Plane: dc.w 4,0,4,0,4,1,4,1,4,2,4,2,8,3,12,4,12,6,26,5,5,5,5,1 Priotity: ; 0 if you compute it; 1 if always draw it; 2 if it is the last dc.w 0,0,0,0,0,0,2,2,2,2,2,2To draw the object you need :
- place X in Wx - place Y in Wy - place Z in Wz - select draw modeLet's do an example .
YOU CANNOT DRAW FACES RANDOMLY IF THE ERASE HIDDEN FACES ROUTINE IS PRESENT ! ! ! !
If we want to draw a cube, the first face will be in this way :
0----1 | | | | | | 3----2Now we need to give a priority to the face :
0--------1 | -> | | | /\ | ||| || | ||| || | |\/ | | | | 3--------2 <-As you may see, the face goes from point 0 to 1, from 1 to 2, from 2 to 3 and from 3 to 0. It is IMPORTANT to start always from 0.
Next face must have opposite priority ! !
4 /| / | / | 0--------1/ | | -> | | | | | /\ | | 5 || | ||| / || | ||| / | \/| / | |/ 3--------2 <- 4 /| -> / ||| / ||| 0--------1/ |\/ | | | | | | | /\| 5 | ||| / | ||| / | | /<- | |/ 3--------2Now, with coords in 3D and central symmetry :
Y (-100,-100,100) (100,-100,100) /\ 0---------1 | | | | | | | | | | | / Z | - - | | / | | | | / | | |/ | | ----------> X 3---------2 (-100,100,100) (100,100,100)Foreground face has Z=100, while background one has Z=-100
So we have, for the first three faces :
Wx: dc.w -100,100,100,-100,100,100 Wy: dc.w -100,-100,100,100,-100,-100 Wz: dc.w 100,100,100,100,-100,-100 Lines: dc.w 0,1,1,2,2,3,3,0 dc.w 5,2,2,1,1,4,4,5 Plane: dc.w 4,0,4,1Plane defines:
4,0 = face made by 4 lines with colour 0
4,1 = face made by 4 lines with colour 1
example :13,89 = face made by 13 lines with colour no. 89
Colors : ; 0= first plane ; 1= second plane ; 2= third plane ; 3= first + second plane ; 4= first + third plane ; 5= second + third plane ; 6= first + second + third plane ; use of grid for stencil vector !!!! ; 7= first plane ; 8= second plane ; 9= third plane ; 10= first + second plane ; 11= first + third plane ; 12= second + third plane ; 13= first + second + third plane
P.S.: Data for the program can be d/l from the archive of the last month. P.S.2: If I have missed something, send me an e-mail.
Main Page
Written By: Alfredo Ornaghi e-mail: ted@intercom.it ITALY tel: