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:
gewlitys
2003-02-26 17:05:59 +00:00
parent 80ea46fdc3
commit 570eb15ee0
4 changed files with 89 additions and 53 deletions
+2
View File
@@ -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);
+86 -22
View File
@@ -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)
c |= C_RIGHT;
else if (x < xmin)
c |= C_LEFT;
return c;
}
getpix = getpixel_for (surface); int
putpix = putpixel_for (surface); 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;
SDL_LockSurface(surface); x0 = (float)*lx1;
y0 = (float)*ly1;
x1 = (float)*lx2;
y1 = (float)*ly2;
w = surface->w; xmin = (float)r->x;
h = surface->h; ymin = (float)r->y;
xmax = (float)r->x + r->w - 1;
ymax = (float)r->y + r->h - 1;
for (y=0;y<h;++y) C0 = compute_code (x0, y0, xmin, ymin, xmax, ymax);
{ C1 = compute_code (x1, y1, xmin, ymin, xmax, ymax);
for (x=0;x<w;++x)
for (;;) {
/* trivial accept: both ends in rectangle */
if ((C0 | C1) == 0)
{ {
p = getpix (surface,x,y); *lx1 = (int)x0;
SDL_GetRGBA (p, surface->format, &r, &g, &b, &a); *ly1 = (int)y0;
*lx2 = (int)x1;
if (a) *ly2 = (int)y1;
putpix (surface,x,y,color); 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);
} }
} }
SDL_UnlockSurface(surface);
} }
#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