# HG changeset patch # User John Tsiombikas # Date 1437442200 -10800 # Node ID 72752a1b3dbe21b39ce1aea1e40c0632199f35d9 # Parent bc64090fe3d1d193f5df5eda2967b9c9439e1f64 images and shapes diff -r bc64090fe3d1 -r 72752a1b3dbe Makefile --- a/Makefile Mon Jul 20 04:38:53 2015 +0300 +++ b/Makefile Tue Jul 21 04:30:00 2015 +0300 @@ -5,6 +5,7 @@ bin = tgi CFLAGS = -pedantic -Wall -g +LDFLAGS = -lvmath -lm $(bin): $(obj) $(CC) -o $@ $(obj) $(LDFLAGS) diff -r bc64090fe3d1 -r 72752a1b3dbe src/image.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/image.c Tue Jul 21 04:30:00 2015 +0300 @@ -0,0 +1,31 @@ +#include +#include "tgi_impl.h" +#include "image.h" + +void tgi_init_image(struct image *img) +{ + img->width = img->height = 0; + img->pixels = 0; +} + +void tgi_destroy_image(struct image *img) +{ + if(img) { + free(img->pixels); + } +} + +int tgi_resize_image(struct image *img, int xsz, int ysz) +{ + float *npix = malloc(xsz * ysz * 4 * sizeof *npix); + if(!npix) { + tgi_log("failed to allocate %dx%d image\n", xsz, ysz); + return -1; + } + + free(img->pixels); + img->pixels = npix; + img->width = xsz; + img->height = ysz; + return 0; +} diff -r bc64090fe3d1 -r 72752a1b3dbe src/image.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/image.h Tue Jul 21 04:30:00 2015 +0300 @@ -0,0 +1,14 @@ +#ifndef TGI_IMAGE_H_ +#define TGI_IMAGE_H_ + +struct image { + int width, height; + float *pixels; +}; + +void tgi_init_image(struct image *img); +void tgi_destroy_image(struct image *img); + +int tgi_resize_image(struct image *img, int xsz, int ysz); + +#endif /* TGI_IMAGE_H_ */ diff -r bc64090fe3d1 -r 72752a1b3dbe src/main.c --- a/src/main.c Mon Jul 20 04:38:53 2015 +0300 +++ b/src/main.c Tue Jul 21 04:30:00 2015 +0300 @@ -1,4 +1,16 @@ #include #include "tinygi.h" +struct tinygi *tgi; +int main(int argc, char **argv) +{ + if(!(tgi = tgi_init())) { + return 1; + } + + /* stuff ... */ + + tgi_destroy(tgi); + return 0; +} diff -r bc64090fe3d1 -r 72752a1b3dbe src/object.c --- a/src/object.c Mon Jul 20 04:38:53 2015 +0300 +++ b/src/object.c Tue Jul 21 04:30:00 2015 +0300 @@ -38,9 +38,6 @@ if(o->shape) { tgi_destroy_shape(o->shape); } - if(o->mtl) { - tgi_destroy_material(o->mtl); - } free(o->name); } } @@ -53,14 +50,6 @@ o->shape = s; } -void tgi_set_object_mtl(struct tgi_object *o, struct tgi_material *m) -{ - if(o->mtl) { - tgi_destroy_material(o->mtl); - } - o->mtl = m; -} - /* mat should point to an array of 16 floats (4x4 homogeneous transformation matrix) */ void tgi_load_matrix(struct tgi_object *o, const float *mat) { diff -r bc64090fe3d1 -r 72752a1b3dbe src/object.h --- a/src/object.h Mon Jul 20 04:38:53 2015 +0300 +++ b/src/object.h Tue Jul 21 04:30:00 2015 +0300 @@ -4,10 +4,17 @@ #include "tinygi.h" #include "vmath/vmath.h" +struct material { + vec3_t color; + float roughness; + float opacity; + float ior; +}; + struct tgi_object { char *name; struct tgi_shape *shape; - struct tgi_material *mtl; + struct material mtl; mat4_t xform, inv_xform; struct tgi_object *next; /* for linking it into various lists */ diff -r bc64090fe3d1 -r 72752a1b3dbe src/scene.c --- a/src/scene.c Mon Jul 20 04:38:53 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -#include -#include -#include -#include "tgi_impl.h" -#include "object.h" -#include "dynarr.h" - -struct tinygi *tgi_init(void) -{ - struct tinygi *tgi; - - if(!(tgi = malloc(sizeof *tgi))) { - tgi_log("failed to allocate memory\n"); - return 0; - } - if(!(tgi->objects = dynarr_alloc(0, sizeof *tgi->objects))) { - tgi_log("failed to allocate objects array\n"); - free(tgi); - return 0; - } - - return tgi; -} - -void tgi_destroy(struct tinygi *tgi) -{ - tgi_clear_scene(tgi); - free(tgi); -} - -void tgi_clear_scene(struct tinygi *tgi) -{ - int i, nobj = dynarr_size(tgi->objects); - - for(i=0; iobjects[i]); - } - tgi->objects = dynarr_resize(tgi->objects, 0); - assert(tgi->objects); -} - -int tgi_load_scene(struct tinygi *tgi, const char *fname) -{ - return -1; /* TODO implement later */ -} - -void tgi_add_object(struct tinygi *tgi, struct tgi_object *o) -{ - tgi->objects = dynarr_push(tgi->objects, o); - assert(tgi->objects); -} - -int tgi_remove_object(struct tinygi *tgi, struct tgi_object *o) -{ - int i, idx = -1, sz = dynarr_size(tgi->objects); - - if(!sz) return -1; - - for(i=0; iobjects[i] == o) { - idx = i; - break; - } - } - if(idx == -1) { - return -1; - } - - tgi->objects[idx] = tgi->objects[sz - 1]; - tgi->objects = dynarr_pop(tgi->objects); - assert(tgi->objects); - return 0; -} - -struct tgi_object *tgi_find_object(struct tinygi *tgi, const char *name) -{ - int i, sz = dynarr_size(tgi->objects); - - for(i=0; iobjects[i]->name, name) == 0) { - return tgi->objects[i]; - } - } - return 0; -} - - -struct tgi_object *tgi_get_object(struct tinygi *tgi, int idx) -{ - return tgi->objects[idx]; -} - -int tgi_get_object_count(struct tinygi *tgi) -{ - return dynarr_size(tgi->objects); -} - - diff -r bc64090fe3d1 -r 72752a1b3dbe src/shape.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shape.c Tue Jul 21 04:30:00 2015 +0300 @@ -0,0 +1,91 @@ +#include "tgi_impl.h" +#include "shape.h" + +static int ray_sphere_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit); +static int ray_box_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit); + +struct tgi_shape *tgi_create_sphere(float x, float y, float z, float rad) +{ + struct tgi_shape *shape; + struct tgi_sphere_data *sphere; + + if(!(shape = malloc(sizeof *shape)) || !(sphere = malloc(sizeof *sphere))) { + free(shape); + tgi_log("failed to allocate sphere shape\n"); + return 0; + } + shape->data = sphere; + shape->obj = 0; + shape->intersect = ray_sphere_intersect; + + sphere->pos.x = x; + sphere->pos.y = y; + sphere->pos.z = z; + sphere->rad = rad; + return shape; +} + +struct tgi_shape *tgi_create_box(float x0, float y0, float z0, float x1, float y1, float z1) +{ + return 0; /* TODO */ +} + +void tgi_destroy_shape(struct tgi_shape *s) +{ + if(s) { + if(s->obj) { + s->obj->shape = 0; + } + free(s->data); + free(s); + } +} + +static int ray_sphere_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit) +{ + float x0, x1, t; + struct tgi_sphere_data *sph = shape->data; + ray_t oray = ray_transform(ray, shape->obj->inv_xform); + + float a = v3_dot(oray.dir, oray.dir); + float b = 2.0 * oray.dir.x * (oray.origin.x - sph->pos.x) + + 2.0 * oray.dir.y * (oray.origin.y - sph->pos.y) + + 2.0 * oray.dir.z * (oray.origin.z - sph->pos.z); + float c = v3_dot(oray.origin, oray.origin) + v3_dot(sph->pos, sph->pos) - + 2.0 * v3_dot(oray.origin, sph->pos) - sph->rad * sph->rad; + + float disc = b * b - 4.0 * a * c; + if(disc < 0.0) { + return 0; + } + + x0 = (-b + sqrt(disc)) / (2.0 * a); + x1 = (-b - sqrt(disc)) / (2.0 * a); + + if(x0 < 1e-5) x0 = x1; + if(x1 < 1e-5) x1 = x0; + + t = x0 < x1 ? x0 : x1; + if(t < 1e-5) { + return 0; + } + + if(hit) { + vec3_t gcent = v3_transform(sph->pos, shape->obj->xform); + + hit->t = t; + hit->ray = ray; + hit->local_ray = oray; + hit->pos = v3_scale(v3_add(ray.origin, ray.dir), t); + hit->norm = v3_scale(v3_sub(hit->pos, gcent), 1.0 / sph->rad); + hit->uv.x = atan2(hit->norm.z, hit->norm.x); + hit->uv.y = acos(hit->norm.y); + } + return 1; +} + +static int ray_box_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit) +{ + return 0; +} + diff -r bc64090fe3d1 -r 72752a1b3dbe src/shape.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shape.h Tue Jul 21 04:30:00 2015 +0300 @@ -0,0 +1,31 @@ +#ifndef TGI_SHAPE_H_ +#define TGI_SHAPE_H_ + +#include "tinygi.h" +#include "vmath/vmath.h" + +struct tgi_hitpoint { + float t; + ray_t ray, local_ray; + vec3_t pos, norm; + vec2_t uv; + struct tgi_shape *shape; +}; + +struct tgi_shape { + void *data; /* shape-specific data */ + struct tgi_object *obj; + + int (*intersect)(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit); +}; + +struct tgi_sphere_data { + vec3_t pos; + float rad; +}; + +struct tgi_box_data { + vec3_t vmin, vmax; +}; + +#endif /* TGI_SHAPE_H_ */ diff -r bc64090fe3d1 -r 72752a1b3dbe src/tgi_impl.h --- a/src/tgi_impl.h Mon Jul 20 04:38:53 2015 +0300 +++ b/src/tgi_impl.h Tue Jul 21 04:30:00 2015 +0300 @@ -5,8 +5,14 @@ #include "object.h" #include "logger.h" #include "vmath/vmath.h" +#include "image.h" struct tinygi { + /* fb is a sample accumulator, needs to be divided by nsamples for fbfinal */ + struct image fb; + struct image fbfinal; /* result of tgi_expose */ + float *fb_nsamples; + struct tgi_object **objects; /* dynarr */ }; diff -r bc64090fe3d1 -r 72752a1b3dbe src/tinygi.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tinygi.c Tue Jul 21 04:30:00 2015 +0300 @@ -0,0 +1,103 @@ +#include +#include +#include +#include "tgi_impl.h" +#include "object.h" +#include "dynarr.h" + +struct tinygi *tgi_init(void) +{ + struct tinygi *tgi; + + if(!(tgi = malloc(sizeof *tgi))) { + tgi_log("failed to allocate memory\n"); + return 0; + } + if(!(tgi->objects = dynarr_alloc(0, sizeof *tgi->objects))) { + tgi_log("failed to allocate objects array\n"); + free(tgi); + return 0; + } + + tgi_init_image(&tgi->fb); + tgi_init_image(&tgi->fbfinal); + tgi->fb_nsamples = 0; + + return tgi; +} + +void tgi_destroy(struct tinygi *tgi) +{ + tgi_clear_scene(tgi); + tgi_destroy_image(&tgi->fb); + tgi_destroy_image(&tgi->fbfinal); + free(tgi->fb_nsamples); + free(tgi); +} + +void tgi_clear_scene(struct tinygi *tgi) +{ + int i, nobj = dynarr_size(tgi->objects); + + for(i=0; iobjects[i]); + } + tgi->objects = dynarr_resize(tgi->objects, 0); + assert(tgi->objects); +} + +int tgi_load_scene(struct tinygi *tgi, const char *fname) +{ + return -1; /* TODO implement later */ +} + +void tgi_add_object(struct tinygi *tgi, struct tgi_object *o) +{ + tgi->objects = dynarr_push(tgi->objects, o); + assert(tgi->objects); +} + +int tgi_remove_object(struct tinygi *tgi, struct tgi_object *o) +{ + int i, idx = -1, sz = dynarr_size(tgi->objects); + + if(!sz) return -1; + + for(i=0; iobjects[i] == o) { + idx = i; + break; + } + } + if(idx == -1) { + return -1; + } + + tgi->objects[idx] = tgi->objects[sz - 1]; + tgi->objects = dynarr_pop(tgi->objects); + assert(tgi->objects); + return 0; +} + +struct tgi_object *tgi_find_object(struct tinygi *tgi, const char *name) +{ + int i, sz = dynarr_size(tgi->objects); + + for(i=0; iobjects[i]->name, name) == 0) { + return tgi->objects[i]; + } + } + return 0; +} + + +struct tgi_object *tgi_get_object(struct tinygi *tgi, int idx) +{ + return tgi->objects[idx]; +} + +int tgi_get_object_count(struct tinygi *tgi) +{ + return dynarr_size(tgi->objects); +} diff -r bc64090fe3d1 -r 72752a1b3dbe src/tinygi.h --- a/src/tinygi.h Mon Jul 20 04:38:53 2015 +0300 +++ b/src/tinygi.h Tue Jul 21 04:30:00 2015 +0300 @@ -1,8 +1,6 @@ #ifndef TINYGI_H_ #define TINYGI_H_ -struct tgi_vec3 { float x, y, z; }; - struct tinygi; struct tgi_object; struct tgi_shape; @@ -32,8 +30,6 @@ void tgi_destroy_object(struct tgi_object *o); /* object takes ownership of the shape */ void tgi_set_object_shape(struct tgi_object *o, struct tgi_shape *s); -/* object takes ownership of the material */ -void tgi_set_object_mtl(struct tgi_object *o, struct tgi_material *m); /* mat should point to an array of 16 floats (4x4 homogeneous transformation matrix) */ void tgi_load_matrix(struct tgi_object *o, const float *mat); @@ -45,9 +41,14 @@ void tgi_lookat(struct tgi_object *o, float x, float y, float z, float tx, float ty, float tz, float ux, float uy, float uz); -/* materials */ -struct tgi_material *tgi_create_material(void); -void tgi_destroy_material(struct tgi_material *mtl); -/* TODO */ +/* rendering */ +float *tgi_begin(struct tinygi *tgi, int width, int height); +float *tgi_expose(struct tinygi *tgi, float gamma); + +void tgi_render_frame(struct tinygi *tgi, int num_samples); +void tgi_render(struct tinygi *tgi, int sample_idx); +void tgi_render_rect(struct tinygi *tgi, int x, int y, int xsz, int ysz, int sample_idx); + + #endif /* TINYGI_H_ */