Skip to content

Commit

Permalink
finished circles
Browse files Browse the repository at this point in the history
  • Loading branch information
br-olf committed Jul 18, 2024
1 parent e5ee6fa commit 8dc968c
Showing 1 changed file with 90 additions and 61 deletions.
151 changes: 90 additions & 61 deletions src/modules/gfx_circles.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Circles
//
// How to draw circles without ever using a multiplication?
//
// Copyright (c) 2024, Olaf "brolf" Pichler <brolf@magheute.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
Expand Down Expand Up @@ -28,7 +30,7 @@

#define FPS 60
#define FRAMETIME (T_SECOND / FPS)
#define FRAMES (TIME_LONG * FPS)
#define FRAMES (TIME_MEDIUM * FPS)

static int modno;
static unsigned int frame;
Expand All @@ -37,16 +39,23 @@ static oscore_time nexttick;
static u_int16_t xmax;
static u_int16_t ymax;

#define P_MAX 25
// random seeds for color selection
static u_int16_t rs1;
static u_int16_t rs2;

typedef struct {
u_int16_t x;
u_int16_t y;
u_int16_t r;
u_int16_t x; // x coordinate of center
u_int16_t y; // y coordinate of center
u_int16_t r; // r curent radius of circle
u_int16_t lt; // livetime (rmax) after which the circle should die
} Circle;
static Circle points[P_MAX];

static const RGB black = RGB(0,0,0);
// Number of circles to draw
#define P_MAX 25
static Circle circles[P_MAX];

