diff options
author | David Snopek <dsnopek@gmail.com> | 2024-04-05 19:54:07 -0500 |
---|---|---|
committer | David Snopek <dsnopek@gmail.com> | 2024-04-06 08:37:30 -0500 |
commit | 025f2b8e7c0d11857ed15452249ecda509b4ed48 (patch) | |
tree | e78a4ef18f6408d38ba0a1fc9d3f67ac61bacd9d /modules/openxr/scene/openxr_composition_layer_equirect.cpp | |
parent | 655e93d5846b2ef8ebb7d22c8878f51b8f22b312 (diff) | |
download | redot-engine-025f2b8e7c0d11857ed15452249ecda509b4ed48.tar.gz |
Add `intersects_ray()` method to `OpenXRCompositionLayer`
Diffstat (limited to 'modules/openxr/scene/openxr_composition_layer_equirect.cpp')
-rw-r--r-- | modules/openxr/scene/openxr_composition_layer_equirect.cpp | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/modules/openxr/scene/openxr_composition_layer_equirect.cpp b/modules/openxr/scene/openxr_composition_layer_equirect.cpp index c911dbf6ae..d67e71443c 100644 --- a/modules/openxr/scene/openxr_composition_layer_equirect.cpp +++ b/modules/openxr/scene/openxr_composition_layer_equirect.cpp @@ -207,3 +207,54 @@ void OpenXRCompositionLayerEquirect::set_fallback_segments(uint32_t p_fallback_s uint32_t OpenXRCompositionLayerEquirect::get_fallback_segments() const { return fallback_segments; } + +Vector2 OpenXRCompositionLayerEquirect::intersects_ray(const Vector3 &p_origin, const Vector3 &p_direction) const { + Transform3D equirect_transform = get_global_transform(); + + Vector3 offset = p_origin - equirect_transform.origin; + float a = p_direction.dot(p_direction); + float b = 2.0 * offset.dot(p_direction); + float c = offset.dot(offset) - (radius * radius); + + float discriminant = b * b - 4.0 * a * c; + if (discriminant < 0.0) { + return Vector2(-1.0, -1.0); + } + + float t0 = (-b - Math::sqrt(discriminant)) / (2.0 * a); + float t1 = (-b + Math::sqrt(discriminant)) / (2.0 * a); + float t = MAX(t0, t1); + + if (t < 0.0) { + return Vector2(-1.0, -1.0); + } + Vector3 intersection = p_origin + p_direction * t; + + Basis correction = equirect_transform.basis.inverse(); + correction.rotate(Vector3(0.0, 1.0, 0.0), -Math_PI / 2.0); + Vector3 relative_point = correction.xform(intersection - equirect_transform.origin); + + float horizontal_intersection_angle = Math::atan2(relative_point.z, relative_point.x); + if (Math::abs(horizontal_intersection_angle) > central_horizontal_angle / 2.0) { + return Vector2(-1.0, -1.0); + } + + float vertical_intersection_angle = Math::acos(relative_point.y / radius) - (Math_PI / 2.0); + if (vertical_intersection_angle < 0) { + if (Math::abs(vertical_intersection_angle) > upper_vertical_angle) { + return Vector2(-1.0, -1.0); + } + } else if (vertical_intersection_angle > lower_vertical_angle) { + return Vector2(-1.0, -1.0); + } + + // Re-center the intersection angle if the vertical angle is uneven between upper and lower. + if (upper_vertical_angle != lower_vertical_angle) { + vertical_intersection_angle -= (-upper_vertical_angle + lower_vertical_angle) / 2.0; + } + + float u = 0.5 + (horizontal_intersection_angle / central_horizontal_angle); + float v = 0.5 + (vertical_intersection_angle / (upper_vertical_angle + lower_vertical_angle)); + + return Vector2(u, v); +} |