TIC-80
TIC-80 copied to clipboard
tri() not drawing lines correctly in 1.0
Lines drawn with tri()
aren't displayed correctly in 1.0. Either you don't see the line at all or it appears as dots here and there.
1.0:
0.90:
EDIT: Thought first I was drawing the lines with line()
but i was actually using tri()
instead.
Lines draw more accurate now (so they might render slightly differently, but this certainly looks like a bug.
@nesbox It also looks like the thickness of the lines can vary depending on the angle.. if that is a side effect of the accuracy changes I'd consider that "broken" personally. Each "step" should only draw a single pixel. IE a 46 degree stair step should look like this for large portions:
..O
.O.
O..
Not:
..OO
.OO.
OO..
O...
IE, the width shouldn't appear to vary because of the angle given. Right now it looks like the new algorithm can "double up" pixels in different cases...
Right now it looks like the new algorithm can "double up" pixels in different cases
It's weird, the line()
function can't "double up" pixels, because it makes only one pass on the long side, anyway we need exact line coordinates to reproduce and fix this.
Oops, I was drawing the lines with tri()
instead of line()
. My bad!
Anyway, here's a short code that produces very different results on 1.0 and 0.90.
t=0
a=60
x=120
y=60
function TIC()
cls(0)
t=t+1
tri(
x,
y,
x+1,
y+1,
x+a*math.sin(t/10),
y+a*math.cos(t/10),
4
)
end
This is a new triangle rasterization algorithm, it draws pixels if their centers are inside the triangle.
Sometimes it looks weird, but it's correct. Don't know, maybe use line()
instead.
I need tri()
because i want to make the lines thicker on other end when the scanner is rotated, so using line()
in this case is unfortunately out of the question.
I'm sure this new version of tri is more accurate and all, but for this it isn't very usable (and I'm sure this change in drawing algorithm will break many carts in tic80.com). Could it be possible to add the new version as a separate argument for tri, for instance as a boolean newAlgorithm=true
or something like that? Or maybe the other way around, as oldAlgorithm=true
at least.
I'd like to update to 1.0, but I can't just yet, at least for EMUUROM development.
@borbware One idea: write your own fatLine
that just calls line (with transformed end coordinates). IE, it would call line several times to get the effect you desire.
@nesbox I think if the triangles edges aren't complete it's really hard to argue it's "correct" in any meaningful way... unless we just want to officially document "triangle only works if the length of all sides are greater than 5 pixels" or some such. Is that a new requirement we want to enforce? It seems kind of ugly to need to state that.
I'd argue this is a bug in the fill algorithm? IE, if our fill array looks like this:
y:20 x:12-15
// pixels 16, 17, 18, and 19 are unrendered
y:21 x:20-25
It's clear that is a 5 pixel gap in the render and we should extend the prior segment (or the current segment) to cover the difference... wouldn't this be a fairly easy fix? IE, the expectation should be that the ranges will always touch... I believe this would require one/two extra conditionals per fill line.
Correct:
y:20 x:12-15
y:21 x:16-25 // rewound to 16 to touch 15 from the previous segment
You willing to consider a fix along these lines?
Another solution is to use tri()
together with trib()
function _tri(x0,y0,x1,y1,x2,y2,c)
tri(x0,y0,x1,y1,x2,y2,c)
trib(x0,y0,x1,y1,x2,y2,c)
end
@borbware Since you seem to know the math here could you provide a small "clock" example with just one hand spinning in a slow circle? IE, something that will show the issue from a lot of different angles so if I find a fix it's easy to confirm it works in all cases.
If you do I'll take a look at this myself and see if there seems to be a simple solution or not.
@joshgoebel here ya go: a clock example with tri()
drawn on top of trib()
.
I think it would make sense that tri()
would draw the exact same shape as trib
, but just the middle parts coloured - at least in 1.0 tri()
seems to draw a smaller triangle.
t=0
a=60
b=20
x=100
y=60
function draw(x,y,c,func)
func(
x,
y,
x+b*math.sin(t/100+math.pi/8),
y+b*math.cos(t/100+math.pi/8),
x+a*math.sin(t/100),
y+a*math.cos(t/100),
c
)
end
function TIC()
cls(0)
t=t+1
draw(x,y,4,trib)
draw(x,y,7,tri)
end
I don't know how to find a suitable solution for this situation, the new triangle rasterization algorithm works great with texturing and I don't want to give it up.
As a solution, I suggest calling tri()
and trib()
sequentially to draw the filled triangle as before.