07f7a9b8beccea14362f02a333056d88726927dc
[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, pos;
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(&tri->norm, &vdir) / ndotdir) <= 1e-6 || t > tmax) {
17                 return 0;
18         }
19
20         cgm_raypos(&pos, ray, t);
21         cgm_bary(&bc, &tri->v[0].pos, &tri->v[1].pos, &tri->v[2].pos, &pos);
22
23         if(bc.x < 0.0f || bc.x > 1.0f) return 0;
24         if(bc.y < 0.0f || bc.y > 1.0f) return 0;
25         if(bc.z < 0.0f || bc.z > 1.0f) return 0;
26
27         if(hit) {
28                 hit->t = t;
29                 hit->ray = *ray;
30                 hit->mtl = tri->mtl;
31
32                 hit->v.pos = pos;
33
34                 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;
35                 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;
36                 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;
37
38                 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;
39                 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;
40         }
41         return 1;
42 }
43
44 #define SLABCHECK(dim)  \
45         do { \
46                 invdir = 1.0f / ray->dir.dim;   \
47                 t0 = (box->vmin.dim - ray->origin.dim) * invdir;        \
48                 t1 = (box->vmax.dim - ray->origin.dim) * invdir;        \
49                 if(invdir < 0.0f) {     \
50                         tmp = t0;       \
51                         t0 = t1;        \
52                         t1 = tmp;       \
53                 }       \
54                 tmin = t0 > tmin ? t0 : tmin;   \
55                 tmax = t1 < tmax ? t1 : tmax;   \
56                 if(tmax <= tmin) return 0; \
57         } while(0)
58
59 int ray_aabox_any(cgm_ray *ray, struct aabox *box, float tmax)
60 {
61         float invdir, t0, t1, tmp;
62         float tmin = 0.0f;
63
64         SLABCHECK(x);
65         SLABCHECK(y);
66         SLABCHECK(z);
67
68         return 1;
69 }
70
71 void aabox_union(struct aabox *res, struct aabox *a, struct aabox *b)
72 {
73         res->vmin.x = a->vmin.x < b->vmin.x ? a->vmin.x : b->vmin.x;
74         res->vmax.x = a->vmax.x > b->vmax.x ? a->vmax.x : b->vmax.x;
75         res->vmin.y = a->vmin.y < b->vmin.y ? a->vmin.y : b->vmin.y;
76         res->vmax.y = a->vmax.y > b->vmax.y ? a->vmax.y : b->vmax.y;
77         res->vmin.z = a->vmin.z < b->vmin.z ? a->vmin.z : b->vmin.z;
78         res->vmax.z = a->vmax.z > b->vmax.z ? a->vmax.z : b->vmax.z;
79 }
80
81 float aabox_surf_area(struct aabox *box)
82 {
83         float dx, dy, dz;
84
85         dx = box->vmax.x - box->vmin.x;
86         dy = box->vmax.y - box->vmin.y;
87         dz = box->vmax.z - box->vmin.z;
88
89         return surf_area(dx, dy, dz);
90 }
91
92 float surf_area(float dx, float dy, float dz)
93 {
94         if(dx <= 0 || dy <= 0 || dz <= 0) {
95                 return 0.0f;
96         }
97         return (dx * dy + dx * dz + dy * dz) * 2.0f;
98 }