X-Git-Url: http://git.kpe.io/?p=ctsim.git;a=blobdiff_plain;f=libctgraphics%2Fbresenham.cpp;h=070f44e1e5cbdaf0d9ef10dfd86201db716dee9b;hp=e9936fe0231d8cb44861c927b3cd5de5d002ad0a;hb=3ea498d51ce4597e9649cd21f155b51175ea0bea;hpb=bf7295a63667dcca309389ee6dd5328a3a25f22b diff --git a/libctgraphics/bresenham.cpp b/libctgraphics/bresenham.cpp index e9936fe..070f44e 100644 --- a/libctgraphics/bresenham.cpp +++ b/libctgraphics/bresenham.cpp @@ -1,278 +1,95 @@ -/* ; 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() +/***************************************************************************** +** This is part of the CTSim program +** Copyright (c) 1983-2001 Kevin Rosenberg +** +** $Id: bresenham.cpp,v 1.2 2001/03/21 21:45:31 kevin Exp $ +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License (version 2) as +** published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +******************************************************************************/ + +// REFERENCES FOR BRESENHAM'S ALGORITHM +// Newman & Sproll, "Principals of Interactive Computer Graphics", page 25. +// Foley & van Dam, "Fundementals of Interactive Computer Graphics", page 433 + + + +void +bresenham (int x1, int y1, int x2, int y2) { - /* 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 delta_x = x2 - x1; + int dx_abs = (delta_x >= 0 ? delta_x : -delta_x); + + int delta_y = y2 - y1; + int dy_abs = (delta_y >= 0 ? delta_y : -delta_y); + + // draws a line when abs(dx) >= abs(dy) + if (dx_abs > dy_abs) { + int count = dx_abs + 1; + int major_inc = (x1 <= x2 ? 1 : -1); + int min_inc = (delta_y >= 0 ? 1 : -1); // determine direction of minor axis + + int d = dy_abs * 2 - dx_abs; // Put decision variable in d 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. - */ - - + + bresx (x1, y1, major_inc, d, d1, d2); + } else { //For plotting lines with abs(dy) > abs(sx) int count = dy_abs + 1; - - /* check direction of minor axis */ - - min_inc = 1; - if (delta_x < 0) - min_inc = -1; - - + + int major_inc = (y1 <= y2 ? 1 : -1); + int min_inc = (delta_x >= 0 ? 1 : -1); // check direction of minor axis + 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); + + bresy (x1, y1, major_inc, min_inc, count, d, d1, d2); + } } + +static void +bresx (int x, int y, int majorinc, int minorinc, int count, int d, int d1, int d2) +{ + do { + setpixel(); + x += majorinc; + + if (d < 0) + d += dinc2; + else { + d += dinc1; + y += min_inc; + } + } while (--count > 0); +} + + +static void +bresy (int x, int y, int majorinc, int minorinc, int count, int d, int d1, int d2) +{ + do { + setpixel(); + y += majorinc; + + if (d < 0) + d += dinc2; + else { + d += dinc1; + x += min_inc; + } + } while (--count > 0); +} + +