Refine the bresenham implementation
This commit is contained in:
parent
c9e0775b4b
commit
a81d8cec6b
|
@ -1,43 +1,82 @@
|
|||
#include "animation.h"
|
||||
#include <stdio.h>
|
||||
|
||||
line_t line_new(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) {
|
||||
uint8_t dx = x1 - x0;
|
||||
int8_t dy = y1 - y0;
|
||||
int8_t inc = dy > 0 ? 1 : dy == 0 ? 0 : -1;
|
||||
int8_t m = 2 * dy;
|
||||
int8_t error = 0;
|
||||
time_line_t time_line_new(int t0, int y0, int t1, int y1) {
|
||||
int dt = t1 - t0;
|
||||
int dy = y1 - y0;
|
||||
int de = 2 * dy;
|
||||
|
||||
int inc = dy > 0 ? 1 : dy == 0 ? 0 : -1;
|
||||
int error;
|
||||
|
||||
if (de > 0) {
|
||||
error = de - dt;
|
||||
} else {
|
||||
error = de + dt;
|
||||
}
|
||||
|
||||
return (time_line_t){ .y = y0, .dt = dt, .de = de, .error = error, .inc = inc, .dy = dy };
|
||||
}
|
||||
|
||||
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 - dx;
|
||||
error = m - dt;
|
||||
} else {
|
||||
error = m + dx;
|
||||
error = m + dt;
|
||||
}
|
||||
|
||||
return (line_t){ .y = y0, .m = m, .error = error, .inc = inc, .dx = dx };
|
||||
return (time_line_t){ .y = y0, .m = m, .error = error, .inc = inc, .dt = dt };
|
||||
}
|
||||
*/
|
||||
|
||||
uint8_t line_next(line_t *slope) {
|
||||
/*
|
||||
int time_line_next(time_line_t *slope) {
|
||||
slope->error += slope->m;
|
||||
|
||||
if (slope->m > 0) {
|
||||
if (slope->error >= 0) {
|
||||
slope->y += slope->inc;
|
||||
slope->error -= 2 * slope->dx;
|
||||
slope->error -= 2 * slope->dt;
|
||||
}
|
||||
} else {
|
||||
if (slope->error <= 0) {
|
||||
slope->y += slope->inc;
|
||||
slope->error += 2 * slope->dx;
|
||||
slope->error += 2 * slope->dt;
|
||||
}
|
||||
}
|
||||
|
||||
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__
|
||||
#define __ANIMATION_H__
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
typedef struct line_s {
|
||||
uint8_t y;
|
||||
int8_t m;
|
||||
int8_t error;
|
||||
int8_t inc;
|
||||
uint8_t dx;
|
||||
} line_t;
|
||||
typedef struct {
|
||||
int y;
|
||||
int de;
|
||||
int error;
|
||||
int inc;
|
||||
int dt;
|
||||
int dy;
|
||||
} time_line_t;
|
||||
|
||||
// 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.
|
||||
uint8_t line_next(line_t *line);
|
||||
int time_line_next(time_line_t *);
|
||||
|
||||
// Diagnostic printout of the current state of line_t.
|
||||
// void line_print(line_t *line);
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
void bresenham(int x1, int y1, int x2, int y2) {
|
||||
int dx = x2 - x1;
|
||||
void bresenham_time(int t1, int y1, int t2, int y2) {
|
||||
int dt = t2 - t1;
|
||||
int dy = y2 - y1;
|
||||
int m = 2 * dy;
|
||||
int err = 0;
|
||||
|
||||
if (m > 0) {
|
||||
err = m - dx;
|
||||
err = m - dt;
|
||||
} else if (m < 0) {
|
||||
err = m + dx;
|
||||
err = m + dt;
|
||||
}
|
||||
for (int x = x1, y = y1; x <= x2; x++) {
|
||||
printf("(%d, %d) [%d]\n", x, y, err);
|
||||
for (int t = t1, y = y1; t <= t2; t++) {
|
||||
printf("(%d, %d) [%d]\n", t, y, err);
|
||||
|
||||
err += m;
|
||||
|
||||
if (m > 0) {
|
||||
if (err >= 0) {
|
||||
y++;
|
||||
err -= 2 * dx;
|
||||
err -= 2 * dt;
|
||||
}
|
||||
} else if (m < 0) {
|
||||
if (err <= 0) {
|
||||
y--;
|
||||
err += 2 * dx;
|
||||
err += 2 * dt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,36 @@
|
|||
#include <stdlib.h>
|
||||
#include <base.h>
|
||||
#include <rng.h>
|
||||
|
||||
typedef struct RGB_s {
|
||||
uint8_t brightness;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} rgb_t;
|
||||
|
||||
#include <stdio.h>
|
||||
#include <animation.h>
|
||||
|
||||
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++) {
|
||||
animation_step(&animation, &rng);
|
||||
printf("[%d] %d %d %d\n", animation.frame, animation.lamp.r, animation.lamp.g, animation.lamp.b);
|
||||
printf("\n");
|
||||
|
||||
{
|
||||
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" =
|
||||
{ mcu, chip_select, f_cpu }:
|
||||
# { gcc, mcu, chip_select, f_cpu }:
|
||||
{ gcc }:
|
||||
let
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
||||
avr = pkgs.pkgsCross.avr.buildPackages;
|
||||
in pkgs.stdenv.mkDerivation rec {
|
||||
name = "animation";
|
||||
src = ./.;
|
||||
|
||||
CFLAGS = cflags { inherit mcu chip_select f_cpu; };
|
||||
# CFLAGS = cflags { inherit mcu chip_select f_cpu; };
|
||||
|
||||
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 = ''
|
||||
|
@ -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" =
|
||||
{ mcu, chip_select, f_cpu }:
|
||||
let
|
||||
|
|
Loading…
Reference in New Issue