ray.position.y + ray.direction.y * amount,
ray.position.z + ray.direction.z * amount};
}
+
+std::optional<Vector3> ray_collision_triangle(const Ray &ray, const Vector3 &a,
+ const Vector3 &b,
+ const Vector3 &c) {
+ const Vector3 ab = Vector3Subtract(a, b);
+ const Vector3 cb = Vector3Subtract(c, b);
+ Vector3 ortho = Vector3CrossProduct(ab, cb);
+ ortho = Vector3Normalize(ortho);
+
+ Ray plane{.position = b, .direction = ortho};
+
+ auto result = ray_to_plane(ray, plane);
+ if (!result.has_value()) {
+ return std::nullopt;
+ }
+
+ Vector3 bary = Vector3Barycenter(result.value(), a, b, c);
+ if (bary.x >= 0.0F && bary.x <= 1.0F && bary.y >= 0.0F && bary.y <= 1.0F &&
+ bary.z >= 0.0F && bary.z <= 1.0F) {
+ float sum = bary.x + bary.y + bary.z;
+ if (sum > 0.999F && sum < 1.001) {
+ return result;
+ }
+ }
+
+ return std::nullopt;
+}
/// plane.direction is plane normal, plane.position is position on plane.
extern std::optional<Vector3> ray_to_plane(const Ray &ray, const Ray &plane);
+extern std::optional<Vector3> ray_collision_triangle(const Ray &ray,
+ const Vector3 &a,
+ const Vector3 &b,
+ const Vector3 &c);
+
// Unimplemented as this function isn't really needed and it exposes some
// weirdness regarding column-major matrices.
// extern Vector4 operator*(const Matrix &m, const Vector4 &v);
Vector3 sw{xf - 0.5F, current.sw, zf + 0.5F};
Vector3 se{xf + 0.5F, current.se, zf + 0.5F};
- {
- Vector3 a = Vector3Subtract(nw, sw);
- Vector3 b = Vector3Subtract(ne, sw);
- Vector3 ortho = Vector3CrossProduct(a, b);
- ortho = Vector3Normalize(ortho);
-
- Ray plane{.position = sw, .direction = ortho};
-
- auto result = ray_to_plane(ray, plane);
- if (!result.has_value()) {
- continue;
- }
-
- Vector3 bary = Vector3Barycenter(result.value(), nw, sw, ne);
- if (bary.x >= 0.0F && bary.x <= 1.0F && bary.y >= 0.0F &&
- bary.y <= 1.0F && bary.z >= 0.0F && bary.z <= 1.0F) {
- float sum = bary.x + bary.y + bary.z;
- if (sum > 0.999F && sum < 1.001) {
- idx_hit = idx;
+ if (ray_collision_triangle(ray, nw, sw, ne).has_value()) {
+ idx_hit = idx;
#ifndef NDEBUG
- std::cout << "first: idx_hit set to " << idx_hit << std::endl;
+ std::cout << "first: idx_hit set to " << idx_hit << std::endl;
#endif
- break;
- }
- }
- }
-
- {
- Vector3 a = Vector3Subtract(se, sw);
- Vector3 b = Vector3Subtract(ne, sw);
- Vector3 ortho = Vector3CrossProduct(a, b);
- ortho = Vector3Normalize(ortho);
-
- Ray plane{.position = sw, .direction = ortho};
-
- auto result = ray_to_plane(ray, plane);
- if (!result.has_value()) {
- continue;
- }
-
- Vector3 bary = Vector3Barycenter(result.value(), se, sw, ne);
- if (bary.x >= 0.0F && bary.x <= 1.0F && bary.y >= 0.0F &&
- bary.y <= 1.0F && bary.z >= 0.0F && bary.z <= 1.0F) {
- float sum = bary.x + bary.y + bary.z;
- if (sum > 0.999F && sum < 1.001) {
- idx_hit = idx;
+ break;
+ } else if (ray_collision_triangle(ray, ne, sw, se).has_value()) {
+ idx_hit = idx;
#ifndef NDEBUG
- std::cout << "second: idx_hit set to " << idx_hit << std::endl;
+ std::cout << "second: idx_hit set to " << idx_hit << std::endl;
#endif
- break;
- }
- }
+ break;
}
}