Compare commits

...

3 Commits

  1. 21
      Makefile
  2. 209
      camera.c
  3. 22
      camera.h
  4. 8
      colours.c
  5. 310
      distfuncs.c
  6. 24
      distfuncs.h
  7. 166
      main.c
  8. 14
      main.h
  9. 65
      scene.c
  10. 14
      scene.h
  11. 23
      types.h
  12. 34
      vect.c
  13. 3
      vect.h

21
Makefile

@ -1,20 +1,27 @@ @@ -1,20 +1,27 @@
LINKS = -lSDL2 -lm -Wall -g
LINKS = -lSDL2 -lm -lGL -lGLEW -Wall -g
GCC = g++
all: colours.o vect.o distfuncs.o camera.o
gcc main.c colours.o vect.o distfuncs.o camera.o $(LINKS) -o blackpink
all: colours.o vect.o distfuncs.o camera.o scene.o
$(GCC) main.c colours.o vect.o distfuncs.o camera.o scene.o $(LINKS) -o blackpink
colours.o: colours.c colours.h
gcc $(LINKS) -c colours.c -o colours.o
$(GCC) $(LINKS) -c colours.c -o colours.o
vect.o: vect.c vect.h
gcc $(LINKS) -c vect.c -o vect.o
$(GCC) $(LINKS) -c vect.c -o vect.o
distfuncs.o: distfuncs.c distfuncs.h
gcc $(LINKS) -c distfuncs.c -o distfuncs.o
$(GCC) $(LINKS) -c distfuncs.c -o distfuncs.o
camera.o: camera.c
gcc $(LINKS) -c camera.c -o camera.o
$(GCC) $(LINKS) -c camera.c -o camera.o
scene.o: scene.c
$(GCC) $(LINKS) -c scene.c -o scene.o
pres: presentation.md
pandoc -t beamer presentation.md -o pres.pdf
clean:
rm *.o blackpink

209
camera.c

@ -1,12 +1,14 @@ @@ -1,12 +1,14 @@
#include "main.h"
#include "types.h"
#include "math.h"
#include "vect.h"
#include "distfuncs.h"
#include "SCENE.h"
#include "camera.h"
#define DRAW_DIST 10000.0
#define MAX_ITERATIONS 25
#define DRAW_DIST 2055.0
#define MAX_ITERATIONS 255
#define EPSILON 0.1
#define NORMAL_EPSILON 0.0001
double dabs(double yeet) {
if (yeet > 0) {
@ -26,16 +28,29 @@ double dsign(double yeet) { @@ -26,16 +28,29 @@ double dsign(double yeet) {
double manidist(struct vec *v)
{
// return magnitude_vec(v) - 1;
return v->elements[3];
//double yeet = (SDL_GetTicks() / 10);
double yeet = 300;
v->elements[3] -= yeet;
double out = magnitude_vec(v) - yeet;
v->elements[3] += yeet;
return out;
}
struct solid manifold = (struct solid) {
.dist = manidist,
};
struct colour
solid_col(struct object *s, struct ray *r) {
subtract_vec_ip(r->pos, &(s->sol.pos));
struct colour out = s->col(r, s);
add_vec_ip(r->pos, &(s->sol.pos));
return out;
}
double solid_dist(struct solid *s, struct vec *v) {
subtract_vec_ip(v, &s->pos);
subtract_vec_ip(v, &(s->pos));
double out = s->dist(v);
add_vec_ip(v, &s->pos);
return out;
@ -48,27 +63,26 @@ estimateNormal(struct vec *r, struct solid *sol) @@ -48,27 +63,26 @@ estimateNormal(struct vec *r, struct solid *sol)
struct vec *out = new_vec(r->dimension);
struct vec *tmp = new_vec(r->dimension);
for (int i = 0; i < out->dimension; i++) {
tmp->elements[i] = EPSILON;
tmp->elements[i] = NORMAL_EPSILON;
double s1 = solid_dist(sol, tmp);
tmp->elements[i] = -EPSILON;
tmp->elements[i] = -NORMAL_EPSILON;
double s2 = solid_dist(sol, tmp);
out->elements[i] = s1 - s2;
tmp->elements[i] = 0;
out->elements[i] = s1 - s2;
}
free(tmp->elements);
free_vec(tmp);
return normalise_vec_ip(out);
}
struct vec *
reyeet(struct vec *v, struct vec *k) {
struct vec *vs [v->dimension - 1];
struct vec *tmp = new_vec_of(v->dimension, 1);
struct vec *vs [2];
// struct vec *tmp = new_vec_of(v->dimension, 1);
vs[0] = k;
vs[1] = v;
for (int i = 1; i < v->dimension; i++) vs[i] = k;
struct vec *out = perpendicular_vec(v->dimension - 1, vs);
free_vec(tmp);
// for (int i = 1; i < v->dimension; i++) vs[i] = k;
struct vec *out = perpendicular_vec(2, vs);
// free_vec(tmp);
return out;
}
@ -83,27 +97,49 @@ rotateaxis(struct vec *v, struct vec *k, double a) @@ -83,27 +97,49 @@ rotateaxis(struct vec *v, struct vec *k, double a)
free(v->elements);
v->elements = p->elements;
free(p);
}
int vectorisnan(struct vec *v)
{
for (int i = 0; i < v->dimension; i++) {
if (v->elements[i] != v->elements[i])
return 1;
}
return 0;
}
void
manifoldturn(struct ray *r, struct vec *v, double distance)
void
manifoldstepaxees(struct vec *pos, struct vec *dir, struct vec **lads, int numlads, double distance)
{
if (numlads == 0) {
*((int *) 0) = 0;
}
struct vec *yaxisold = estimateNormal(&r->pos, &manifold);
struct vec *yaxisold = estimateNormal(pos, &manifold);
/* move the vector foward in euclid */
add_scaled_vec_ip(&r->pos, &r->dir, distance);
add_scaled_vec_ip(pos, dir, distance);
struct vec *yaxisnew = estimateNormal(&r->pos, &manifold);
struct vec *yaxisnew = estimateNormal(pos, &manifold);
/* stick it to the manifold */
add_scaled_vec_ip(&r->pos, yaxisnew, manifold.dist(&r->pos));
add_scaled_vec_ip(pos, yaxisnew, manifold.dist(pos));
double protamtloc = acos(dot_product_vec(yaxisold,yaxisnew));
struct vec *protaxisloc = normalise_vec_ip(reyeet(yaxisold, yaxisnew));
rotateaxis(v, protaxisloc, protamtloc); /* change the direction */
for (int i = 0; i < numlads; i++) {
struct vec *temp = copy_vec(lads[i]);
rotateaxis(temp, protaxisloc, protamtloc); /* change the direction */
if (!vectorisnan(temp)) {
free(lads[i]->elements);
lads[i]->elements = temp->elements;
free(temp);
} else {
free_vec(temp);
}
}
free_vec(yaxisnew);
free_vec(yaxisold);
@ -111,54 +147,70 @@ manifoldturn(struct ray *r, struct vec *v, double distance) @@ -111,54 +147,70 @@ manifoldturn(struct ray *r, struct vec *v, double distance)
}
void
manifoldstep(struct ray *r, double distance)
manifoldturn(struct ray *r, struct vec *v, double distance)
{
struct vec *yaxisold = estimateNormal(&r->pos, &manifold);
struct vec *yaxisold = estimateNormal(r->pos, &manifold);
/* move the vector foward in euclid */
add_scaled_vec_ip(&r->pos, &r->dir, distance);
add_scaled_vec_ip(r->pos, r->dir, distance);
struct vec *yaxisnew = estimateNormal(&r->pos, &manifold);
struct vec *yaxisnew = estimateNormal(r->pos, &manifold);
/* stick it to the manifold */
add_scaled_vec_ip(&r->pos, yaxisnew, manifold.dist(&r->pos));
add_scaled_vec_ip(r->pos, yaxisnew, manifold.dist(r->pos));
double protamtloc = acos(dot_product_vec(yaxisold,yaxisnew));
struct vec *protaxisloc = normalise_vec_ip(reyeet(yaxisold, yaxisnew));
rotateaxis(&r->dir, protaxisloc, protamtloc); /* change the direction */
struct vec *temp = copy_vec(v);
rotateaxis(temp, protaxisloc, protamtloc); /* change the direction */
if (!vectorisnan(temp)) {
free(v->elements);
v->elements = temp->elements;
free(temp);
} else {
free_vec(temp);
}
free_vec(yaxisnew);
free_vec(yaxisold);
free_vec(protaxisloc);
}
void place(struct solid *v) {
struct vec *dirs [v->pos.dimension];
void
manifoldstep(struct ray *r, double distance)
{
manifoldturn(r, r->dir, distance);
}
void
place(struct solid *v) {
struct vec **dirs = (struct vec **)malloc(sizeof(struct vec *) * v->pos.dimension);
for (int d = 0; d < v->pos.dimension; d++) {
dirs[d] = new_vec(v->pos.dimension);
dirs[d]->elements[d] = 1;
}
struct vec *tdir = new_vec(v->pos.dimension);
struct vec *tpos = new_vec(v->pos.dimension);
struct ray ree = (struct ray) {
.dir = *tdir,
.pos = *tpos,
};
for (int d = 0; d < v->pos.dimension; d++) {
for (double yee = v->pos.elements[d]; dabs(yee) > EPSILON; yee -= dsign(yee) * EPSILON) {
for (int i = 0; i < v->pos.dimension; i++) {
if (i == d) continue;
for (int j = 0; j < v->pos.dimension; j++) {
ree.dir.elements[j] = dirs[d]->elements[j];
ree.pos.elements[j] = v->pos.elements[j];
}
manifoldturn(&ree, dirs[i], EPSILON);
}
manifoldstep(&ree, EPSILON);
struct vec *temp = copy_vec(dirs[d]);
manifoldstepaxees(tpos, temp, dirs, v->pos.dimension, EPSILON);
free_vec(temp);
}
tpos->elements[d] = v->pos.elements[d];
}
v->pos.elements = tpos->elements;
free(tpos);
free_vec(tdir);
for (int d = 0; d < v->pos.dimension; d++) free_vec(dirs[d]);
free(dirs);
}
struct pixel_info
@ -168,27 +220,31 @@ march(struct ray *r, struct object *scene) @@ -168,27 +220,31 @@ march(struct ray *r, struct object *scene)
double scene_dist;
double min_dist = DRAW_DIST;
int i;
struct colour out = (struct colour) {};
int fligs = 0;
struct colour out = (struct colour) {.sp = CS_RGB};
for (i = 0; (i < MAX_ITERATIONS) && (travel_dist < DRAW_DIST); i++) {
scene_dist = scene->sol.dist(&(r->pos));
/* calculate the distance to the scene */
scene_dist = solid_dist(&(scene->sol), r->pos);
if (scene_dist < EPSILON) { /* we've hit an object */
out = scene->col(r);
break;
out = solid_col(scene, r);
fligs |= 0x01;
break;
}
if (min_dist > scene_dist)
min_dist = scene_dist;
/* step foward the calculated distance */
manifoldstep(r, scene_dist);
travel_dist += scene_dist;
}
/* no colour reached */
return (struct pixel_info) {
.flags = 1,
.iterations = i,
.flags = fligs,
.col = out,
.iterations = i,
.travel_dist = travel_dist,
.scene_dist = min_dist
};
@ -197,9 +253,9 @@ march(struct ray *r, struct object *scene) @@ -197,9 +253,9 @@ march(struct ray *r, struct object *scene)
union badpixelformat {
struct {
Uint8 r;
Uint8 g;
Uint8 b;
Uint8 g;
Uint8 r;
Uint8 a;
};
Uint32 pixel;
@ -218,28 +274,55 @@ Uint32 get_stl_colour(struct colour *cl) { @@ -218,28 +274,55 @@ Uint32 get_stl_colour(struct colour *cl) {
Uint32
process_pixel(int i, int j)
{
struct object white_sphere = new_sphere(100);
struct vec *pos = new_vec(4);
struct vec *dir = normalise_vec_ip(new_vec4(i - B_INTERNAL_WIDTH/2, j - B_INTERNAL_HEIGHT/2, 100, 0));
struct ray r = (struct ray) {
.pos = *pos,
.dir = *dir,
.pos = new_vec(4),
.dir = normalise_vec_ip(new_vec4(i - B_INTERNAL_WIDTH/2, j - B_INTERNAL_HEIGHT/2, 100, 0))
};
struct pixel_info p = march(&r, &white_sphere);
p.col.r -= p.iterations*10;
p.col.b -= p.iterations*10;
p.col.g -= p.iterations*10;
struct pixel_info p = march(&r, scene_object);
// p.col.r += p.travel_dist;
if (!(p.flags & 0x01)) {
p.col.b = 255;
p.col.r = j * 7;
p.col.g += (16.0 / p.scene_dist);
p.col.b += (16.0 / p.scene_dist);
} else {
// p.col.r -= p.iterations;
// p.col.g -= p.iterations;
// p.col.b -= p.iterations;
}
double fade_intensity = 10;
if (p.travel_dist < DRAW_DIST) {
p.col.r -= fade_intensity * p.travel_dist / DRAW_DIST;
p.col.g -= fade_intensity * p.travel_dist / DRAW_DIST;
p.col.b -= fade_intensity * p.travel_dist / DRAW_DIST;
}
p.col.r = clamp(p.col.r, 0, 255);
p.col.g = clamp(p.col.g, 0, 255);
p.col.b = clamp(p.col.b, 0, 255);
// p.col.g = 0;
// printf("%d, ", p.iterations);
/*
if (p.col.r < 0) p.col.r = 0;
if (p.col.g < 0) p.col.g = 0;
if (p.col.b < 0) p.col.b = 0;
if (p.col.r > 255) p.col.r = 255;
if (p.col.g > 255) p.col.g = 255;
if (p.col.b > 255) p.col.b = 255;
*/
// p.col.b = 255.0 / p.scene_dist;
// if (p.col.b > 255) p.col.b = 255;
free_vec(pos);
// free_vec(dir);
free_vec(r.pos);
free_vec(r.dir);
return get_stl_colour(&p.col);
}
}

22
camera.h

@ -1,3 +1,23 @@ @@ -1,3 +1,23 @@
#include "types.h"
#include "math.h"
#include "vect.h"
#include "distfuncs.h"
#include "scene.h"
#ifndef CAMH
#define CAMH
struct pixel_info march(struct ray *r, struct object *scene);
Uint32 process_pixel(int, int);
void place(struct solid *v);
struct colour solid_col(struct object *s, struct ray *r);
double solid_dist(struct solid *s, struct vec *v);
void place(struct solid *v);
struct vec * estimateNormal(struct vec *r, struct solid *sol);
void manifoldstep(struct ray *r, double distance);
void manifoldturn(struct ray *r, struct vec *v, double distance);
void manifoldstepaxees(struct vec *pos, struct vec *dir, struct vec **lads, int numlads, double distance);
#endif

8
colours.c

@ -19,7 +19,7 @@ struct colour get_random_color(void) { @@ -19,7 +19,7 @@ struct colour get_random_color(void) {
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};
return (SDL_Color){(char)c.r, (char)c.g, (char)c.b, alpha};
}
double m_min(double arr[], int len) {
@ -182,7 +182,7 @@ struct colour *get_adjacent(struct colour base, int deg, int num) { @@ -182,7 +182,7 @@ 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);
struct colour* colours = (struct colour *)alloca(sizeof(struct colour) * num);
for (int i = 0; i < num; i++) {
int m = (i % 2 == 0) ? -i : i;
@ -192,7 +192,7 @@ struct colour *get_adjacent(struct colour base, int deg, int num) { @@ -192,7 +192,7 @@ struct colour *get_adjacent(struct colour base, int deg, int num) {
colours[i].h += fmod(colours[i].h, 360);
}
struct colour *ret_colours = calloc(num, sizeof(struct colour) * num);
struct colour *ret_colours = (struct colour *)calloc(num, sizeof(struct colour) * num);
for (int i = 0; i < num; i++) {
ret_colours[i] = get_rgb(colours[i]);
@ -205,7 +205,7 @@ struct colour *get_adjacent(struct colour base, int deg, int num) { @@ -205,7 +205,7 @@ struct colour *get_adjacent(struct colour base, int deg, int num) {
}
void print_colour(struct colour c) {
char *colour = calloc(20, sizeof(char));
char *colour = (char *)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);

310
distfuncs.c

@ -1,28 +1,98 @@ @@ -1,28 +1,98 @@
#include "main.h"
#include "types.h"
#include "vect.h"
#include "camera.h"
#define SOFT_LIGHT 1
#define HARD_LIGHT 2
#define WHITE_LIGHT 2
struct colour yeet_pho(struct ray *ray, struct object *o);
double divid_fp(double a, double b) {
return a / b;
}
/*
*
* float sdEllipsoid( vec3 p, vec3 r )
{
float k0 = length(p/r);
float k1 = length(p/(r*r));
return k0*(k0-1.0)/k1;
}
*
*/
double sdf_4ellipsoid(struct vec *x) {
double r = 1;
struct vec *shape = new_vec4(1.5,3,1,4);
struct vec *v = copy_vec(x);
double dim = 0;
for (int i = 0 ; i < v->dimension; i ++) {
v->elements[i] = v->elements[i] / shape->elements[i];
}
double k0 = magnitude_vec(v);
free_vec(v);
v = copy_vec(x);
for (int i = 0 ; i < v->dimension; i ++) {
v->elements[i] = v->elements[i] / pow(shape->elements[i], 2);
}
double k1 = magnitude_vec(v);
double result = k0 * (k0 - 1.0) / k1;
free_vec(v);
return result;
}
double sdf_3ellipsoid(struct vec *x) {
double r = 1;
struct vec *shape = new_vec3(1.5,3,1);
struct vec *v = copy_vec(x);
double dim = 0;
for (int i = 0 ; i < 3; i ++) {
v->elements[i] = v->elements[i] / shape->elements[i];
}
double k0 = magnitude_vec(v);
free_vec(v);
v = copy_vec(x);
for (int i = 0 ; i < 3; i ++) {
v->elements[i] = v->elements[i] / pow(shape->elements[i], 2);
}
double k1 = magnitude_vec(v);
double result = k0 * (k0 - 1.0) / k1;
free_vec(v);
free_vec(shape);
return result;
}
double sdf_sphere(struct vec *x) {
static const double r = 1.4;
struct vec *v = copy_vec(x);
//v->elements[2] -= 5;
// v->elements[2] -= 5;
// v->elements[1] += (SDL_GetTicks()/1000.0) - 5;
v->elements[2] -= 2;
// v->elements[2] -= 2;
// v->elements[1] += (SDL_GetTicks()/1000.0) - 5;
double res = magnitude_vec(v) - r;
free_vec(v);
// return magnitude_vec(x - centre) - r
//
// printf("v %f %f\n", magnitude_vec(x) - r);
return res;
}
double sdf_hplane(struct vec *x) {
static const double h = -5;
return -(x->e->y) - h ;
static const double h = -0.5;
return -(x->elements[1] + h);
}
double clamp(double val, double min, double max) {
@ -72,19 +142,18 @@ double sdf_cone(struct vec *x) { @@ -72,19 +142,18 @@ double sdf_cone(struct vec *x) {
}
*/
double is_pos(double a) {
double clamp_positive(double a) {
if (a > 0) {
return a;
}
return 0;
}
double sdf_fat_vert_line(struct vec *x) {
static const double h = 10;
static const double r = 1;
double sdf_phat_vert_line(struct vec *x) {
static const double h = 2;
static const double r = 0.5;
struct vec *v = copy_vec(x);
v->elements[2] -= 50;
v->e->y -= clamp(v->e->y, 0.0, h);
double val = magnitude_vec(v) - r;
@ -92,43 +161,240 @@ double sdf_fat_vert_line(struct vec *x) { @@ -92,43 +161,240 @@ double sdf_fat_vert_line(struct vec *x) {
return val;
}
double is_pos(double a) {
if (a > 0) {
return a;
}
return 0;
}
/* https://www.alanzucconi.com/2016/07/01/signed-distance-functions/#part3 */
/* http://mercury.sexy/hg_sdf/ */
double sdf_box(struct vec *x) {
struct vec *v = copy_vec(x);
v->elements[2] -= 50;
do_on_vec_ip(v, fabs);
static struct vec * box_shape = NULL;
if (!box_shape) {
box_shape = new_vec_of(v->dimension, -0.5);
}
struct vec * box_shape = new_vec_of(v->dimension, 5);
subtract_vec_ip(box_shape, v);
do_on_vec_ip(v, is_pos);
double result = magnitude_vec(v);
free_vec(v);
free(box_shape);
return result;
}
struct colour yeet(struct ray *ray) {
struct colour c = {.r = 255, .g = 0, .b = 255, .a = 255, .sp=CS_RGB};
struct colour yeet_pho(struct ray *ray, struct object *o) {
double specular = 0.6;
double diffuse = 0.90;
double ambient = 0.2;
double shin = 41;
int light_type = SOFT_LIGHT;
struct colour light_col = {.sp = CS_RGB, .r = 200, .g = 0, .b = 100};
//struct vec *light = new_vec4(-1, 1, 1, 0);
struct vec *light = copy_vec(camera->light);
//struct vec *light = add_vec_ip(new_vec4(50,50,-50,0), &o->sol.pos);
//struct vec *colour = new_vec3(o->base_col.r, o->base_col.g, o->base_col.b);
/* ambient */
//scalar_multiply_vec_ip(colour, ambient);
double intensity = ambient;
struct vec *surf_norm = normalise_vec_ip(estimateNormal(ray->pos, &o->sol));
// struct vec *light_vec = normalise_vec_ip(subtract_vec(ray->pos, light));
struct vec *light_vec = normalise_vec_ip(subtract_vec_ip(scalar_multiply_vec(light, 1), ray->pos));
double diffuse_val = clamp(dot_product_vec(light_vec, surf_norm),0,1) * diffuse;
printf("%f %f %f \n", diffuse_val, dot_product_vec(light_vec, surf_norm), diffuse);
// r = 2 * (l . n) * n - L
struct vec *camera_vec = normalise_vec_ip(scalar_multiply_vec(ray->pos, -1));
struct vec *reflection = scalar_multiply_vec(surf_norm,
2 * dot_product_vec(light_vec, surf_norm));
subtract_vec_ip(reflection, light_vec);
double spec_val = clamp(pow(clamp(dot_product_vec(reflection, camera_vec),-1,1), shin) * specular, 0, 1);
struct colour c = get_hsl(o->base_col);
intensity = clamp(ambient + diffuse_val + spec_val, 0,1);
c.l = intensity;
c.a = 255;
c = get_rgb(c);
print_colour(c);
printf("ambient %f diffuse %f specular %f\n", ambient, diffuse_val, spec_val);
// specular highlights
light_col = get_hsl(light_col);
light_col.l = spec_val;
light_col = get_rgb(light_col);
return c;
if (1 && spec_val > 0.0) {
if (light_type == HARD_LIGHT) {
c.r = light_col.r > c.r ? c.r + (light_col.r - c.r) / 2 : c.r;
c.g = light_col.g > c.g ? c.g + (light_col.g - c.g) / 2 : c.g;
c.b = light_col.b > c.b ? c.b + (light_col.b - c.b) / 2 : c.b;
} else if (light_type == SOFT_LIGHT) {
c.r = light_col.r > c.r ? light_col.r: c.r;
c.g = light_col.g > c.g ? light_col.g: c.g;
c.b = light_col.b > c.b ? light_col.b: c.b;
}
}
free_vec(camera_vec);
free_vec(reflection);
free_vec(surf_norm);
free_vec(light_vec);
free_vec(light);
print_colour(c);
printf("==\n");
c = get_rgb(c);
return c;
}
struct colour yeet_col_og(struct ray *ray, struct object *obj) {
struct vec *l = new_vec4(1,1,1,1);
struct vec *n = subtract_vec_ip(l, ray->pos);
struct vec *nl = normalise_vec(l);
struct colour c;
c.r = nl->e->x * 555;
c.g = nl->e->y * 555;
c.b = nl->e->z * 555;
c.a = 255;
c.sp=CS_RGB;
free_vec(n);
return (c);
}
/*
struct object new_sphere(double radius) {
struct object s;
struct vec * v = new_vec4(0,0,5,0);
s.base_col = get_random_color();
s.sol.pos = *v;
s.sol.op = B_ADD;
s.col = yeet;
s.sol.dist = sdf_fat_vert_line;
<<<<<<< HEAD
s.col = dlight;
s.sol.dist = sdf_sphere;
=======
s.col = yeet_pho;
s.sol.dist = sdf_sphere;
>>>>>>> c7d411c56163ce7ff7ce27b88bbcb70b07f806d9
return s;
*/
/**
* Creates a new struct object with the given parameters. The position passed
* in should be a vec4 as this is converted to a vec3 when the object is added
* to the scene.
*/
struct object
new_object(struct vec* position, double rotation, double scale,
double (*dist)(struct vec*), struct colour (*col)(struct ray *, struct object *))
{
struct object new_obj;
struct colour default_col = {.sp=CS_RGB, .r = 255, .g=255, .b=255, .a=255};
new_obj.base_col = default_col;
new_obj.col = col;
new_obj.sol.dist = dist;
new_obj.sol.pos = *position;
new_obj.sol.rotation = rotation;
new_obj.sol.scale = scale;
new_obj.sol.op = B_ADD;
return new_obj;
}
struct object new_plane(struct vec* position, double rotation, double scale) {
return new_object(position, rotation, scale, sdf_hplane, yeet_pho);
}
struct object new_sphere(struct vec* position, double rotation, double scale) {
return new_object(position, rotation, scale, sdf_sphere, yeet_pho);
}
struct object new_ellipse(struct vec* position, double rotation, double scale) {
return new_object(position, rotation, scale, sdf_3ellipsoid, yeet_pho);
}
struct object new_box(struct vec* position, double rotation, double scale) {
return new_object(position, rotation, scale, sdf_box, yeet_pho);
}
/* DON'T CALL THIS */
struct object new_cone(struct vec* position, double rotation, double scale) {
return new_object(position, rotation, scale, NULL, NULL);
}
struct object new_vert_line(struct vec* position, double rotation, double scale) {
return new_object(position, rotation, scale, sdf_phat_vert_line, yeet_pho);
}
struct colour yeet_whit(struct ray *ray, struct object* obj) {
struct colour c = {.sp=CS_RGB, .r = 200, .g = 200, .b = 200, .a = 255};
return c;
}
struct colour yeet_green(struct ray *ray, struct object* obj) {
short g = ((int)rand() % 127) + 127;
struct colour c = { .sp=CS_RGB, .r = 0, .g = g, .b = 0, .a = 255};
return c;
}
struct colour yeet_brown(struct ray *ray, struct object* obj) {
struct colour c = {.sp=CS_RGB, .r = 210, .g = 105, .b = 30};
return c;
}
/**
* The absolute jankiest way to make a tree but I couldn't think of anything
* better.
*
* Returns a pointer to the first element of an array of the components of the
* tree (trunk and leaves). Iterate over the array when adding to a scene.
*/
struct object* new_tree(struct vec* position, double rotation, double scale) {
struct object* tree = (struct object *)malloc(2 * sizeof(struct object));
struct object trunk = new_object(position, rotation, scale, sdf_phat_vert_line, yeet_pho);
trunk.base_col = (struct colour){.sp = CS_RGB, .r = 210, .g = 105, .b = 30};
struct vec* leaf_pos = add_vec_ip(new_vec4(0, -3, 0, 0), position);
struct object leaves = new_object(leaf_pos, rotation, scale, sdf_3ellipsoid, yeet_pho);
leaves.base_col = (struct colour){ .sp = CS_RGB, .r = 0, .g = 255, .b = 0};
leaves.base_col.r = 30 + rand() % 20;
leaves.base_col.g = 155 + rand() % 100;
leaves.base_col.b = random() % 90;
leaves.base_col.sp = CS_RGB;
// leaves.base_col = (struct colour){.r = 30 + random() % 20, .g = 155 + random() % 100, .b = random() % 90, .sp = CS_RGB};
tree[0] = trunk;
tree[1] = leaves;
return tree;
}

24
distfuncs.h

@ -1,6 +1,28 @@ @@ -1,6 +1,28 @@
#ifndef DISTFU
#define DISTFU
struct object new_sphere(double radius);
struct object new_sphere(struct vec *, double, double);
/* Don't call this, it's just a placeholder rn */
struct object new_cone(struct vec *, double, double);
struct object new_box(struct vec *, double, double);
struct object new_vert_line(struct vec *, double, double);
struct object* new_tree(struct vec *, double, double);
struct object new_object(struct vec *, double, double, double (*) (struct vec *),
struct colour (*)(struct ray *, struct object *));
struct object new_plane(struct vec* position, double rotation, double scale);
double sdf_box(struct vec *);
double sdf_hplane(struct vec *);
double sdf_phat_vert_line(struct vec *);
double sdf_sphere(struct vec *);
struct colour yeet_col(struct ray *);
double sdf_3ellipsoid(struct vec *x);
double sdf_4ellipsoid(struct vec *x);
double clamp(double val, double min, double max);
#endif

166
main.c

@ -1,11 +1,15 @@ @@ -1,11 +1,15 @@
#include "main.h"
#include "queue.h"
#include "camera.h"
#include "distfuncs.h"
#include "scene.h"
#include "types.h"
#include "vect.h"
#include "camera.h"
#include <SDL2/SDL_blendmode.h>
#include <SDL2/SDL_gamecontroller.h>
#include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_stdinc.h>
#include <SDL2/SDL_thread.h>
@ -13,19 +17,23 @@ @@ -13,19 +17,23 @@
#include <SDL2/SDL_video.h>
#include <stdlib.h>
int keyboardstate[322] = {}; // 322 is the number of SDLK_DOWN events
int exitnow = 0;
SDL_Renderer * ren;
Uint32 pixels[B_INTERNAL_HEIGHT][B_INTERNAL_WIDTH];
struct object white_sphere;
struct object *scene_object;
struct camera *camera;
SDL_mutex *frame_mutex;
struct SDL_Window* make_window(void) {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
printf("error initializing SDL: %s\n", SDL_GetError());
}
return SDL_CreateWindow("sdl_tester",
return SDL_CreateWindow("𝕧 𝕒 𝕡 𝕠 𝕣 𝕨 𝕒 𝕧 𝕖",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
B_WINDOW_WIDTH, B_WINDOW_HEIGHT,
@ -35,20 +43,50 @@ struct SDL_Window* make_window(void) { @@ -35,20 +43,50 @@ struct SDL_Window* make_window(void) {
void handle_inputs(void)
{
if (keyboardstate[SDL_SCANCODE_UP])
printf("up");
if (keyboardstate[SDL_SCANCODE_DOWN])
printf("down");
if (keyboardstate[SDL_SCANCODE_LEFT])
printf("left");
if (keyboardstate[SDL_SCANCODE_RIGHT])
printf("right");
/* this is so broken it leaks memory everywhere and crashes and idek why
* Pressing UP will crash immediately and anything else will crash
* eventually
*
* It also makes the object disappear off into the 4th dimension
*/
struct ray r;
r.dir = new_vec(4);
r.pos = new_vec(4);
const double dist = 1;
struct vec ** in = (struct vec **)malloc(sizeof(struct vec *) * 3);
in[0] = camera->x;
in[1] = camera->y;
in[2] = camera->z;
if (keyboardstate[SDL_SCANCODE_J]) {
manifoldstepaxees(camera->pos, camera->y, in, 3, -dist);
}
if (keyboardstate[SDL_SCANCODE_K]) {
manifoldstepaxees(camera->pos, camera->y, in, 3, dist);
}
if (keyboardstate[SDL_SCANCODE_UP] ) {
manifoldstepaxees(camera->pos, camera->z, in, 3, -dist);
}
if (keyboardstate[SDL_SCANCODE_DOWN]) {
manifoldstepaxees(camera->pos, camera->z, in, 3, dist);
}
if (keyboardstate[SDL_SCANCODE_LEFT] || keyboardstate[SDL_SCANCODE_H]) {
manifoldstepaxees(camera->pos, camera->x, in, 3, dist);
}
if (keyboardstate[SDL_SCANCODE_RIGHT] || keyboardstate[SDL_SCANCODE_L]) {
manifoldstepaxees(camera->pos, camera->x, in, 3, -dist);
}
r.dir->elements[0] = -1;
if (keyboardstate[SDL_SCANCODE_ESCAPE]) {
exitnow = 1;
}
return;
};
free(in);
}
int input_loop(void *ptr) {
@ -59,7 +97,7 @@ int input_loop(void *ptr) { @@ -59,7 +97,7 @@ int input_loop(void *ptr) {
switch (event.type) {
case SDL_QUIT:
exitnow = 1;
// *(int *)0 = 1; // segfault
// *(int *)0 = 1; // segfault
break;
case SDL_KEYDOWN:
keyboardstate[event.key.keysym.scancode] = 1;
@ -69,8 +107,10 @@ int input_loop(void *ptr) { @@ -69,8 +107,10 @@ int input_loop(void *ptr) {
break;
}
}
SDL_Delay(50);
SDL_LockMutex(frame_mutex);
handle_inputs();
SDL_Delay(100);
SDL_UnlockMutex(frame_mutex);
}
return 0;
}
@ -93,39 +133,106 @@ static int raymarch_threadfn(void *data) { @@ -93,39 +133,106 @@ static int raymarch_threadfn(void *data) {
free(data);
return 0;
}
void setup_camera_scene()
{
//struct object white_sphere = new_object(new_vec3(0.75, 0, 8), 0, 1, sdf_box, yeet_whit);
camera = (struct camera *)calloc(1, sizeof(struct camera));
camera->pos = new_vec(4);
camera->x = new_vec(4);
camera->y = new_vec(4);
camera->z = new_vec(4);
camera->x->elements[0] = 1;
camera->y->elements[1] = 1;
camera->z->elements[2] = 1;
struct solid templight;
camera->light = new_vec4(0, 1000, -1000, 0);
templight.pos = *camera->light;
place(&templight);
*camera->light = templight.pos;
// struct object white_sphere = new_box(new_vec3(-0.75, 0, 8), 0, 1);
// struct object other_white_sphere = new_sphere(new_vec3(0.75, 0, 8), 0, 1);
const double lower_pos_bound = -5;
const double upper_pos_bound = 5;
//const double upper_pos_bound = 5;
const int num_trees = 4;
int lastelem = 1;
struct object* scene_objects = (struct object *)malloc((lastelem + 2 * num_trees) * sizeof(struct object));
struct vec *plane_pos = new_vec4(0,2,-5,0);
scene_objects[0] = new_plane(plane_pos, 1, 1);
for (int i = lastelem; i < lastelem + 2 * num_trees; i+=2) {
struct vec* random_pos = new_random_vec(4, lower_pos_bound, upper_pos_bound);
random_pos->elements[1] = 0;
random_pos->elements[3] = 0;
struct object* tree = new_tree(random_pos, 0, 1);
scene_objects[i] = tree[0];
scene_objects[i + 1] = tree[1];
}
scene_object = new_scene(2 * num_trees + lastelem, scene_objects);
scene_object->sol.pos.dimension = 4;
scene_object->sol.pos.elements = camera->pos->elements;
}
int main(int argc, char **argv) {
SDL_Window * win = make_window();
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_Window *win = make_window();
ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_RenderSetLogicalSize(ren, B_INTERNAL_HEIGHT, B_INTERNAL_HEIGHT);
SDL_GLContext glContext = SDL_GL_CreateContext(win);
GLenum status = glewInit();
if (status != GLEW_OK)
{
exit(1);
}
// SDL_RenderSetLogicalSize(ren, B_INTERNAL_HEIGHT, B_INTERNAL_HEIGHT);
// use this to turn on antristroptic filtering
// SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
// SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
frame_mutex = SDL_CreateMutex();
SDL_Thread *input_thread = SDL_CreateThread(input_loop, "input", (void *)NULL);
double elapsed;
int framct = 0;
Uint64 start, end;
white_sphere = new_sphere(100);
/* texture for drawing into */
SDL_Rect view = {.w = B_INTERNAL_WIDTH, .h = B_INTERNAL_HEIGHT, .x = 0, .y = 0};
SDL_Texture *texture = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STATIC, B_INTERNAL_WIDTH, B_INTERNAL_HEIGHT);
SDL_Thread ** threads = calloc(B_NUM_RAYMARCH_THREADS, sizeof(SDL_Thread *));
SDL_Thread ** threads = (SDL_Thread **)calloc(B_NUM_RAYMARCH_THREADS, sizeof(SDL_Thread *));
SDL_Thread *input_thread = SDL_CreateThread(input_loop, "input", (void *)NULL);
setup_camera_scene();
while (!exitnow) {
/* clear the view */
start = SDL_GetPerformanceCounter();
SDL_LockMutex(frame_mutex);
SDL_RenderClear(ren);
for (int i = 0; i < B_NUM_RAYMARCH_THREADS; i++) {
int *tid = malloc(sizeof(int));
int *tid = (int *)malloc(sizeof(int));
*tid = i;
threads[i] = SDL_CreateThread(raymarch_threadfn, "raymarch", tid);
// tid is freed in raymarch_threadfn
@ -136,7 +243,8 @@ int main(int argc, char **argv) { @@ -136,7 +243,8 @@ int main(int argc, char **argv) {
SDL_WaitThread(threads[i], &status);
}
SDL_UpdateTexture(texture, &view, pixels, B_INTERNAL_WIDTH * sizeof(Uint32));
SDL_UnlockMutex(frame_mutex);
SDL_UpdateTexture(texture, NULL, pixels, B_INTERNAL_WIDTH * sizeof(Uint32));
SDL_RenderCopy(ren, texture, NULL, NULL);
@ -147,8 +255,12 @@ int main(int argc, char **argv) { @@ -147,8 +255,12 @@ int main(int argc, char **argv) {
if (el > 0) {
elapsed = 1000 / el;
}
printf("\rframerate: %f", elapsed);
// fflush(stdout);
framct++;
printf("\rframerate: %f, %d", elapsed, framct);
fflush(stdout);
if (framct++ >= 10) {
}
}

14
main.h

@ -14,13 +14,27 @@ @@ -14,13 +14,27 @@
#include <SDL2/SDL_scancode.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <SDL2/SDL_opengl.h>
#include "colours.h"
#include "types.h"
#include "vect.h"
#include "math.h"
#include "queue.h"
#ifndef MIAINH
#define MIAINH
extern struct object white_sphere;
extern SDL_Renderer *ren;
void sdlb_set_colour(struct colour col);
void sdlb_draw_col_pixel(struct colour col, int x, int y);
extern struct object *scene_object;
extern int keyboardstate[322]; // 322 is the number of SDLK_DOWN events
extern struct camera *camera;
#endif

65
scene.c

@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
#include "scene.h"
struct scene_objects {
int num_objects;
struct object* objects;
};
struct scene_objects scene;
struct colour
colour_function(struct ray* ray, struct object* obj)
{
if (scene.num_objects == 0) {
return (struct colour) {};
}
struct colour scene_colour = scene.objects[0].col(ray, &scene.objects[0]);
double min = DBL_MAX;
for (int i = 0; i < scene.num_objects; i++) {
double distance = solid_dist(&(scene.objects[i].sol), ray->pos);
if (distance < min) {
min = distance;
scene_colour = solid_col(scene.objects + i, ray);
}
}
return scene_colour;
}
double
distance_function(struct vec* position)
{
double min = DBL_MAX;
for (int i = 0; i < scene.num_objects; i++) {
double distance = solid_dist(&(scene.objects[i].sol), position);
if (distance < min) {
min = distance;
}
}
return min;
}
struct object *
new_scene(int num_scene_objects, struct object* scene_objects)
{
scene.num_objects = num_scene_objects;
scene.objects = scene_objects;
for (int i = 0; i < num_scene_objects; i++) {
place(&(scene.objects[i].sol));
}
struct object *scene_rep = (struct object *)malloc(sizeof(struct object));
scene_rep->sol.dist = distance_function;
scene_rep->sol.op = B_ADD;
scene_rep->sol.rotation = 0;
scene_rep->sol.scale = 1;
scene_rep->col = colour_function;
return scene_rep;
}

14
scene.h

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
#ifndef SCENE_H
#define SCENE_H
#include <stdio.h>
#include <stdlib.h>
#include "types.h"
#include "camera.h"
extern struct scene_objects scene;
struct object * new_scene(int, struct object*);
#endif

23
types.h

@ -2,10 +2,10 @@ @@ -2,10 +2,10 @@
#define TYPES_H
#define B_NUM_RAYMARCH_THREADS 8
#define B_WINDOW_WIDTH 800
#define B_WINDOW_HEIGHT 600
#define B_INTERNAL_HEIGHT 100
#define B_INTERNAL_WIDTH 100
#define B_WINDOW_WIDTH 900
#define B_WINDOW_HEIGHT 504
#define B_INTERNAL_HEIGHT 64
#define B_INTERNAL_WIDTH 114
#include "vect.h"
#include "main.h"
@ -16,14 +16,18 @@ enum solid_op { @@ -16,14 +16,18 @@ enum solid_op {
struct ray
{
struct vec pos;
struct vec dir;
struct vec *pos;
struct vec *dir;
};
struct camera
{
struct vec pos;
struct vec rot;
struct vec *x;
struct vec *y;
struct vec *z;
struct vec *pos;
struct vec *light;
//struct vec *rot;
int dims;
};
@ -47,7 +51,8 @@ struct solid { @@ -47,7 +51,8 @@ struct solid {
struct object
{
struct solid sol;
struct colour (*col)(struct ray *);
struct colour (*col)(struct ray *, struct object *);
struct colour base_col;
};
#endif

34
vect.c

@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
#include <math.h>
#include <float.h>
/**
* Creates a new vec* struct with the given number of dimenions.
* All elements are set to 0.
@ -9,10 +11,22 @@ @@ -9,10 +11,22 @@
struct vec*
new_vec(int num_dimensions)
{
struct vec* new_vector = calloc(1,sizeof(struct vec));
struct vec* new_vector = (struct vec *)calloc(1,sizeof(struct vec));
new_vector->dimension = num_dimensions;
new_vector->elements = calloc(num_dimensions, sizeof(double));
new_vector->elements = (double *)calloc(num_dimensions, sizeof(double));
return new_vector;
}
struct vec*
new_random_vec(int num_dimensions, double min, double max)
{
struct vec* new_vector = new_vec(num_dimensions);
for (int i = 0; i < num_dimensions; i++) {
double rand_val = (double) rand() / RAND_MAX;
new_vector->elements[i] = min + rand_val * (max - min);
}
return new_vector;
}
@ -186,7 +200,7 @@ add_scaled_vec_ip(struct vec* a, struct vec* b, double scaleFactor) { @@ -186,7 +200,7 @@ add_scaled_vec_ip(struct vec* a, struct vec* b, double scaleFactor) {
* Subtracts vec b from vec a and returns a reference to the difference vec.
*/
struct vec*
subtract_vec(struct vec* a, struct vec* b)
subtract_vec(const struct vec* const a, const struct vec* const b)
{
int smallest_dimension = a->dimension < b->dimension ? a->dimension : b->dimension;
int largest_dimension = a->dimension > b->dimension? a->dimension : b->dimension;
@ -367,12 +381,12 @@ vec_min(const struct vec *v) @@ -367,12 +381,12 @@ vec_min(const struct vec *v)
struct mat2*
new_mat(int num_rows, int num_cols)
{
struct mat2* new_matrix = calloc(1, sizeof(struct mat2));
struct mat2* new_matrix = (struct mat2 *)calloc(1, sizeof(struct mat2));
new_matrix->num_rows = num_rows;
new_matrix->num_cols = num_cols;
new_matrix->elements = calloc(num_rows, sizeof(double*));
new_matrix->elements = (double **)calloc(num_rows, sizeof(double*));
for (int r = 0; r < num_rows; r++) {
new_matrix->elements[r] = calloc(num_cols, sizeof(double));
new_matrix->elements[r] = (double *)calloc(num_cols, sizeof(double));
}
return new_matrix;
@ -399,7 +413,7 @@ new_mat_from_vecs(int num_vectors, struct vec** vectors) @@ -399,7 +413,7 @@ new_mat_from_vecs(int num_vectors, struct vec** vectors)
}
struct mat2* new_matrix = new_mat(num_vectors, vectors[0]->dimension);
struct mat2* new_matrix = new_mat(num_vectors, num_vectors + 1);
for (int r = 0; r < new_matrix->num_rows; r++) {
for (int c = 0; c < new_matrix->num_cols; c++) {
new_matrix->elements[r][c] = vectors[r]->elements[c];
@ -521,13 +535,14 @@ perpendicular_vec(int num_vectors, struct vec** vectors) @@ -521,13 +535,14 @@ perpendicular_vec(int num_vectors, struct vec** vectors)
if (num_vectors == 0 || vectors[0] == NULL) {
// This shouldnt happen
}
if (num_vectors != vectors[0]->dimension) {
if (num_vectors + 1 != vectors[0]->dimension) {
// This shouldnt happen
}
struct mat2* matrix = new_mat_from_vecs(num_vectors, vectors);
struct vec* perpendicular = new_vec(vectors[0]->dimension);
for (int i = 0; i < perpendicular->dimension; i++) {
for (int i = 0; i < num_vectors + 1; i++) {
struct mat2* sub_mat = get_determinant_sub_mat(i, -1, matrix);
if (i % 2 == 0) {
perpendicular->elements[i] = calc_determinant_mat2(sub_mat);
@ -542,4 +557,3 @@ perpendicular_vec(int num_vectors, struct vec** vectors) @@ -542,4 +557,3 @@ perpendicular_vec(int num_vectors, struct vec** vectors)
return perpendicular;
}

3
vect.h

@ -26,6 +26,7 @@ struct mat2 { @@ -26,6 +26,7 @@ struct mat2 {
};
struct vec* new_vec(int num_dimensions);
struct vec* new_random_vec(int num_dimensions, double min, double max);
struct vec* new_vec_of(int num_dimensions, double value);
void free_vec(struct vec*);
@ -38,7 +39,7 @@ struct vec* add_vec(struct vec* a, struct vec* b); @@ -38,7 +39,7 @@ struct vec* add_vec(struct vec* a, struct vec* b);
struct vec* add_vec_ip(struct vec* a, struct vec* b);
struct vec* add_scaled_vec_ip(struct vec* a, struct vec* b, double scaleFactor);
struct vec* subtract_vec(struct vec* a, struct vec* b);
struct vec* subtract_vec(const struct vec* const a, const struct vec* const b);
struct vec* subtract_vec_ip(struct vec* a, struct vec* b);
struct vec* normalise_vec(struct vec* a);

Loading…
Cancel
Save