]> git.localhorst.tv Git - blank.git/blob - src/geometry.cpp
place and remove blocks via mouse
[blank.git] / src / geometry.cpp
1 #include "geometry.hpp"
2
3 #include <limits>
4
5
6 namespace blank {
7
8 bool Intersection(
9         const Ray &ray,
10         const AABB &aabb,
11         const glm::mat4 &M,
12         float *dist,
13         glm::vec3 *normal
14 ) {
15         float t_min = 0.0f;
16         float t_max = 1.0e5f;
17         const glm::vec3 aabb_pos(M[3].x, M[3].y, M[3].z);
18         const glm::vec3 delta = aabb_pos - ray.orig;
19
20         glm::vec3 t1(t_min, t_min, t_min), t2(t_max, t_max, t_max);
21         bool x_swap = false, y_swap = false, z_swap = false;
22
23         { // X
24                 const glm::vec3 xaxis(M[0].x, M[0].y, M[0].z);
25                 const float e = glm::dot(xaxis, delta);
26                 const float f = glm::dot(ray.dir, xaxis);
27
28                 if (std::abs(f) > std::numeric_limits<float>::epsilon()) {
29                         t1.x = (e + aabb.min.x) / f;
30                         t2.x = (e + aabb.max.x) / f;
31
32                         if (t1.x > t2.x) {
33                                 std::swap(t1.x, t2.x);
34                                 x_swap = true;
35                         }
36                         if (t1.x > t_min) {
37                                 t_min = t1.x;
38                         }
39                         if (t2.x < t_max) {
40                                 t_max = t2.x;
41                         }
42                         if (t_max < t_min) {
43                                 return false;
44                         }
45                 } else {
46                         if (aabb.min.x - e > 0.0f || aabb.max.x < 0.0f) {
47                                 return false;
48                         }
49                 }
50         }
51
52         { // Y
53                 const glm::vec3 yaxis(M[1].x, M[1].y, M[1].z);
54                 const float e = glm::dot(yaxis, delta);
55                 const float f = glm::dot(ray.dir, yaxis);
56
57                 if (std::abs(f) > std::numeric_limits<float>::epsilon()) {
58                         t1.y = (e + aabb.min.y) / f;
59                         t2.y = (e + aabb.max.y) / f;
60
61                         if (t1.y > t2.y) {
62                                 std::swap(t1.y, t2.y);
63                                 y_swap = true;
64                         }
65                         if (t1.y > t_min) {
66                                 t_min = t1.y;
67                         }
68                         if (t2.y < t_max) {
69                                 t_max = t2.y;
70                         }
71                         if (t_max < t_min) {
72                                 return false;
73                         }
74                 } else {
75                         if (aabb.min.y - e > 0.0f || aabb.max.y < 0.0f) {
76                                 return false;
77                         }
78                 }
79         }
80
81         { // Z
82                 const glm::vec3 zaxis(M[2].x, M[2].y, M[2].z);
83                 const float e = glm::dot(zaxis, delta);
84                 const float f = glm::dot(ray.dir, zaxis);
85
86                 if (std::abs(f) > std::numeric_limits<float>::epsilon()) {
87                         t1.z = (e + aabb.min.z) / f;
88                         t2.z = (e + aabb.max.z) / f;
89
90                         if (t1.z > t2.z) {
91                                 std::swap(t1.z, t2.z);
92                                 z_swap = true;
93                         }
94                         if (t1.z > t_min) {
95                                 t_min = t1.z;
96                         }
97                         if (t2.z < t_max) {
98                                 t_max = t2.z;
99                         }
100                         if (t_max < t_min) {
101                                 return false;
102                         }
103                 } else {
104                         if (aabb.min.z - e > 0.0f || aabb.max.z < 0.0f) {
105                                 return false;
106                         }
107                 }
108         }
109
110         if (dist) {
111                 *dist = t_min;
112         }
113         if (normal) {
114                 if (t1.x > t1.y) {
115                         if (t1.x > t1.z) {
116                                 *normal = glm::vec3(x_swap ? 1 : -1, 0, 0);
117                         } else {
118                                 *normal = glm::vec3(0, 0, z_swap ? 1 : -1);
119                         }
120                 } else if (t1.y > t1.z) {
121                         *normal = glm::vec3(0, y_swap ? 1 : -1, 0);
122                 } else {
123                         *normal = glm::vec3(0, 0, z_swap ? 1 : -1);
124                 }
125         }
126         return true;
127 }
128
129 }