diff options
author | Philip J Freeman <elektron@halo.nu> | 2017-01-09 00:35:32 -0800 |
---|---|---|
committer | Philip J Freeman <elektron@halo.nu> | 2017-01-09 00:35:32 -0800 |
commit | c8b77543492c56b747394e2a460074febeaaeab5 (patch) | |
tree | c84a80e4252291882dc0dc972dd1e42f222a2ede /modules | |
parent | bc0ea63460100f61e6c6b73abe20c1f4ffae5db4 (diff) |
stars: add starfield simulator from ph1l/stars
Diffstat (limited to 'modules')
-rw-r--r-- | modules/stars/draw.h | 32 | ||||
-rw-r--r-- | modules/stars/stars.c | 63 | ||||
-rw-r--r-- | modules/stars/stars.h | 8 | ||||
-rw-r--r-- | modules/stars/starslib.c | 133 | ||||
-rw-r--r-- | modules/stars/starslib.h | 19 |
5 files changed, 255 insertions, 0 deletions
diff --git a/modules/stars/draw.h b/modules/stars/draw.h new file mode 100644 index 0000000..58a4a36 --- /dev/null +++ b/modules/stars/draw.h @@ -0,0 +1,32 @@ +#ifndef _DRAW_H +#define _DRAW_H + +#include <stdint.h> + +#include "fb.h" + +/* helper for scaling rgb colors and packing them into an pixel */ +static inline uint32_t makergb(uint32_t r, uint32_t g, uint32_t b, float intensity) +{ + r = (((float)intensity) * r); + g = (((float)intensity) * g); + b = (((float)intensity) * b); + + return (((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff)); +} + +static inline int draw_pixel(fb_fragment_t *f, int x, int y, uint32_t pixel) +{ + uint32_t *pixels = f->buf; + + if (y < 0 || y >= f->height || x < 0 || x >= f->width) { + return 0; + } + + /* FIXME this assumes stride is aligned to 4 */ + pixels[(y * f->width + (f->stride >> 2)) + x] = pixel; + + return 1; +} + +#endif diff --git a/modules/stars/stars.c b/modules/stars/stars.c new file mode 100644 index 0000000..e009714 --- /dev/null +++ b/modules/stars/stars.c @@ -0,0 +1,63 @@ +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <time.h> +#include <sys/types.h> +#include <unistd.h> + +#include "draw.h" +#include "fb.h" +#include "rototiller.h" +#include "starslib.h" + +/* Copyright (C) 2017 Philip J. Freeman <elektron@halo.nu> */ + +static void stars(fb_fragment_t *fragment) +{ + static int initialized, z; + static struct universe* u; + + struct return_point rp; + int x, y, width = fragment->width, height = fragment->height; + + if (!initialized) { + z = 128; + srand(time(NULL) + getpid()); + + // Initialize the stars lib (and pre-add a bunch of stars) + new_universe(&u, width, height, z); + for(y=0; y<z; y++) { + while (process_point(u, &rp) != 0); + for(x=0; x<rand()%128; x++){ + new_point(u); + } + } + initialized = 1; + } + + // draw space (or blank the frame, if you prefer) + memset(fragment->buf, 0, ((fragment->width << 2) + fragment->stride) * fragment->height); + + // draw stars + for (;;) { + int ret = process_point( u, &rp ); + if (ret==0) break; + if (ret==1) draw_pixel(fragment, rp.x+(width/2), rp.y+(height/2), + makergb(0xFF, 0xFF, 0xFF, (float)rp.opacity/OPACITY_MAX) + ); + } + + // add stars at horizon + for (x=0; x<rand()%128; x++) { + new_point(u); + } +} + +rototiller_renderer_t stars_renderer = { + .render = stars, + .name = "stars", + .description = "basic starfield", + .author = "Philip J Freeman <elektron@halo.nu>", + .license = "GPLv2", +}; diff --git a/modules/stars/stars.h b/modules/stars/stars.h new file mode 100644 index 0000000..70ef6f2 --- /dev/null +++ b/modules/stars/stars.h @@ -0,0 +1,8 @@ +#ifndef _STARS_H +#define _STARS_H + +#include "fb.h" + +void stars(fb_fragment_t *fragment); + +#endif diff --git a/modules/stars/starslib.c b/modules/stars/starslib.c new file mode 100644 index 0000000..3c1905c --- /dev/null +++ b/modules/stars/starslib.c @@ -0,0 +1,133 @@ +/* + * a starfield simulation library from: https://github.com/ph1l/stars + * Copyright 2014 Philip J. Freeman <elektron@halo.nu> + */ + +#include <stdlib.h> +#ifdef DEBUG +#include <stdio.h> +#endif +#include "starslib.h" + +struct points +{ + int x, y, z; + struct points *next; +}; + +void new_universe( struct universe** u, int width, int height, int depth ) +{ + *u = malloc(sizeof(struct universe)); + + (*u)->width = width; + (*u)->height = height; + (*u)->depth = depth; + + (*u)->iterator = NULL; + (*u)->points = NULL; + #ifdef DEBUG + printf("NEW UNIVERSE: %lx: (%i,%i,%i)\n", (long unsigned int )(*u), (*u)->width, (*u)->height, (*u)->depth); + #endif + + return; +} + +void new_point( struct universe* u ) +{ + + struct points* p_ptr = malloc(sizeof(struct points)); + + p_ptr->x = (rand()%u->width - (u->width/2)) * u->depth; + p_ptr->y = (rand()%u->height - (u->height/2)) * u->depth; + p_ptr->z = u->depth; + + p_ptr->next = u->points; + u->points = p_ptr; + #ifdef DEBUG + printf("NEW POINT: %lx: (%i,%i,%i) next=%lx\n", (long unsigned int )p_ptr, p_ptr->x, p_ptr->y, p_ptr->z, (long unsigned int) p_ptr->next); + #endif + + return; +} + +void kill_point( struct universe* universe, struct points* to_kill ) +{ + + struct points *p_ptr, *last_ptr = NULL; + + + for ( p_ptr = universe->points; p_ptr != NULL; p_ptr = p_ptr->next) + { + if (p_ptr == to_kill) + { + #ifdef DEBUG + printf("KILL POINT: %lx: (%i,%i,%i).\n", (long unsigned int )p_ptr, p_ptr->x, p_ptr->y, p_ptr->z); + #endif + if (last_ptr == NULL) + { + universe->points = p_ptr->next; + } else { + last_ptr->next = p_ptr->next; + } + free(p_ptr); + } else { + last_ptr = p_ptr; + } + } + #ifdef DEBUG + printf("KILL POINT: %lx\n", (long unsigned int )p_ptr); + #endif + return; +} + +int process_point( struct universe *u, struct return_point *rp ) +{ + + if ( u->iterator == NULL ) { + if (u->points == NULL){ + return 0; + } else { + u->iterator = u->points; + } + } + + if ( u->iterator->z == 0 ){ + // Delete point that has reached us. + struct points *tmp = u->iterator; + u->iterator = u->iterator->next; + kill_point( u, tmp ); + return(-1); + } else { + // Plot the point + int x, y; + x = u->iterator->x / u->iterator->z; + y = u->iterator->y / u->iterator->z; + if ( abs(x) >= u->width/2 || abs(y) >= u->height/2 ){ + // Delete point that is off screen + struct points *tmp = u->iterator; + u->iterator = u->iterator->next; + kill_point( u, tmp ); + if ( u->iterator == NULL ) { + return(0); + } else { + return(-1); + } + } else { + int m = OPACITY_MAX*((u->depth-u->iterator->z)*4)/u->depth; + if ( m>=OPACITY_MAX ){ m=OPACITY_MAX-1; } + u->iterator->z = u->iterator->z - 1; + #ifdef DEBUG + printf("RETURN POINT: %lx\n", (long unsigned int )u->iterator); + #endif + u->iterator = u->iterator->next; + rp->x = x; + rp->y = y; + rp->opacity = m; + if ( u->iterator == NULL ) { + return(0); + } else { + return(1); + } + } + } +} diff --git a/modules/stars/starslib.h b/modules/stars/starslib.h new file mode 100644 index 0000000..0c125a3 --- /dev/null +++ b/modules/stars/starslib.h @@ -0,0 +1,19 @@ +struct universe +{ + int width, height, depth; + struct points* points; + struct points* iterator; +}; + +void new_universe( struct universe** u, int width, int height, int depth ); +void new_point( struct universe* universe ); + +#define OPACITY_MAX 8 +struct return_point +{ + int x, y; + int opacity; +}; + +int process_point( struct universe *u, struct return_point *rp ); + |