mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-11 04:31:35 -10:00
715 lines
18 KiB
C++
715 lines
18 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* $Logfile: /Freespace2/code/Graphics/aaline.cpp $
|
|
* $Revision: 2.3 $
|
|
* $Date: 2003-03-02 05:42:25 $
|
|
* $Author: penguin $
|
|
*
|
|
* Code to draw antialiased lines
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
* Revision 2.2 2002/08/01 01:41:05 penguin
|
|
* The big include file move
|
|
*
|
|
* Revision 2.1 2002/07/07 19:55:59 penguin
|
|
* Back-port to MSVC
|
|
*
|
|
* Revision 2.0 2002/06/03 04:02:22 penguin
|
|
* Warpcore CVS sync
|
|
*
|
|
* Revision 1.2 2002/05/03 22:07:08 mharris
|
|
* got some stuff to compile
|
|
*
|
|
* Revision 1.1 2002/05/02 18:03:07 mharris
|
|
* Initial checkin - converted filenames and includes to lower case
|
|
*
|
|
*
|
|
* 3 12/02/98 5:47p Dave
|
|
* Put in interface xstr code. Converted barracks screen to new format.
|
|
*
|
|
* 2 10/07/98 10:52a Dave
|
|
* Initial checkin.
|
|
*
|
|
* 1 10/07/98 10:48a Dave
|
|
*
|
|
* 13 5/06/98 5:30p John
|
|
* Removed unused cfilearchiver. Removed/replaced some unused/little used
|
|
* graphics functions, namely gradient_h and _v and pixel_sp. Put in new
|
|
* DirectX header files and libs that fixed the Direct3D alpha blending
|
|
* problems.
|
|
*
|
|
* 12 3/24/98 4:03p Lawrance
|
|
* JOHN: Fix up outline drawing code to support different colors
|
|
*
|
|
* 11 3/10/98 4:18p John
|
|
* Cleaned up graphics lib. Took out most unused gr functions. Made D3D
|
|
* & Glide have popups and print screen. Took out all >8bpp software
|
|
* support. Made Fred zbuffer. Made zbuffer allocate dynamically to
|
|
* support Fred. Made zbuffering key off of functions rather than one
|
|
* global variable.
|
|
*
|
|
* 10 1/19/98 6:15p John
|
|
* Fixed all my Optimized Build compiler warnings
|
|
*
|
|
* 9 11/30/97 4:26p John
|
|
* Added 32-bpp antialiased line. Took gamma out of alphacolor
|
|
* calculation.
|
|
*
|
|
* 8 11/29/97 2:06p John
|
|
* added mode 16-bpp support
|
|
*
|
|
* 7 10/20/97 8:47a John
|
|
* fixed gr_lock bug in aaline
|
|
*
|
|
* 6 10/19/97 12:55p John
|
|
* new code to lock / unlock surfaces for smooth directx integration.
|
|
*
|
|
* 5 10/14/97 8:08a John
|
|
* added a bunch more 16 bit support
|
|
*
|
|
* 4 10/04/97 11:27a John
|
|
* took out debug code
|
|
*
|
|
* 3 10/03/97 9:50a John
|
|
* enabled antialiasing lines in alphacolor set.
|
|
*
|
|
* 2 10/03/97 9:10a John
|
|
* added better antialiased line drawer
|
|
*
|
|
* 1 10/03/97 9:07a John
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
/*
|
|
|
|
Code for drawing antialiased lines. Taken from some code
|
|
published in the Journal of Graphic Tools at www.acm.org/jgt
|
|
|
|
Here is the README that came with the source code:
|
|
|
|
Sample code to draw antialiased lines as described in the Journal of
|
|
Graphic Tools article High Quality Hardware Line Antialiasing by
|
|
Scott R. Nelson of Sun Microsystems.
|
|
|
|
The code is written in C and designed to run on any machine with the
|
|
addition of a proper "display" module. Currently, display modules
|
|
exist for Macintosh, Unix, and Wintel machines. Thanks to Sanjay Gupta
|
|
([email protected]) for the Unix X11 display code and Chris
|
|
Babcock ([email protected]) for the Windows code.
|
|
|
|
This code is not 100% bug free and is definitely not optimized for
|
|
performance. It does, however, illustrate all of the points made in
|
|
the JGT article.
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "globalincs/pstypes.h"
|
|
#include "graphics/2d.h"
|
|
#include "graphics/line.h"
|
|
#include "graphics/grinternal.h"
|
|
#include "palman/palman.h"
|
|
|
|
// Convert from floating-point to internal fixed-point formats
|
|
#define ONE_XY (long int) 0x00100000
|
|
#define FIX_XY_SHIFT (long int) 20
|
|
#define ONEHALF_XY (long int) 0x00080000
|
|
#define ONE_Z (long int) 0x40000000
|
|
#define ONE_RGB (long int) 0x40000000
|
|
#define ONE_16 (long int) 0x4000
|
|
|
|
#define FLOAT_TO_FIX_XY(x) ((long int) ((x) * (float) ONE_XY))
|
|
|
|
#define FLOAT_TO_FIX_RGB(x) ((long int) ((x) * (float) ONE_RGB))
|
|
#define FLOAT_TO_FIX_16(x) ((long int) ((x) * (float) ONE_16))
|
|
#define FIX_TO_INT_XY(x) ((x) >> FIX_XY_SHIFT)
|
|
#define FIX_16_TO_FLOAT(x) ((float) (x) / (float) ONE_16)
|
|
#define FIX_TO_FLOAT_XY(x) ((float) (x) / (float) ONE_XY)
|
|
#define FIX_TO_FLOAT_RGB(x) ((float) (x) / (float) ONE_RGB)
|
|
|
|
// Get fractional part, next lowest integer part
|
|
#define FRACT_XY(x) ((x) & (long int) 0x000fffff)
|
|
#define FLOOR_XY(x) ((x) & (long int) 0xfff00000)
|
|
#define FIX_XY_TO_INT(x) ((long int) (x) >> (long int) FIX_XY_SHIFT)
|
|
|
|
// Sizes for tables in Draw
|
|
#define FILTER_WIDTH 0.75 // Line filter width adjustment // .75 // .5 works good with 5.0 gamma
|
|
#define F_TABLE_SIZE 64 // Filter table size
|
|
#define SC_TABLE_SIZE 32 // Slope correction table size
|
|
#define SRT_INT 5 // Sqrt table index integer bits
|
|
#define SRT_FRACT 4 // ...fraction bits
|
|
#define SR_INT 3 // Square root result integer bits
|
|
#define SR_FRACT 5 // ...fraction bits
|
|
#define SR_TABLE_SIZE (1 << (SRT_INT + SRT_FRACT))
|
|
#define INV_FILTER 47
|
|
|
|
#define EP_MASK (long int) 0x000f0000u // AA line end-point filter mask
|
|
#define EP_SHIFT 13u // Number of bits to shift end-point
|
|
|
|
|
|
typedef long int fix_xy; // S11.20
|
|
|
|
// One vertex at any of the various stages of the pipeline
|
|
|
|
typedef struct aa_vertex {
|
|
float x, y;
|
|
} aa_vertex;
|
|
|
|
// All values needed to draw one line
|
|
typedef struct aa_setup_line {
|
|
int x_major;
|
|
int negative;
|
|
|
|
fix_xy vs; // Starting point
|
|
fix_xy us;
|
|
fix_xy ue; // End (along major axis)
|
|
fix_xy dvdu; // Delta for minor axis step
|
|
|
|
} aa_setup_line;
|
|
|
|
|
|
// Tables that need to be initialized
|
|
long int slope_corr_table[SC_TABLE_SIZE];
|
|
long int filter_table[F_TABLE_SIZE];
|
|
long int sqrt_table[SR_TABLE_SIZE];
|
|
|
|
ubyte new_table[F_TABLE_SIZE*512];
|
|
|
|
int aaline_inited = 0;
|
|
|
|
// Initialize the tables normally found in ROM in the hardware.
|
|
void aaline_init_tables()
|
|
{
|
|
int i,j; // Iterative counter
|
|
double m; // Slope
|
|
double d; // Distance from center of curve
|
|
double v; // Value to put in table
|
|
double sr; // The square root value
|
|
|
|
aaline_inited = 1;
|
|
|
|
// Build slope correction table. The index into this table
|
|
// is the truncated 5-bit fraction of the slope used to draw
|
|
// the line. Round the computed values here to get the closest
|
|
// fit for all slopes matching an entry.
|
|
|
|
for (i = 0; i < SC_TABLE_SIZE; i++) {
|
|
// Round and make a fraction
|
|
m = ((double) i + 0.5) / (float) SC_TABLE_SIZE;
|
|
v = sqrt(m * m + 1) * 0.707106781; /* (m + 1)^2 / sqrt(2) */
|
|
slope_corr_table[i] = (long int) (v * 256.0);
|
|
}
|
|
|
|
// Build the Gaussian filter table, round to the middle of the sample region.
|
|
for (i = 0; i < F_TABLE_SIZE; i++) {
|
|
d = ((double) i + 0.5) / (float) (F_TABLE_SIZE / 2.0);
|
|
d = d / FILTER_WIDTH;
|
|
v = 1.0 / exp(d * d); // Gaussian function
|
|
filter_table[i] = (long int) (v * 256.0);
|
|
}
|
|
|
|
for ( i=0; i<512; i++ ) {
|
|
long int corr_slope = i<<8;
|
|
for (j=0; j<F_TABLE_SIZE; j++ ) {
|
|
new_table[i*F_TABLE_SIZE+j] = (ubyte)(((corr_slope * filter_table[j]) & 0xf00000) >> (16+4));
|
|
if (new_table[i*F_TABLE_SIZE+j]==15 ) {
|
|
// HACK!!! Account for "glass" pixel for hud bitmaps.
|
|
new_table[i*F_TABLE_SIZE+j] = 14;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Build the square root table for big dots.
|
|
for (i = 0; i < SR_TABLE_SIZE; i++) {
|
|
v = (double) ((i << 1) + 1) / (double) (1 << (SRT_FRACT + 1));
|
|
sr = sqrt(v);
|
|
sqrt_table[i] = (long int) (sr * (double) (1 << SR_FRACT));
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Multiply a fixed-point number by a s11.20 fixed-point
|
|
// number. The actual multiply uses less bits for the
|
|
// multiplier, since it always represents a fraction
|
|
// less than 1.0 and less total bits are sufficient.
|
|
// Some of the steps here are not needed. This was originally
|
|
// written to simulate exact hardware behavior.
|
|
#if defined _WIN32
|
|
long int fix_xy_mult(long int oa, fix_xy ob)
|
|
{
|
|
int retval;
|
|
|
|
#if defined _MSC_VER
|
|
_asm {
|
|
mov edx, oa
|
|
mov eax, ob
|
|
imul edx
|
|
shrd eax,edx,20
|
|
mov retval, eax
|
|
}
|
|
#elif defined __GNUC__
|
|
asm(
|
|
"mov %1,%%edx;"
|
|
"mov %2,%%eax;"
|
|
"imul %%edx;"
|
|
"shrd $20,%%eax,%%edx;"
|
|
"mov %%eax,%0"
|
|
: "=g" (retval) // outputs
|
|
: "g" (oa), "g" (ob) // inputs
|
|
: "eax", "edx" // clobbered registers
|
|
);
|
|
#else
|
|
#error unknown compiler
|
|
#endif
|
|
return retval;
|
|
}
|
|
#else
|
|
#error unknown OS
|
|
long int fix_xy_mult(long int oa, fix_xy ob);
|
|
#endif
|
|
|
|
|
|
|
|
// Draw one span of an antialiased line (for horizontal lines).
|
|
void draw_aa_hspan8(fix_xy x, fix_xy y, long int ep_corr, long int slope)
|
|
{
|
|
#ifndef HARDWARE_ONLY
|
|
long int sample_dist; // Distance from line to sample point
|
|
long int filter_index; // Index into filter table
|
|
long int i; // Count pixels across span
|
|
long int index; // Final filter table index
|
|
int a; // Alpha
|
|
|
|
sample_dist = (FRACT_XY(y) >> (FIX_XY_SHIFT - 5)) - 16;
|
|
y = y - ONE_XY;
|
|
filter_index = sample_dist + 32;
|
|
|
|
|
|
int yi = FIX_XY_TO_INT( y );
|
|
int xi = FIX_XY_TO_INT( x );
|
|
|
|
if ( xi < gr_screen.clip_left ) return;
|
|
if ( xi > gr_screen.clip_right ) return;
|
|
|
|
int clipped = 0;
|
|
|
|
if ( yi < gr_screen.clip_top ) clipped++;
|
|
if ( yi+3 > gr_screen.clip_bottom ) clipped++;
|
|
|
|
long int corr_slope = (slope * ep_corr) & 0x1ff00;
|
|
|
|
ubyte * lookup = (ubyte *)&Current_alphacolor->table.lookup[0][0];
|
|
|
|
ubyte * filter_lookup = (ubyte *)&new_table[(corr_slope>>8)*F_TABLE_SIZE];
|
|
|
|
|
|
if ( clipped ) {
|
|
ubyte * dptr;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (filter_index < 0)
|
|
index = ~filter_index; // Invert when negative
|
|
else
|
|
index = filter_index;
|
|
|
|
if (index > INV_FILTER) {
|
|
Assert( i == 3 );
|
|
return; // Not a valid pixel
|
|
}
|
|
|
|
//a = ((corr_slope * filter_table[index]) & 0xf00000) >> (16+4-8);
|
|
a = filter_lookup[index]<<8;
|
|
|
|
// Should include the alpha value as well...
|
|
if ( (yi >= gr_screen.clip_top) && (yi <= gr_screen.clip_bottom) ) {
|
|
dptr = GR_SCREEN_PTR(ubyte,xi, yi);
|
|
|
|
*dptr = lookup[*dptr+a];
|
|
}
|
|
|
|
filter_index -= 32;
|
|
//y += ONE_XY;
|
|
yi++;
|
|
}
|
|
} else {
|
|
ubyte * dptr;
|
|
|
|
dptr = GR_SCREEN_PTR(ubyte,xi, yi);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (filter_index < 0)
|
|
index = ~filter_index; // Invert when negative
|
|
else
|
|
index = filter_index;
|
|
|
|
if (index > INV_FILTER) {
|
|
Assert( i == 3 );
|
|
return; // Not a valid pixel
|
|
}
|
|
|
|
a = filter_lookup[index]<<8;
|
|
|
|
// Should include the alpha value as well...
|
|
*dptr = lookup[*dptr+a];
|
|
|
|
dptr += gr_screen.rowsize;
|
|
|
|
filter_index -= 32;
|
|
}
|
|
|
|
|
|
}
|
|
#else
|
|
Int3();
|
|
#endif
|
|
}
|
|
|
|
// draw_aa_vspan
|
|
// Draw one span of an antialiased line (for vertical lines).
|
|
|
|
void draw_aa_vspan8(fix_xy x, fix_xy y, long int ep_corr, long int slope)
|
|
{
|
|
#ifndef HARDWARE_ONLY
|
|
long int sample_dist; // Distance from line to sample point
|
|
long int filter_index; // Index into filter table
|
|
long int i; // Count pixels across span
|
|
long int index; // Final filter table index
|
|
int a; // Alpha
|
|
|
|
sample_dist = (FRACT_XY(x) >> (FIX_XY_SHIFT - 5)) - 16;
|
|
x = x - ONE_XY;
|
|
filter_index = sample_dist + 32;
|
|
|
|
int yi = FIX_XY_TO_INT( y );
|
|
int xi = FIX_XY_TO_INT( x );
|
|
|
|
if ( yi < gr_screen.clip_top ) return;
|
|
if ( yi > gr_screen.clip_bottom ) return;
|
|
|
|
int clipped = 0;
|
|
|
|
if ( xi < gr_screen.clip_left ) clipped++;
|
|
if ( xi+3 > gr_screen.clip_right ) clipped++;
|
|
|
|
long int corr_slope = (slope * ep_corr) & 0x1ff00;
|
|
|
|
ubyte * lookup = (ubyte *)&Current_alphacolor->table.lookup[0][0];
|
|
|
|
ubyte * filter_lookup = (ubyte *)&new_table[(corr_slope>>8)*F_TABLE_SIZE];
|
|
|
|
|
|
if ( clipped ) {
|
|
ubyte * dptr;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (filter_index < 0)
|
|
index = ~filter_index; // Invert when negative
|
|
else
|
|
index = filter_index;
|
|
|
|
if (index > INV_FILTER) {
|
|
Assert( i == 3 );
|
|
return; // Not a valid pixel
|
|
}
|
|
|
|
//a = ((corr_slope * filter_table[index]) & 0xf00000) >> (16+4-8);
|
|
a = filter_lookup[index]<<8;
|
|
|
|
// Draw the pixel
|
|
if ( (xi >= gr_screen.clip_left) && (xi <= gr_screen.clip_right) ) {
|
|
dptr = GR_SCREEN_PTR(ubyte,xi, yi);
|
|
|
|
*dptr = lookup[*dptr+a];
|
|
}
|
|
|
|
filter_index -= 32;
|
|
xi++;
|
|
}
|
|
} else {
|
|
|
|
ubyte *dptr = GR_SCREEN_PTR(ubyte,xi, yi);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (filter_index < 0)
|
|
index = ~filter_index; // Invert when negative
|
|
else
|
|
index = filter_index;
|
|
|
|
if (index > INV_FILTER) {
|
|
Assert( i == 3 );
|
|
return; // Not a valid pixel
|
|
}
|
|
|
|
a = filter_lookup[index]<<8;
|
|
|
|
// Should include the alpha value as well...
|
|
|
|
// Draw the pixel
|
|
*dptr = lookup[*dptr+a];
|
|
|
|
filter_index -= 32;
|
|
dptr++;
|
|
}
|
|
}
|
|
#else
|
|
Int3();
|
|
#endif
|
|
}
|
|
|
|
|
|
void draw_line(aa_setup_line *line)
|
|
{
|
|
fix_xy x, y; // Start value
|
|
fix_xy dudu; // Constant 1 or -1 for step
|
|
fix_xy dx, dy; // Steps in X and Y
|
|
fix_xy u_off; // Offset to starting sample grid
|
|
fix_xy us, vs, ue; // Start and end for drawing
|
|
fix_xy count; // How many pixels to draw
|
|
long int slope_index; // Index into slope correction table
|
|
long int slope; // Slope correction value
|
|
long int ep_corr; // End-point correction value
|
|
long int scount, ecount; // Start/end count for endpoints
|
|
long int sf, ef; // Sand and end fractions
|
|
long int ep_code; // One of 9 endpoint codes
|
|
|
|
// Get directions
|
|
if (line->negative) {
|
|
dudu = -ONE_XY;
|
|
} else {
|
|
dudu = ONE_XY;
|
|
}
|
|
|
|
if (line->x_major) {
|
|
dx = dudu;
|
|
dy = line->dvdu;
|
|
} else {
|
|
dx = line->dvdu;
|
|
dy = dudu;
|
|
}
|
|
|
|
// Get initial values and count
|
|
if (line->negative) {
|
|
u_off = FRACT_XY(line->us) - ONE_XY;
|
|
us = line->us + ONE_XY;
|
|
ue = line->ue;
|
|
count = FLOOR_XY(us) - FLOOR_XY(ue);
|
|
} else {
|
|
u_off = 0 - FRACT_XY(line->us);
|
|
us = line->us;
|
|
ue = line->ue + ONE_XY;
|
|
count = FLOOR_XY(ue) - FLOOR_XY(us);
|
|
}
|
|
|
|
vs = line->vs + fix_xy_mult(line->dvdu, u_off) + ONEHALF_XY;
|
|
|
|
if (line->x_major) {
|
|
x = us;
|
|
y = vs;
|
|
} else {
|
|
x = vs;
|
|
y = us;
|
|
}
|
|
|
|
//a = line->as + fix_xy_mult(line->dadu, u_off);
|
|
|
|
// Compute slope correction once per line
|
|
slope_index = (line->dvdu >> (FIX_XY_SHIFT - 5)) & 0x3fu;
|
|
|
|
if (line->dvdu < 0) {
|
|
slope_index ^= 0x3fu;
|
|
}
|
|
|
|
if ((slope_index & 0x20u) == 0) {
|
|
slope = slope_corr_table[slope_index];
|
|
} else {
|
|
slope = 0x100; /* True 1.0 */
|
|
}
|
|
|
|
// Set up counters for determining endpoint regions
|
|
scount = 0;
|
|
ecount = FIX_TO_INT_XY(count);
|
|
|
|
// Get 4-bit fractions for end-point adjustments
|
|
sf = (us & EP_MASK) >> EP_SHIFT;
|
|
ef = (ue & EP_MASK) >> EP_SHIFT;
|
|
|
|
// Interpolate the edges
|
|
while (count >= 0) {
|
|
|
|
/*-
|
|
* Compute end-point code (defined as follows):
|
|
* 0 = 0, 0: short, no boundary crossing
|
|
* 1 = 0, 1: short line overlap (< 1.0)
|
|
* 2 = 0, 2: 1st pixel of 1st endpoint
|
|
* 3 = 1, 0: short line overlap (< 1.0)
|
|
* 4 = 1, 1: short line overlap (> 1.0)
|
|
* 5 = 1, 2: 2nd pixel of 1st endpoint
|
|
* 6 = 2, 0: last of 2nd endpoint
|
|
* 7 = 2, 1: first of 2nd endpoint
|
|
* 8 = 2, 2: regular part of line
|
|
*/
|
|
|
|
ep_code = ((scount < 2) ? scount : 2) * 3 + ((ecount < 2) ? ecount : 2);
|
|
|
|
if (line->negative) {
|
|
|
|
// Drawing in the negative direction
|
|
|
|
// Compute endpoint information
|
|
switch (ep_code) {
|
|
case 0: ep_corr = 0; break;
|
|
case 1: ep_corr = ((sf - ef) & 0x78) | 4; break;
|
|
case 2: ep_corr = sf | 4; break;
|
|
case 3: ep_corr = ((sf - ef) & 0x78) | 4; break;
|
|
case 4: ep_corr = ((sf - ef) + 0x80) | 4; break;
|
|
case 5: ep_corr = (sf + 0x80) | 4; break;
|
|
case 6: ep_corr = (0x78 - ef) | 4; break;
|
|
case 7: ep_corr = ((0x78 - ef) + 0x80) | 4; break;
|
|
case 8: ep_corr = 0x100; break;
|
|
default: ep_corr = 0; break;
|
|
}
|
|
|
|
} else {
|
|
// Drawing in the positive direction
|
|
|
|
// Compute endpoint information
|
|
switch (ep_code) {
|
|
case 0: ep_corr = 0; break;
|
|
case 1: ep_corr = ((ef - sf) & 0x78) | 4; break;
|
|
case 2: ep_corr = (0x78 - sf) | 4; break;
|
|
case 3: ep_corr = ((ef - sf) & 0x78) | 4; break;
|
|
case 4: ep_corr = ((ef - sf) + 0x80) | 4; break;
|
|
case 5: ep_corr = ((0x78 - sf) + 0x80) | 4; break;
|
|
case 6: ep_corr = ef | 4; break;
|
|
case 7: ep_corr = (ef + 0x80) | 4; break;
|
|
case 8: ep_corr = 0x100; break;
|
|
default: ep_corr = 0; break;
|
|
}
|
|
}
|
|
|
|
if (line->x_major) {
|
|
draw_aa_hspan8(x, y, ep_corr, slope);
|
|
} else {
|
|
draw_aa_vspan8(x, y, ep_corr, slope);
|
|
}
|
|
|
|
x += dx;
|
|
y += dy;
|
|
//a += line->dadu;
|
|
|
|
scount++;
|
|
ecount--;
|
|
count -= ONE_XY;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Perform the setup operation for a line, then draw it
|
|
|
|
void aaline_setup(aa_vertex *v1, aa_vertex *v2)
|
|
{
|
|
float dx, dy; // Deltas in X and Y
|
|
float udx, udy; // Positive version of deltas
|
|
float one_du; // 1.0 / udx or udy
|
|
aa_setup_line line;
|
|
|
|
if ( !aaline_inited )
|
|
aaline_init_tables();
|
|
|
|
|
|
dx = v1->x - v2->x;
|
|
dy = v1->y - v2->y;
|
|
|
|
if (dx < 0.0) {
|
|
udx = -dx;
|
|
} else {
|
|
udx = dx;
|
|
}
|
|
|
|
if (dy < 0.0) {
|
|
udy = -dy;
|
|
} else {
|
|
udy = dy;
|
|
}
|
|
|
|
if (udx > udy) {
|
|
// X major line
|
|
line.x_major = 1;
|
|
line.negative = (dx < 0.0);
|
|
line.us = FLOAT_TO_FIX_XY(v2->x);
|
|
line.vs = FLOAT_TO_FIX_XY(v2->y);
|
|
line.ue = FLOAT_TO_FIX_XY(v1->x);
|
|
one_du = 1.0f / udx;
|
|
line.dvdu = FLOAT_TO_FIX_XY(dy * one_du);
|
|
} else {
|
|
// Y major line
|
|
line.x_major = 0;
|
|
line.negative = (dy < 0.0);
|
|
line.us = FLOAT_TO_FIX_XY(v2->y);
|
|
line.vs = FLOAT_TO_FIX_XY(v2->x);
|
|
line.ue = FLOAT_TO_FIX_XY(v1->y);
|
|
one_du = 1.0f / udy;
|
|
line.dvdu = FLOAT_TO_FIX_XY(dx * one_du);
|
|
}
|
|
|
|
// Convert colors to fixed-point
|
|
//line.as = FLOAT_TO_FIX_RGB(v2->a);
|
|
|
|
// Compute delta values for colors
|
|
//line.dadu = FLOAT_TO_FIX_RGB((v1->a - v2->a) * one_du);
|
|
|
|
// Now go draw it
|
|
|
|
gr_lock();
|
|
draw_line(&line);
|
|
gr_unlock();
|
|
}
|
|
|
|
|
|
void gr8_aaline( vertex *v1, vertex *v2 )
|
|
{
|
|
aa_vertex aa1, aa2;
|
|
|
|
if ( !Current_alphacolor ) {
|
|
gr_line(fl2i(v1->sx),fl2i(v1->sy),fl2i(v2->sx),fl2i(v2->sy));
|
|
return;
|
|
}
|
|
|
|
// return;
|
|
|
|
aa1.x = v1->sx;
|
|
aa1.y = v1->sy;
|
|
|
|
aa2.x = v2->sx;
|
|
aa2.y = v2->sy;
|
|
|
|
{
|
|
int clipped = 0, swapped = 0;
|
|
float a1, b1, a2, b2;
|
|
a1 = (float)gr_screen.clip_left;
|
|
b1 = (float)gr_screen.clip_top;
|
|
a2 = (float)gr_screen.clip_right;
|
|
b2 = (float)gr_screen.clip_bottom;
|
|
|
|
FL_CLIPLINE(aa1.x,aa1.y,aa2.x,aa2.y,a1,b1,a2,b2,return,clipped=1,swapped=1);
|
|
}
|
|
|
|
aaline_setup( &aa1, &aa2 );
|
|
}
|