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_ */