diff options
-rw-r--r-- | main.c | 111 | ||||
-rw-r--r-- | scene.c | 99 | ||||
-rw-r--r-- | scene.h | 38 | ||||
-rw-r--r-- | test.png | bin | 467637 -> 696052 bytes |
4 files changed, 185 insertions, 63 deletions
@@ -10,63 +10,70 @@ #define TESTW 1000 #define TESTH 1000 +char container[ CONTAINER_SIZE(5, 4, 1) ]; + int main() { - //printf("Starting\n"); - space_t s; - s.objects = NULL; - s.lights = NULL; - color_set(&s.ambient, 0.09, 0.09, 0.09); - // Currently havin issues with white background - // color_set(&s.back, 255, 255, 255); - color_set(&s.back, 0.8, 0.8, 0.8); - color_set(&s.env_color, 0.13, 0.13, 0.13); - s.env_samples = 256; - - material_t m; - vector_set(&m.color, 0.4, 0.4, 1); - m.defuse = 1; - m.specular = 0.0; - m.shine = 80; - m.reflective = 0.0; - - material_t m3; - vector_set(&m3.color, 1, 0.3, 0.1); - m3.defuse = 0.95; - m3.specular = 0.0; - m3.shine = 80; - m3.reflective = 0.05; - - material_t m2; - vector_set(&m2.color, 1, 1, 1); - m2.defuse = 0.0; - m2.specular = 0.5; - m2.shine = 80; - m2.reflective = 1; - - material_t mpl; + + container_t *cont = (container_t *) container; + container_init(cont, 5, 4, 1); + + // Init space_t + space_t *s = container_prepare_space(cont);; + + // Set space options + color_set(&s->ambient, 0.09, 0.09, 0.09); + color_set(&s->back, 0.8, 0.8, 0.8); + color_set(&s->env_color, 0.13, 0.13, 0.13); + s->env_samples = 16; + + // Set viewpoint options + vector_set(&s->view.position, 0, 16, 6); + vector_set(&s->view.target, 0, 0, 6); + s->view.width = TESTW; + s->view.height = TESTH; + + // Create materials + material_t *m = add_material(cont); + vector_set(&m->color, 0.4, 0.4, 1); + m->defuse = 1; + m->specular = 0.0; + m->shine = 80; + m->reflective = 0.0; + + material_t *m3 = add_material(cont); + vector_set(&m3->color, 1, 0.3, 0.1); + m3->defuse = 0.95; + m3->specular = 0.0; + m3->shine = 80; + m3->reflective = 0.05; + + material_t *m2 = add_material(cont); + vector_set(&m2->color, 1, 1, 1); + m2->defuse = 0.0; + m2->specular = 0.5; + m2->shine = 80; + m2->reflective = 1; + + material_t *mpl = add_material(cont); //vector_set(&mpl.color, 0, 0.396, 0.7019); - vector_set(&mpl.color, 1, 1, 1); - mpl.defuse = 1; - mpl.specular = 0.0; - mpl.shine = 50; - mpl.reflective = 0.0; - - vector_set(&s.view.position, 0, 16, 6); - vector_set(&s.view.target, 0, 0, 6); - s.view.width = TESTW; - s.view.height = TESTH; - - viewpoint_init(&s.view); + vector_set(&mpl->color, 1, 1, 1); + mpl->defuse = 1; + mpl->specular = 0.0; + mpl->shine = 50; + mpl->reflective = 0.0; + + + viewpoint_init(&s->view); // Setup plane - add_sphere(&s, vector_set(NULL, 0, 4, 7), 5, &m2); - add_sphere(&s, vector_set(NULL, 8, 8, 4), 2, &m3); - add_sphere(&s, vector_set(NULL, -10, 9, 5), 3, &m); - add_sphere(&s, vector_set(NULL, -10, -5, 5), 3, &m); - add_plane(&s, vector_set(NULL, 0, 0, 2), vector_set(NULL, 0, 0, 1), &mpl); + add_sphere(cont, vector_set(NULL, 0, 4, 7), 5, m2); + add_sphere(cont, vector_set(NULL, 8, 8, 4), 2, m3); + add_sphere(cont, vector_set(NULL, -10, 9, 5), 3, m); + add_sphere(cont, vector_set(NULL, -10, -5, 5), 3, m); + add_plane(cont, vector_set(NULL, 0, 0, 2), vector_set(NULL, 0, 0, 1), mpl); //add_plane(&s, vector_set(NULL, 0, -20, 0), vector_set(NULL, 0, 1, 0), &mpl); - add_light(&s, vector_set(NULL, 20, 10, 30), color_set(NULL, 0.3, 0.3, 0.3), color_set(NULL, 0.5, 0.5, 0.5)); + add_light(cont, vector_set(NULL, 20, 10, 30), color_set(NULL, 0.3, 0.3, 0.3), color_set(NULL, 0.5, 0.5, 0.5)); //add_light(&s, vector_set(NULL, 0, 10, 20), color_set(NULL, 0.5, 0.5, 0.5), color_set(NULL, 0.5, 0.5, 0.5)); pgm_write_header(stdout, TESTW, TESTH); @@ -77,7 +84,7 @@ int main() for (int y = TESTH; y; y--) { for (int x = TESTW; x; x--) { - color_t *c = ray_trace(&s, x, y, 2); + color_t *c = ray_trace(&cont->space, x, y, 2); if (c) { pgm_write_pixel(stdout, c); @@ -1,6 +1,7 @@ #include "scene.h" #include <stdlib.h> +#include <string.h> static inline void link_object(space_t *s, object_t *o) { @@ -12,24 +13,94 @@ static inline void link_object(space_t *s, object_t *o) } } -object_t *add_sphere(space_t *s, vector_t *c, COORD_T r, material_t *m) +container_t *container_init(container_t *c, unsigned objs, unsigned mats, unsigned ligs) { - object_t *o = (object_t *) malloc(sizeof(object_t)); + c->obj_index = c->mat_index = c->lig_index = 0; + c->obj_cap = objs; + c->mat_cap = mats; + c->lig_cap = ligs; + + return c; +} + +space_t *container_prepare_space(container_t *c) +{ + memset(&c->space, 0, sizeof(space_t)); +} + +// Finds the next empty object_t space +// Return NULL if full +static inline object_t *container_obj_space(container_t *cont) +{ + if (cont->obj_index >= cont->obj_cap) { + fprintf(stderr, "Could not create object, because container is full\n"); + return NULL; + } + + // Find a nice spot in the content blob + return &((object_t *) cont->content)[cont->obj_index++]; +} + +static inline material_t *container_mat_space(container_t *cont) +{ + if (cont->mat_index >= cont->mat_cap) { + fprintf(stderr, "Could not create material, because container is full\n"); + return NULL; + } + + // Find a nice spot in the content blob. + // Remember to jump over objects + return &((material_t *) ( + cont->content + + sizeof(object_t) * cont->obj_cap + ))[cont->mat_index++]; +} + +static inline light_t *container_lig_space(container_t *cont) +{ + if (cont->lig_index >= cont->lig_cap) { + fprintf(stderr, "Could not create light, because container is full\n"); + return NULL; + } + + // Find a nice spot in the content blob. + // Remember to jump over objects and materials + return &((light_t *) ( + cont->content + + sizeof(object_t) * cont->obj_cap + + sizeof(material_t) * cont->mat_cap + ))[cont->lig_index++]; +} + +object_t *add_sphere(container_t *cont, vector_t *c, COORD_T r, material_t *m) +{ + + object_t *o = container_obj_space(cont); + if (!o) { + return NULL; + } + + // Fill out the data o->type = TYPE_SPHERE; o->m = m; o->sph.center = c; o->sph.radius = r; - link_object(s, o); + // Link to the linked list + link_object(&cont->space, o); return o; } -object_t *add_plane(space_t *s, vector_t *start, vector_t *dir, material_t *m) +object_t *add_plane(container_t *cont, vector_t *start, vector_t *dir, material_t *m) { - object_t *o = (object_t *) malloc(sizeof(object_t)); + + object_t *o = container_obj_space(cont); + if (!o) { + return NULL; + } o->type = TYPE_PLANE; o->m = m; @@ -37,19 +108,23 @@ object_t *add_plane(space_t *s, vector_t *start, vector_t *dir, material_t *m) o->pl.start = start; o->pl.norm = dir; - link_object(s, o); + link_object(&cont->space, o); return o; } -light_t *add_light(space_t *s, vector_t *pos, color_t *defuse, color_t *specular) +light_t *add_light(container_t *cont, vector_t *pos, color_t *defuse, color_t *specular) { - light_t *o = (light_t *) malloc(sizeof(light_t)); + light_t *o = container_lig_space(cont); + if (!o) { + return NULL; + } o->pos = pos; o->defuse = defuse; o->specular = specular; + space_t *s = &cont->space; if (s) { o->next = s->lights; s->lights = o; @@ -60,6 +135,14 @@ light_t *add_light(space_t *s, vector_t *pos, color_t *defuse, color_t *specular return o; } +// It's alot easier to set the stuff outside of this function +material_t *add_material(container_t *cont) +{ + material_t *m = container_mat_space(cont); + + return m; +} + void obj_norm_at(object_t *o, vector_t *dest, vector_t *point) { switch(o->type) { @@ -11,6 +11,8 @@ #define TYPE_SPHERE 1 #define TYPE_PLANE 2 +#define CONTAINER_SIZE(objs, mats, ligs) (sizeof(container_t) + objs * sizeof(object_t) + ligs * sizeof(light_t)) + typedef struct { vector_t *center; COORD_T radius; @@ -57,6 +59,7 @@ typedef struct object_s{ typedef struct { viewpoint_t view; + object_t *objects; light_t *lights; @@ -70,9 +73,38 @@ typedef struct { color_t env_color; } space_t; -object_t *add_sphere(space_t *s, vector_t *c, COORD_T r, material_t *m); -object_t *add_plane(space_t *s, vector_t *start, vector_t *dir, material_t *m); -light_t *add_light(space_t *s, vector_t *pos, color_t *defuse, color_t *specular); +// Contains materials, space, objects and lights. Made to keep it all together. +// They will still be linked list, but close together. +typedef struct { + space_t space; + + // Number of objects + unsigned obj_index; + unsigned mat_index; + unsigned lig_index; + + // Number of objects that will fit. + unsigned obj_cap; + unsigned mat_cap; + unsigned lig_cap; + + // Memory blob + // Contains objects -> materials -> lights + uint8_t content[0]; +} container_t; + + +// Initialice container in buffer c. Should be big enough for the whole scene. +// Use the container_size to calculate the needed space. +// Leave c at NULL to allocate container +container_t *container_init(container_t *c, unsigned objs, unsigned mats, unsigned ligs); + +space_t *container_prepare_space(container_t *c); + +object_t *add_sphere(container_t *cont, vector_t *c, COORD_T r, material_t *m); +object_t *add_plane(container_t *cont, vector_t *start, vector_t *dir, material_t *m); +light_t *add_light(container_t *cont, vector_t *pos, color_t *defuse, color_t *specular); +material_t *add_material(container_t *cont); void obj_norm_at(object_t *o, vector_t *dest, vector_t *point); |