home *** CD-ROM | disk | FTP | other *** search
- ; A Polygon fill routine.
- ; Alex Chalfin 10/25/94
- ; Internet: achalfin@uceng.uc.edu
- ;
- ; Pascal Declaration:
- ;
- ; Procedure DrawPoly(Var VertexList;NumVert:Word;Color:Byte;PageAddr:Word);
- ;
-
- .Model Large,Pascal
- .Data
-
- MinY dw ? ; Starting Y value (Minimum)
- Edges dw ? ; Number of edges in the polygon
- StartVert1 dw ? ; Start vertex index for line1
- StartVert2 dw ? ; Start vertex index for line2
- EndVert1 dw ? ; End vertex index for line 1
- EndVert2 dw ? ; End vertex index for line 2
- Delta1 dd ? ; Change in X location for line 1
- Delta2 dd ? ; Change in X location for line 2
- Count1 dw ? ; Y Counter for line 1
- Count2 dw ? ; Y Counter for line 2
- XVal1 dd ? ; X place holder for line 1
- XVal2 dd ? ; X place holder for line 2
- YCount dw ? ; Store current Y location
- PolyColor db ? ; Color to draw polygon
-
- .Code
- .386
-
- Public DrawPoly
-
-
- FINDMINMAX Macro
- Lfs di,Vert ;; Make fs:di point to screen vertex list
- ;*** Find the minimum and maximum values of polyogn
- Mov ax,06fffh ; use ax for minimum value
- Mov MinY,ax
- Mov cx,0
- @MinMaxLooper:
- Mov bx,cx
- Shl bx,2
- Mov ax,Word Ptr fs:[di+bx+2] ; Get Y value for vertex list
- Cmp ax,MinY ; Check for minimum value
- Jge @SkipMinStore
- Mov StartVert1,cx ; Store the starting (top) vertex
- Mov MinY,ax
- @SkipMinStore:
- Inc cx
- Cmp cx,Num
- Jnz @MinMaxLooper
- Mov ax,MinY
- Mov YCount,ax
- EndM ;FINDMINMAX
-
- Proc ZeroCheck Near
- Cmp bx,0
- Jne @Skip
- Inc bx
- @Skip:
- Ret
- EndP ZeroCheck
-
- CALCDELTA1 Macro
- Mov bx,StartVert1
- Shl bx,2
- Movsx eax,Word Ptr fs:[di+bx] ; Get first X value, X1
- Mov XVal1,eax
- Push eax ; Store X value on stack
- Movsx eax,Word Ptr fs:[di+bx+2] ; Get Y Value, Y1
- Mov bx,EndVert1
- Shl bx,2
- Movsx ecx,Word Ptr fs:[di+bx] ; Get Second X Value, X2
- Push ecx
- Movsx ecx,Word Ptr fs:[di+bx+2] ; Get Y value, Y2
- Sub ecx,eax
- Inc ecx ; cx := Y2-Y1+1
- Mov edx,ecx ; store in dx for later use
- Pop ecx ; Restore X2
- Pop eax ; Restore X1
- Sub ecx,eax
- Shl ecx,8 ; cx := (X2-X1) Shl 8
- Mov eax,ecx
- Mov ebx,edx ; bx := Y2-Y1+1
- Mov Count1,bx ; Store Count1
- Cdq ; Convert DWord in EAX to QWord in EDX:EAX
- Call ZeroCheck ; Make sure divisor isn't 0
- Idiv ebx
- Mov Delta1,eax ; Store the first delta
- EndM
-
- CALCDELTA2 Macro
- Mov bx,StartVert2
- Shl bx,2
- Movsx eax,Word Ptr fs:[di+bx] ; Get first X value, X1
- Mov XVal2,eax
- Push eax ; Store X value on stack
- Movsx eax,Word Ptr fs:[di+bx+2] ; Get Y Value, Y1
- Mov bx,EndVert2
- Shl bx,2
- Movsx ecx,Word Ptr fs:[di+bx] ; Get Second X Value, X2
- Push ecx
- Movsx ecx,Word Ptr fs:[di+bx+2] ; Get Y value, Y2
- Sub ecx,eax
- Inc ecx ; cx := Y2-Y1+1
- Mov edx,ecx ; store in dx for later use
- Pop ecx ; Restore X2
- Pop eax ; Restore X1
- Sub ecx,eax
- Shl ecx,8 ; cx := (X2-X1) Shl 8
- Mov eax,ecx
- Mov ebx,edx ; bx := Y2-Y1+1
- Mov Count2,bx ; Store Count2
- Cdq ; Convert DWord in EAX to QWord in EDX:EAX
- Call ZeroCheck ; Make sure divisor isn't 0
- Idiv ebx
- Mov Delta2,eax ; Store the first delta
- EndM
-
- HLINE Macro
- ;; eax = X1, ebx = x2, dx = y
- Push eax
- Push ebx
- Push dx
- Cmp dx,0 ; Check lower Y bound
- Jl @Nothing
- Cmp dx,199 ; Check upper Y bound
- Jg @Nothing
- Shr eax,8
- Shr ebx,8
- ;;; Do clipping
- Cmp bx,ax
- Jl @Nothing
- Cmp ax,319
- Jg @Nothing
- Cmp bx,0
- Jl @Nothing
- Cmp ax,0 ; Left Clip
- Jg @CheckBX
- Mov ax,0
- @CheckBX:
- Cmp bx,319 ; Right Clip
- Jle @DrawIt
- Mov bx,319
- @DrawIt:
- Sub bx,ax
- Inc bx
- Mov cx,bx ; Put Count in CX
- Mov di,ax
- Mov ax,320
- Mov bx,dx
- Mul bx
- Add di,ax
- Mov al,PolyColor
- Mov ah,al
- Shr cx,1
- Jnc @SkipSingle
- Stosb
- @SkipSingle:
- Jcxz @Nothing
- Rep Stosw
- @Nothing:
- Pop dx
- Pop ebx
- Pop eax
- EndM
-
-
- Proc DrawPoly Uses es si di,Vert:DWord,Num:Word,Col:Byte,PgSg:Word
- ;; VERT is a list of screen points
- ;; NUM is the number of points
- ;; COL is the color to draw the polygon
- ;; PGSG is the segment pointer to the screen
- Mov al,Col
- Mov PolyColor,al
- Mov es,PgSg
- Mov ax,Num
- Mov Edges,ax
- ;;; Find minimum and maximum values
- FINDMINMAX
- ;;; Set up initial start an end vertex indicies
- Mov ax,StartVert1
- Mov StartVert2,ax
- Dec ax
- Jns @SkipV1Reset
- Mov ax,Num
- Dec ax
- @SkipV1Reset:
- Mov EndVert1,ax ; EVert1 := StartVert1 - 1;
- Mov ax,StartVert2
- Inc ax
- Cmp ax,Num
- Jnz @SkipV2Reset
- Mov ax,0
- @SkipV2Reset: ; EVert2 := StartVert2 + 1;
- Mov EndVert2,ax
- ;;;; Calculate the delta values
- CALCDELTA1
- CALCDELTA2
- ;;;; Begin Main loop
- ; While Edge > 1 do
- @EdgeLooper:
- Mov ax,Edges
- Cmp ax,1
- Jle @ExitTraceLoop
- Push di
- Mov eax,XVal1
- Mov ebx,XVal2
- Shl eax,8 ; Make XVals .8 fixed point
- Shl ebx,8
- Mov cx,Count1
- Shl ecx,16
- Mov cx,Count2
- Mov dx,YCount
- Push ebp
- Mov ebp,Delta1
- Mov esi,Delta2
- @TraceLoop: ; This is it! This loop draws everything
- Push ecx
- Cmp cx,0 ; Check if count2 is zero yet
- Jle @ExitInnerTraceLoop
- Shr ecx,16
- Cmp cx,0 ; Check if count1 is zero
- Jle @ExitInnerTraceLoop
- HLINE
- Add eax,ebp ; Increment XVal1 by Delta1
- Add ebx,esi ; Increment XVal2 by Delta2
- Pop ecx
- Sub ecx,00010001h ; Subtract 1 from Count1 and Count2
- Inc dx
- Jmp @TraceLoop
- @ExitInnerTraceLoop:
- Shr eax,8
- Mov XVal1,eax ; Store updated XVals
- Shr ebx,8
- Mov XVal2,ebx
- Pop ecx
- Pop ebp
- Pop di
- Mov Count2,cx
- Shr ecx,16
- Mov Count1,cx
- Mov YCount,dx
- ;;;;;; Up date left side vertex
- Mov ax,Count1
- Cmp ax,0 ; Check Count1
- Jg @CheckNext
- Mov ax,EndVert1
- Mov StartVert1,ax
- Dec ax
- Jns @SkipV1Reset2
- Mov ax,Num
- Dec ax
- @SkipV1Reset2:
- Mov EndVert1,ax
- CALCDELTA1
- Dec Edges
- @CheckNext:
- ;;;;;; Update right side vertex
- Mov ax,Count2
- Cmp ax,0
- Jg @SkipCount2
- Mov ax,EndVert2
- Mov StartVert2,ax
- Inc ax
- Cmp ax,Num
- Jnz @SkipV2Reset2
- Mov ax,0
- @SkipV2Reset2:
- Mov EndVert2,ax
- CALCDELTA2
- Dec Edges
- @SkipCount2:
- Jmp @EdgeLooper
- @ExitTraceLoop:
- Ret
- Endp DrawPoly
-
- End