Significantly improve and simplify vector drawing with Bresenham's Line algo.
This commit is contained in:
parent
9c15bfa245
commit
288616fea8
|
@ -1,167 +1,131 @@
|
|||
|
||||
#include "tiles_generic.h"
|
||||
#include "math.h"
|
||||
|
||||
#define TABLE_SIZE 0x10000 // excessive?
|
||||
|
||||
struct vector_line {
|
||||
INT32 x;
|
||||
INT32 y;
|
||||
INT32 color;
|
||||
UINT8 intensity;
|
||||
};
|
||||
|
||||
static struct vector_line *vector_table;
|
||||
struct vector_line *vector_ptr; // pointer
|
||||
static INT32 vector_cnt;
|
||||
|
||||
void vector_add_point(INT32 x, INT32 y, INT32 color, INT32 intensity)
|
||||
{
|
||||
vector_ptr->x = x >> 16;
|
||||
vector_ptr->y = y >> 16;
|
||||
vector_ptr->color = color;
|
||||
vector_ptr->intensity = intensity;
|
||||
|
||||
vector_cnt++;
|
||||
if (vector_cnt > (TABLE_SIZE - 2)) return;
|
||||
vector_ptr++;
|
||||
vector_ptr->color = -1; // mark it as the last one to save some cycles later...
|
||||
}
|
||||
|
||||
static void lineSimple(INT32 x0, INT32 y0, INT32 x1, INT32 y1, INT32 color, INT32 intensity)
|
||||
{
|
||||
INT32 dx = x1 - x0;
|
||||
INT32 dy = y1 - y0;
|
||||
|
||||
color = color * 256 + intensity;
|
||||
|
||||
if (!dx && dy) // vertical line
|
||||
{
|
||||
INT32 sy = (y1 < y0) ? y1 : y0;
|
||||
INT32 y2 = (y1 < y0) ? (y0 - y1) : (y1 - y0);
|
||||
|
||||
if (x1 >= 0 && x1 < nScreenWidth)
|
||||
{
|
||||
UINT16 *dst = pTransDraw + x1;
|
||||
|
||||
for (INT32 y = 0; y < y2; y++, sy++) {
|
||||
if (sy >= 0 && sy < nScreenHeight) {
|
||||
dst[sy * nScreenWidth] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!dy && dx) // horizontal line
|
||||
{
|
||||
INT32 sx = (x1 < x0) ? x1 : x0;
|
||||
INT32 x2 = (x1 < x0) ? (x0 - x1) : (x1 - x0);
|
||||
|
||||
if (y1 >= 0 && y1 < nScreenHeight)
|
||||
{
|
||||
UINT16 *dst = pTransDraw + y1 * nScreenWidth;
|
||||
|
||||
for (INT32 x = 0; x < x2; x++, sx++) {
|
||||
if (sx >= 0 && sx < nScreenWidth) {
|
||||
dst[sx] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (dx && dy) // can we optimize further?
|
||||
{
|
||||
INT32 md = (dy << 16) / dx;
|
||||
INT32 zd = (y0 << 16) - (md * x0) + 0x8000; // + 0x8000 for rounding!
|
||||
|
||||
dx = (x1 > x0) ? 1 : -1;
|
||||
|
||||
while (x0 != x1) {
|
||||
x0 += dx;
|
||||
y0 = ((md * x0) + zd) >> 16;
|
||||
|
||||
if (x0 >= 0 && x0 < nScreenWidth && y0 >= 0 && y0 < nScreenHeight) {
|
||||
pTransDraw[y0 * nScreenWidth + x0] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // point
|
||||
{
|
||||
if (x0 >= 0 && x0 < nScreenWidth && y0 >= 0 && y0 < nScreenHeight) {
|
||||
pTransDraw[y0 * nScreenWidth + x0] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void draw_vector(UINT32 *palette)
|
||||
{
|
||||
struct vector_line *ptr = &vector_table[0];
|
||||
|
||||
INT32 prev_x = 0, prev_y = 0;
|
||||
|
||||
BurnTransferClear();
|
||||
|
||||
for (INT32 i = 0; i < vector_cnt && i < TABLE_SIZE; i++, ptr++)
|
||||
{
|
||||
if (ptr->color == -1) break;
|
||||
|
||||
INT32 curr_y = ptr->y;
|
||||
INT32 curr_x = ptr->x;
|
||||
|
||||
if (ptr->intensity != 0) { // intensity 0 means turn off the beam...
|
||||
lineSimple(curr_x, curr_y, prev_x, prev_y, ptr->color, ptr->intensity);
|
||||
}
|
||||
|
||||
prev_x = curr_x;
|
||||
prev_y = curr_y;
|
||||
}
|
||||
|
||||
BurnTransferCopy(palette);
|
||||
}
|
||||
|
||||
void vector_reset()
|
||||
{
|
||||
vector_cnt = 0;
|
||||
vector_ptr = &vector_table[0];
|
||||
vector_ptr->color = -1;
|
||||
}
|
||||
|
||||
void vector_init()
|
||||
{
|
||||
GenericTilesInit();
|
||||
|
||||
vector_table = (struct vector_line*)malloc(TABLE_SIZE * sizeof(vector_line));
|
||||
|
||||
memset (vector_table, 0, TABLE_SIZE * sizeof(vector_line));
|
||||
|
||||
vector_reset();
|
||||
}
|
||||
|
||||
void vector_exit()
|
||||
{
|
||||
GenericTilesExit();
|
||||
|
||||
free (vector_table);
|
||||
vector_table = NULL;
|
||||
vector_ptr = NULL;
|
||||
}
|
||||
|
||||
INT32 vector_scan(INT32 nAction)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (nAction & ACB_VOLATILE) {
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
|
||||
ba.Data = (UINT8*)vector_table;
|
||||
ba.nLen = TABLE_SIZE * sizeof(vector_line);
|
||||
ba.szName = "Vector Table";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SCAN_VAR(vector_cnt);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
vector_ptr = &vector_table[vector_cnt];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "tiles_generic.h"
|
||||
#include "math.h"
|
||||
|
||||
#define TABLE_SIZE 0x10000 // excessive?
|
||||
|
||||
struct vector_line {
|
||||
INT32 x;
|
||||
INT32 y;
|
||||
INT32 color;
|
||||
UINT8 intensity;
|
||||
};
|
||||
|
||||
static struct vector_line *vector_table;
|
||||
struct vector_line *vector_ptr; // pointer
|
||||
static INT32 vector_cnt;
|
||||
|
||||
void vector_add_point(INT32 x, INT32 y, INT32 color, INT32 intensity)
|
||||
{
|
||||
vector_ptr->x = x >> 16;
|
||||
vector_ptr->y = y >> 16;
|
||||
vector_ptr->color = color;
|
||||
vector_ptr->intensity = intensity;
|
||||
|
||||
vector_cnt++;
|
||||
if (vector_cnt > (TABLE_SIZE - 2)) return;
|
||||
vector_ptr++;
|
||||
vector_ptr->color = -1; // mark it as the last one to save some cycles later...
|
||||
}
|
||||
|
||||
static void lineSimple(INT32 x0, INT32 y0, INT32 x1, INT32 y1, INT32 color, INT32 intensity)
|
||||
{
|
||||
color = color * 256 + intensity;
|
||||
|
||||
// http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm
|
||||
|
||||
INT32 dx = abs(x1 - x0);
|
||||
INT32 dy = abs(y1 - y0);
|
||||
INT32 sx = x0 < x1 ? 1 : -1;
|
||||
INT32 sy = y0 < y1 ? 1 : -1;
|
||||
INT32 err = (dx>dy ? dx : -dy)/2, e2;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (x0 >= 0 && x0 < nScreenWidth && y0 >= 0 && y0 < nScreenHeight) {
|
||||
pTransDraw[y0 * nScreenWidth + x0] = color;
|
||||
}
|
||||
|
||||
if (x0 == x1 && y0 == y1) break;
|
||||
|
||||
e2 = err;
|
||||
|
||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
||||
if (e2 < dy) { err += dx; y0 += sy; }
|
||||
}
|
||||
}
|
||||
|
||||
void draw_vector(UINT32 *palette)
|
||||
{
|
||||
struct vector_line *ptr = &vector_table[0];
|
||||
|
||||
INT32 prev_x = 0, prev_y = 0;
|
||||
|
||||
BurnTransferClear();
|
||||
|
||||
for (INT32 i = 0; i < vector_cnt && i < TABLE_SIZE; i++, ptr++)
|
||||
{
|
||||
if (ptr->color == -1) break;
|
||||
|
||||
INT32 curr_y = ptr->y;
|
||||
INT32 curr_x = ptr->x;
|
||||
|
||||
if (ptr->intensity != 0) { // intensity 0 means turn off the beam...
|
||||
lineSimple(curr_x, curr_y, prev_x, prev_y, ptr->color, ptr->intensity);
|
||||
}
|
||||
|
||||
prev_x = curr_x;
|
||||
prev_y = curr_y;
|
||||
}
|
||||
|
||||
BurnTransferCopy(palette);
|
||||
}
|
||||
|
||||
void vector_reset()
|
||||
{
|
||||
vector_cnt = 0;
|
||||
vector_ptr = &vector_table[0];
|
||||
vector_ptr->color = -1;
|
||||
}
|
||||
|
||||
void vector_init()
|
||||
{
|
||||
GenericTilesInit();
|
||||
|
||||
vector_table = (struct vector_line*)malloc(TABLE_SIZE * sizeof(vector_line));
|
||||
|
||||
memset (vector_table, 0, TABLE_SIZE * sizeof(vector_line));
|
||||
|
||||
vector_reset();
|
||||
}
|
||||
|
||||
void vector_exit()
|
||||
{
|
||||
GenericTilesExit();
|
||||
|
||||
free (vector_table);
|
||||
vector_table = NULL;
|
||||
vector_ptr = NULL;
|
||||
}
|
||||
|
||||
INT32 vector_scan(INT32 nAction)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (nAction & ACB_VOLATILE) {
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
|
||||
ba.Data = (UINT8*)vector_table;
|
||||
ba.nLen = TABLE_SIZE * sizeof(vector_line);
|
||||
ba.szName = "Vector Table";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SCAN_VAR(vector_cnt);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
vector_ptr = &vector_table[vector_cnt];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue