refactored most of the code

bench
Anton Lydike 3 years ago
parent 19292274a8
commit 4ed2c6dd08

3
.gitignore vendored

@ -1,4 +1,5 @@
*.bmp *.bmp
*.png *.png
*.out *.out
out/ obj
out

8
.idea/.gitignore vendored

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/raymarcher.iml" filepath="$PROJECT_DIR$/.idea/raymarcher.iml" />
</modules>
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/images" vcs="Git" />
</component>
</project>

@ -0,0 +1,27 @@
OPTIMIZATION=-O3
CC=gcc
CFLAGS=-Isrc/ -lm -Wall -Wextra -pedantic-errors $(OPTIMIZATION)
.PHONY: directories
directories:
mkdir -p obj out
obj/point.o: src/point.c src/point.h
$(CC) $(CFLAGS) -c -o $@ src/point.c
obj/scene.o: src/scene.c src/scene.h
$(CC) $(CFLAGS) -c -o $@ src/scene.c
obj/camera.o: src/camera.c src/camera.h
$(CC) $(CFLAGS) -c -o $@ src/camera.c
obj/images.o: images/src/images.c images/src/images.h
$(CC) $(CFLAGS) -c -o $@ images/src/images.c
march: obj/camera.o obj/scene.o obj/point.o obj/images.o
$(CC) $(CFLAGS) -o out/march $^ marcher.c

@ -1,6 +1,10 @@
#include <math.h> #include <math.h>
#include "images/images.h" #include <stdlib.h>
#include "marcher.h" #include <stdio.h>
#include "images/src/images.h"
#include "src/scene.h"
#include "src/camera.h"
#include "src/point.h"
#define SCENE_MOD 2 #define SCENE_MOD 2
@ -15,15 +19,15 @@
*/ */
double circle_dist(Point x, SceneObject *self) { double circle_dist(struct point x, struct scene_object *self) {
double r = self->args[0]; double r = self->args[0];
return pt_dist(pt_mod(x, SCENE_MOD), self->location) - r; return pt_dist(pt_mod(x, SCENE_MOD), self->location) - r;
} }
Color circle_color(Point hit, Point direction, SceneObject *self) { Color circle_color(struct point hit, struct point direction, struct scene_object *self) {
Point obj_direction = self->location; struct point obj_direction = self->location;
pt_sub(&obj_direction, pt_mod(hit, SCENE_MOD)); obj_direction = pt_sub(obj_direction, pt_mod(hit, SCENE_MOD));
double angle = pt_angle(direction, obj_direction) / M_PI * 180; double angle = pt_angle(direction, obj_direction) / M_PI * 180;
Color color = self->color; Color color = self->color;
@ -34,15 +38,16 @@ Color circle_color(Point hit, Point direction, SceneObject *self) {
return color; return color;
} }
// constructs the scene object // constructs the scene object
SceneObject circle_new(Point loc, double radius) { struct scene_object circle_new(struct point loc, double radius) {
SceneObject so; double * args = malloc(sizeof (double) * 2);
so.location = loc; args[0] = radius;
so.args = malloc(sizeof(double) * 2); return (struct scene_object) {
so.args[0] = radius; .location = loc,
so.distance = circle_dist; .args = args,
so.get_color = circle_color; .distance = circle_dist,
so.color = color_new(255,255,255); .get_color = circle_color,
return so; .color = color_new(255, 255, 255),
};
} }
@ -55,11 +60,11 @@ SceneObject circle_new(Point loc, double radius) {
Color function is just a flat shader, detail is displayed with ambient occlusion Color function is just a flat shader, detail is displayed with ambient occlusion
*/ */
double mandelbulb_dist(Point pt, SceneObject *self) { double mandelbulb_dist(struct point pt, struct scene_object *self) {
int iters = self->args[0]; int iters = self->args[0];
double power = self->args[1]; double power = self->args[1];
Point z = pt; struct point z = pt;
float dr = 1.0; float dr = 1.0;
float r = 0.0; float r = 0.0;
for (int i = 0; i < iters ; i++) { for (int i = 0; i < iters ; i++) {
@ -79,39 +84,43 @@ double mandelbulb_dist(Point pt, SceneObject *self) {
theta = theta*power; theta = theta*power;
phi = phi*power; phi = phi*power;
// convert back to cartesian coordinates // convert back to cartesian coordinates, add zr and the old pt
z = pt_mult(pt_new(sin(theta)*cos(phi), sin(phi)*sin(theta), cos(theta)), zr); z = (struct point) {
pt_add(&z, pt); .x = sin(theta)*cos(phi) * zr + pt.x,
.y = sin(phi)*sin(theta) * zr + pt.y,
.z = cos(theta) * zr + pt.z
};
} }
return 0.5*log(r)*r/dr; return 0.5*log(r)*r/dr;
} }
Color mandelbulb_color(Point hit, Point direction, SceneObject *self) { Color mandelbulb_color(struct point hit, struct point direction, struct scene_object *self) {
return self->color; return self->color;
} }
// constructs the scene object // constructs the scene object
SceneObject mandelbulb_new(Point location, int iters, double power) { struct scene_object mandelbulb_new(struct point location, int iters, double power) {
SceneObject so; double * args = malloc(sizeof(double) * 3);
so.location = location; args[0] = iters;
so.args = malloc(sizeof(double) * 3); args[1] = power;
so.args[0] = iters; // iterations args[2] = -1;
so.args[1] = power; // power
so.args[2] = -1; // reserved for color calculations return (struct scene_object) {
so.distance = mandelbulb_dist; .location= location,
so.get_color = mandelbulb_color; .args= args,
so.color = color_new(255,255,255); .distance= mandelbulb_dist,
return so; .get_color= mandelbulb_color,
.color= color_new(255,255,255),
};
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
float dpi = 800; float dpi = 200;
int threads = 32; int threads = 32;
int size = dpi * 27.56f; // 400dpi by 70cm size int size = dpi * 27.56f; // 400dpi by 70cm size
float pow = 3; float pow = 3;
float cam_position = 1.15; float cam_position = 1.35;
int steps = 1000; int steps = 1000;
int iters = 500; int iters = 500;
float threshold = 0.001; float threshold = 0.001;
@ -131,15 +140,13 @@ int main(int argc, char* argv[]) {
printf("Rendering to %s\n", path); printf("Rendering to %s\n", path);
Camera cam; struct camera cam;
cam.fov = 90; cam.fov = 90;
camera_set_looking_at(&cam, pt_new(cam_position, cam_position, cam_position), pt_new(0,0,0)); camera_set_looking_at(&cam, (struct point){.x=cam_position, .y= 0, .z = cam_position}, PT_ZERO);
// create basic scene with up to 10 objects // create basic scene with up to 10 objects
Scene scene = scene_new(size, size, 1); struct scene scene = scene_new(size, size, 1);
scene.perf_opts.max_steps = steps; scene.perf_opts.max_steps = steps;
scene.perf_opts.threshold = threshold; scene.perf_opts.threshold = threshold;
scene.perf_opts.speed_cutoff = 10; scene.perf_opts.speed_cutoff = 10;
@ -147,7 +154,7 @@ int main(int argc, char* argv[]) {
//scene_add_obj(&scene, circle_new(pt_new(SCENE_MOD / 2.0, SCENE_MOD/ 2.0, SCENE_MOD / 2.0), .2)); //scene_add_obj(&scene, circle_new(pt_new(SCENE_MOD / 2.0, SCENE_MOD/ 2.0, SCENE_MOD / 2.0), .2));
scene_add_obj(&scene, mandelbulb_new(pt_new(0,0,0), iters, pow)); scene_add_obj(&scene, mandelbulb_new(PT_ZERO, iters, pow));
Image *img = render_scene(&scene, &cam, threads); Image *img = render_scene(&scene, &cam, threads);

@ -1,97 +0,0 @@
#ifndef __MARCHER_H__
#define __MARCHER_H__
#include "images/images.h"
// define pi if not available
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
struct __myvec;
struct __mymtrx;
struct __mycam;
struct __myobject;
struct __myscene;
typedef struct __myvec {
double x;
double y;
double z;
} Point;
typedef struct __mymtrx {
double entries[9];
} Matrix;
inline Point pt_new(double x, double y, double z);
inline Point pt_scale(Point pt, double length);
inline Point pt_normalize(Point pt);
inline double pt_length(Point pt);
inline void pt_add(Point* pt, Point add);
inline void pt_sub(Point* pt, Point sub);
inline double pt_dist(Point p1, Point p2);
inline Point pt_mod(Point pt, double mod);
inline double pt_dot(Point a, Point b);
inline Point pt_cross(Point a, Point b);
inline double pt_angle(Point a, Point b);
inline void pt_print(Point pt);
inline void pt_print_n(const char* name, Point pt);
typedef struct __mycam {
Point location;
Point direction;
unsigned int fov;
} Camera;
Camera camera_new(Point direction, unsigned int fov);
void camera_set_looking_at(Camera *cam, Point origin, Point thing);
// Scene objects have a position, some args, and a distance calculation function
// the distance calc function has the following signature:
// double distanceTo(Point myLocation, double * myArgs, Point externalPoint)
// where myLocation is this.location, myArgs is this.args and externalPoint is the point from wich we want to know the distance
// the get_color function takes args: point_hit, direction_hit, myArgs, MyLocation, MyColor
typedef struct __myobject {
Point location;
double * args;
double (*distance)(Point, struct __myobject *);
Color (*get_color)(Point, Point, struct __myobject *);
Color color;
struct __myscene* scene;
} SceneObject;
typedef struct __perfopts {
int speed_cutoff;
int max_steps;
double threshold;
} PerformanceOptimizations;
typedef struct __myscene {
unsigned int width;
unsigned int height;
SceneObject * objects;
int object_count;
int allocated_space;
// performance opts
PerformanceOptimizations perf_opts;
// colors etc
Color background;
} Scene;
Image* render_scene(Scene *scene, Camera *camera, unsigned int threads);
Scene scene_new(unsigned int width, unsigned int height, int obj_count);
void scene_add_obj(Scene* scene, SceneObject object);
void scene_destroy(Scene scene);
#include "src/point.c"
#include "src/camera.c"
#include "src/scene.c"
#endif

@ -1,10 +1,18 @@
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <stdlib.h>
Camera camera_new(Point direction, unsigned int fov) { #include <stdio.h>
Camera camera; #include "point.h"
camera.location = pt_new(0,0,0); #include "camera.h"
struct camera camera_new(struct point direction, unsigned int fov) {
struct camera camera;
camera.location = (struct point) {
.x = 0,
.y = 0,
.z = 0
};
camera.fov = fov; camera.fov = fov;
// normalize camera direction // normalize camera direction
@ -13,92 +21,17 @@ Camera camera_new(Point direction, unsigned int fov) {
return camera; return camera;
} }
void camera_set_looking_at(Camera *cam, Point origin, Point thing) { void camera_set_looking_at(struct camera *cam, struct point origin, struct point thing) {
cam->location = origin; cam->location = origin;
pt_sub(&thing, origin); cam->direction = pt_normalize(pt_sub(thing, origin));
cam->direction = pt_normalize(thing);
}
void camera_iterate_rays_const_angle(Camera camera, int width, int height, int threads, void (*callback)(Point, int, int)) {
// negative threads => single threaded.
if (threads < 0) threads = 0;
Point span_z, span_xy;
// get rotation axis
pt_orthogonal_plane(camera.direction, &span_z, &span_xy);
printf("rendering %ix%i px", width, height);
pt_print_n("span_xy", span_xy);
pt_print_n("span_z", span_z);
// angle between rays
double angle_step = camera.fov / (double) (width - 1);
// rotation applied to reach the outmost end of the view
double angle_start_h = - (camera.fov / 2.0);
double angle_start_v = ((angle_step * (height - 1)) / 2) ;
printf("step: %f\nstart_h: %f\nstart_v: %f\n", angle_step, angle_start_h, angle_start_v);
// calculate both rotation matrices (expensive!)
Matrix rot_z = mtrx_rotation(span_z, angle_step);
Matrix rot_xy = mtrx_rotation(span_xy, -angle_step);
// rotate vector to starting location (bot left of screen)
// (very expensive!)
Point starting_point = mtrx_mult(
mtrx_rotation(span_xy, angle_start_v),
mtrx_mult(
mtrx_rotation(span_z, angle_start_h),
camera.direction
)
);
// initialize threads
int thread_id = 0;
for (int i = 0; i < threads - 1; i++) {
if (fork() == 0) {
thread_id = i + 1;
break;
}
}
// this point is rotated for every pixel
Point curr_pt = starting_point;
// (0,0) screenspace is bottom left corner
for (int y = 0; y < height; y++) {
curr_pt = mtrx_mult(rot_xy, starting_point);
// move starting point one row down
starting_point = curr_pt;
if (y % threads != thread_id) continue;
for (int x = 0; x < width; x++) {
callback(curr_pt, x, y);
curr_pt = mtrx_mult(rot_z, curr_pt); // rotate point
}
}
if (thread_id != 0) {
printf("Thread %i is finished\n", thread_id);
exit(0);
} }
int status;
for (int i = 0; i < threads - 1; i++) {
while(wait(&status) > 0) {}
}
printf("got threads\n");
}
void camera_iterate_rays_const_dist(Camera camera, int width, int height, int threads, void (*callback)(Point, int, int)) { void camera_iterate_rays_const_dist(struct camera camera, int width, int height, int threads, void (*callback)(struct point, int, int)) {
// negative threads => single threaded. // negative threads => single threaded.
if (threads < 0) threads = 0; if (threads < 0) threads = 0;
Point span_z, span_xy; struct point span_z, span_xy;
// get rotation axis // get rotation axis
pt_orthogonal_plane(camera.direction, &span_z, &span_xy); pt_orthogonal_plane(camera.direction, &span_z, &span_xy);
@ -109,15 +42,15 @@ void camera_iterate_rays_const_dist(Camera camera, int width, int height, int th
double step_dist = 2 / (double) (width - 1); double step_dist = 2 / (double) (width - 1);
// vectors to move on the projection plane // vectors to move on the projection plane
Point move_right = pt_scale(span_xy, step_dist); struct point move_right = pt_scale(span_xy, step_dist);
Point move_up = pt_scale(span_z, step_dist);; struct point move_up = pt_scale(span_z, step_dist);;
// set starting point // set starting point
Point starting_point = pt_normalize(camera.direction); struct point starting_point = pt_normalize(camera.direction);
// rotate starting point to (0,0) // rotate starting point to (0,0)
pt_add(&starting_point, pt_mult(move_right, - width / (double) 2)); starting_point = pt_add(starting_point, pt_mult(move_right, - width / (double) 2));
pt_add(&starting_point, pt_mult(move_up, - height / (double) 2)); starting_point = pt_add(starting_point, pt_mult(move_up, - height / (double) 2));
// initialize threads // initialize threads
int thread_id = 0; int thread_id = 0;
@ -129,12 +62,12 @@ void camera_iterate_rays_const_dist(Camera camera, int width, int height, int th
} }
// this point is moved for every pixel // this point is moved for every pixel
Point curr_pt = starting_point; struct point curr_pt = starting_point;
// (0,0) screenspace is bottom left corner // (0,0) screenspace is bottom left corner
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
// move one row up (this has to be done in every thread!) // move one row up (this has to be done in every thread!)
pt_add(&starting_point, move_up); starting_point = pt_add(starting_point, move_up);
// only render the lines this thread is responsible for // only render the lines this thread is responsible for
if (y % threads != thread_id) continue; if (y % threads != thread_id) continue;
@ -149,7 +82,7 @@ void camera_iterate_rays_const_dist(Camera camera, int width, int height, int th
curr_pt = starting_point; curr_pt = starting_point;
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
callback(curr_pt, x, y); callback(curr_pt, x, y);
pt_add(&curr_pt, move_right); // move pt right to next pt curr_pt = pt_add(curr_pt, move_right); // move pt right to next pt
} }
} }

@ -0,0 +1,11 @@
#pragma once
struct camera {
struct point location;
struct point direction;
unsigned int fov;
};
struct camera camera_new(struct point direction, unsigned int fov);
void camera_set_looking_at(struct camera *cam, struct point origin, struct point thing);
void camera_iterate_rays_const_dist(struct camera camera, int width, int height, int threads, void (*callback)(struct point, int, int));

@ -1,35 +1,27 @@
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include "point.h"
// basically a vector3
inline Point pt_new(double x, double y, double z) {
Point pt;
pt.x = x;
pt.y = y;
pt.z = z;
return pt;
}
// scale vector to length // scale vector to length
inline Point pt_scale(Point pt, double length) { struct point pt_scale(struct point pt, double length) {
double f = length / pt_length(pt); double f = length / pt_length(pt);
return pt_new( return (struct point) {
pt.x * f, .x = pt.x * f,
pt.y * f, .y = pt.y * f,
pt.z * f .z = pt.z * f
); };
} }
inline Point pt_mult(Point pt, double scalar) { struct point pt_mult(struct point pt, double scalar) {
return pt_new( return (struct point) {
pt.x * scalar, .x = pt.x * scalar,
pt.y * scalar, .y = pt.y * scalar,
pt.z * scalar .z = pt.z * scalar
); };
} }
// return internal angle between a and b // return internal angle between a and b
inline double pt_angle(Point a, Point b) { double pt_angle(struct point a, struct point b) {
return acos(pt_dot( return acos(pt_dot(
pt_normalize(a), pt_normalize(a),
pt_normalize(b) pt_normalize(b)
@ -37,144 +29,77 @@ inline double pt_angle(Point a, Point b) {
} }
// get the length of vector // get the length of vector
inline double pt_length(Point pt) { double pt_length(struct point pt) {
return sqrt((pt.x * pt.x) + (pt.y * pt.y) + (pt.z * pt.z)); return sqrt((pt.x * pt.x) + (pt.y * pt.y) + (pt.z * pt.z));
} }
// add the vector add to the vector pt // add the vector add to the vector pt
inline void pt_add(Point* pt, Point add) { struct point pt_add(struct point pt, struct point add) {
pt->x = pt->x + add.x; return (struct point) {
pt->y = pt->y + add.y; .x = pt.x + add.x,
pt->z = pt->z + add.z; .y = pt.y + add.y,
.z = pt.z + add.z,
};
} }
// add the vector add to the vector pt // add the vector add to the vector pt
inline void pt_sub(Point* pt, Point sub) { struct point pt_sub(struct point pt, struct point sub) {
pt->x -= sub.x; return (struct point) {
pt->y -= sub.y; .x = pt.x - sub.x,
pt->z -= sub.z; .y = pt.y - sub.y,
.z = pt.z - sub.z,
};
} }
inline double pt_dist(Point p1, Point p2) { double pt_dist(struct point p1, struct point p2) {
pt_sub(&p1, p2); return pt_length(pt_sub(p1, p2));
return pt_length(p1);
} }
// normalize a vector // normalize a vector
inline Point pt_normalize(Point pt) { struct point pt_normalize(struct point pt) {
return pt_scale(pt, 1); return pt_scale(pt, 1);
} }
// dot product of two vectors // dot product of two vectors
inline double pt_dot(Point a, Point b) { double pt_dot(struct point a, struct point b) {
return a.x*b.x + a.y*b.y + a.z*b.z; return a.x*b.x + a.y*b.y + a.z*b.z;
} }
// cross product of two vectors // cross product of two vectors
inline Point pt_cross(Point a, Point b) { struct point pt_cross(struct point a, struct point b) {
return pt_new( return (struct point) {
a.y*b.z - a.z*b.y, .x = a.y*b.z - a.z*b.y,
a.z*b.x - a.x*b.z, .y = a.z*b.x - a.x*b.z,
a.x*b.y - a.y*b.x .z = a.x*b.y - a.y*b.x
); };
} }
inline void pt_print(Point pt) { void pt_print(struct point pt) {
printf("(%f, %f, %f)\n", pt.x, pt.y, pt.z); printf("(%f, %f, %f)\n", pt.x, pt.y, pt.z);
} }
inline void pt_print_n(const char* name, Point pt) { void pt_print_n(const char* name, struct point pt) {
printf("%s: (%f, %f, %f)\n", name, pt.x, pt.y, pt.z); printf("%s: (%f, %f, %f)\n", name, pt.x, pt.y, pt.z);
} }
// find two vectors that span the orthogonal plane, where // find two vectors that span the orthogonal plane, where
// span_xy is a vector lying on the xy-plane (and pointing left) // span_xy is a vector lying on the xy-plane (and pointing left)
// and span_z is orthogonal to span_xy pointing "upwards" // and span_z is orthogonal to span_xy pointing "upwards"
void pt_orthogonal_plane(Point pt, Point *span_z, Point *span_xy) { void pt_orthogonal_plane(struct point pt, struct point *span_z, struct point *span_xy) {
pt = pt_normalize(pt); pt = pt_normalize(pt);
// get the vector lying on the xy axis // get the vector lying on the xy axis
// this is done by // this is done by
*span_xy = pt_normalize(pt_cross(pt_new(0,0,1), pt)); // points to the "left" (of the viewing direction) *span_xy = pt_normalize(pt_cross((struct point){.x = 0, .y = 0, .z = 1}, pt)); // points to the "left" (of the viewing direction)
// now use this, to find the vector // now use this, to find the vector
*span_z = pt_normalize(pt_cross(pt, *span_xy)); *span_z = pt_normalize(pt_cross(pt, *span_xy));
} }
inline Point pt_mod(Point pt, double mod) { struct point pt_mod(struct point pt, double mod) {
return pt_new( return (struct point) {
fabs(fmod(pt.x, mod)), .x = fabs(fmod(pt.x, mod)),
fabs(fmod(pt.y, mod)), .y = fabs(fmod(pt.y, mod)),
fabs(fmod(pt.z, mod)) .z = fabs(fmod(pt.z, mod))
); };
}
///////////////////////////////
////// Matrix operations //////
///////////////////////////////
/* create a new matrix with entries:
x1 x2 x3
y1 y2 y3
z1 z2 z3
*/
inline Matrix mtrx_new(double x1, double x2, double x3,
double y1, double y2, double y3,
double z1, double z2, double z3)
{
Matrix m;
m.entries[0] = x1;
m.entries[1] = y1;
m.entries[2] = z1;
m.entries[3] = x2;
m.entries[4] = y2;
m.entries[5] = z2;
m.entries[6] = x3;
m.entries[7] = y3;
m.entries[8] = z3;
return m;
}
inline Point mtrx_mult(Matrix mtrx, Point pt) {
Point result;
double *m = mtrx.entries;
result.x = m[0] * pt.x + m[3] * pt.y + m[6] * pt.z;
result.y = m[1] * pt.x + m[4] * pt.y + m[7] * pt.z;
result.z = m[2] * pt.x + m[5] * pt.y + m[8] * pt.z;
return result;
}
// create a rotation matrix around an axis given by the normalized axis vector (u)
// taken from https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
Matrix mtrx_rotation(Point u, double theta) {
double theta_rad = theta * (M_PI / 180);
double cost = cos(theta_rad);
double sint = sin(theta_rad);
return mtrx_new(
cost+u.x*u.x*(1-cost), u.x*u.y*(1-cost)-u.z*sint, u.x*u.z*(1-cost)+u.y*sint,
u.y*u.x*(1-cost)+u.z*sint, cost+u.y*u.y*(1-cost), u.y*u.z*(1-cost)-u.x*sint,
u.z*u.x*(1-cost)-u.y*sint, u.z*u.y*(1-cost)+u.x*sint, cost+u.z*u.z*(1-cost)
);
}
void mtrx_print(Matrix mtrx) {
printf(" %8.2f %8.2f %8.2f\n %8.2f %8.2f %8.2f\n %8.2f %8.2f %8.2f\n",
mtrx.entries[0], mtrx.entries[3], mtrx.entries[6],
mtrx.entries[1], mtrx.entries[4], mtrx.entries[7],
mtrx.entries[2], mtrx.entries[5], mtrx.entries[8]
);
}
inline Matrix mtrx_outer_prod(Point a, Point b) {
return mtrx_new(
a.x*b.x, a.x*b.y, a.x*b.z,
a.y*b.x, a.y*b.y, a.y*b.z,
a.z*b.x, a.z*b.y, a.z*b.z
);
} }

@ -0,0 +1,25 @@
#pragma once
struct point {
double x;
double y;
double z;
};
#define PT_ZERO ((struct point) {.x=0, .y=0, .z=0})
struct point pt_scale(struct point pt, double length);
struct point pt_normalize(struct point pt);
struct point pt_mult(struct point pt, double scalar);
double pt_length(struct point pt);
struct point pt_add(struct point pt, struct point add);
struct point pt_sub(struct point pt, struct point sub);
double pt_dist(struct point p1, struct point p2);
struct point pt_mod(struct point pt, double mod);
double pt_dot(struct point a, struct point b);
struct point pt_cross(struct point a, struct point b);
double pt_angle(struct point a, struct point b);
void pt_print(struct point pt);
void pt_print_n(const char* name, struct point pt);
void pt_orthogonal_plane(struct point pt, struct point *span_z, struct point *span_xy);

@ -1,34 +1,37 @@
#include "../images/images.h" #include "../images/src/images.h"
#include "scene.h"
#include "camera.h"
#include "point.h"
#include <float.h> #include <float.h>
#include <stdlib.h>
static Image* current_image; static Image* current_image;
static Scene* current_scene; static struct scene* current_scene;
static Camera* current_camera; static struct camera* current_camera;
Color march_ray(Point origin, Point direction, Scene* scene); Color march_ray(struct point origin, struct point direction, struct scene* scene);
void camera_iter_callback(Point direction, int x, int y); void camera_iter_callback(struct point direction, int x, int y);
Scene scene_new(unsigned int width, unsigned int height, int obj_count) { struct scene scene_new(unsigned int width, unsigned int height, int obj_count) {
Scene scene; struct scene scene;
scene.height = height; scene.height = height;
scene.width = width; scene.width = width;
scene.object_count = 0; scene.object_count = 0;
scene.objects = malloc(obj_count * sizeof(SceneObject)); scene.objects = malloc(obj_count * sizeof(struct scene_object));
scene.allocated_space = obj_count; scene.allocated_space = obj_count;
scene.background = color_new(0,0,0); scene.background = color_new(0,0,0);
PerformanceOptimizations perf_opts; scene.perf_opts = (struct performance_optimization) {
perf_opts.speed_cutoff = 0; .speed_cutoff = 0,
perf_opts.max_steps = 32; .max_steps = 32,
perf_opts.threshold = 0.02; .threshold = 0.02
};
scene.perf_opts = perf_opts;
return scene; return scene;
} }
void scene_add_obj(Scene* scene, SceneObject object) { void scene_add_obj(struct scene * scene, struct scene_object object) {
if (scene->object_count >= scene->allocated_space) return; // limit reached if (scene->object_count >= scene->allocated_space) return; // limit reached
// TODO realloc // TODO realloc
@ -42,7 +45,7 @@ void scene_add_obj(Scene* scene, SceneObject object) {
// render out the scene with threads // render out the scene with threads
// creates a shared image, so destroy with image_destroy_shared then free struct with free_shared_memory // creates a shared image, so destroy with image_destroy_shared then free struct with free_shared_memory
Image* render_scene(Scene *scene, Camera *camera, unsigned int threads) { Image* render_scene(struct scene *scene, struct camera *camera, unsigned int threads) {
current_image = malloc(sizeof(Image)); current_image = malloc(sizeof(Image));
current_scene = scene; current_scene = scene;
current_camera= camera; current_camera= camera;
@ -59,20 +62,20 @@ Image* render_scene(Scene *scene, Camera *camera, unsigned int threads) {
} }
// march the ray, set the color. repeated for each direction generated by the camera // march the ray, set the color. repeated for each direction generated by the camera
void camera_iter_callback(Point direction, int x, int y) { void camera_iter_callback(struct point direction, int x, int y) {
Color c = march_ray(current_camera->location, direction, current_scene); Color c = march_ray(current_camera->location, direction, current_scene);
image_set_px_c(*current_image, x, y, c); image_set_px_c(*current_image, x, y, c);
} }
Color march_ray(Point origin, Point direction, Scene* scene) { Color march_ray(struct point origin, struct point direction, struct scene* scene) {
// some local variables // some local variables
Point pos = origin; struct point pos = origin;
double closest_encounter = DBL_MAX; double closest_encounter = DBL_MAX;
double dist = closest_encounter; double dist = closest_encounter;
// the closest object we have // the closest object we have
SceneObject* closest_obj = scene->objects; struct scene_object* closest_obj = scene->objects;
// get steps, threshold from scene // get steps, threshold from scene
int steps = scene->perf_opts.max_steps; int steps = scene->perf_opts.max_steps;
@ -86,7 +89,7 @@ Color march_ray(Point origin, Point direction, Scene* scene) {
// find distance to closest object // find distance to closest object
for(int i = 0; i < scene->object_count; i++) { for(int i = 0; i < scene->object_count; i++) {
// get pointer to scene obj // get pointer to scene obj
SceneObject* obj = scene->objects + i; struct scene_object* obj = scene->objects + i;
double curr_dist = scene->objects[i].distance(pos, obj); double curr_dist = scene->objects[i].distance(pos, obj);
// if we are close // if we are close
@ -104,8 +107,8 @@ Color march_ray(Point origin, Point direction, Scene* scene) {
if (dist < closest_encounter) closest_encounter = dist; if (dist < closest_encounter) closest_encounter = dist;
// scale direction vector to distance, then add it to our position // scale direction vector to distance, then add it to our position
Point step_vector = pt_scale(direction, dist); struct point step_vector = pt_scale(direction, dist);
pt_add(&pos, step_vector); pos = pt_add(pos, step_vector);
// one step taken... // one step taken...
steps--; steps--;
@ -135,7 +138,7 @@ Color march_ray(Point origin, Point direction, Scene* scene) {
} }
} }
void scene_destroy(Scene scene) { void scene_destroy(struct scene scene) {
for (int i = 0; i < scene.object_count; i++) { for (int i = 0; i < scene.object_count; i++) {
// free args memory // free args memory
free(scene.objects[i].args); free(scene.objects[i].args);

@ -0,0 +1,52 @@
#pragma once
#include "point.h"
#include "camera.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
struct scene;
// Scene objects have a position, some args, and a distance calculation function
// the distance calc function has the following signature:
// double distanceTo(struct point myLocation, double * myArgs, struct point externalPoint)
// where myLocation is this.location, myArgs is this.args and externalPoint is the point from wich we want to know the distance
// the get_color function takes args: point_hit, direction_hit, myArgs, MyLocation, MyColor
struct scene_object {
struct point location;
double * args;
double (*distance)(struct point, struct scene_object *);
Color (*get_color)(struct point, struct point, struct scene_object *);
Color color;
struct scene* scene;
};
struct performance_optimization {
int speed_cutoff;
int max_steps;
double threshold;
};
struct scene {
unsigned int width;
unsigned int height;
struct scene_object * objects;
int object_count;
int allocated_space;
// performance opts
struct performance_optimization perf_opts;
// colors etc
Color background;
};
Image* render_scene(struct scene *scene, struct camera *camera, unsigned int threads);
struct scene scene_new(unsigned int width, unsigned int height, int obj_count);
void scene_add_obj(struct scene* scene, struct scene_object object);
void scene_destroy(struct scene scene);
Loading…
Cancel
Save