tinygi
changeset 2:72752a1b3dbe tip
images and shapes
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 21 Jul 2015 04:30:00 +0300 |
parents | bc64090fe3d1 |
children | |
files | Makefile src/image.c src/image.h src/main.c src/object.c src/object.h src/scene.c src/shape.c src/shape.h src/tgi_impl.h src/tinygi.c src/tinygi.h |
diffstat | 12 files changed, 306 insertions(+), 118 deletions(-) [+] |
line diff
1.1 --- a/Makefile Mon Jul 20 04:38:53 2015 +0300 1.2 +++ b/Makefile Tue Jul 21 04:30:00 2015 +0300 1.3 @@ -5,6 +5,7 @@ 1.4 bin = tgi 1.5 1.6 CFLAGS = -pedantic -Wall -g 1.7 +LDFLAGS = -lvmath -lm 1.8 1.9 $(bin): $(obj) 1.10 $(CC) -o $@ $(obj) $(LDFLAGS)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/image.c Tue Jul 21 04:30:00 2015 +0300 2.3 @@ -0,0 +1,31 @@ 2.4 +#include <stdlib.h> 2.5 +#include "tgi_impl.h" 2.6 +#include "image.h" 2.7 + 2.8 +void tgi_init_image(struct image *img) 2.9 +{ 2.10 + img->width = img->height = 0; 2.11 + img->pixels = 0; 2.12 +} 2.13 + 2.14 +void tgi_destroy_image(struct image *img) 2.15 +{ 2.16 + if(img) { 2.17 + free(img->pixels); 2.18 + } 2.19 +} 2.20 + 2.21 +int tgi_resize_image(struct image *img, int xsz, int ysz) 2.22 +{ 2.23 + float *npix = malloc(xsz * ysz * 4 * sizeof *npix); 2.24 + if(!npix) { 2.25 + tgi_log("failed to allocate %dx%d image\n", xsz, ysz); 2.26 + return -1; 2.27 + } 2.28 + 2.29 + free(img->pixels); 2.30 + img->pixels = npix; 2.31 + img->width = xsz; 2.32 + img->height = ysz; 2.33 + return 0; 2.34 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/image.h Tue Jul 21 04:30:00 2015 +0300 3.3 @@ -0,0 +1,14 @@ 3.4 +#ifndef TGI_IMAGE_H_ 3.5 +#define TGI_IMAGE_H_ 3.6 + 3.7 +struct image { 3.8 + int width, height; 3.9 + float *pixels; 3.10 +}; 3.11 + 3.12 +void tgi_init_image(struct image *img); 3.13 +void tgi_destroy_image(struct image *img); 3.14 + 3.15 +int tgi_resize_image(struct image *img, int xsz, int ysz); 3.16 + 3.17 +#endif /* TGI_IMAGE_H_ */
4.1 --- a/src/main.c Mon Jul 20 04:38:53 2015 +0300 4.2 +++ b/src/main.c Tue Jul 21 04:30:00 2015 +0300 4.3 @@ -1,4 +1,16 @@ 4.4 #include <stdio.h> 4.5 #include "tinygi.h" 4.6 4.7 +struct tinygi *tgi; 4.8 4.9 +int main(int argc, char **argv) 4.10 +{ 4.11 + if(!(tgi = tgi_init())) { 4.12 + return 1; 4.13 + } 4.14 + 4.15 + /* stuff ... */ 4.16 + 4.17 + tgi_destroy(tgi); 4.18 + return 0; 4.19 +}
5.1 --- a/src/object.c Mon Jul 20 04:38:53 2015 +0300 5.2 +++ b/src/object.c Tue Jul 21 04:30:00 2015 +0300 5.3 @@ -38,9 +38,6 @@ 5.4 if(o->shape) { 5.5 tgi_destroy_shape(o->shape); 5.6 } 5.7 - if(o->mtl) { 5.8 - tgi_destroy_material(o->mtl); 5.9 - } 5.10 free(o->name); 5.11 } 5.12 } 5.13 @@ -53,14 +50,6 @@ 5.14 o->shape = s; 5.15 } 5.16 5.17 -void tgi_set_object_mtl(struct tgi_object *o, struct tgi_material *m) 5.18 -{ 5.19 - if(o->mtl) { 5.20 - tgi_destroy_material(o->mtl); 5.21 - } 5.22 - o->mtl = m; 5.23 -} 5.24 - 5.25 /* mat should point to an array of 16 floats (4x4 homogeneous transformation matrix) */ 5.26 void tgi_load_matrix(struct tgi_object *o, const float *mat) 5.27 {
6.1 --- a/src/object.h Mon Jul 20 04:38:53 2015 +0300 6.2 +++ b/src/object.h Tue Jul 21 04:30:00 2015 +0300 6.3 @@ -4,10 +4,17 @@ 6.4 #include "tinygi.h" 6.5 #include "vmath/vmath.h" 6.6 6.7 +struct material { 6.8 + vec3_t color; 6.9 + float roughness; 6.10 + float opacity; 6.11 + float ior; 6.12 +}; 6.13 + 6.14 struct tgi_object { 6.15 char *name; 6.16 struct tgi_shape *shape; 6.17 - struct tgi_material *mtl; 6.18 + struct material mtl; 6.19 mat4_t xform, inv_xform; 6.20 6.21 struct tgi_object *next; /* for linking it into various lists */
7.1 --- a/src/scene.c Mon Jul 20 04:38:53 2015 +0300 7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 7.3 @@ -1,98 +0,0 @@ 7.4 -#include <stdlib.h> 7.5 -#include <string.h> 7.6 -#include <assert.h> 7.7 -#include "tgi_impl.h" 7.8 -#include "object.h" 7.9 -#include "dynarr.h" 7.10 - 7.11 -struct tinygi *tgi_init(void) 7.12 -{ 7.13 - struct tinygi *tgi; 7.14 - 7.15 - if(!(tgi = malloc(sizeof *tgi))) { 7.16 - tgi_log("failed to allocate memory\n"); 7.17 - return 0; 7.18 - } 7.19 - if(!(tgi->objects = dynarr_alloc(0, sizeof *tgi->objects))) { 7.20 - tgi_log("failed to allocate objects array\n"); 7.21 - free(tgi); 7.22 - return 0; 7.23 - } 7.24 - 7.25 - return tgi; 7.26 -} 7.27 - 7.28 -void tgi_destroy(struct tinygi *tgi) 7.29 -{ 7.30 - tgi_clear_scene(tgi); 7.31 - free(tgi); 7.32 -} 7.33 - 7.34 -void tgi_clear_scene(struct tinygi *tgi) 7.35 -{ 7.36 - int i, nobj = dynarr_size(tgi->objects); 7.37 - 7.38 - for(i=0; i<nobj; i++) { 7.39 - tgi_destroy_object(tgi->objects[i]); 7.40 - } 7.41 - tgi->objects = dynarr_resize(tgi->objects, 0); 7.42 - assert(tgi->objects); 7.43 -} 7.44 - 7.45 -int tgi_load_scene(struct tinygi *tgi, const char *fname) 7.46 -{ 7.47 - return -1; /* TODO implement later */ 7.48 -} 7.49 - 7.50 -void tgi_add_object(struct tinygi *tgi, struct tgi_object *o) 7.51 -{ 7.52 - tgi->objects = dynarr_push(tgi->objects, o); 7.53 - assert(tgi->objects); 7.54 -} 7.55 - 7.56 -int tgi_remove_object(struct tinygi *tgi, struct tgi_object *o) 7.57 -{ 7.58 - int i, idx = -1, sz = dynarr_size(tgi->objects); 7.59 - 7.60 - if(!sz) return -1; 7.61 - 7.62 - for(i=0; i<sz; i++) { 7.63 - if(tgi->objects[i] == o) { 7.64 - idx = i; 7.65 - break; 7.66 - } 7.67 - } 7.68 - if(idx == -1) { 7.69 - return -1; 7.70 - } 7.71 - 7.72 - tgi->objects[idx] = tgi->objects[sz - 1]; 7.73 - tgi->objects = dynarr_pop(tgi->objects); 7.74 - assert(tgi->objects); 7.75 - return 0; 7.76 -} 7.77 - 7.78 -struct tgi_object *tgi_find_object(struct tinygi *tgi, const char *name) 7.79 -{ 7.80 - int i, sz = dynarr_size(tgi->objects); 7.81 - 7.82 - for(i=0; i<sz; i++) { 7.83 - if(strcmp(tgi->objects[i]->name, name) == 0) { 7.84 - return tgi->objects[i]; 7.85 - } 7.86 - } 7.87 - return 0; 7.88 -} 7.89 - 7.90 - 7.91 -struct tgi_object *tgi_get_object(struct tinygi *tgi, int idx) 7.92 -{ 7.93 - return tgi->objects[idx]; 7.94 -} 7.95 - 7.96 -int tgi_get_object_count(struct tinygi *tgi) 7.97 -{ 7.98 - return dynarr_size(tgi->objects); 7.99 -} 7.100 - 7.101 -
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/shape.c Tue Jul 21 04:30:00 2015 +0300 8.3 @@ -0,0 +1,91 @@ 8.4 +#include "tgi_impl.h" 8.5 +#include "shape.h" 8.6 + 8.7 +static int ray_sphere_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit); 8.8 +static int ray_box_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit); 8.9 + 8.10 +struct tgi_shape *tgi_create_sphere(float x, float y, float z, float rad) 8.11 +{ 8.12 + struct tgi_shape *shape; 8.13 + struct tgi_sphere_data *sphere; 8.14 + 8.15 + if(!(shape = malloc(sizeof *shape)) || !(sphere = malloc(sizeof *sphere))) { 8.16 + free(shape); 8.17 + tgi_log("failed to allocate sphere shape\n"); 8.18 + return 0; 8.19 + } 8.20 + shape->data = sphere; 8.21 + shape->obj = 0; 8.22 + shape->intersect = ray_sphere_intersect; 8.23 + 8.24 + sphere->pos.x = x; 8.25 + sphere->pos.y = y; 8.26 + sphere->pos.z = z; 8.27 + sphere->rad = rad; 8.28 + return shape; 8.29 +} 8.30 + 8.31 +struct tgi_shape *tgi_create_box(float x0, float y0, float z0, float x1, float y1, float z1) 8.32 +{ 8.33 + return 0; /* TODO */ 8.34 +} 8.35 + 8.36 +void tgi_destroy_shape(struct tgi_shape *s) 8.37 +{ 8.38 + if(s) { 8.39 + if(s->obj) { 8.40 + s->obj->shape = 0; 8.41 + } 8.42 + free(s->data); 8.43 + free(s); 8.44 + } 8.45 +} 8.46 + 8.47 +static int ray_sphere_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit) 8.48 +{ 8.49 + float x0, x1, t; 8.50 + struct tgi_sphere_data *sph = shape->data; 8.51 + ray_t oray = ray_transform(ray, shape->obj->inv_xform); 8.52 + 8.53 + float a = v3_dot(oray.dir, oray.dir); 8.54 + float b = 2.0 * oray.dir.x * (oray.origin.x - sph->pos.x) + 8.55 + 2.0 * oray.dir.y * (oray.origin.y - sph->pos.y) + 8.56 + 2.0 * oray.dir.z * (oray.origin.z - sph->pos.z); 8.57 + float c = v3_dot(oray.origin, oray.origin) + v3_dot(sph->pos, sph->pos) - 8.58 + 2.0 * v3_dot(oray.origin, sph->pos) - sph->rad * sph->rad; 8.59 + 8.60 + float disc = b * b - 4.0 * a * c; 8.61 + if(disc < 0.0) { 8.62 + return 0; 8.63 + } 8.64 + 8.65 + x0 = (-b + sqrt(disc)) / (2.0 * a); 8.66 + x1 = (-b - sqrt(disc)) / (2.0 * a); 8.67 + 8.68 + if(x0 < 1e-5) x0 = x1; 8.69 + if(x1 < 1e-5) x1 = x0; 8.70 + 8.71 + t = x0 < x1 ? x0 : x1; 8.72 + if(t < 1e-5) { 8.73 + return 0; 8.74 + } 8.75 + 8.76 + if(hit) { 8.77 + vec3_t gcent = v3_transform(sph->pos, shape->obj->xform); 8.78 + 8.79 + hit->t = t; 8.80 + hit->ray = ray; 8.81 + hit->local_ray = oray; 8.82 + hit->pos = v3_scale(v3_add(ray.origin, ray.dir), t); 8.83 + hit->norm = v3_scale(v3_sub(hit->pos, gcent), 1.0 / sph->rad); 8.84 + hit->uv.x = atan2(hit->norm.z, hit->norm.x); 8.85 + hit->uv.y = acos(hit->norm.y); 8.86 + } 8.87 + return 1; 8.88 +} 8.89 + 8.90 +static int ray_box_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit) 8.91 +{ 8.92 + return 0; 8.93 +} 8.94 +
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/shape.h Tue Jul 21 04:30:00 2015 +0300 9.3 @@ -0,0 +1,31 @@ 9.4 +#ifndef TGI_SHAPE_H_ 9.5 +#define TGI_SHAPE_H_ 9.6 + 9.7 +#include "tinygi.h" 9.8 +#include "vmath/vmath.h" 9.9 + 9.10 +struct tgi_hitpoint { 9.11 + float t; 9.12 + ray_t ray, local_ray; 9.13 + vec3_t pos, norm; 9.14 + vec2_t uv; 9.15 + struct tgi_shape *shape; 9.16 +}; 9.17 + 9.18 +struct tgi_shape { 9.19 + void *data; /* shape-specific data */ 9.20 + struct tgi_object *obj; 9.21 + 9.22 + int (*intersect)(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit); 9.23 +}; 9.24 + 9.25 +struct tgi_sphere_data { 9.26 + vec3_t pos; 9.27 + float rad; 9.28 +}; 9.29 + 9.30 +struct tgi_box_data { 9.31 + vec3_t vmin, vmax; 9.32 +}; 9.33 + 9.34 +#endif /* TGI_SHAPE_H_ */
10.1 --- a/src/tgi_impl.h Mon Jul 20 04:38:53 2015 +0300 10.2 +++ b/src/tgi_impl.h Tue Jul 21 04:30:00 2015 +0300 10.3 @@ -5,8 +5,14 @@ 10.4 #include "object.h" 10.5 #include "logger.h" 10.6 #include "vmath/vmath.h" 10.7 +#include "image.h" 10.8 10.9 struct tinygi { 10.10 + /* fb is a sample accumulator, needs to be divided by nsamples for fbfinal */ 10.11 + struct image fb; 10.12 + struct image fbfinal; /* result of tgi_expose */ 10.13 + float *fb_nsamples; 10.14 + 10.15 struct tgi_object **objects; /* dynarr */ 10.16 }; 10.17
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/tinygi.c Tue Jul 21 04:30:00 2015 +0300 11.3 @@ -0,0 +1,103 @@ 11.4 +#include <stdlib.h> 11.5 +#include <string.h> 11.6 +#include <assert.h> 11.7 +#include "tgi_impl.h" 11.8 +#include "object.h" 11.9 +#include "dynarr.h" 11.10 + 11.11 +struct tinygi *tgi_init(void) 11.12 +{ 11.13 + struct tinygi *tgi; 11.14 + 11.15 + if(!(tgi = malloc(sizeof *tgi))) { 11.16 + tgi_log("failed to allocate memory\n"); 11.17 + return 0; 11.18 + } 11.19 + if(!(tgi->objects = dynarr_alloc(0, sizeof *tgi->objects))) { 11.20 + tgi_log("failed to allocate objects array\n"); 11.21 + free(tgi); 11.22 + return 0; 11.23 + } 11.24 + 11.25 + tgi_init_image(&tgi->fb); 11.26 + tgi_init_image(&tgi->fbfinal); 11.27 + tgi->fb_nsamples = 0; 11.28 + 11.29 + return tgi; 11.30 +} 11.31 + 11.32 +void tgi_destroy(struct tinygi *tgi) 11.33 +{ 11.34 + tgi_clear_scene(tgi); 11.35 + tgi_destroy_image(&tgi->fb); 11.36 + tgi_destroy_image(&tgi->fbfinal); 11.37 + free(tgi->fb_nsamples); 11.38 + free(tgi); 11.39 +} 11.40 + 11.41 +void tgi_clear_scene(struct tinygi *tgi) 11.42 +{ 11.43 + int i, nobj = dynarr_size(tgi->objects); 11.44 + 11.45 + for(i=0; i<nobj; i++) { 11.46 + tgi_destroy_object(tgi->objects[i]); 11.47 + } 11.48 + tgi->objects = dynarr_resize(tgi->objects, 0); 11.49 + assert(tgi->objects); 11.50 +} 11.51 + 11.52 +int tgi_load_scene(struct tinygi *tgi, const char *fname) 11.53 +{ 11.54 + return -1; /* TODO implement later */ 11.55 +} 11.56 + 11.57 +void tgi_add_object(struct tinygi *tgi, struct tgi_object *o) 11.58 +{ 11.59 + tgi->objects = dynarr_push(tgi->objects, o); 11.60 + assert(tgi->objects); 11.61 +} 11.62 + 11.63 +int tgi_remove_object(struct tinygi *tgi, struct tgi_object *o) 11.64 +{ 11.65 + int i, idx = -1, sz = dynarr_size(tgi->objects); 11.66 + 11.67 + if(!sz) return -1; 11.68 + 11.69 + for(i=0; i<sz; i++) { 11.70 + if(tgi->objects[i] == o) { 11.71 + idx = i; 11.72 + break; 11.73 + } 11.74 + } 11.75 + if(idx == -1) { 11.76 + return -1; 11.77 + } 11.78 + 11.79 + tgi->objects[idx] = tgi->objects[sz - 1]; 11.80 + tgi->objects = dynarr_pop(tgi->objects); 11.81 + assert(tgi->objects); 11.82 + return 0; 11.83 +} 11.84 + 11.85 +struct tgi_object *tgi_find_object(struct tinygi *tgi, const char *name) 11.86 +{ 11.87 + int i, sz = dynarr_size(tgi->objects); 11.88 + 11.89 + for(i=0; i<sz; i++) { 11.90 + if(strcmp(tgi->objects[i]->name, name) == 0) { 11.91 + return tgi->objects[i]; 11.92 + } 11.93 + } 11.94 + return 0; 11.95 +} 11.96 + 11.97 + 11.98 +struct tgi_object *tgi_get_object(struct tinygi *tgi, int idx) 11.99 +{ 11.100 + return tgi->objects[idx]; 11.101 +} 11.102 + 11.103 +int tgi_get_object_count(struct tinygi *tgi) 11.104 +{ 11.105 + return dynarr_size(tgi->objects); 11.106 +}
12.1 --- a/src/tinygi.h Mon Jul 20 04:38:53 2015 +0300 12.2 +++ b/src/tinygi.h Tue Jul 21 04:30:00 2015 +0300 12.3 @@ -1,8 +1,6 @@ 12.4 #ifndef TINYGI_H_ 12.5 #define TINYGI_H_ 12.6 12.7 -struct tgi_vec3 { float x, y, z; }; 12.8 - 12.9 struct tinygi; 12.10 struct tgi_object; 12.11 struct tgi_shape; 12.12 @@ -32,8 +30,6 @@ 12.13 void tgi_destroy_object(struct tgi_object *o); 12.14 /* object takes ownership of the shape */ 12.15 void tgi_set_object_shape(struct tgi_object *o, struct tgi_shape *s); 12.16 -/* object takes ownership of the material */ 12.17 -void tgi_set_object_mtl(struct tgi_object *o, struct tgi_material *m); 12.18 12.19 /* mat should point to an array of 16 floats (4x4 homogeneous transformation matrix) */ 12.20 void tgi_load_matrix(struct tgi_object *o, const float *mat); 12.21 @@ -45,9 +41,14 @@ 12.22 void tgi_lookat(struct tgi_object *o, float x, float y, float z, 12.23 float tx, float ty, float tz, float ux, float uy, float uz); 12.24 12.25 -/* materials */ 12.26 -struct tgi_material *tgi_create_material(void); 12.27 -void tgi_destroy_material(struct tgi_material *mtl); 12.28 -/* TODO */ 12.29 +/* rendering */ 12.30 +float *tgi_begin(struct tinygi *tgi, int width, int height); 12.31 +float *tgi_expose(struct tinygi *tgi, float gamma); 12.32 + 12.33 +void tgi_render_frame(struct tinygi *tgi, int num_samples); 12.34 +void tgi_render(struct tinygi *tgi, int sample_idx); 12.35 +void tgi_render_rect(struct tinygi *tgi, int x, int y, int xsz, int ysz, int sample_idx); 12.36 + 12.37 + 12.38 12.39 #endif /* TINYGI_H_ */