Refine the bresenham implementation
This commit is contained in:
parent
c9e0775b4b
commit
a81d8cec6b
|
@ -1,43 +1,82 @@
|
||||||
#include "animation.h"
|
#include "animation.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
line_t line_new(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) {
|
time_line_t time_line_new(int t0, int y0, int t1, int y1) {
|
||||||
uint8_t dx = x1 - x0;
|
int dt = t1 - t0;
|
||||||
int8_t dy = y1 - y0;
|
int dy = y1 - y0;
|
||||||
int8_t inc = dy > 0 ? 1 : dy == 0 ? 0 : -1;
|
int de = 2 * dy;
|
||||||
int8_t m = 2 * dy;
|
|
||||||
int8_t error = 0;
|
|
||||||
|
|
||||||
if (m > 0) {
|
int inc = dy > 0 ? 1 : dy == 0 ? 0 : -1;
|
||||||
error = m - dx;
|
int error;
|
||||||
|
|
||||||
|
if (de > 0) {
|
||||||
|
error = de - dt;
|
||||||
} else {
|
} else {
|
||||||
error = m + dx;
|
error = de + dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (line_t){ .y = y0, .m = m, .error = error, .inc = inc, .dx = dx };
|
return (time_line_t){ .y = y0, .dt = dt, .de = de, .error = error, .inc = inc, .dy = dy };
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t line_next(line_t *slope) {
|
int time_line_next(time_line_t *self) {
|
||||||
|
int error = self->error + self->de;
|
||||||
|
|
||||||
|
if (self->de > 0) {
|
||||||
|
while (error >= 0) {
|
||||||
|
self->y += self->inc;
|
||||||
|
error -= 2 * self->dt;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (error < 0) {
|
||||||
|
self->y -= self->inc;
|
||||||
|
error += 2 * self->dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self->error = error;
|
||||||
|
return self->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
time_line_t time_line_new(int t0, int y0, int t1, int y1) {
|
||||||
|
int dt = t1 - t0;
|
||||||
|
int dy = y1 - y0;
|
||||||
|
int inc = dy > 0 ? 1 : dy == 0 ? 0 : -1;
|
||||||
|
int m = 2 * dy;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
if (m > 0) {
|
||||||
|
error = m - dt;
|
||||||
|
} else {
|
||||||
|
error = m + dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (time_line_t){ .y = y0, .m = m, .error = error, .inc = inc, .dt = dt };
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
int time_line_next(time_line_t *slope) {
|
||||||
slope->error += slope->m;
|
slope->error += slope->m;
|
||||||
|
|
||||||
if (slope->m > 0) {
|
if (slope->m > 0) {
|
||||||
if (slope->error >= 0) {
|
if (slope->error >= 0) {
|
||||||
slope->y += slope->inc;
|
slope->y += slope->inc;
|
||||||
slope->error -= 2 * slope->dx;
|
slope->error -= 2 * slope->dt;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (slope->error <= 0) {
|
if (slope->error <= 0) {
|
||||||
slope->y += slope->inc;
|
slope->y += slope->inc;
|
||||||
slope->error += 2 * slope->dx;
|
slope->error += 2 * slope->dt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return slope->y;
|
return slope->y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
void line_print(line_t *line) {
|
|
||||||
printf("y: %d\tm: %d\terror: %d\tinc: %d\t:dx: %d\n", line->y, line->m, line->error, line->inc, line->dx);
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void time_line_print(time_line_t *self) {
|
||||||
|
printf("y: %d\tde: %d\terror: %d\tinc: %d\t:dt: %d\n", self->y, self->de, self->error, self->inc, self->dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
#ifndef __ANIMATION_H__
|
#ifndef __ANIMATION_H__
|
||||||
#define __ANIMATION_H__
|
#define __ANIMATION_H__
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
|
|
||||||
// line_t provides a simplified implementation of Bresenham's line drawing
|
// line_t provides a simplified implementation of Bresenham's line drawing
|
||||||
// technique. At this time, it assumes a transition of x = 0 -> 60, and a dy
|
// technique. At this time, it assumes a transition of x = 0 -> 60, and a dy
|
||||||
// between -59 and 59. I am not sure I understand Bresenham's algorithm yet,
|
// between -59 and 59. I am not sure I understand Bresenham's algorithm yet,
|
||||||
// but I'll need to revisit all of this if I want to expand the boundaries.
|
// but I'll need to revisit all of this if I want to expand the boundaries.
|
||||||
typedef struct line_s {
|
typedef struct {
|
||||||
uint8_t y;
|
int y;
|
||||||
int8_t m;
|
int de;
|
||||||
int8_t error;
|
int error;
|
||||||
int8_t inc;
|
int inc;
|
||||||
uint8_t dx;
|
int dt;
|
||||||
} line_t;
|
int dy;
|
||||||
|
} time_line_t;
|
||||||
|
|
||||||
// Construct a new line object. x1 must be greater than x0, and dy must be less than dx.
|
// Construct a new line object. x1 must be greater than x0, and dy must be less than dx.
|
||||||
line_t line_new(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);
|
time_line_t time_line_new(int, int, int, int);
|
||||||
|
|
||||||
// Calculate the next y value of the line.
|
// Calculate the next y value of the line.
|
||||||
uint8_t line_next(line_t *line);
|
int time_line_next(time_line_t *);
|
||||||
|
|
||||||
// Diagnostic printout of the current state of line_t.
|
// Diagnostic printout of the current state of line_t.
|
||||||
// void line_print(line_t *line);
|
// void line_print(line_t *line);
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
void bresenham(int x1, int y1, int x2, int y2) {
|
void bresenham_time(int t1, int y1, int t2, int y2) {
|
||||||
int dx = x2 - x1;
|
int dt = t2 - t1;
|
||||||
int dy = y2 - y1;
|
int dy = y2 - y1;
|
||||||
int m = 2 * dy;
|
int m = 2 * dy;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (m > 0) {
|
if (m > 0) {
|
||||||
err = m - dx;
|
err = m - dt;
|
||||||
} else if (m < 0) {
|
} else if (m < 0) {
|
||||||
err = m + dx;
|
err = m + dt;
|
||||||
}
|
}
|
||||||
for (int x = x1, y = y1; x <= x2; x++) {
|
for (int t = t1, y = y1; t <= t2; t++) {
|
||||||
printf("(%d, %d) [%d]\n", x, y, err);
|
printf("(%d, %d) [%d]\n", t, y, err);
|
||||||
|
|
||||||
err += m;
|
err += m;
|
||||||
|
|
||||||
if (m > 0) {
|
if (m > 0) {
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
y++;
|
y++;
|
||||||
err -= 2 * dx;
|
err -= 2 * dt;
|
||||||
}
|
}
|
||||||
} else if (m < 0) {
|
} else if (m < 0) {
|
||||||
if (err <= 0) {
|
if (err <= 0) {
|
||||||
y--;
|
y--;
|
||||||
err += 2 * dx;
|
err += 2 * dt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,36 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <base.h>
|
#include <stdio.h>
|
||||||
#include <rng.h>
|
#include <animation.h>
|
||||||
|
|
||||||
typedef struct RGB_s {
|
|
||||||
uint8_t brightness;
|
|
||||||
uint8_t r;
|
|
||||||
uint8_t g;
|
|
||||||
uint8_t b;
|
|
||||||
} rgb_t;
|
|
||||||
|
|
||||||
|
|
||||||
int main (void) {
|
int main (void) {
|
||||||
rng_t rng = rng_new(0);
|
{
|
||||||
animation_t animation = animation_new();
|
time_line_t line = time_line_new(0, 0, 15, 10);
|
||||||
|
time_line_print(&line);
|
||||||
|
for (int i = 0; i < 15; i++) {
|
||||||
|
time_line_next(&line);
|
||||||
|
time_line_print(&line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 120; i++) {
|
printf("\n");
|
||||||
animation_step(&animation, &rng);
|
|
||||||
printf("[%d] %d %d %d\n", animation.frame, animation.lamp.r, animation.lamp.g, animation.lamp.b);
|
{
|
||||||
|
time_line_t line = time_line_new(0, 0, 15, 25);
|
||||||
|
time_line_print(&line);
|
||||||
|
for (int i = 0; i < 15; i++) {
|
||||||
|
time_line_next(&line);
|
||||||
|
time_line_print(&line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
{
|
||||||
|
time_line_t line = time_line_new(0, 0, 10, 255);
|
||||||
|
time_line_print(&line);
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
time_line_next(&line);
|
||||||
|
time_line_print(&line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
flake.nix
34
flake.nix
|
@ -75,18 +75,18 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
packages."x86_64-linux"."animation" =
|
packages."x86_64-linux"."animation" =
|
||||||
{ mcu, chip_select, f_cpu }:
|
# { gcc, mcu, chip_select, f_cpu }:
|
||||||
|
{ gcc }:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
||||||
avr = pkgs.pkgsCross.avr.buildPackages;
|
|
||||||
in pkgs.stdenv.mkDerivation rec {
|
in pkgs.stdenv.mkDerivation rec {
|
||||||
name = "animation";
|
name = "animation";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
|
|
||||||
CFLAGS = cflags { inherit mcu chip_select f_cpu; };
|
# CFLAGS = cflags { inherit mcu chip_select f_cpu; };
|
||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
${avr.gcc}/bin/avr-gcc ${CFLAGS} -o animation.o -c ${src}/animation/animation.c
|
${gcc} -o animation.o -c ${src}/animation/animation.c
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
|
@ -95,6 +95,32 @@
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
packages."x86_64-linux"."animation-test" =
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
||||||
|
lib = pkgs.lib;
|
||||||
|
in pkgs.stdenv.mkDerivation rec {
|
||||||
|
name = "animation-test";
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
(packages."x86_64-linux"."animation" { inherit gcc; })
|
||||||
|
];
|
||||||
|
|
||||||
|
INCLUDE_DIRS = lib.concatStringsSep " " (map (dir: "-I${dir}") buildInputs);
|
||||||
|
OBJECT_FILES = lib.concatStringsSep " " (map (dir: "${dir}/*.o") buildInputs);
|
||||||
|
gcc = "${pkgs.gcc}/bin/gcc";
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
${gcc} ${INCLUDE_DIRS} -o main.o -c ${src}/animation/main.c
|
||||||
|
${gcc} ${INCLUDE_DIRS} -o animation-test main.o ${OBJECT_FILES}
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
mkdir $out
|
||||||
|
cp animation-test $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
packages."x86_64-linux"."sk9822" =
|
packages."x86_64-linux"."sk9822" =
|
||||||
{ mcu, chip_select, f_cpu }:
|
{ mcu, chip_select, f_cpu }:
|
||||||
let
|
let
|
||||||
|
|
Loading…
Reference in New Issue