| 151 | } |
| 152 | |
| 153 | f32 ray_mesh_intersection(const Vector3 &from, const Vector3 &dir, const Matrix4x4 &tm, const void *vertices, u32 stride, const u16 *indices, u32 num) |
| 154 | { |
| 155 | bool hit = false; |
| 156 | f32 tmin = FLT_MAX; |
| 157 | |
| 158 | for (u32 i = 0; i < num; i += 3) { |
| 159 | const u32 i0 = indices[i + 0]; |
| 160 | const u32 i1 = indices[i + 1]; |
| 161 | const u32 i2 = indices[i + 2]; |
| 162 | |
| 163 | const Vector3 &v0 = *(Vector3 *)((char *)vertices + i0*stride) * tm; |
| 164 | const Vector3 &v1 = *(Vector3 *)((char *)vertices + i1*stride) * tm; |
| 165 | const Vector3 &v2 = *(Vector3 *)((char *)vertices + i2*stride) * tm; |
| 166 | |
| 167 | // https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm |
| 168 | |
| 169 | // Find vectors for two edges sharing v0 |
| 170 | const Vector3 e1 = v1 - v0; |
| 171 | const Vector3 e2 = v2 - v0; |
| 172 | |
| 173 | // Begin calculating determinant - also used to calculate u parameter |
| 174 | const Vector3 P = cross(dir, e2); |
| 175 | |
| 176 | // If determinant is near zero, ray lies in plane of triangle |
| 177 | const f32 det = dot(e1, P); |
| 178 | if (fequal(det, 0.0f)) |
| 179 | continue; |
| 180 | |
| 181 | const f32 inv_det = 1.0f / det; |
| 182 | |
| 183 | // Distance from v0 to ray origin |
| 184 | const Vector3 T = from - v0; |
| 185 | |
| 186 | // u parameter and test bound |
| 187 | const f32 u = dot(T, P) * inv_det; |
| 188 | |
| 189 | // The intersection lies outside of the triangle |
| 190 | if (u < 0.0f || u > 1.0f) |
| 191 | continue; |
| 192 | |
| 193 | // Prepare to test v parameter |
| 194 | const Vector3 Q = cross(T, e1); |
| 195 | |
| 196 | // v parameter and test bound |
| 197 | const f32 v = dot(dir, Q) * inv_det; |
| 198 | |
| 199 | // The intersection lies outside of the triangle |
| 200 | if (v < 0.0f || u + v > 1.0f) |
| 201 | continue; |
| 202 | |
| 203 | const f32 t = dot(e2, Q) * inv_det; |
| 204 | |
| 205 | // Ray intersection |
| 206 | if (t > FLOAT_EPSILON) { |
| 207 | hit = true; |
| 208 | tmin = min(t, tmin); |
| 209 | } |
| 210 | } |
no test coverage detected