370 lines
8.3 KiB
C
370 lines
8.3 KiB
C
![]() |
/*
|
||
|
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
|
||
|
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
|
||
|
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
|
||
|
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
|
||
|
IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
|
||
|
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
|
||
|
FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
|
||
|
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
|
||
|
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
|
||
|
COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
||
|
*/
|
||
|
/*
|
||
|
* $Source: /cvsroot/dxx-rebirth/d1x-rebirth/2d/line.c,v $
|
||
|
* $Revision: 1.1.1.1 $
|
||
|
* $Author: zicodxx $
|
||
|
* $Date: 2006/03/17 19:39:00 $
|
||
|
*
|
||
|
* Graphical routines for drawing lines.
|
||
|
*
|
||
|
* $Log: line.c,v $
|
||
|
* Revision 1.1.1.1 2006/03/17 19:39:00 zicodxx
|
||
|
* initial import
|
||
|
*
|
||
|
* Revision 1.3 1999/10/07 02:27:14 donut
|
||
|
* OGL includes to remove warnings
|
||
|
*
|
||
|
* Revision 1.2 1999/09/30 23:02:27 donut
|
||
|
* opengl direct support for ingame and normal menus, fonts as textures, and automap support
|
||
|
*
|
||
|
* Revision 1.1.1.1 1999/06/14 21:57:25 donut
|
||
|
* Import of d1x 1.37 source.
|
||
|
*
|
||
|
* Revision 1.10 1994/11/18 22:50:02 john
|
||
|
* Changed shorts to ints in parameters.
|
||
|
*
|
||
|
* Revision 1.9 1994/07/13 12:03:04 john
|
||
|
* Added assembly modex line-drawer.
|
||
|
*
|
||
|
* Revision 1.8 1993/12/06 18:18:03 john
|
||
|
* took out aaline.
|
||
|
*
|
||
|
* Revision 1.7 1993/12/03 12:11:17 john
|
||
|
* ,
|
||
|
*
|
||
|
* Revision 1.6 1993/11/18 09:40:22 john
|
||
|
* Added laser-line
|
||
|
*
|
||
|
* Revision 1.5 1993/10/15 16:23:36 john
|
||
|
* y
|
||
|
*
|
||
|
* Revision 1.4 1993/09/29 16:13:58 john
|
||
|
* optimized
|
||
|
*
|
||
|
* Revision 1.3 1993/09/26 18:44:12 matt
|
||
|
* Added gr_uline(), which just calls gr_line(), and made both take
|
||
|
* fixes, and shift down themselves.
|
||
|
*
|
||
|
* Revision 1.2 1993/09/11 19:50:15 matt
|
||
|
* In gr_vline() & gr_hline(), check for start > end, and EXCHG if so
|
||
|
*
|
||
|
* Revision 1.1 1993/09/08 11:43:54 john
|
||
|
* Initial revision
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include "u_mem.h"
|
||
|
|
||
|
#include "gr.h"
|
||
|
#include "grdef.h"
|
||
|
#include "fix.h"
|
||
|
|
||
|
#include "clip.h"
|
||
|
|
||
|
#ifdef __MSDOS__
|
||
|
#include "modex.h"
|
||
|
#endif
|
||
|
#ifdef OGL
|
||
|
#include "ogl_init.h"
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
Symmetric Double Step Line Algorithm
|
||
|
by Brian Wyvill
|
||
|
from "Graphics Gems", Academic Press, 1990
|
||
|
*/
|
||
|
|
||
|
/* non-zero flag indicates the pixels needing EXCHG back. */
|
||
|
void plot(int x,int y,int flag)
|
||
|
{ if (flag)
|
||
|
gr_upixel(y, x);
|
||
|
else
|
||
|
gr_upixel(x, y);
|
||
|
}
|
||
|
|
||
|
int gr_hline(int x1, int x2, int y)
|
||
|
{ int i;
|
||
|
|
||
|
if (x1 > x2) EXCHG(x1,x2);
|
||
|
for (i=x1; i<=x2; i++ )
|
||
|
gr_upixel( i, y );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int gr_vline(int y1, int y2, int x)
|
||
|
{ int i;
|
||
|
if (y1 > y2) EXCHG(y1,y2);
|
||
|
for (i=y1; i<=y2; i++ )
|
||
|
gr_upixel( x, i );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void gr_universal_uline(int a1, int b1, int a2, int b2)
|
||
|
{
|
||
|
int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
|
||
|
int x1, y1;
|
||
|
int sign_x = 1, sign_y = 1, step, reverse, i;
|
||
|
|
||
|
if (a1==a2) {
|
||
|
gr_vline(b1,b2,a1);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (b1==b2) {
|
||
|
gr_hline(a1,a2,b1);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
dx = a2 - a1;
|
||
|
dy = b2 - b1;
|
||
|
|
||
|
if (dx < 0) {
|
||
|
sign_x = -1;
|
||
|
dx *= -1;
|
||
|
}
|
||
|
if (dy < 0) {
|
||
|
sign_y = -1;
|
||
|
dy *= -1;
|
||
|
}
|
||
|
|
||
|
/* decide increment sign by the slope sign */
|
||
|
if (sign_x == sign_y)
|
||
|
step = 1;
|
||
|
else
|
||
|
step = -1;
|
||
|
|
||
|
if (dy > dx) { /* chooses axis of greatest movement (make * dx) */
|
||
|
EXCHG(a1, b1);
|
||
|
EXCHG(a2, b2);
|
||
|
EXCHG(dx, dy);
|
||
|
reverse = 1;
|
||
|
} else
|
||
|
reverse = 0;
|
||
|
/* note error check for dx==0 should be included here */
|
||
|
if (a1 > a2) { /* start from the smaller coordinate */
|
||
|
x = a2;
|
||
|
y = b2;
|
||
|
x1 = a1;
|
||
|
y1 = b1;
|
||
|
} else {
|
||
|
x = a1;
|
||
|
y = b1;
|
||
|
x1 = a2;
|
||
|
y1 = b2;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Note dx=n implies 0 - n or (dx+1) pixels to be set */
|
||
|
/* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
|
||
|
/* In fact (dx-1)/4 as 2 pixels are already plottted */
|
||
|
xend = (dx - 1) / 4;
|
||
|
pixels_left = (dx - 1) % 4; /* number of pixels left over at the
|
||
|
* end */
|
||
|
plot(x, y, reverse);
|
||
|
plot(x1, y1, reverse); /* plot first two points */
|
||
|
incr2 = 4 * dy - 2 * dx;
|
||
|
if (incr2 < 0) { /* slope less than 1/2 */
|
||
|
c = 2 * dy;
|
||
|
incr1 = 2 * c;
|
||
|
D = incr1 - dx;
|
||
|
|
||
|
for (i = 0; i < xend; i++) { /* plotting loop */
|
||
|
++x;
|
||
|
--x1;
|
||
|
if (D < 0) {
|
||
|
/* pattern 1 forwards */
|
||
|
plot(x, y, reverse);
|
||
|
plot(++x, y, reverse);
|
||
|
/* pattern 1 backwards */
|
||
|
plot(x1, y1, reverse);
|
||
|
plot(--x1, y1, reverse);
|
||
|
D += incr1;
|
||
|
} else {
|
||
|
if (D < c) {
|
||
|
/* pattern 2 forwards */
|
||
|
plot(x, y, reverse);
|
||
|
plot(++x, y += step, reverse);
|
||
|
/* pattern 2 backwards */
|
||
|
plot(x1, y1, reverse);
|
||
|
plot(--x1, y1 -= step, reverse);
|
||
|
} else {
|
||
|
/* pattern 3 forwards */
|
||
|
plot(x, y += step, reverse);
|
||
|
plot(++x, y, reverse);
|
||
|
/* pattern 3 backwards */
|
||
|
plot(x1, y1 -= step, reverse);
|
||
|
plot(--x1, y1, reverse);
|
||
|
}
|
||
|
D += incr2;
|
||
|
}
|
||
|
} /* end for */
|
||
|
|
||
|
/* plot last pattern */
|
||
|
if (pixels_left) {
|
||
|
if (D < 0) {
|
||
|
plot(++x, y, reverse); /* pattern 1 */
|
||
|
if (pixels_left > 1)
|
||
|
plot(++x, y, reverse);
|
||
|
if (pixels_left > 2)
|
||
|
plot(--x1, y1, reverse);
|
||
|
} else {
|
||
|
if (D < c) {
|
||
|
plot(++x, y, reverse); /* pattern 2 */
|
||
|
if (pixels_left > 1)
|
||
|
plot(++x, y += step, reverse);
|
||
|
if (pixels_left > 2)
|
||
|
plot(--x1, y1, reverse);
|
||
|
} else {
|
||
|
/* pattern 3 */
|
||
|
plot(++x, y += step, reverse);
|
||
|
if (pixels_left > 1)
|
||
|
plot(++x, y, reverse);
|
||
|
if (pixels_left > 2)
|
||
|
plot(--x1, y1 -= step, reverse);
|
||
|
}
|
||
|
}
|
||
|
} /* end if pixels_left */
|
||
|
}
|
||
|
/* end slope < 1/2 */
|
||
|
else { /* slope greater than 1/2 */
|
||
|
c = 2 * (dy - dx);
|
||
|
incr1 = 2 * c;
|
||
|
D = incr1 + dx;
|
||
|
for (i = 0; i < xend; i++) {
|
||
|
++x;
|
||
|
--x1;
|
||
|
if (D > 0) {
|
||
|
/* pattern 4 forwards */
|
||
|
plot(x, y += step, reverse);
|
||
|
plot(++x, y += step, reverse);
|
||
|
/* pattern 4 backwards */
|
||
|
plot(x1, y1 -= step, reverse);
|
||
|
plot(--x1, y1 -= step, reverse);
|
||
|
D += incr1;
|
||
|
} else {
|
||
|
if (D < c) {
|
||
|
/* pattern 2 forwards */
|
||
|
plot(x, y, reverse);
|
||
|
plot(++x, y += step, reverse);
|
||
|
|
||
|
/* pattern 2 backwards */
|
||
|
plot(x1, y1, reverse);
|
||
|
plot(--x1, y1 -= step, reverse);
|
||
|
} else {
|
||
|
/* pattern 3 forwards */
|
||
|
plot(x, y += step, reverse);
|
||
|
plot(++x, y, reverse);
|
||
|
/* pattern 3 backwards */
|
||
|
plot(x1, y1 -= step, reverse);
|
||
|
plot(--x1, y1, reverse);
|
||
|
}
|
||
|
D += incr2;
|
||
|
}
|
||
|
} /* end for */
|
||
|
/* plot last pattern */
|
||
|
if (pixels_left) {
|
||
|
if (D > 0) {
|
||
|
plot(++x, y += step, reverse); /* pattern 4 */
|
||
|
if (pixels_left > 1)
|
||
|
plot(++x, y += step, reverse);
|
||
|
if (pixels_left > 2)
|
||
|
plot(--x1, y1 -= step, reverse);
|
||
|
} else {
|
||
|
if (D < c) {
|
||
|
plot(++x, y, reverse); /* pattern 2 */
|
||
|
if (pixels_left > 1)
|
||
|
plot(++x, y += step, reverse);
|
||
|
if (pixels_left > 2)
|
||
|
plot(--x1, y1, reverse);
|
||
|
} else {
|
||
|
/* pattern 3 */
|
||
|
plot(++x, y += step, reverse);
|
||
|
if (pixels_left > 1)
|
||
|
plot(++x, y, reverse);
|
||
|
if (pixels_left > 2) {
|
||
|
if (D > c) /* step 3 */
|
||
|
plot(--x1, y1 -= step, reverse);
|
||
|
else /* step 2 */
|
||
|
plot(--x1, y1, reverse);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//unclipped version just calls clipping version for now
|
||
|
int gr_uline(fix _a1, fix _b1, fix _a2, fix _b2)
|
||
|
{
|
||
|
int a1,b1,a2,b2;
|
||
|
a1 = f2i(_a1); b1 = f2i(_b1); a2 = f2i(_a2); b2 = f2i(_b2);
|
||
|
switch(TYPE)
|
||
|
{
|
||
|
#ifdef OGL
|
||
|
case BM_OGL:
|
||
|
ogl_ulinec(a1,b1,a2,b2,COLOR);
|
||
|
return 0;
|
||
|
#endif
|
||
|
case BM_LINEAR:
|
||
|
#ifdef NO_ASM
|
||
|
gr_universal_uline( a1,b1,a2,b2);
|
||
|
#else
|
||
|
gr_linear_line( a1, b1, a2, b2 );
|
||
|
#endif
|
||
|
return 0;
|
||
|
#ifdef __MSDOS__
|
||
|
case BM_MODEX:
|
||
|
modex_line_x1 = a1+XOFFSET;
|
||
|
modex_line_y1 = b1+YOFFSET;
|
||
|
modex_line_x2 = a2+XOFFSET;
|
||
|
modex_line_y2 = b2+YOFFSET;
|
||
|
modex_line_Color = grd_curcanv->cv_color;
|
||
|
gr_modex_line();
|
||
|
return 0;
|
||
|
default:
|
||
|
gr_universal_uline( a1, b1, a2, b2 );
|
||
|
return 0;
|
||
|
#endif
|
||
|
}
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
// Returns 0 if drawn with no clipping, 1 if drawn but clipped, and
|
||
|
// 2 if not drawn at all.
|
||
|
|
||
|
int gr_line(fix a1, fix b1, fix a2, fix b2)
|
||
|
{
|
||
|
int x1, y1, x2, y2;
|
||
|
int clipped=0;
|
||
|
|
||
|
x1 = i2f(MINX);
|
||
|
y1 = i2f(MINY);
|
||
|
x2 = i2f(MAXX);
|
||
|
y2 = i2f(MAXY);
|
||
|
|
||
|
CLIPLINE(a1,b1,a2,b2,x1,y1,x2,y2,return 2,clipped=1, FSCALE );
|
||
|
|
||
|
gr_uline( a1, b1, a2, b2 );
|
||
|
|
||
|
return clipped;
|
||
|
|
||
|
}
|
||
|
|
||
|
|