private IEnumerator HostCloudAnchor() { // Wait until the anchor is fully uploaded to the cloud yield return(new WaitWhile(() => WorldAnchorCloud.cloudAnchorState == CloudAnchorState.None || WorldAnchorCloud.cloudAnchorState == CloudAnchorState.TaskInProgress)); if (WorldAnchorCloud.cloudAnchorState == CloudAnchorState.Success) { // save its ID to PlayerPrefs PlayerPrefs.SetString("cloud_anchor_id", WorldAnchorCloud.cloudAnchorId); PlayerPrefs.Save(); // create new calibration cube representing cloud anchor and attach scene to it worldAnchorVis = Instantiate(WorldAnchorPrefab, Vector3.zero, Quaternion.identity); worldAnchorVis.transform.SetParent(WorldAnchorCloud.transform, false); AttachScene(WorldAnchorCloud.gameObject); // remove temporary local anchor RemoveLocalWorldAnchor(); Notifications.Instance.ShowNotification("Cloud anchor created", WorldAnchorCloud.cloudAnchorState.ToString() + " ID: " + WorldAnchorCloud.cloudAnchorId); Calibrated = true; UsingCloudAnchors = true; OnARCalibrated?.Invoke(this, new CalibrationEventArgs(true, WorldAnchorCloud.gameObject)); Notifications.Instance.ShowNotification("Calibration successful", ""); ActivateCalibrationElements((bool)MainSettingsMenu.Instance.CalibrationElements.GetValue()); GameManager.Instance.SceneSetActive(true); } else { Notifications.Instance.ShowNotification("Cloud anchor error", WorldAnchorCloud.cloudAnchorState.ToString()); Debug.LogError("Cloud anchor error: " + WorldAnchorCloud.cloudAnchorState); } }
private void Start() { #if UNITY_STANDALONE || !AR_ON Calibrated = true; OnARCalibrated?.Invoke(this, new CalibrationEventArgs(true, WorldAnchorLocal.gameObject)); #endif }
//public async void GetCameraPosition(CameraParameters cameraParams, string image, bool autoCalibrate = false) { // try { // // receive cameraPose from server // IO.Swagger.Model.EstimatedPose cameraEstimatedPose = await WebsocketManager.Instance.GetCameraPose(cameraParams, image, inverse:false); // IO.Swagger.Model.Pose cameraPose = cameraEstimatedPose.Pose; // Vector3 cameraPositionReceived = new Vector3((float) cameraPose.Position.X, (float) cameraPose.Position.Y, (float) cameraPose.Position.Z); // Quaternion cameraRotationReceived = new Quaternion((float) cameraPose.Orientation.X, (float) cameraPose.Orientation.Y, // (float) cameraPose.Orientation.Z, (float) cameraPose.Orientation.W); // //Matrix4x4 cameraMatrix = AdjustMatrixByScreenOrientation(Matrix4x4.TRS(cameraPositionReceived, cameraRotationReceived, Vector3.one)); // Matrix4x4 cameraMatrix = Matrix4x4.TRS(cameraPositionReceived, cameraRotationReceived, Vector3.one); // Vector3 cameraPosition = TransformConvertor.OpenCVToUnity(TransformConvertor.GetPositionFromMatrix(cameraMatrix)); // Quaternion cameraRotation = TransformConvertor.OpenCVToUnity(TransformConvertor.GetQuaternionFromMatrix(cameraMatrix)); // // Transformation Inversion to get Marker Position // cameraMatrix = Matrix4x4.TRS(cameraPosition, cameraRotation, Vector3.one); // create translation, rotation and scaling matrix // Matrix4x4 markerMatrix = cameraMatrix.inverse; // inverse to get marker rotation matrix // markerMatrix.SetColumn(3, Vector4.zero); // set translation column to zeros // Vector3 markerPos = markerMatrix.MultiplyPoint3x4(cameraPosition); // transform cameraPosition by marker matrix // markerPos = -1 * markerPos; // markerMatrix = AdjustMatrixByScreenOrientation(Matrix4x4.TRS(markerPos, TransformConvertor.GetQuaternionFromMatrix(markerMatrix), Vector3.one)); // // Marker Position // GameObject marker = Instantiate(MarkerPositionGameObject); // create marker gameobject as child of the camera // marker.transform.localPosition = ARCameraTransformMatrix.MultiplyPoint3x4(TransformConvertor.GetPositionFromMatrix(markerMatrix)); //ARCamera.TransformPoint(markerPos); // marker.transform.localRotation = TransformConvertor.GetQuaternionFromMatrix(ARCameraTransformMatrix) * TransformConvertor.GetQuaternionFromMatrix(markerMatrix); //ARCamera.transform.rotation * Quaternion.LookRotation(markerMatrix.GetColumn(2), markerMatrix.GetColumn(1)); // get quaternion from rotation matrix // marker.transform.localScale = new Vector3(1f, 1f, 1f); // CreateLocalAnchor(marker); // //if (WorldAnchorLocal != null) { // // // Camera Position // // GameObject camera = Instantiate(MarkerPositionGameObject, WorldAnchorLocal.transform); // // camera.transform.localPosition = cameraPosition; // // camera.transform.localRotation = cameraRotation; // // camera.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f); // //} // //Notifications.Instance.ShowNotification("Camera position", "GetCameraPose inverse false"); // markerDetectionState = MarkerDetectionState.Success; // } catch (RequestFailedException ex) { // markerDetectionState = MarkerDetectionState.Failure; // Debug.Log("No markers visible"); // Notifications.Instance.ShowNotification("No markers visible", ex.Message); // } //} public void CreateLocalAnchor(GameObject marker) { #if (UNITY_ANDROID || UNITY_IOS) && AR_ON // remove all old local anchors, if there are some (in case we are recalibrating) RemoveLocalWorldAnchor(); //FeatureMapQuality mapQuality = ARAnchorManager.EstimateFeatureMapQualityForHosting(new UnityEngine.Pose(marker.transform.position, marker.transform.rotation)); //Debug.Log("FeatureMapQuality: " + mapQuality); //Notifications.Instance.ShowNotification("FeatureMapQuality", mapQuality.ToString()); WorldAnchorLocal = marker.AddComponent <ARAnchor>(); // immediately attach scene to local anchor (after cloud anchor is created, scene will be attached to it) AttachScene(WorldAnchorLocal.gameObject); GameManager.Instance.Scene.transform.localEulerAngles = new Vector3(0f, 90f, 90f); // Create cloud anchor if (Settings.Instance.UseCloudAnchors) { WorldAnchorCloud = ARAnchorManager.HostCloudAnchor(WorldAnchorLocal); StartCoroutine(HostCloudAnchor()); } else { Calibrated = true; UsingCloudAnchors = false; OnARCalibrated?.Invoke(this, new CalibrationEventArgs(true, WorldAnchorLocal.gameObject)); //Notifications.Instance.ShowNotification("Calibration successful", ""); worldAnchorVis = null; ActivateCalibrationElements((bool)MainSettingsMenu.Instance.CalibrationElements.GetValue()); } GameManager.Instance.SceneSetActive(true); ActivateTrackableMarkers(false); #endif }
public void RecalibrateUsingARFoundation() { #if (UNITY_ANDROID || UNITY_IOS) && AR_ON HideCurrentWorldAnchor(); ActivateTrackableMarkers(true); Calibrated = false; OnARCalibrated?.Invoke(this, new CalibrationEventArgs(false, null)); OnARRecalibrate?.Invoke(this, new EventArgs()); GameManager.Instance.SceneSetActive(false); #endif }
/// <summary> /// Immediately creates local anchor after detected marker intersects detected plane beneath it. /// Cloud anchor is created afterwards, but it takes some time. When it is finished, scene will be attached to it. /// Called if user clicks on the calibration cube displayed over detected marker. /// </summary> /// <param name="tf"></param> public void CreateAnchor(Transform tf) { #if (UNITY_ANDROID || UNITY_IOS) && AR_ON ARPlane plane = null; UnityEngine.Pose hitPose = new UnityEngine.Pose(); // try to raycast straight down to intersect closest plane List <ARRaycastHit> raycastHits = new List <ARRaycastHit>(); if (ARRaycastManager.Raycast(new Ray(tf.position, Vector3.down), raycastHits, TrackableType.PlaneWithinPolygon)) { hitPose = raycastHits[0].pose; TrackableId hitPlaneId = raycastHits[0].trackableId; plane = ARPlaneManager.GetPlane(hitPlaneId); } // remove all old local anchors, if there are some (in case we are recalibrating) RemoveLocalWorldAnchor(); RemoveCloudWorldAnchor(); // set temporary world anchor //WorldAnchorLocal = ARAnchorManager.AttachAnchor(plane, // new Pose(hitPose.position, Quaternion.FromToRotation(tf.up, plane.normal) * tf.rotation)); //WorldAnchorLocal = ARAnchorManager.AddAnchor(new UnityEngine.Pose(hitPose != new UnityEngine.Pose() ? hitPose.position : tf.position, // plane != null ? Quaternion.FromToRotation(tf.up, plane.normal) * tf.rotation : tf.rotation)); WorldAnchorLocal = ARAnchorManager.AddAnchor(new UnityEngine.Pose(tf.position, plane != null ? Quaternion.FromToRotation(tf.up, plane.normal) * tf.rotation : tf.rotation)); // immediately attach scene to local anchor (after cloud anchor is created, scene will be attached to it) AttachScene(WorldAnchorLocal.gameObject); // Create cloud anchor if (Settings.Instance.UseCloudAnchors) { WorldAnchorCloud = ARAnchorManager.HostCloudAnchor(WorldAnchorLocal); StartCoroutine(HostCloudAnchor()); } else { Calibrated = true; UsingCloudAnchors = false; OnARCalibrated?.Invoke(this, new CalibrationEventArgs(true, WorldAnchorLocal.gameObject)); Notifications.Instance.ShowNotification("Calibration successful", ""); worldAnchorVis = null; ActivateCalibrationElements((bool)MainSettingsMenu.Instance.CalibrationElements.GetValue()); } GameManager.Instance.SceneSetActive(true); ActivateTrackableMarkers(false); #endif }
private void RunServerAutoCalibration() { #if (UNITY_ANDROID || UNITY_IOS) && AR_ON // If we used local calibration before, remove all local anchors and prepare for server calibration if (!UsingServerCalibration) { //Debug.Log("Server: Was using local calibration"); Calibrated = false; OnARCalibrated?.Invoke(this, new CalibrationEventArgs(false, null)); if (localCalibration != null) { //Debug.Log("Server: Stopping local calibration coroutine"); StopCoroutine(localCalibration); localCalibration = null; } RemoveLocalWorldAnchor(); GameManager.Instance.SceneSetActive(false); } ARTrackedImageManager.enabled = false; if (!Calibrated) { //Debug.Log("Server: not calibrated"); // stop previously running calibration coroutine if (autoCalibration != null) { //Debug.Log("Server: Stopping autocalib"); StopCoroutine(autoCalibration); } autoCalibration = StartCoroutine(AutoCalibrate()); } UsingServerCalibration = true; #endif }
private IEnumerator AutoCalibrate() { // Do nothing while in the MainScreen (just track feature points, planes, etc. as user moves unintentionally with the device) yield return(new WaitUntil(() => GameManager.Instance.GetGameState() == GameManager.GameStateEnum.SceneEditor || GameManager.Instance.GetGameState() == GameManager.GameStateEnum.ProjectEditor || GameManager.Instance.GetGameState() == GameManager.GameStateEnum.PackageRunning)); if (!Calibrated) { Notifications.Instance.ShowNotification("Calibrating", "Move the device around your workspace"); TrackingLostAnimation.PlayVideo(); //yield return new WaitForSeconds(10f); // Check how many features and planes the tracking has detected yield return(new WaitUntil(() => TrackingManager.Instance.GetTrackingQuality() == TrackingManager.TrackingQuality.GOOD_QUALITY)); TrackingLostAnimation.StopVideo(); Calibrated = false; OnARCalibrated?.Invoke(this, new CalibrationEventArgs(false, null)); Notifications.Instance.ShowNotification("Locate as much markers as possible", "Calibration will be done automatically"); } while (!Calibrated) { markerDetectionState = MarkerDetectionState.Processing; bool calibrated = false; yield return(CalibrateUsingServerAsync(success => { calibrated = success; markerDetectionState = success ? MarkerDetectionState.Success : MarkerDetectionState.Failure; }, inverse: true, force: true)); Calibrated = calibrated; yield return(new WaitForSeconds(0.5f)); } OnARCalibrated?.Invoke(this, new CalibrationEventArgs(true, WorldAnchorLocal.gameObject)); // Main autocalibration loop while (Application.isFocused) { // Do nothing while in the MainScreen (just track feature points, planes, etc. as user moves unintentionally with the device) yield return(new WaitUntil(() => (GameManager.Instance.GetGameState() == GameManager.GameStateEnum.SceneEditor || GameManager.Instance.GetGameState() == GameManager.GameStateEnum.ProjectEditor || GameManager.Instance.GetGameState() == GameManager.GameStateEnum.PackageRunning) && TrackingManager.Instance.IsDeviceTracking())); if (AutoRecalibration) { markerDetectionState = MarkerDetectionState.Processing; yield return(CalibrateUsingServerAsync(success => { if (success) { markerDetectionState = MarkerDetectionState.Success; recalibrateTime = 2f; } else { markerDetectionState = MarkerDetectionState.Failure; if (anchorQuality > 0) { anchorQuality -= 0.05f; } //if (recalibrateTime > 1f) { // recalibrateTime -= 10f; //} } }, inverse: true, autoCalibrate: true)); //Debug.Log("Current quality: " + anchorQuality); } yield return(new WaitForSeconds(AutoRecalibrateTime)); } }
private IEnumerator Calibrate() { #if (UNITY_ANDROID || UNITY_IOS) && AR_ON // Do nothing while in the MainScreen (just track feature points, planes, etc. as user moves unintentionally with the device) yield return(new WaitUntil(() => GameManager.Instance.GetGameState() == GameManager.GameStateEnum.SceneEditor || GameManager.Instance.GetGameState() == GameManager.GameStateEnum.ProjectEditor || GameManager.Instance.GetGameState() == GameManager.GameStateEnum.PackageRunning)); Notifications.Instance.ShowNotification("Calibrating", "Move the device around your workspace"); TrackingLostAnimation.PlayVideo(); //yield return new WaitForSeconds(10f); // Check how many features and planes the tracking has detected yield return(new WaitUntil(() => TrackingManager.Instance.GetTrackingQuality() == TrackingManager.TrackingQuality.GOOD_QUALITY)); TrackingLostAnimation.StopVideo(); if (Settings.Instance.UseCloudAnchors) { // Try to load cloud anchor defined by ID saved in PlayerPrefs if (LoadCloudAnchor()) { // if anchor exist in the cloud, wait for it to be fully loaded yield return(new WaitUntil(() => WorldAnchorCloud.cloudAnchorState == CloudAnchorState.Success)); worldAnchorVis = Instantiate(WorldAnchorPrefab, Vector3.zero, Quaternion.identity); worldAnchorVis.transform.SetParent(WorldAnchorCloud.transform, false); AttachScene(WorldAnchorCloud.gameObject); // disactivate marker tracking, because anchor is loaded from the cloud ActivateTrackableMarkers(false); Notifications.Instance.ShowNotification("Cloud anchor loaded", "Cloud anchor loaded sucessfully"); Calibrated = true; UsingCloudAnchors = true; OnARCalibrated?.Invoke(this, new CalibrationEventArgs(true, WorldAnchorCloud.gameObject)); Notifications.Instance.ShowNotification("Calibration successful", ""); GameManager.Instance.SceneSetActive(true); } //TODO If anchor is not present in the system, play animation to manually calibrate by clicking on marker else { Calibrated = false; OnARCalibrated?.Invoke(this, new CalibrationEventArgs(false, null)); Notifications.Instance.ShowNotification("Calibrate by clicking on the Calibration cube", "Cloud anchor does not exist. Please calibrate manually by clicking on the cube displayed on your marker"); //AttachScene(null, initLocalAnchor: true); ActivateTrackableMarkers(true); } } else { Calibrated = false; OnARCalibrated?.Invoke(this, new CalibrationEventArgs(false, null)); Notifications.Instance.ShowNotification("Calibrate by clicking on the Calibration cube", "Please calibrate manually by clicking on the cube displayed on your marker"); //AttachScene(null, initLocalAnchor: true); ActivateTrackableMarkers(true); } #endif yield return(null); }