|
32 | 32 |
|
33 | 33 | #include "core/os/os.h" |
34 | 34 | #include "platform/android/display_server_android.h" |
| 35 | +#include "platform/android/java_godot_io_wrapper.h" |
| 36 | +#include "platform/android/os_android.h" |
35 | 37 |
|
36 | 38 | ////////////////////////////////////////////////////////////////////////// |
37 | 39 | // Helper functions |
@@ -94,22 +96,35 @@ CameraFeedAndroid::~CameraFeedAndroid() { |
94 | 96 | } |
95 | 97 |
|
96 | 98 | void CameraFeedAndroid::_set_rotation() { |
97 | | - int display_rotation = DisplayServerAndroid::get_singleton()->get_display_rotation(); |
98 | | - // reverse rotation |
99 | | - switch (display_rotation) { |
100 | | - case 90: |
101 | | - display_rotation = 270; |
102 | | - break; |
103 | | - case 270: |
104 | | - display_rotation = 90; |
105 | | - break; |
106 | | - default: |
107 | | - break; |
108 | | - } |
| 99 | + CameraRotationParams params; |
| 100 | + params.sensorOrientation = orientation; |
| 101 | + params.cameraFacing = (position == CameraFeed::FEED_FRONT) ? CameraFacing::FRONT : CameraFacing::BACK; |
| 102 | + params.displayRotation = get_app_orientation(); |
| 103 | + params.needsMirror = false; |
| 104 | + |
| 105 | + RotationResult result = calculate_rotation(params); |
109 | 106 |
|
110 | | - int sign = position == CameraFeed::FEED_FRONT ? 1 : -1; |
111 | | - float imageRotation = (orientation - display_rotation * sign + 360) % 360; |
112 | | - transform.set_rotation(real_t(Math::deg_to_rad(imageRotation))); |
| 107 | + if (result.isValid) { |
| 108 | + float imageRotation = static_cast<float>(result.rotationAngle); |
| 109 | + transform.set_rotation(real_t(Math::deg_to_rad(imageRotation))); |
| 110 | + } else { |
| 111 | + // Fallback. |
| 112 | + int display_rotation = DisplayServerAndroid::get_singleton()->get_display_rotation(); |
| 113 | + switch (display_rotation) { |
| 114 | + case 90: |
| 115 | + display_rotation = 270; |
| 116 | + break; |
| 117 | + case 270: |
| 118 | + display_rotation = 90; |
| 119 | + break; |
| 120 | + default: |
| 121 | + break; |
| 122 | + } |
| 123 | + |
| 124 | + int sign = position == CameraFeed::FEED_FRONT ? 1 : -1; |
| 125 | + float imageRotation = (orientation - display_rotation * sign + 360) % 360; |
| 126 | + transform.set_rotation(real_t(Math::deg_to_rad(imageRotation))); |
| 127 | + } |
113 | 128 | } |
114 | 129 |
|
115 | 130 | void CameraFeedAndroid::_add_formats() { |
@@ -594,3 +609,57 @@ void CameraAndroid::set_monitoring_feeds(bool p_monitoring_feeds) { |
594 | 609 | CameraAndroid::~CameraAndroid() { |
595 | 610 | remove_all_feeds(); |
596 | 611 | } |
| 612 | + |
| 613 | +////////////////////////////////////////////////////////////////////////// |
| 614 | +// Camera rotation calculation |
| 615 | +// Based on https://developer.android.com/media/camera/camerax/orientation-rotation |
| 616 | + |
| 617 | +RotationResult CameraFeedAndroid::calculate_rotation(const CameraRotationParams ¶ms) { |
| 618 | + RotationResult result = { 0, false, false }; |
| 619 | + |
| 620 | + if (params.sensorOrientation < 0 || params.sensorOrientation > 270 || |
| 621 | + params.sensorOrientation % 90 != 0) { |
| 622 | + return result; |
| 623 | + } |
| 624 | + |
| 625 | + int rotationAngle = params.sensorOrientation - params.displayRotation; |
| 626 | + |
| 627 | + result.rotationAngle = normalize_angle(rotationAngle); |
| 628 | + result.shouldMirror = params.needsMirror || (params.cameraFacing == CameraFacing::FRONT); |
| 629 | + result.isValid = true; |
| 630 | + |
| 631 | + return result; |
| 632 | +} |
| 633 | + |
| 634 | +int CameraFeedAndroid::normalize_angle(int angle) { |
| 635 | + while (angle < 0) { |
| 636 | + angle += 360; |
| 637 | + } |
| 638 | + return angle % 360; |
| 639 | +} |
| 640 | + |
| 641 | +int CameraFeedAndroid::get_display_rotation() { |
| 642 | + return DisplayServerAndroid::get_singleton()->get_display_rotation(); |
| 643 | +} |
| 644 | + |
| 645 | +int CameraFeedAndroid::get_app_orientation() { |
| 646 | + GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); |
| 647 | + ERR_FAIL_NULL_V(godot_io_java, 0); |
| 648 | + |
| 649 | + int orientation = godot_io_java->get_screen_orientation(); |
| 650 | + switch (orientation) { |
| 651 | + case 0: // SCREEN_LANDSCAPE |
| 652 | + return 90; |
| 653 | + case 1: // SCREEN_PORTRAIT |
| 654 | + return 0; |
| 655 | + case 2: // SCREEN_REVERSE_LANDSCAPE |
| 656 | + return 270; |
| 657 | + case 3: // SCREEN_REVERSE_PORTRAIT |
| 658 | + return 180; |
| 659 | + case 4: // SCREEN_SENSOR_LANDSCAPE |
| 660 | + case 5: // SCREEN_SENSOR_PORTRAIT |
| 661 | + case 6: // SCREEN_SENSOR |
| 662 | + default: |
| 663 | + return get_display_rotation(); |
| 664 | + } |
| 665 | +} |
0 commit comments