// Color palette and stuff
static const RGB black = RGB(0,0,0);
static const RGB palette[] = {
RGB(255, 0, 0), RGB(204, 0, 0), RGB(153, 0, 0), RGB(255, 85, 85),
RGB(204, 68, 68), RGB(153, 51, 51), RGB(255, 127, 0), RGB(204, 102, 0),
Expand All @@ -67,49 +76,62 @@ static const RGB palette[] = {
RGB(204, 68, 204), RGB(153, 51, 153), RGB(255, 0, 127), RGB(204, 0, 102),
RGB(153, 0, 76), RGB(255, 85, 170), RGB(204, 68, 136), RGB(153, 51, 102)
};
static const u_int16_t palette_size = sizeof(palette)/sizeof(RGB);
static const u_int16_t palette_size = sizeof(palette) / sizeof(RGB);


// xor the color value at the given position with `color`
static void matrix_xor( u_int16_t x, u_int16_t y, RGB color ){

RGB tmp = matrix_get(x, y);
tmp.red = tmp.red ^ color.red;
tmp.green = tmp.green ^ color.green;
tmp.blue = tmp.blue ^ color.blue;
tmp.alpha = color.alpha;

matrix_set(x, y, tmp);


// printf("%i, %i, %i, %i\n", tmp.red, tmp.green, tmp.blue, tmp.alpha);

}

static void reinit_circle(Circle *c){
c->x = rand()%(xmax/2) + xmax/4;
c->y = rand()%(ymax/2) + ymax/4;
static void check_or_reinit(Circle *c);
// reinitializes a circle given by the pointer `c`
static void reinit_circle( Circle *c ){

c->x = rand()%(xmax);
c->y = rand()%(ymax);
c->lt = rand() % (( xmax > ymax ? xmax : ymax ) / 4) + 2;
c->r = 1;
// check if the coosen circle is valid
check_or_reinit(c);
}

// checks if th circle given by pointer `c` fits inside matrix else it calls `reinit_circle`
static void check_or_reinit(Circle *c){

if( !(xmax > c->x + c->r) ||
!(c->x >= c->r) ||
!(ymax > c->y + c->r) ||
!(c->y >= c->r)
!(c->y >= c->r) ||
!(c->lt > c->r)
)
{
reinit_circle(c);
check_or_reinit(c);
}
}

static void xor_circle(Circle *c, u_int16_t color_id) {

// draws the circle `c` by using xor and a given `color_id`
// `color_id` maps to the `palette`
static void xor_circle(Circle *c, u_int16_t color_id){

// randomly but consistently choose a color
RGB color = palette[(color_id * rs1 + rs2) % palette_size];

// asserts so we do not over or underflow
assert(xmax > c->x + c->r);
assert(c->x >= c->r);

assert(ymax > c->y + c->r);
assert(c->y >= c->r);

// here comes the magic
const u_int16_t cr2 = c->r+c->r;

int16_t x = c->r;
Expand All @@ -118,18 +140,16 @@ static void xor_circle(Circle *c, u_int16_t color_id) {
int16_t dx = cr2+cr2 - 4;
int16_t d = cr2 - 1;

while(y <= x){
matrix_xor( (c->y - y), (c->x - x), color);
matrix_xor( (c->y - y), (c->x + x), color);
matrix_xor( (c->y + y), (c->x - x), color);
matrix_xor( (c->y + y), (c->x + x), color);

while(y <= x)
{
matrix_xor( (c->y - y), (c->x- x), palette[color_id%palette_size]);
matrix_xor( (c->y - y), (c->x + x), palette[color_id%palette_size]);
matrix_xor( (c->y + y), (c->x - x), palette[color_id%palette_size]);
matrix_xor( (c->y + y), (c->x + x), palette[color_id%palette_size]);

matrix_xor( (c->y - x), (c->x - y), palette[color_id%palette_size]);
matrix_xor( (c->y - x), (c->x + y), palette[color_id%palette_size]);
matrix_xor( (c->y + x), (c->x - y), palette[color_id%palette_size]);
matrix_xor( (c->y + x), (c->x + y), palette[color_id%palette_size]);
matrix_xor( (c->y - x), (c->x - y), color);
matrix_xor( (c->y - x), (c->x + y), color);
matrix_xor( (c->y + x), (c->x - y), color);
matrix_xor( (c->y + x), (c->x + y), color);

d += dy;
dy -= 4;
Expand All @@ -141,7 +161,7 @@ static void xor_circle(Circle *c, u_int16_t color_id) {
dx -= 4;
--x;
}
#else
#else // why not make it branchless
int Mask = (d >> 31);
d += dx & Mask;
dx -= -4 & Mask;
Expand All @@ -150,59 +170,68 @@ static void xor_circle(Circle *c, u_int16_t color_id) {
}
}

int init(int moduleno, char* argstr)
{
xmax = matrix_getx();
ymax = matrix_gety();

for( u_int16_t x = 0; x < xmax; x++){
// effect reset and initialisation
static void my_init(){

for( u_int16_t y = 0; y < ymax; y++){
matrix_set(x,y, black);
rs1 = rand() % 65536;
rs2 = rand() % 65536;

// sometimes draw the circles on top of old effect
if( rand() % 3 ) matrix_clear();
else {
static RGB tmp;
for(u_int16_t x = 0; x < xmax; x++){
for(u_int16_t y = 0; y < ymax; y++){
tmp = matrix_get(x, y);
matrix_set(x, y, RGB(tmp.red/2, tmp.green/2, tmp.blue/2));
}
}
}

for( u_int16_t i = 0; i < P_MAX; i++ ){
reinit_circle(&points[i]);
xor_circle(&points[i], i);
// initialize the circles
reinit_circle(&circles[i]);
// darw the first circles
xor_circle(&circles[i], i);
}
}

int init(int moduleno, char* argstr){

xmax = matrix_getx();
ymax = matrix_gety();

my_init();

modno = moduleno;
frame = 0;

return 0;
}

void reset(int _modno)
{

for( u_int16_t x = 0; x < xmax; x++){

for( u_int16_t y = 0; y < ymax; y++){
matrix_set(x,y, black);
}
}

for( u_int16_t i = 0; i < P_MAX; i++ ){
reinit_circle(&points[i]);
xor_circle(&points[i], i);
}
void reset(int _modno) {

my_init();

nexttick = udate();
frame = 0;
}

int draw(int _modno, int argc, char* argv[])
{
int draw(int _modno, int argc, char* argv[]){

// slow the effect down a bit
if (frame % 2 == 0){

for (u_int16_t i = 0; i < P_MAX; ++i) {
xor_circle(&points[i], i);
points[i].r += 1;
check_or_reinit(&points[i]);
xor_circle(&points[i], i);
for (u_int16_t i = 0; i < P_MAX; ++i){
// delete old trace
xor_circle(&circles[i], i);
// increase the radius of current circle
circles[i].r += 1;
// check if circle still valid
check_or_reinit(&circles[i]);
// paint new circle
xor_circle(&circles[i], i);
}
}

Expand Down

0 comments on commit 8dc968c

Please sign in to comment.