Esempio n. 1
0
        /// <summary>
        /// Get the intrinsic calibration parameters for a given camera, this also aligns the camera intrinsics based
        /// on device orientation.
        ///
        /// For example, if the device orientation is portrait and camera intrinsics is in
        /// landscape. This function will inverse the intrinsic x and y, and report intrinsics in portrait mode.
        ///
        /// The intrinsics are as specified by the TangoCameraIntrinsics struct.  Intrinsics are read from the
        /// on-device intrinsics file (typically <code>/sdcard/config/calibration.xml</code>, but to ensure
        /// compatibility applications should only access these parameters via the API), or default internal model
        /// parameters corresponding to the device are used if the calibration.xml file is not found.
        /// </summary>
        /// <param name="cameraId">The camera ID to retrieve the calibration intrinsics for.</param>
        /// <param name="alignedIntrinsics">
        /// A TangoCameraIntrinsics filled with calibration intrinsics for the camera, this intrinsics is also
        /// aligned with device orientation.
        /// </param>
        public static void GetDeviceOientationAlignedIntrinsics(TangoEnums.TangoCameraId cameraId,
                                                                TangoCameraIntrinsics alignedIntrinsics)
        {
            TangoCameraIntrinsics intrinsics = new TangoCameraIntrinsics();

            GetIntrinsics(TangoEnums.TangoCameraId.TANGO_CAMERA_COLOR, intrinsics);

            float intrinsicsRatio = (float)intrinsics.width / (float)intrinsics.height;

            bool isLandscape = (AndroidHelper.GetDefaultOrientation() +
                                (int)AndroidHelper.GetDisplayRotation()) % 2 == 0;

            // If the intrinsics ratio and camera render ratio don't agree with each other, we invert the intrinsics
            // reading to align to camera render orientation.
            if ((!isLandscape && intrinsicsRatio > 1.0f) || (isLandscape && intrinsicsRatio < 1.0f))
            {
                alignedIntrinsics.cx     = intrinsics.cy;
                alignedIntrinsics.cy     = intrinsics.cx;
                alignedIntrinsics.fx     = intrinsics.fy;
                alignedIntrinsics.fy     = intrinsics.fx;
                alignedIntrinsics.height = intrinsics.width;
                alignedIntrinsics.width  = intrinsics.height;
            }
            else
            {
                alignedIntrinsics.cx     = intrinsics.cx;
                alignedIntrinsics.cy     = intrinsics.cy;
                alignedIntrinsics.fx     = intrinsics.fx;
                alignedIntrinsics.fy     = intrinsics.fy;
                alignedIntrinsics.height = intrinsics.height;
                alignedIntrinsics.width  = intrinsics.width;
            }

            alignedIntrinsics.distortion0      = intrinsics.distortion0;
            alignedIntrinsics.distortion1      = intrinsics.distortion1;
            alignedIntrinsics.distortion2      = intrinsics.distortion2;
            alignedIntrinsics.distortion3      = intrinsics.distortion3;
            alignedIntrinsics.distortion4      = intrinsics.distortion4;
            alignedIntrinsics.camera_id        = intrinsics.camera_id;
            alignedIntrinsics.calibration_type = intrinsics.calibration_type;
        }
Esempio n. 2
0
    /// <summary>
    /// Update AR screen rendering and attached Camera's projection matrix.
    /// </summary>
    /// <param name="displayRotation">Activity (screen) rotation.</param>
    /// <param name="colorCameraRotation">Color camera sensor rotation.</param>
    private void _SetRenderAndCamera(OrientationManager.Rotation displayRotation,
                                     OrientationManager.Rotation colorCameraRotation)
    {
        float cameraWidth  = (float)Screen.width;
        float cameraHeight = (float)Screen.height;

        #pragma warning disable 0219
        // Here we are computing if current display orientation is landscape or portrait.
        // AndroidHelper.GetAndroidDefaultOrientation() returns 1 if device default orientation is in portrait,
        // returns 2 if device default orientation is landscape. Adding device default orientation with
        // how much the display is rotated from default orientation will get us the result of current display
        // orientation. (landscape vs. portrait)
        bool  isLandscape           = (AndroidHelper.GetDefaultOrientation() + (int)displayRotation) % 2 == 0;
        bool  needToFlipCameraRatio = false;
        float cameraRatio           = (float)Screen.width / (float)Screen.height;
        #pragma warning restore 0219

#if !UNITY_EDITOR
        // In most cases, we don't need to flip the camera width and height. However, in some cases Unity camera
        // only updates a couple of frames after the display changed callback from Android; thus, we need to flip the width
        // and height in this case.
        //
        // This does not happen in the editor, because the emulated device does not ever rotate.
        needToFlipCameraRatio = (!isLandscape & (cameraRatio > 1.0f)) || (isLandscape & (cameraRatio < 1.0f));

        if (needToFlipCameraRatio)
        {
            cameraRatio = 1.0f / cameraRatio;
            float tmp = cameraWidth;
            cameraWidth  = cameraHeight;
            cameraHeight = tmp;
        }
#endif

        TangoCameraIntrinsics alignedIntrinsics = new TangoCameraIntrinsics();
        TangoCameraIntrinsics intrinsics        = new TangoCameraIntrinsics();
        VideoOverlayProvider.GetDeviceOrientationAlignedIntrinsics(TangoEnums.TangoCameraId.TANGO_CAMERA_COLOR,
                                                                   alignedIntrinsics);
        VideoOverlayProvider.GetIntrinsics(TangoEnums.TangoCameraId.TANGO_CAMERA_COLOR,
                                           intrinsics);

        if (alignedIntrinsics.width != 0 && alignedIntrinsics.height != 0)
        {
            // The camera to which this script is attached is an Augmented Reality camera.  The color camera
            // image must fill that camera's viewport.  That means we must clip the color camera image to make
            // its ratio the same as the Unity camera.  If we don't do this the color camera image will be
            // stretched non-uniformly, making a circle into an ellipse.
            float widthRatio  = (float)cameraWidth / (float)alignedIntrinsics.width;
            float heightRatio = (float)cameraHeight / (float)alignedIntrinsics.height;

            if (widthRatio >= heightRatio)
            {
                m_uOffset = 0;
                m_vOffset = (1 - (heightRatio / widthRatio)) / 2;
            }
            else
            {
                m_uOffset = (1 - (widthRatio / heightRatio)) / 2;
                m_vOffset = 0;
            }

            // Note that here we are passing in non-inverted intrinsics, because the YUV conversion is still operating
            // on native buffer layout.
            OrientationManager.Rotation rotation = TangoSupport.RotateFromAToB(displayRotation, colorCameraRotation);
            _MaterialUpdateForIntrinsics(m_uOffset, m_vOffset, rotation);
            _CameraUpdateForIntrinsics(m_camera, alignedIntrinsics, m_uOffset, m_vOffset);
            if (m_arCameraPostProcess != null)
            {
                m_arCameraPostProcess.SetupIntrinsic(intrinsics);
            }
        }
        else
        {
            Debug.LogError("AR Camera intrinsic is not valid.");
        }
    }