/// <summary> /// Calculates the depth in the color camera space at a user-specified /// location using nearest-neighbor interpolation. /// </summary> /// <returns> /// <c>true</c>, if a point is found is found successfully, <c>false</c> otherwise. /// </returns> /// <param name="pointCloud"> /// The point cloud. Cannot be null and must have at least three points. /// </param> /// <param name="colorCameraTimestamp"> /// Color camera's timestamp when UV is captured. /// </param> /// <param name="uvCoordinates"> /// The UV coordinates for the user selection. This is expected to be /// in Unity viewport space. The bottom-left of the camera is (0,0); /// the top-right is (1,1). /// </param> /// <param name="colorCameraPoint"> /// The point (x, y, z), where (x, y) is the back-projection of the UV /// coordinates to the color camera space and z is the z coordinate of /// the point in the point cloud nearest to the user selection after /// projection onto the image plane. If there is not a point cloud point /// close to the user selection after projection onto the image plane, /// then the point will be set to (0.0, 0.0, 0.0) and isValidPoint will /// be set to false. /// </param> public static bool ScreenCoordinateToWorldNearestNeighbor( TangoPointCloudData pointCloud, double colorCameraTimestamp, Vector2 uvCoordinates, out Vector3 colorCameraPoint) { TangoPoseData depth_T_colorCameraPose = new TangoPoseData(); int returnValue = TangoSupportAPI.TangoSupport_calculateRelativePose( pointCloud.m_timestamp, TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_CAMERA_DEPTH, colorCameraTimestamp, TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_CAMERA_COLOR, depth_T_colorCameraPose); if (returnValue != Common.ErrorType.TANGO_SUCCESS) { Debug.LogError("TangoSupport_calculateRelativePose error. " + Environment.StackTrace); colorCameraPoint = Vector3.zero; return(false); } GCHandle pointCloudHandle = GCHandle.Alloc(pointCloud.m_points, GCHandleType.Pinned); TangoPointCloudIntPtr tangoPointCloudIntPtr = new TangoPointCloudIntPtr(); tangoPointCloudIntPtr.m_points = pointCloudHandle.AddrOfPinnedObject(); tangoPointCloudIntPtr.m_timestamp = pointCloud.m_timestamp; tangoPointCloudIntPtr.m_numPoints = pointCloud.m_numPoints; // Unity viewport space is: the bottom-left of the camera is (0,0); // the top-right is (1,1). // Tango (Android) defined UV space is: the top-left of the camera is (0,0); // the bottom-right is (1,1). Vector2 uvCoordinatesTango = new Vector2(uvCoordinates.x, 1.0f - uvCoordinates.y); DVector4 pointCloudRotation = DVector4.IdentityQuaternion; DVector3 pointCloudTranslation = DVector3.Zero; returnValue = TangoSupportAPI.TangoSupport_getDepthAtPointNearestNeighbor( ref tangoPointCloudIntPtr, ref pointCloudTranslation, ref pointCloudRotation, ref uvCoordinatesTango, AndroidHelper.GetDisplayRotation(), ref depth_T_colorCameraPose.translation, ref depth_T_colorCameraPose.orientation, out colorCameraPoint); pointCloudHandle.Free(); if (returnValue != Common.ErrorType.TANGO_SUCCESS) { Debug.LogError("TangoSupport_getDepthAtPointNearestNeighbor error. " + Environment.StackTrace); colorCameraPoint = Vector3.zero; return(false); } return(true); }
/// <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 and are accessed via the API. /// </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 GetDeviceOrientationAlignedIntrinsics(TangoEnums.TangoCameraId cameraId, TangoCameraIntrinsics alignedIntrinsics) { TangoCameraIntrinsics intrinsics = new TangoCameraIntrinsics(); GetIntrinsics(TangoEnums.TangoCameraId.TANGO_CAMERA_COLOR, intrinsics); float intrinsicsRatio = (float)intrinsics.width / (float)intrinsics.height; Tango.OrientationManager.Rotation rotation = TangoSupport.RotateFromAToB( AndroidHelper.GetDisplayRotation(), AndroidHelper.GetColorCameraRotation()); switch (rotation) { case Tango.OrientationManager.Rotation.ROTATION_90: alignedIntrinsics.cx = intrinsics.cy; alignedIntrinsics.cy = intrinsics.width - intrinsics.cx; alignedIntrinsics.fx = intrinsics.fy; alignedIntrinsics.fy = intrinsics.fx; alignedIntrinsics.width = intrinsics.height; alignedIntrinsics.height = intrinsics.width; break; case Tango.OrientationManager.Rotation.ROTATION_180: alignedIntrinsics.cx = intrinsics.width - intrinsics.cx; alignedIntrinsics.cy = intrinsics.height - intrinsics.cy; alignedIntrinsics.fx = intrinsics.fx; alignedIntrinsics.fy = intrinsics.fy; alignedIntrinsics.width = intrinsics.width; alignedIntrinsics.height = intrinsics.height; break; case Tango.OrientationManager.Rotation.ROTATION_270: alignedIntrinsics.cx = intrinsics.height - intrinsics.cy; alignedIntrinsics.cy = intrinsics.cx; alignedIntrinsics.fx = intrinsics.fy; alignedIntrinsics.fy = intrinsics.fx; alignedIntrinsics.width = intrinsics.height; alignedIntrinsics.height = intrinsics.width; break; default: alignedIntrinsics.cx = intrinsics.cx; alignedIntrinsics.cy = intrinsics.cy; alignedIntrinsics.fx = intrinsics.fx; alignedIntrinsics.fy = intrinsics.fy; alignedIntrinsics.width = intrinsics.width; alignedIntrinsics.height = intrinsics.height; break; } 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; }
/// <summary> /// This is called when successfully connected to the Tango service. /// </summary> public void OnTangoServiceConnected() { // Disable if (!m_tangoApplication.EnableVideoOverlay) { IsRendering = false; return; } CommandBuffer buf = VideoOverlayProvider.CreateARScreenCommandBuffer(); m_camera.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, buf); m_camera.AddCommandBuffer(CameraEvent.BeforeGBuffer, buf); _SetRenderAndCamera(AndroidHelper.GetDisplayRotation(), AndroidHelper.GetColorCameraRotation()); IsRendering = true; }
/// <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; }
/// <summary> /// This is called when successfully connected to the Tango service. /// </summary> public void OnTangoServiceConnected() { _SetRenderAndCamera(AndroidHelper.GetDisplayRotation(), AndroidHelper.GetColorCameraRotation()); }
public Tango.OrientationManager.Rotation GetDisplayRotation() { return(AndroidHelper.GetDisplayRotation()); }