X-Git-Url: http://git.kpe.io/?a=blobdiff_plain;f=libctgraphics%2Fbresenham.cpp;fp=libctgraphics%2Fbresenham.cpp;h=e9936fe0231d8cb44861c927b3cd5de5d002ad0a;hb=bf7295a63667dcca309389ee6dd5328a3a25f22b;hp=0000000000000000000000000000000000000000;hpb=1eb1fcf291b39a016864d78a4060e83cd9046437;p=ctsim.git diff --git a/libctgraphics/bresenham.cpp b/libctgraphics/bresenham.cpp new file mode 100644 index 0000000..e9936fe --- /dev/null +++ b/libctgraphics/bresenham.cpp @@ -0,0 +1,278 @@ +/* ; FILE IDENTIFICATION +; +; Name: CRT_LINE.ASM +; Purpose: Draw lines on screen using Bresenham's integer algorithm +; Programmer: Kevin Rosenberg +; Date Started: 1 Jun 84 +; Last Modification: 15 Jul 85, Version 1.0 +; +; CORRESPONDENCE +; Kevin Rosenberg +; 2515 E. 16th St. +; Newport Beach, CA 92663 +; (714) 642-0119 (voice) +; (714) 842-6348 (E-Mail on Consultant's Exchange RBBS) +; Compuserve 73775,1232 +; +; LANGAUGE +; IBM macro v1.000000000 +; +; LANGAUGE INTERFACE +; Public routines callable from Lattice C v2.0+ +; Works with S & L memory models. Can easily add support for the +; other models by changing the STK structure below. +; +; NEEDED FILES +; egadrive.inc Definitions, macros, & procedures for driving EGA +; hidden.inc Defines OPTIONAL public procedure, crt_hdn_line(). +; dos.mac Lattice's file containing memory model macros +; See inclusion statement for more documentation +; +; GRAPHIC MODES SUPPORTED +; - Standard CGA modes -- BIOS codes 4, 5, & 6 -- are support through +; the ROM BIOS pixel setting routine. Things could be speeded up +; by a factor of 7-15 by writing to the video buffer directly. +; - You may remove support for the CGA completely by changing the +; EQU of STD_GRF to 0, a slight speed increase in EGA operations +; is the gain. +; - All EGA graphic modes are supported with optimized direct pixel +; accessing. Note: mode 13 (320x200) is bugged, see LOG date 6-20-85 +; +; LANGUAGE INTERFACE +; Lattice C v2.0+ +; +; HISTORY LOG +; 7-15-85 +; Released in PD as version 1.0 +; 6-27-85 +; Put EGA routines in INCLUDE file EGADRIVE.INC +; Put Hidden line routines in OPTIONAL INCLUDE file HIDDEN.INC +; 6-20-85 +; Tested with video modes 13 (320x200) & 14 (640x200). Mode 14 worked +; ok, mode 13 was missing every other vertical line: I'm probably +; not setting one of the myriad of registers correctly. Since I'll +; never use mode 13, I won't investigate it further. +; 6-05-85 +; Added & updated documentation +; 2-28-85 +; Added hidden line routines +; PUBLIC crt_hdn_line plus internal routines +; (see function summary for more info) +; 1-20-85 +; Added global variable STD_GRF +; Will support standard graphic modes if it is set to non-zero value; +; however, the slow ROM BIOS is used as well as a slight overhead +; for the EG code. IT IS MUCH FASTER TO USE THE EGA ENHANCED +; (350 line) GRAPHIC MODES. +; 1-09-85 +; Convert to support IBM's Enhanced graphics adapter. +; Remove all optimized code for color graphics adapter (CGA) +; 7-16-84 +; Changed calls to ROM that set pixels to speedy routines which use +; incremental address calculation and direct writing the to graphics +; buffer. +; 1-12-84 +; File creation: +; Converted C function, bresline.c, to assembly langauge. +; Retained C source of Bresenham's integer rastering algorithm +; as comments. +; +; FUNCTION SUMMARY +; +; crt_line_page (page) +; Set graphics page to plot lines on [default = 0] +; +; crt_line_style (style) +; Set line style [Default = solid line] +; +; crt_line (x1, y1, x2, y1, color) +; Plots a line on the screen using Bresenham's integer algorithm +; +; crt_hdn_line (x1, y1, x2, y1, color, col_min, col_max) +; OPTIONAL routine to plots lines using hidden areas +; INCLUDE file HIDDEN.INC if you wish to use this routine +; +; crt_init_hdn (col_min, col_max) +; Initializes vectors for use with crt_hdn_line() +; +; +; int x1, y1 - starting point +; int x2, y2 - end point +; int color - color to draw line, as defined by IBM bios setting +; int linestyle - 16 bit wide dot setting pattern +; int col_min[640] Minimum values for each X column (initialize to 349) +; int col_max[640] Maximum values for each X column (initialize to 0) +; (Do not display any points between the min & max, +; and update these values for each new min & max) +; If a vector == NULL, then do not clip against that +; boundary. +; +; REFERENCES FOR BRESENHAM'S ALGORITHM +; Newman & Sproll, "Principals of Interactive Computer Graphics", +; page 25. +; Foley & van Dam, "Fundementals of Interactive Computer Graphics", +; page 433 +*/ + +;------ Bresenham variables + + deltx dw ? + delty dw ? + absdx dw ? + absdy dw ? + min_inc dw ? ; (-1, 1) indicates direction of minor axis + dinc1 dw ? ; d increment if (d >= 0) + dinc2 dw ? ; d increment if (d < 0) + + + + +;------------------------------------------------------------------------------ +; PROCEDURE +; crt_line [PUBLIC] Plot a line on the screen using Bresenham's alg +; +; SYNOPSIS +; crt_line (x1, y1, x2, y2, color) + +void bresenham (int x1, int y1, int x2, int y2) +{ + delta_x = x2 - x1; + dx_abs = (delta_x >= 0 ? delta_x : -delta_x); + + delta_y = y2 - y1; + dy_abs = (delta_y >= 0 ? delta_y : -delta_y); + +if (dx_abs > dy_abs) + bresx(); +else + bresy(); +} + +lastx= x2; +lasty = y2; + + +;------------------------------------------------------------------------------ +; MACRO NAME +; BRES +; +; FUNCTION +; Do inner most loop to draw pictures +; +; SYNOPSIS +; BRES P1,P2 +; P1 Major axis & direction +; P2 Minor axis +; +; EXAMPLES +; BRES INC_COL,ROW +; +; INPUT +; (DI) Address of local routine to call when setting pixel +; (BX) Decision variable +; (CX) Number of points to plot on major axis (loop counter) +; [bp].min_inc Direction of minor axis increments +; [bp].dinc1 Bresenham decision increments (see references) +; [bp].dinc2 +; MACROS ADDR_INC_ROW, _DEC_ROW, _INC_COL, _DEC_COL +; +; REGISTERS USED BY PIXEL SETTING ROUTINES +; (SI) Offset in EGA buffer +; (AH) Bitmask +; +; REGISTERS AVAILABLE FOR USE +; (AL) +; (DX) +; +; CALLS +; LS_PSET, this routine uses the addr in (DI) to set a point if +; the linestyle allows. +;------------------------------------------------------------------------------ + +BRES MACRO P1,P2 + LOCAL b0,b1 + cmp [bp].min_inc,0 ;if (min_inc >= 0) + jl b0 + _BRES P1,INC_&P2 ; inc_minor_axis + jmp b1 ;else +b0: _BRES P1,DEC_&P2 ; dec_minor_axis +b1: + ENDM + + +_BRES MACRO P1,P2 + LOCAL bres0,bres1,bres2 +bres0: ; do { + LS_PSET ; ls_pset() /* set pix using linestyle */ + + ADDR_&P1 ; P1 (change major axis) + + cmp bx,0 ; + jge bres1 ; if (d < 0) + add bx,[bp].dinc2 ; d += dinc2; + jmp bres2 ; else { +bres1: ; + add bx,[bp].dinc1 ; d += dinc1 + ADDR_&P2 ; P2 (change minor axis) + ; } +bres2: + loop bres0 ; } while (--count > 0) + ENDM + +bresx() +{ + /* draws a line then abs(dx) >= abs(dy) */ + + int npix = dx_abs + 1; + + /* determine direction of minor axis */ + + int min_inc = 1; + if (delta_y < 0) + min_inc = -1; + + /* Put decision variable in d */ + + int d = dy_abs * 2 - dx_abs; + int dinc1 = (dy_abs - dx_abs) * 2; + int dinc2 = 2 * dy_abs; + + if (x1 <= x2) + bres(INC_COL, ROW); + else + breas (DEC_COL, ROW)l + + } + + +void bresy() +{ + /*; bresy [LOCAL] For plotting lines with abs(dy) > abs(sx) + + NOTES + Logic identical to bresx's, substitution x for y and + vice versa. I separate the into two routines rather + than having the main loop spending time determining + which are the major & minor axis. + */ + + + int count = dy_abs + 1; + + /* check direction of minor axis */ + + min_inc = 1; + if (delta_x < 0) + min_inc = -1; + + + int d = dx_abs * 2 - dy_abs; + dinc1 = (dx_abs - dy_abs) * 2; + dinc2 = 2 * dx_abs; + + if (y1 <= y2) + bres(INC_ROW,COL); + else + bres(DEL_ROW,COL); +} +