mirror of https://github.com/buggins/dlangui.git
triangle clipping
This commit is contained in:
parent
e715c52d0b
commit
ec4b6c9392
|
@ -1088,11 +1088,22 @@ void main()
|
|||
canvas.font.drawText(buf, x + 300, y + 100, "drawPixel()"d, 0x000080);
|
||||
for (int i = 0; i < 80; i++)
|
||||
buf.drawPixel(x+300 + i * 4, y+140 + i * 3 % 100, 0xFF0000 + i * 2);
|
||||
canvas.font.drawText(buf, x + 200, y + 250, "drawLine()"d, 0x800020);
|
||||
canvas.font.drawText(buf, x + 300, y + 420, "drawLine()"d, 0x800020);
|
||||
for (int i = 0; i < 40; i+=3)
|
||||
buf.drawLine(Point(x+200 + i * 4, y+290), Point(x+150 + i * 7, y+420 + i * 2), 0x008000 + i * 5);
|
||||
PointF[] poly = [vec2(130, 150), vec2(240, 110), vec2(270, 170), vec2(300, 290), vec2(220, 400), vec2(180, 330)];
|
||||
buf.polyLineF(poly, 3.5f, 0x804020, true);
|
||||
// poly line test
|
||||
Rect newClipRect = Rect(x + 110, y + 100, x + 350, y + 320);
|
||||
buf.fillRect(newClipRect, 0xC08080FF);
|
||||
Rect oldClip = buf.clipRect;
|
||||
buf.clipRect = newClipRect;
|
||||
PointF[] poly = [vec2(x+130, y+150), vec2(x+240, y+80), vec2(x+170, y+170), vec2(x+380, y+270), vec2(x+220, y+400), vec2(x+180, y+330)];
|
||||
buf.polyLineF(poly, 8.0f, 0x804020, true);
|
||||
buf.fillTriangleF(vec2(x+230, y+50), vec2(x+400, y+250), vec2(x+130, y+200), 0xC0FF0000);
|
||||
buf.fillTriangleF(vec2(x+230, y+250), vec2(x+200, y+350), vec2(x+80, y+200), 0xC000FF00);
|
||||
buf.fillTriangleF(vec2(x+430, y+250), vec2(x+280, y+150), vec2(x+200, y+300), 0xC00000FF);
|
||||
buf.fillTriangleF(vec2(x+80, y+150), vec2(x+280, y+250), vec2(x+80, y+200), 0xC0008080);
|
||||
buf.clipRect = oldClip;
|
||||
canvas.font.drawText(buf, x + 190, y + 260, "polyLineF()"d, 0x603010);
|
||||
};
|
||||
tabs.addTab(canvas, "TAB_CANVAS"c);
|
||||
|
||||
|
|
|
@ -371,9 +371,170 @@ class DrawBuf : RefCountedObject {
|
|||
}
|
||||
}
|
||||
|
||||
/// draw filled triangle in float coordinates; clipping is already applied
|
||||
protected void fillTriangleFClipped(PointF p1, PointF p2, PointF p3, uint colour) {
|
||||
// override and implement it
|
||||
}
|
||||
|
||||
/// find intersection of line p1..p2 with clip rectangle
|
||||
protected bool intersectClipF(ref PointF p1, ref PointF p2, ref bool p1moved, ref bool p2moved) {
|
||||
if (p1.x < _clipRect.left && p2.x < _clipRect.left)
|
||||
return true;
|
||||
if (p1.x >= _clipRect.right && p2.x >= _clipRect.right)
|
||||
return true;
|
||||
if (p1.y < _clipRect.top && p2.y < _clipRect.top)
|
||||
return true;
|
||||
if (p1.y >= _clipRect.bottom && p2.y >= _clipRect.bottom)
|
||||
return true;
|
||||
// horizontal clip
|
||||
if (p1.x < _clipRect.left && p2.x >= _clipRect.left) {
|
||||
// move p1 to clip left
|
||||
p1 += (p2 - p1) * ((_clipRect.left - p1.x) / (p2.x - p1.x));
|
||||
p1moved = true;
|
||||
}
|
||||
if (p2.x < _clipRect.left && p1.x >= _clipRect.left) {
|
||||
// move p2 to clip left
|
||||
p2 += (p1 - p2) * ((_clipRect.left - p2.x) / (p1.x - p2.x));
|
||||
p2moved = true;
|
||||
}
|
||||
if (p1.x > _clipRect.right && p2.x < _clipRect.right) {
|
||||
// move p1 to clip right
|
||||
p1 += (p2 - p1) * ((_clipRect.right - p1.x) / (p2.x - p1.x));
|
||||
p1moved = true;
|
||||
}
|
||||
if (p2.x > _clipRect.right && p1.x < _clipRect.right) {
|
||||
// move p1 to clip right
|
||||
p2 += (p1 - p2) * ((_clipRect.right - p2.x) / (p1.x - p2.x));
|
||||
p2moved = true;
|
||||
}
|
||||
// vertical clip
|
||||
if (p1.y < _clipRect.top && p2.y >= _clipRect.top) {
|
||||
// move p1 to clip left
|
||||
p1 += (p2 - p1) * ((_clipRect.top - p1.y) / (p2.y - p1.y));
|
||||
p1moved = true;
|
||||
}
|
||||
if (p2.y < _clipRect.top && p1.y >= _clipRect.top) {
|
||||
// move p2 to clip left
|
||||
p2 += (p1 - p2) * ((_clipRect.top - p2.y) / (p1.y - p2.y));
|
||||
p2moved = true;
|
||||
}
|
||||
if (p1.y > _clipRect.bottom && p2.y < _clipRect.bottom) {
|
||||
// move p1 to clip right <0 <0
|
||||
p1 += (p2 - p1) * ((_clipRect.bottom - p1.y) / (p2.y - p1.y));
|
||||
p1moved = true;
|
||||
}
|
||||
if (p2.y > _clipRect.bottom && p1.y < _clipRect.bottom) {
|
||||
// move p1 to clip right
|
||||
p2 += (p1 - p2) * ((_clipRect.bottom - p2.y) / (p1.y - p2.y));
|
||||
p2moved = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// draw filled triangle in float coordinates
|
||||
void fillTriangleF(PointF p1, PointF p2, PointF p3, uint colour) {
|
||||
// override and implement it
|
||||
if (_clipRect.empty) // clip rectangle is empty - all drawables are clipped out
|
||||
return;
|
||||
// apply clipping
|
||||
bool p1insideClip = (p1.x >= _clipRect.left && p1.x < _clipRect.right && p1.y >= _clipRect.top && p1.y < _clipRect.bottom);
|
||||
bool p2insideClip = (p2.x >= _clipRect.left && p2.x < _clipRect.right && p2.y >= _clipRect.top && p2.y < _clipRect.bottom);
|
||||
bool p3insideClip = (p3.x >= _clipRect.left && p3.x < _clipRect.right && p3.y >= _clipRect.top && p3.y < _clipRect.bottom);
|
||||
if (p1insideClip && p2insideClip && p3insideClip) {
|
||||
// all points inside clipping area - no clipping required
|
||||
fillTriangleFClipped(p1, p2, p3, colour);
|
||||
return;
|
||||
}
|
||||
// do triangle clipping
|
||||
// check if all points outside the same bound
|
||||
if ((p1.x < _clipRect.left && p2.x < _clipRect.left && p3.x < _clipRect.left)
|
||||
|| (p1.x >= _clipRect.right && p2.x >= _clipRect.right && p3.x >= _clipRect.bottom)
|
||||
|| (p1.y < _clipRect.top && p2.y < _clipRect.top && p3.y < _clipRect.top)
|
||||
|| (p1.y >= _clipRect.bottom && p2.y >= _clipRect.bottom && p3.y >= _clipRect.bottom))
|
||||
return;
|
||||
/++
|
||||
+ side 1
|
||||
+ p1-------p11------------p21--------------p2
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ p13\ /p22
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ \ / side 2
|
||||
+ side 3 \ /
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ \ /p32
|
||||
+ p33\ /
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ \ /
|
||||
+ p3
|
||||
+/
|
||||
PointF p11 = p1;
|
||||
PointF p13 = p1;
|
||||
PointF p21 = p2;
|
||||
PointF p22 = p2;
|
||||
PointF p32 = p3;
|
||||
PointF p33 = p3;
|
||||
bool p1moved = false;
|
||||
bool p2moved = false;
|
||||
bool p3moved = false;
|
||||
bool side1clipped = intersectClipF(p11, p21, p1moved, p2moved);
|
||||
bool side2clipped = intersectClipF(p22, p32, p2moved, p3moved);
|
||||
bool side3clipped = intersectClipF(p33, p13, p3moved, p1moved);
|
||||
if (!p1moved && !p2moved && !p3moved) {
|
||||
// no moved - no clipping
|
||||
fillTriangleFClipped(p1, p2, p3, colour);
|
||||
} else if (p1moved && !p2moved && !p3moved) {
|
||||
fillTriangleFClipped(p11, p2, p3, colour);
|
||||
fillTriangleFClipped(p3, p13, p11, colour);
|
||||
} else if (!p1moved && p2moved && !p3moved) {
|
||||
fillTriangleFClipped(p22, p3, p1, colour);
|
||||
fillTriangleFClipped(p1, p21, p22, colour);
|
||||
} else if (!p1moved && !p2moved && p3moved) {
|
||||
fillTriangleFClipped(p33, p1, p2, colour);
|
||||
fillTriangleFClipped(p2, p32, p33, colour);
|
||||
} else if (p1moved && p2moved && !p3moved) {
|
||||
if (!side1clipped) {
|
||||
fillTriangleFClipped(p13, p11, p21, colour);
|
||||
fillTriangleFClipped(p21, p22, p13, colour);
|
||||
}
|
||||
fillTriangleFClipped(p22, p3, p13, colour);
|
||||
} else if (!p1moved && p2moved && p3moved) {
|
||||
if (!side2clipped) {
|
||||
fillTriangleFClipped(p21, p22, p32, colour);
|
||||
fillTriangleFClipped(p32, p33, p21, colour);
|
||||
}
|
||||
fillTriangleFClipped(p21, p33, p1, colour);
|
||||
} else if (p1moved && !p2moved && p3moved) {
|
||||
if (!side3clipped) {
|
||||
fillTriangleFClipped(p13, p11, p32, colour);
|
||||
fillTriangleFClipped(p32, p33, p13, colour);
|
||||
}
|
||||
fillTriangleFClipped(p11, p2, p32, colour);
|
||||
} else if (p1moved && p2moved && p3moved) {
|
||||
if (side1clipped) {
|
||||
fillTriangleFClipped(p13, p22, p32, colour);
|
||||
fillTriangleFClipped(p32, p33, p13, colour);
|
||||
} else if (side2clipped) {
|
||||
fillTriangleFClipped(p11, p21, p33, colour);
|
||||
fillTriangleFClipped(p33, p13, p11, colour);
|
||||
} else if (side3clipped) {
|
||||
fillTriangleFClipped(p11, p21, p22, colour);
|
||||
fillTriangleFClipped(p22, p32, p11, colour);
|
||||
} else {
|
||||
fillTriangleFClipped(p13, p11, p21, colour);
|
||||
fillTriangleFClipped(p21, p22, p13, colour);
|
||||
fillTriangleFClipped(p22, p32, p33, colour);
|
||||
fillTriangleFClipped(p33, p13, p22, colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// draw filled quad in float coordinates
|
||||
|
|
|
@ -180,16 +180,12 @@ class GLDrawBuf : DrawBuf, GLConfigCallback {
|
|||
_scene.add(new LineSceneItem(p1, p2, colour));
|
||||
}
|
||||
|
||||
/// draw filled triangle in float coordinates
|
||||
override void fillTriangleF(PointF p1, PointF p2, PointF p3, uint colour) {
|
||||
/// draw filled triangle in float coordinates; clipping is already applied
|
||||
override protected void fillTriangleFClipped(PointF p1, PointF p2, PointF p3, uint colour) {
|
||||
assert(_scene !is null);
|
||||
//if (!clipLine(_clipRect, p1, p2))
|
||||
// return;
|
||||
// TODO: clipping
|
||||
_scene.add(new TriangleSceneItem(p1, p2, p3, colour));
|
||||
}
|
||||
|
||||
|
||||
/// cleanup resources
|
||||
override void clear() {
|
||||
if (_framebuffer) {
|
||||
|
|
Loading…
Reference in New Issue