tinygi

view src/shape.c @ 2:72752a1b3dbe

images and shapes
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 21 Jul 2015 04:30:00 +0300
parents
children
line source
1 #include "tgi_impl.h"
2 #include "shape.h"
4 static int ray_sphere_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit);
5 static int ray_box_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit);
7 struct tgi_shape *tgi_create_sphere(float x, float y, float z, float rad)
8 {
9 struct tgi_shape *shape;
10 struct tgi_sphere_data *sphere;
12 if(!(shape = malloc(sizeof *shape)) || !(sphere = malloc(sizeof *sphere))) {
13 free(shape);
14 tgi_log("failed to allocate sphere shape\n");
15 return 0;
16 }
17 shape->data = sphere;
18 shape->obj = 0;
19 shape->intersect = ray_sphere_intersect;
21 sphere->pos.x = x;
22 sphere->pos.y = y;
23 sphere->pos.z = z;
24 sphere->rad = rad;
25 return shape;
26 }
28 struct tgi_shape *tgi_create_box(float x0, float y0, float z0, float x1, float y1, float z1)
29 {
30 return 0; /* TODO */
31 }
33 void tgi_destroy_shape(struct tgi_shape *s)
34 {
35 if(s) {
36 if(s->obj) {
37 s->obj->shape = 0;
38 }
39 free(s->data);
40 free(s);
41 }
42 }
44 static int ray_sphere_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit)
45 {
46 float x0, x1, t;
47 struct tgi_sphere_data *sph = shape->data;
48 ray_t oray = ray_transform(ray, shape->obj->inv_xform);
50 float a = v3_dot(oray.dir, oray.dir);
51 float b = 2.0 * oray.dir.x * (oray.origin.x - sph->pos.x) +
52 2.0 * oray.dir.y * (oray.origin.y - sph->pos.y) +
53 2.0 * oray.dir.z * (oray.origin.z - sph->pos.z);
54 float c = v3_dot(oray.origin, oray.origin) + v3_dot(sph->pos, sph->pos) -
55 2.0 * v3_dot(oray.origin, sph->pos) - sph->rad * sph->rad;
57 float disc = b * b - 4.0 * a * c;
58 if(disc < 0.0) {
59 return 0;
60 }
62 x0 = (-b + sqrt(disc)) / (2.0 * a);
63 x1 = (-b - sqrt(disc)) / (2.0 * a);
65 if(x0 < 1e-5) x0 = x1;
66 if(x1 < 1e-5) x1 = x0;
68 t = x0 < x1 ? x0 : x1;
69 if(t < 1e-5) {
70 return 0;
71 }
73 if(hit) {
74 vec3_t gcent = v3_transform(sph->pos, shape->obj->xform);
76 hit->t = t;
77 hit->ray = ray;
78 hit->local_ray = oray;
79 hit->pos = v3_scale(v3_add(ray.origin, ray.dir), t);
80 hit->norm = v3_scale(v3_sub(hit->pos, gcent), 1.0 / sph->rad);
81 hit->uv.x = atan2(hit->norm.z, hit->norm.x);
82 hit->uv.y = acos(hit->norm.y);
83 }
84 return 1;
85 }
87 static int ray_box_intersect(struct tgi_shape *shape, ray_t ray, struct tgi_hitpoint *hit)
88 {
89 return 0;
90 }