fix bresenham line

This commit is contained in:
Irmen de Jong 2020-03-28 12:33:16 +01:00
parent fac2a2d7cb
commit fffe36e358
4 changed files with 123 additions and 62 deletions

View File

@ -14,6 +14,12 @@ import kotlin.math.pow
/* /*
todo add more expression optimizations todo add more expression optimizations
x + x -> x << 1 (for words... for bytes too?)
x + x + x + x -> x << 2 (for words... for bytes too?)
x + x + x -> ???? x*3 ??? words/bytes?
x - x -> 0
Investigate what optimizations binaryen has, also see https://egorbo.com/peephole-optimizations.html Investigate what optimizations binaryen has, also see https://egorbo.com/peephole-optimizations.html
*/ */

View File

@ -1,61 +1,53 @@
%import c64lib %import c64lib
%import c64utils
%zeropage basicsafe
; bitmap pixel graphics module for the C64
; only black/white monchrome for now
main { ; you could put this code at $4000 which is after the bitmap screen in memory ($2000-$3fff),
; this leaves more space for user program code.
graphics {
const uword bitmap_address = $2000 const uword bitmap_address = $2000
sub enable_bitmap_mode() {
sub start() {
; enable bitmap screen, erase it and set colors to black/white. ; enable bitmap screen, erase it and set colors to black/white.
c64.SCROLY |= %00100000 c64.SCROLY |= %00100000
c64.VMCSB = (c64.VMCSB & %11110000) | %00001000 ; $2000-$3fff c64.VMCSB = (c64.VMCSB & %11110000) | %00001000 ; $2000-$3fff
memset(bitmap_address, 320*200/8, 0) memset(bitmap_address, 320*200/8, 0)
c64scr.clear_screen($10, 0) c64scr.clear_screen($10, 0) ; pixel color $1 (white) backround $0 (black)
lines()
circles()
forever {
}
} }
sub line(uword x1, ubyte y1, uword x2, ubyte y2) {
sub circles() {
ubyte xx
for xx in 3 to 7 {
circle(xx*50-100, 10+xx*16, (xx+6)*4)
disc(xx*50-100, 10+xx*16, (xx+6)*2)
}
}
sub lines() {
ubyte ix
for ix in 1 to 15 {
line(10, 10, ix*4, 50) ; TODO fix lines of lenghts > 128
}
}
sub line(ubyte x1, ubyte y1, ubyte x2, ubyte y2) {
; Bresenham algorithm ; Bresenham algorithm
byte d = 0 word dx
ubyte dx = abs(x2 - x1) word dy
ubyte dy = abs(y2 - y1) byte ix = 1
ubyte dx2 = 2 * dx byte iy = 1
ubyte dy2 = 2 * dy if x2>x1 {
word ix = sgn(x2 as byte - x1 as byte) dx = x2-x1
word iy = sgn(y2 as byte - y1 as byte) } else {
ix = -1
dx = x1-x2
}
if y2>y1 {
dy = y2-y1
} else {
iy = -1
dy = y1-y2
}
word dx2 = 2 * dx
word dy2 = 2 * dy
word d = 0
plotx = x1 plotx = x1
if dx >= dy { if dx >= dy {
if ix<0 {
forever { forever {
plot(y1) graphics.plot(y1)
if plotx==x2 if plotx==x2
return return
plotx += ix plotx--
d += dy2 d += dy2
if d > dx { if d > dx {
y1 += iy y1 += iy
@ -63,17 +55,44 @@ main {
} }
} }
} else { } else {
forever {
graphics.plot(y1)
if plotx==x2
return
plotx++
d += dy2
if d > dx {
y1 += iy
d -= dx2
}
}
}
} else {
if iy<0 {
forever { forever {
plot(y1) plot(y1)
if y1 == y2 if y1 == y2
return return
y1 += iy y1--
d += dx2 d += dx2
if d > dy { if d > dy {
plotx += ix plotx += ix as word
d -= dy2 d -= dy2
} }
} }
} else {
forever {
plot(y1)
if y1 == y2
return
y1++
d += dx2
if d > dy {
plotx += ix as word
d -= dy2
}
}
}
} }
} }
@ -149,6 +168,13 @@ main {
} }
; here is the non-asm code for the plot routine below:
; sub plot_nonasm(uword px, ubyte py) {
; ubyte[] ormask = [128, 64, 32, 16, 8, 4, 2, 1]
; uword addr = bitmap_address + 320*(py>>3) + (py & 7) + (px & %0000000111111000)
; @(addr) |= ormask[lsb(px) & 7]
; }
uword plotx ; 0..319 uword plotx ; 0..319
asmsub plot(ubyte ploty @A) { ; plotx is 16 bits 0 to 319... doesn't fit in a register asmsub plot(ubyte ploty @A) { ; plotx is 16 bits 0 to 319... doesn't fit in a register
@ -219,13 +245,6 @@ _y_lookup_lo
}} }}
} }
; here is the non-asm code for the same plot routine:
; sub plot_nonasm(uword px, ubyte py) {
; ubyte[] ormask = [128, 64, 32, 16, 8, 4, 2, 1]
; uword addr = bitmap_address + 320*(py>>3) + (py & 7) + (px & %0000000111111000)
; @(addr) |= ormask[lsb(px) & 7]
; }
} }

View File

@ -0,0 +1,35 @@
%import c64lib
%import c64graphics
%zeropage basicsafe
main {
sub start() {
graphics.enable_bitmap_mode()
draw_lines()
draw_circles()
forever {
}
}
sub draw_circles() {
ubyte xx
for xx in 3 to 7 {
graphics.circle(xx*50-100, 10+xx*16, (xx+6)*4)
graphics.disc(xx*50-100, 10+xx*16, (xx+6)*2)
}
}
sub draw_lines() {
ubyte i
for i in 0 to 255 step 4 {
; uword x1 = (320-256)/2 + sin8u(i)
uword x1 = ((320-256)/2 as uword) + sin8u(i) ; TODO fix the need for a cast here
uword y1 = (200-128)/2 + cos8u(i)/2
uword x2 = ((320-64)/2 as uword) + sin8u(i)/4 ; TODO fix the need for a cast here
uword y2 = (200-64)/2 + cos8u(i)/4
graphics.line(x1, lsb(y1), x2, lsb(y2))
}
}
}

View File

@ -64,7 +64,8 @@ main {
} }
sub line(ubyte x1, ubyte y1, ubyte x2, ubyte y2) { sub line(ubyte x1, ubyte y1, ubyte x2, ubyte y2) {
; Bresenham algorithm ; Bresenham algorithm, not very optimized to keep clear code.
; For a better optimized version have a look in the graphics.p8 module.
byte d = 0 byte d = 0
ubyte dx = abs(x2 - x1) ubyte dx = abs(x2 - x1)
ubyte dy = abs(y2 - y1) ubyte dy = abs(y2 - y1)