Line clipping is now handled correctly; fixes #28 (one pixel
corruptions) and #198 (beam weapons changing direction) git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@832 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
Changes towards version 0.3:
|
Changes towards version 0.3:
|
||||||
|
- Line clipping is now handled correctly; fixes #28 (one pixel corruptions)
|
||||||
|
and #198 (beam weapons changing direction)
|
||||||
- Vux warps in close (fixes bug 93) -from Nic
|
- Vux warps in close (fixes bug 93) -from Nic
|
||||||
- Fixed lockup on lander-report (Bug #144 annd 187?)
|
- Fixed lockup on lander-report (Bug #144 annd 187?)
|
||||||
- Version # is now printed in the main menu, from Nic
|
- Version # is now printed in the main menu, from Nic
|
||||||
|
|||||||
@@ -10,38 +10,10 @@ TFB_DrawCanvas_Line (int x1, int y1, int x2, int y2, int r, int g, int b, TFB_Ca
|
|||||||
{
|
{
|
||||||
Uint32 color;
|
Uint32 color;
|
||||||
PutPixelFn screen_plot;
|
PutPixelFn screen_plot;
|
||||||
SDL_Rect rect;
|
|
||||||
|
|
||||||
screen_plot = putpixel_for (target);
|
screen_plot = putpixel_for (target);
|
||||||
color = SDL_MapRGB (((NativeCanvas) target)->format, r, g, b);
|
color = SDL_MapRGB (((NativeCanvas) target)->format, r, g, b);
|
||||||
|
|
||||||
SDL_GetClipRect((NativeCanvas) target, &rect);
|
|
||||||
|
|
||||||
/* Danger, Will Robinson! This code
|
|
||||||
looks VERY suspicious. It will end
|
|
||||||
up changing the slope of the
|
|
||||||
line! */
|
|
||||||
|
|
||||||
if (x1 < rect.x)
|
|
||||||
x1 = rect.x;
|
|
||||||
else if (x1 > rect.x + rect.w)
|
|
||||||
x1 = rect.x + rect.w;
|
|
||||||
|
|
||||||
if (x2 < rect.x)
|
|
||||||
x2 = rect.x;
|
|
||||||
else if (x2 > rect.x + rect.w)
|
|
||||||
x2 = rect.x + rect.w;
|
|
||||||
|
|
||||||
if (y1 < rect.y)
|
|
||||||
y1 = rect.y;
|
|
||||||
else if (y1 > rect.y + rect.h)
|
|
||||||
y1 = rect.y + rect.h;
|
|
||||||
|
|
||||||
if (y2 < rect.y)
|
|
||||||
y2 = rect.y;
|
|
||||||
else if (y2 > rect.y + rect.h)
|
|
||||||
y2 = rect.y + rect.h;
|
|
||||||
|
|
||||||
SDL_LockSurface ((NativeCanvas) target);
|
SDL_LockSurface ((NativeCanvas) target);
|
||||||
line (x1, y1, x2, y2, color, screen_plot, (NativeCanvas) target);
|
line (x1, y1, x2, y2, color, screen_plot, (NativeCanvas) target);
|
||||||
SDL_UnlockSurface ((NativeCanvas) target);
|
SDL_UnlockSurface ((NativeCanvas) target);
|
||||||
|
|||||||
@@ -153,6 +153,11 @@ PutPixelFn putpixel_for(SDL_Surface *surface)
|
|||||||
void line(int x1, int y1, int x2, int y2, Uint32 color, PutPixelFn plot, SDL_Surface *surface)
|
void line(int x1, int y1, int x2, int y2, Uint32 color, PutPixelFn plot, SDL_Surface *surface)
|
||||||
{
|
{
|
||||||
int d, x, y, ax, ay, sx, sy, dx, dy;
|
int d, x, y, ax, ay, sx, sy, dx, dy;
|
||||||
|
SDL_Rect r;
|
||||||
|
|
||||||
|
SDL_GetClipRect (surface, &r);
|
||||||
|
if (!clip_line (&x1, &y1, &x2, &y2, &r))
|
||||||
|
return; // line is completely outside clipping rectangle
|
||||||
|
|
||||||
dx = x2-x1;
|
dx = x2-x1;
|
||||||
ax = ((dx < 0) ? -dx : dx) << 1;
|
ax = ((dx < 0) ? -dx : dx) << 1;
|
||||||
@@ -192,36 +197,95 @@ void line(int x1, int y1, int x2, int y2, Uint32 color, PutPixelFn plot, SDL_Sur
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// replaces all non-alpha pixels by color
|
|
||||||
void replace_color (Uint32 color, SDL_Surface *surface)
|
// Clips line against rectangle using Cohen-Sutherland algorithm
|
||||||
|
|
||||||
|
static enum {C_TOP = 0x1, C_BOTTOM = 0x2, C_RIGHT = 0x4, C_LEFT = 0x8};
|
||||||
|
|
||||||
|
static int
|
||||||
|
compute_code (float x, float y, float xmin, float ymin, float xmax, float ymax)
|
||||||
{
|
{
|
||||||
int x,y,w,h;
|
int c = 0;
|
||||||
Uint32 p;
|
if (y > ymax)
|
||||||
Uint8 r,g,b,a;
|
c |= C_TOP;
|
||||||
GetPixelFn getpix;
|
else if (y < ymin)
|
||||||
PutPixelFn putpix;
|
c |= C_BOTTOM;
|
||||||
|
if (x > xmax)
|
||||||
getpix = getpixel_for (surface);
|
c |= C_RIGHT;
|
||||||
putpix = putpixel_for (surface);
|
else if (x < xmin)
|
||||||
|
c |= C_LEFT;
|
||||||
SDL_LockSurface(surface);
|
return c;
|
||||||
|
|
||||||
w = surface->w;
|
|
||||||
h = surface->h;
|
|
||||||
|
|
||||||
for (y=0;y<h;++y)
|
|
||||||
{
|
|
||||||
for (x=0;x<w;++x)
|
|
||||||
{
|
|
||||||
p = getpix (surface,x,y);
|
|
||||||
SDL_GetRGBA (p, surface->format, &r, &g, &b, &a);
|
|
||||||
|
|
||||||
if (a)
|
|
||||||
putpix (surface,x,y,color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UnlockSurface(surface);
|
int
|
||||||
|
clip_line (int *lx1, int *ly1, int *lx2, int *ly2, SDL_Rect *r)
|
||||||
|
{
|
||||||
|
int C0, C1, C;
|
||||||
|
float x, y, x0, y0, x1, y1, xmin, ymin, xmax, ymax;
|
||||||
|
|
||||||
|
x0 = (float)*lx1;
|
||||||
|
y0 = (float)*ly1;
|
||||||
|
x1 = (float)*lx2;
|
||||||
|
y1 = (float)*ly2;
|
||||||
|
|
||||||
|
xmin = (float)r->x;
|
||||||
|
ymin = (float)r->y;
|
||||||
|
xmax = (float)r->x + r->w - 1;
|
||||||
|
ymax = (float)r->y + r->h - 1;
|
||||||
|
|
||||||
|
C0 = compute_code (x0, y0, xmin, ymin, xmax, ymax);
|
||||||
|
C1 = compute_code (x1, y1, xmin, ymin, xmax, ymax);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
/* trivial accept: both ends in rectangle */
|
||||||
|
if ((C0 | C1) == 0)
|
||||||
|
{
|
||||||
|
*lx1 = (int)x0;
|
||||||
|
*ly1 = (int)y0;
|
||||||
|
*lx2 = (int)x1;
|
||||||
|
*ly2 = (int)y1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* trivial reject: both ends on the external side of the rectangle */
|
||||||
|
if ((C0 & C1) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* normal case: clip end outside rectangle */
|
||||||
|
C = C0 ? C0 : C1;
|
||||||
|
if (C & C_TOP)
|
||||||
|
{
|
||||||
|
x = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0);
|
||||||
|
y = ymax;
|
||||||
|
}
|
||||||
|
else if (C & C_BOTTOM)
|
||||||
|
{
|
||||||
|
x = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0);
|
||||||
|
y = ymin;
|
||||||
|
}
|
||||||
|
else if (C & C_RIGHT)
|
||||||
|
{
|
||||||
|
x = xmax;
|
||||||
|
y = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = xmin;
|
||||||
|
y = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set new end point and iterate */
|
||||||
|
if (C == C0)
|
||||||
|
{
|
||||||
|
x0 = x; y0 = y;
|
||||||
|
C0 = compute_code (x0, y0, xmin, ymin, xmax, ymax);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x1 = x; y1 = y;
|
||||||
|
C1 = compute_code (x1, y1, xmin, ymin, xmax, ymax);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,7 +29,5 @@ PutPixelFn putpixel_for(SDL_Surface *surface);
|
|||||||
|
|
||||||
void line(int x1, int y1, int x2, int y2, Uint32 color, PutPixelFn plot,
|
void line(int x1, int y1, int x2, int y2, Uint32 color, PutPixelFn plot,
|
||||||
SDL_Surface *surface);
|
SDL_Surface *surface);
|
||||||
|
int clip_line(int *lx1, int *ly1, int *lx2, int *ly2, SDL_Rect *r);
|
||||||
void replace_color (Uint32 color, SDL_Surface *surface);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user