A tiny software raymarcher that attempts to render "n-dimension" manofold insertions as an image appearing to be a non-euclidean 3-dimensional space. Written for the uqcs hackathon 2020. This repo is a mirror of: https://github.com/ailrst/blackpink
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

239 lines
5.4 KiB

#include "colours.h"
int c_round(double a) {
return a - (int)a > 0.5 ? (int)a + 1 : (int)a;
}
struct colour get_random_color(void) {
int red = rand() % 255;
int blue = rand() % 255;
int green = rand() % 255;
struct colour col;
col.r = red;
col.g = green;
col.b = blue;
col.a = 255;
return col;
}
SDL_Colour get_sdlcolour(struct colour col, int alpha) {
struct colour c = get_rgb(col);
return (SDL_Color){c.r, c.g, c.b, alpha};
}
double m_min(double arr[], int len) {
double largest = arr[0];
for (int i = 0; i < len; i ++) {
if (arr[i] < largest) {
largest = arr[i];
}
}
return largest;
}
double m_max(double arr[], int len) {
double largest = arr[0];
for (int i = 0; i < len; i ++) {
if (arr[i] > largest) {
largest = arr[i];
}
}
return largest;
}
bool m_equal(double a, double b) {
return (a - b) * (a - b) < 0.00001;
}
// https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
// h = [0,360], s = [0,1], v = [0,1]
// if s == 0, then h = -1 (undefined)
struct colour get_hs_l_v(struct colour c, enum colour_space sp) {
struct colour ret = {};
double r = (double)c.r / 255;
double g = (double)c.g / 255;
double b = (double)c.b / 255;
double arr[] = {r, g, b};
double max = m_max(arr, 3);
double min = m_min(arr, 3);
ret.v = max;
double chroma = max - min;
double lum = (max + min) / 2;
ret.l = lum;
if (m_equal(chroma, 0)) {
ret.h = 0;
} else if (m_equal(ret.v,r)) {
ret.h = (g - b) / chroma;
} else if (m_equal(max,g)) {
ret.h = 2 + (b - r) / chroma;
} else if (m_equal(max,b)) {
ret.h = 4 + (r - g) / chroma;
} else {
printf("NOPE BAD ERROR\n");
}
ret.h *= 60;
ret.h = fmod(ret.h, 360);
if (ret.h < 0) {
ret.h += 360;
}
if (sp == CS_HSV) {
if (m_equal(max,0)) {
ret.s = 0;
} else {
ret.s = chroma / max;
}
} else {
double arr[] = {ret.l, 1 - ret.l};
if (m_equal(0, lum) || m_equal(1, lum)) {
ret.s = 0;
} else {
ret.s = (ret.v - ret.l) / m_min(arr, 2);
}
}
ret.sp = CS_HSL;
return ret;
}
struct colour get_hsl(struct colour c) {
return get_hs_l_v(c, CS_HSL);
}
struct colour get_hsv(struct colour c) {
return get_hs_l_v(c, CS_HSV);
}
double magic_hsv_function(int n, struct colour c) {
double res = 0;
double k = fmod(n + (c.h / 60), 6);
double arr[] = {k, 4 - k, 1};
double k_b = m_min(arr, 3);
double k_c = 0 > k_b ? 0 : k_b;
res = c.v - c.v * c.s * k_c;
return res;
}
struct colour get_rgb_from_hsv(struct colour c) {
double r = magic_hsv_function(5, c);
double g = magic_hsv_function(3, c);
double b = magic_hsv_function(1, c);
struct colour res;
res.r = c_round(r * 255);
res.g = c_round(g * 255);
res.b = c_round(b * 255);
return res;
}
double magic_hsl_function(int n, struct colour c) {
double a = c.s * ( c.l < (1-c.l) ? c.l : 1 - c.l );
double k = fmod(n + c.h / 30, 12);
double b[] = {k - 3, 9 -k, 1};
double d[] = {-1, m_min(b, 3)};
return c.l - a * (d[0] > d[1] ? d[0] : d[1]);
}
struct colour get_rgb_from_hsl(struct colour c) {
double r = magic_hsl_function(0, c);
double g = magic_hsl_function(8, c);
double b = magic_hsl_function(4, c);
struct colour res;
res.r = c_round(r * 255);
res.g = c_round(g * 255);
res.b = c_round(b * 255);
return res;
}
struct colour get_rgb(struct colour c) {
if (c.sp & CS_RGB){
return c;
}
if (c.sp & CS_HSL) {
return get_rgb_from_hsl(c);
}
if (c.sp & CS_HSV) {
return get_rgb_from_hsv(c);
}
return c;
}
int compare_perceived_lum(const void* c1, const void* c2) {
struct colour rgb_c1 = *(struct colour*)c1;
struct colour rgb_c2 = *(struct colour*)c2;
double lum1 = 0.299*rgb_c1.r + 0.587*rgb_c1.g + 0.114*rgb_c1.b;
double lum2 = 0.299*rgb_c2.r + 0.587*rgb_c2.g + 0.114*rgb_c2.b;
return lum1 - lum2;
}
struct colour *get_adjacent(struct colour base, int deg, int num) {
struct colour col = get_hsl(base);
num += 1;
struct colour* colours = alloca(sizeof(struct colour) * num);
for (int i = 0; i < num; i++) {
int m = (i % 2 == 0) ? -i : i;
colours[i] = col;
colours[i].h += m * deg;
colours[i].h += fmod(colours[i].h, 360);
}
struct colour *ret_colours = calloc(num, sizeof(struct colour) * num);
for (int i = 0; i < num; i++) {
ret_colours[i] = get_rgb(colours[i]);
}
// sort from dark to bright
qsort(ret_colours, num, sizeof(struct colour), compare_perceived_lum);
return ret_colours;
}
void print_colour(struct colour c) {
char *colour = calloc(20, sizeof(char));
sprintf(colour, "#%02x%02x%02x (%d)", c.r, c.g, c.b, c.a);
printf("\x1b[38;2;%d;%d;%dm%s\x1b[0m\n", c.r, c.g, c.b, colour);
free(colour);
}
void test(int seed) {
struct colour c = get_random_color();
struct colour *adj = get_adjacent(c, 5, 4);
for (int i = 0; i < 5; i++) {
print_colour(adj[i]);
}
free(adj);
printf("\n");
}
void test_print_wheel() {
struct colour c;
c.s = 0.999;
c.v = 0.99;
c.l = 0.5;
c.sp = CS_HSV;
for(int i = 0; i < 360; i+=5) {
c.h = (double)i;
struct colour rgb = get_rgb(c);
print_colour(rgb);
}
}