started implementing intersection functions and the main renderer data
[cyberay] / src / geom.c
1 #include <float.h>
2 #include "geom.h"
3
4 int ray_triangle(cgm_ray *ray, struct triangle *tri, float tmax, struct rayhit *hit)
5 {
6         float t, ndotdir;
7         cgm_vec3 vdir, bc;
8
9         if(fabs(ndotdir = cgm_vdot(&ray->dir, &tri->norm)) <= 1e-6) {
10                 return 0;
11         }
12
13         vdir = tri->v[0].pos;
14         cgm_vsub(&vdir, &ray->origin);
15
16         if((t = cgm_vdot(&ray->dir, &vdir) / ndotdir) <= 1e-6 || t > tmax) {
17                 return 0;
18         }
19
20         if(hit) {
21                 hit->t = t;
22                 hit->ray = *ray;
23                 hit->mtl = tri->mtl;
24
25                 cgm_raypos(&hit->v.pos, ray, t);
26                 cgm_bary(&bc, &tri->v[0].pos, &tri->v[1].pos, &tri->v[2].pos, &hit->v.pos);
27
28                 hit->v.norm.x = tri->v[0].norm.x * bc.x + tri->v[1].norm.x * bc.y + tri->v[2].norm.x * bc.z;
29                 hit->v.norm.y = tri->v[0].norm.y * bc.x + tri->v[1].norm.y * bc.y + tri->v[2].norm.y * bc.z;
30                 hit->v.norm.z = tri->v[0].norm.z * bc.x + tri->v[1].norm.z * bc.y + tri->v[2].norm.z * bc.z;
31
32                 hit->v.tex.x = tri->v[0].tex.x * bc.x + tri->v[1].tex.x * bc.y + tri->v[2].tex.x * bc.z;
33                 hit->v.tex.y = tri->v[0].tex.y * bc.x + tri->v[1].tex.y * bc.y + tri->v[2].tex.y * bc.z;
34         }
35         return 1;
36 }
37
38 #define SLABCHECK(dim)  \
39         do { \
40                 min = box->p.dim - box->r.dim;  \
41                 max = box->p.dim + box->r.dim;  \
42                 invdir = 1.0f / ray->dir.dim;   \
43                 t0 = (min - ray->origin.dim) * invdir;  \
44                 t1 = (max - ray->origin.dim) * invdir;  \
45                 if(invdir < 0.0f) {     \
46                         tmp = t0;       \
47                         t0 = t1;        \
48                         t1 = tmp;       \
49                 }       \
50                 tmin = t0 > tmin ? t0 : tmin;   \
51                 tmax = t1 < tmax ? t1 : tmax;   \
52                 if(tmax <= tmin) return 0; \
53         } while(0)
54
55 int ray_aabox_any(cgm_ray *ray, struct aabox *box, float tmax)
56 {
57         float invdir, t0, t1, tmp;
58         float min, max, tmin = 0.0f;
59
60         SLABCHECK(x);
61         SLABCHECK(y);
62         SLABCHECK(z);
63
64         return 1;
65 }
66
67 int ray_bvhnode(cgm_ray *ray, struct bvhnode *bn, float tmax, struct rayhit *hit)
68 {
69         int i, res = 0;
70         struct rayhit hit0;
71
72         if(!ray_aabox_any(ray, &bn->aabb, tmax)) {
73                 return 0;
74         }
75
76         if(!hit) {
77                 for(i=0; i<bn->num_faces; i++) {
78                         if(ray_triangle(ray, bn->faces[i], tmax, 0)) {
79                                 return 1;
80                         }
81                 }
82                 return 0;
83         }
84
85         hit0.t = FLT_MAX;
86         for(i=0; i<bn->num_faces; i++) {
87                 if(ray_triangle(ray, bn->faces[i], tmax, hit) && hit->t < hit0.t) {
88                         hit0 = *hit;
89                         res = 1;
90                 }
91         }
92         *hit = hit0;
93         return res;
94 }