(only DirectX9 interface, feel free to do the same for the other ones).
First i changed the IVideoDriver::draw2DLine(...) so it can do clipping:
Code: Select all
virtual void draw2DLine(const core::position2d<s32>& start,
const core::position2d<s32>& end,
SColor color=SColor(255,255,255,255),
const core::rect<s32>* clip = 0) = 0;Code: Select all
//! Draws a 2d line.
virtual void draw2DLine(const core::position2d<s32>& start,
const core::position2d<s32>& end,
SColor color=SColor(255,255,255,255),
const core::rect<s32>* clip = 0);New Function which does a 2d clipping line <-> rectangle:
This function belongs to class CVideoNull in CVideoNull.h as a protected function:
Code: Select all
//! Clip a 2D Line to 2D Rectangle : 0: outside, 1:inside, 2:clipped
int clip2DLineRect(const core::rect<s32>* clip, core::position2d<s32>& p1, core::position2d<s32>& p2);Code: Select all
//! Clip a 2D Line to 2D Rectangle : 0: outside, 1:inside, 2:clipped
int CVideoNull::clip2DLineRect(const core::rect<s32>* clip, core::position2d<s32>& p1, core::position2d<s32>& p2)
{
enum { LEFT=1, RIGHT=2, BOTTOM=4, TOP=8};
#define OUTCODE(x, y, rc, c) \
c = 0; \
if (y < rc->UpperLeftCorner.Y) c |= TOP; \
else if (y > rc->LowerRightCorner.Y) c |= BOTTOM; \
if (x < rc->UpperLeftCorner.X) c |= LEFT; \
else if (x > rc->LowerRightCorner.X) c |= RIGHT;
char outcode1=0;
char outcode2=0;
char outside;
core::position2d<s32> tmp;
// do trivial rejects and outcodes
if (p1.Y > clip->LowerRightCorner.Y)
outcode1 = BOTTOM;
else if (p1.Y < clip->UpperLeftCorner.Y)
outcode1 = TOP;
if (p2.Y > clip->LowerRightCorner.Y)
outcode2 = BOTTOM;
else if (p2.Y < clip->UpperLeftCorner.Y)
outcode2 = TOP;
// trivially outside
if (outcode1 & outcode2)
return 0;
if (p1.X < clip->UpperLeftCorner.X)
outcode1 |= LEFT;
else if (p1.X > clip->LowerRightCorner.X)
outcode1 |= RIGHT;
if (p2.X < clip->UpperLeftCorner.X)
outcode2 |= LEFT;
else if (p2.X > clip->LowerRightCorner.X)
outcode2 |= RIGHT;
// trivially outside
if (outcode1 & outcode2)
return 0;
// trivially accept
if (outcode1 == 0 && outcode2 == 0)
return 1;
while (outcode1 | outcode2)
{
// may be partially inside box, find an outside point
if (outcode1)
outside = outcode1;
else
outside = outcode2;
// clip each side
if (outside & TOP) // y=y0+t(y1-y0)
{
tmp.Y = clip->UpperLeftCorner.Y;
tmp.X = p1.X + s32( f32(p2.X-p1.X) * f32(tmp.Y-p1.Y) / f32(p2.Y-p1.Y));
} else if (outside & BOTTOM)
{
tmp.Y = clip->LowerRightCorner.Y;
tmp.X = p1.X + s32( f32(p2.X-p1.X) * f32(tmp.Y-p1.Y) / f32(p2.Y-p1.Y));
} else if (outside & RIGHT)
{
tmp.X = clip->LowerRightCorner.X;
tmp.Y = p1.Y + s32( f32(p2.Y-p1.Y) * f32(tmp.X-p1.X) / f32(p2.X-p1.X));
} else if (outside & LEFT)
{
tmp.X = clip->UpperLeftCorner.X;
tmp.Y = p1.Y + s32( f32(p2.Y-p1.Y) * f32(tmp.X-p1.X) / f32(p2.X-p1.X));
}
if (outside == outcode1)
{
p1 = tmp;
OUTCODE(p1.X, p1.Y, clip, outcode1)
} else
{
p2 = tmp;
OUTCODE(p2.X, p2.Y, clip, outcode2)
}
if (outcode1 & outcode2)
return false;
}
return 2;
}Code: Select all
//! Draws a 2d line.
void CVideoDirectX9::draw2DLine(const core::position2d<s32>& start,
const core::position2d<s32>& end,
SColor color,
const core::rect<s32>* clip)
{
core::position2d<s32> spos = start;
core::position2d<s32> epos = end;
if (clip)
{
if (clip2DLineRect(clip, spos, epos) == 0)
return;
}
s32 xPlus = -(ScreenSize.Width>>1);
f32 xFact = 1.0f / (ScreenSize.Width>>1);
s32 yPlus = ScreenSize.Height-(ScreenSize.Height>>1);
f32 yFact = 1.0f / (ScreenSize.Height>>1);
S3DVertex vtx[2];
vtx[0] = S3DVertex((f32)(spos.X+xPlus) * xFact, (f32)(yPlus-spos.Y) * yFact , 0.0f, 0.0f, 0.0f, 0.0f, color, 0.0f, 0.0f);
vtx[1] = S3DVertex((f32)(epos.X+xPlus) * xFact, (f32)(yPlus- epos.Y) * yFact, 0.0f, 0.0f, 0.0f, 0.0f, color, 0.0f, 1.0f);
s16 indices[2] = {0,1};
setRenderStates2DMode(color.getAlpha() < 255, false, false);
setTexture(0,0);
setVertexShader(EVT_STANDARD);
pID3DDevice->DrawIndexedPrimitiveUP( D3DPT_LINELIST, 0, 2, 1, &indices[0],
D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex));
}- adjust the software draw2DLine(...) to do clipping (should be easy)
- implement OpenGL, DirectX8 versions of draw2DLine