/// <summary> /// Given a screen coordinate, finds a plane that most closely fits the /// depth values in that area. /// /// This function is slow, as it looks at every single point in the point /// cloud. Avoid calling this more than once a frame. This also assumes the /// Unity camera intrinsics match the device's color camera. /// </summary> /// <returns><c>true</c>, if a plane was found; <c>false</c> otherwise.</returns> /// <param name="cam">The Unity camera.</param> /// <param name="pos">The point in screen space to perform detection on.</param> /// <param name="planeCenter">Filled in with the center of the plane in Unity world space.</param> /// <param name="plane">Filled in with a model of the plane in Unity world space.</param> public bool FindPlane(Camera cam, Vector2 pos, out Vector3 planeCenter, out Plane plane) { if (m_pointsCount == 0) { // No points to check, maybe not connected to the service yet planeCenter = Vector3.zero; plane = new Plane(); return(false); } Matrix4x4 colorCameraTUnityWorld = m_colorCameraTUnityCamera * cam.transform.worldToLocalMatrix; Vector2 normalizedPos = cam.ScreenToViewportPoint(pos); // If the camera has a TangoARScreen attached, it is not displaying the entire color camera image. Correct // the normalized coordinates by taking the clipping into account. TangoARScreen arScreen = cam.gameObject.GetComponent <TangoARScreen>(); if (arScreen != null) { normalizedPos = arScreen.ViewportPointToCameraImagePoint(normalizedPos); } TangoCameraIntrinsics alignedIntrinsics = new TangoCameraIntrinsics(); VideoOverlayProvider.GetDeviceOientationAlignedIntrinsics(TangoEnums.TangoCameraId.TANGO_CAMERA_COLOR, alignedIntrinsics); int returnValue = TangoSupport.FitPlaneModelNearClick( m_points, m_pointsCount, m_depthTimestamp, alignedIntrinsics, ref colorCameraTUnityWorld, normalizedPos, out planeCenter, out plane); if (returnValue == Common.ErrorType.TANGO_SUCCESS) { return(true); } else { return(false); } }
/// <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 cameraRatio = (float)Screen.width / (float)Screen.height; float cameraWidth = (float)Screen.width; float cameraHeight = (float)Screen.height; bool needToFlipCameraRatio = false; // Here we are computing if current display orientation is landscape or portrait. // AndroidHelper.GetAndroidDefaultOrientation() returns 1 if deivce default orientation is in portrait, // returns 2 if device default orientation is landscape. Adding device default orientation with // how much the display is rotation from default orientation will get us the result of current display // orientation. (landscape vs. portrait) bool isLandscape = (AndroidHelper.GetDefaultOrientation() + (int)displayRotation) % 2 == 0; #if !UNITY_EDITOR // In most of the time, we don't need to flip the camera width and height. However, in some cases Unity camera // only updates 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.GetDeviceOientationAlignedIntrinsics(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."); } }