/// <summary>
    /// Correct all saved marks when loop closure happens.
    ///
    /// When Tango Service is in learning mode, the drift will accumulate overtime, but when the system sees a
    /// pre-exsiting area, it will do a operation to correct all previously saved poses
    /// (the pose you can query with GetPoseAtTime). This operation is called loop closure. When loop closure happens,
    /// we will need to re-query all previously saved marker position in order to achieve the best result.
    /// This function is doing the querying job based on timestamp.
    /// </summary>
    private void _UpdateMarkersForLoopClosures()
    {
        // Adjust mark's position each time we have a loop closure detected.
        foreach (GameObject obj in m_markerList)
        {
            ARLocationMarker tempMarker = obj.GetComponent <ARLocationMarker>();
            if (tempMarker.m_timestamp != -1.0f)
            {
                TangoCoordinateFramePair pair;
                TangoPoseData            relocalizedPose = new TangoPoseData();

                pair.baseFrame   = TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_AREA_DESCRIPTION;
                pair.targetFrame = TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_DEVICE;
                PoseProvider.GetPoseAtTime(relocalizedPose, tempMarker.m_timestamp, pair);
                Vector3 pDevice = new Vector3((float)relocalizedPose.translation[0],
                                              (float)relocalizedPose.translation[1],
                                              (float)relocalizedPose.translation[2]);
                Quaternion qDevice = new Quaternion((float)relocalizedPose.orientation[0],
                                                    (float)relocalizedPose.orientation[1],
                                                    (float)relocalizedPose.orientation[2],
                                                    (float)relocalizedPose.orientation[3]);

                Matrix4x4 uwTDevice = m_uwTss * Matrix4x4.TRS(pDevice, qDevice, Vector3.one) * m_dTuc;
                Matrix4x4 uwTMarker = uwTDevice * tempMarker.m_deviceTMarker;

                obj.transform.position = uwTMarker.GetColumn(3);
                obj.transform.rotation = Quaternion.LookRotation(uwTMarker.GetColumn(2), uwTMarker.GetColumn(1));
            }
        }
    }
    /// <summary>
    /// Unity OnGUI function.
    ///
    /// Mainly for removing markers.
    /// </summary>
    public void OnGUI()
    {
        if (m_selectedMarker != null)
        {
            Renderer selectedRenderer = m_selectedMarker.GetComponent <Renderer>();

            // GUI's Y is flipped from the mouse's Y
            Rect  screenRect = _WorldBoundsToScreen(Camera.main, selectedRenderer.bounds);
            float yMin       = Screen.height - screenRect.yMin;
            float yMax       = Screen.height - screenRect.yMax;
            screenRect.yMin = Mathf.Min(yMin, yMax);
            screenRect.yMax = Mathf.Max(yMin, yMax);

            if (GUI.Button(screenRect, "<size=30>Hide</size>"))
            {
                m_markerList.Remove(m_selectedMarker.gameObject);
                m_selectedMarker.SendMessage("Hide");
                m_selectedMarker = null;
                m_selectedRect   = new Rect();
            }
            else
            {
                m_selectedRect = screenRect;
            }
        }
        else
        {
            m_selectedRect = new Rect();
        }
    }
    /// <summary>
    /// Update location marker state.
    /// </summary>
    private void _UpdateLocationMarker()
    {
        if (Input.touchCount == 1)
        {
            // Single tap -- place new location or select existing location.
            Touch t = Input.GetTouch(0);
            Vector2 guiPosition = new Vector2(t.position.x, Screen.height - t.position.y);
            Camera cam = Camera.main;
            RaycastHit hitInfo;

            if (t.phase != TouchPhase.Began)
            {
                return;
            }

            if (m_selectedRect.Contains(guiPosition) || m_hideAllRect.Contains(guiPosition))
            {
                // do nothing, the button will handle it
            }
            else if (Physics.Raycast(cam.ScreenPointToRay(t.position), out hitInfo))
            {
                // Found a marker, select it (so long as it isn't disappearing)!
                GameObject tapped = hitInfo.collider.gameObject;
                if (!tapped.GetComponent<Animation>().isPlaying)
                {
                    m_selectedMarker = tapped.GetComponent<ARLocationMarker>();
                }
            }
            else
            {
                // Place a new point at that location, clear selection
                Vector3 planeCenter;
                Plane plane;

                if (!m_pointCloud.FindPlane(cam, t.position, out planeCenter, out plane))
                {
                    return;
                }

                // Ensure the location is always facing the camera.  This is like a LookRotation, but for the Y axis.
                Vector3 up = plane.normal;
                Vector3 forward;
                if (Vector3.Angle(plane.normal, cam.transform.forward) < 175)
                {
                    Vector3 right = Vector3.Cross(up, cam.transform.forward).normalized;
                    forward = Vector3.Cross(right, up).normalized;
                }
                else
                {
                    // Normal is nearly parallel to camera look direction, the cross product would have too much
                    // floating point error in it.
                    forward = Vector3.Cross(up, cam.transform.right);
                }
                Instantiate(m_prefabLocation, planeCenter, Quaternion.LookRotation(forward, up));
                m_selectedMarker = null;
            }
        }
        if (Input.touchCount == 2)
        {
            // Two taps -- toggle debug text
            Touch t0 = Input.GetTouch(0);
            Touch t1 = Input.GetTouch(1);

            if (t0.phase != TouchPhase.Began && t1.phase != TouchPhase.Began)
            {
                return;
            }

            m_showDebug = !m_showDebug;
            return;
        }

        if (Input.touchCount != 1)
        {
            return;
        }
    }
    /// <summary>
    /// Display simple GUI.
    /// </summary>
    public void OnGUI()
    {
        Rect distortionButtonRec = new Rect(UI_BUTTON_GAP_X,
                                            Screen.height - UI_BUTTON_SIZE_Y - UI_BUTTON_GAP_X,
                                            UI_BUTTON_SIZE_X,
                                            UI_BUTTON_SIZE_Y);
        string isOn = m_arCameraPostProcess.enabled ? "Off" : "On";
        if (GUI.Button(distortionButtonRec,
                       UI_FONT_SIZE + "Turn Distortion " + isOn + "</size>"))
        {
            m_arCameraPostProcess.enabled = !m_arCameraPostProcess.enabled;
        }

        if (m_showDebug && m_tangoApplication.HasRequestedPermissions())
        {
            Color oldColor = GUI.color;
            GUI.color = Color.white;

            GUI.color = Color.black;
            GUI.Label(new Rect(UI_LABEL_START_X,
                               UI_LABEL_START_Y,
                               UI_LABEL_SIZE_X,
                               UI_LABEL_SIZE_Y),
                      UI_FONT_SIZE + String.Format(UX_TANGO_SERVICE_VERSION, m_tangoServiceVersion) + "</size>");

            GUI.Label(new Rect(UI_LABEL_START_X,
                               UI_FPS_LABEL_START_Y,
                               UI_LABEL_SIZE_X,
                               UI_LABEL_SIZE_Y),
                      UI_FONT_SIZE + m_fpsText + "</size>");

            // MOTION TRACKING
            GUI.Label(new Rect(UI_LABEL_START_X,
                               UI_POSE_LABEL_START_Y - UI_LABEL_OFFSET,
                               UI_LABEL_SIZE_X,
                               UI_LABEL_SIZE_Y),
                      UI_FONT_SIZE + String.Format(UX_TARGET_TO_BASE_FRAME, "Device", "Start") + "</size>");

            Vector3 pos = m_tangoPose.transform.position;
            Quaternion quat = m_tangoPose.transform.rotation;
            string positionString = pos.x.ToString(UI_FLOAT_FORMAT) + ", " +
                pos.y.ToString(UI_FLOAT_FORMAT) + ", " +
                    pos.z.ToString(UI_FLOAT_FORMAT);
            string rotationString = quat.x.ToString(UI_FLOAT_FORMAT) + ", " +
                quat.y.ToString(UI_FLOAT_FORMAT) + ", " +
                    quat.z.ToString(UI_FLOAT_FORMAT) + ", " +
                    quat.w.ToString(UI_FLOAT_FORMAT);
            string statusString = String.Format(UX_STATUS,
                                                _GetLoggingStringFromPoseStatus(m_tangoPose.m_poseStatus),
                                                _GetLoggingStringFromFrameCount(m_tangoPose.m_poseCount),
                                                positionString, rotationString);
            GUI.Label(new Rect(UI_LABEL_START_X,
                               UI_POSE_LABEL_START_Y,
                               UI_LABEL_SIZE_X,
                               UI_LABEL_SIZE_Y),
                      UI_FONT_SIZE + statusString + "</size>");
            GUI.color = oldColor;
        }

        if (m_selectedMarker != null)
        {
            Renderer selectedRenderer = m_selectedMarker.GetComponent<Renderer>();

            // GUI's Y is flipped from the mouse's Y
            Rect screenRect = WorldBoundsToScreen(Camera.main, selectedRenderer.bounds);
            float yMin = Screen.height - screenRect.yMin;
            float yMax = Screen.height - screenRect.yMax;
            screenRect.yMin = Mathf.Min(yMin, yMax);
            screenRect.yMax = Mathf.Max(yMin, yMax);

            if (GUI.Button(screenRect, "<size=30>Hide</size>"))
            {
                m_selectedMarker.SendMessage("Hide");
                m_selectedMarker = null;
                m_selectedRect = new Rect();
            }
            else
            {
                m_selectedRect = screenRect;
            }
        }
        else
        {
            m_selectedRect = new Rect();
        }

        if (GameObject.FindObjectOfType<ARLocationMarker>() != null)
        {
            m_hideAllRect = new Rect(Screen.width - UI_BUTTON_SIZE_X - UI_BUTTON_GAP_X,
                                     Screen.height - UI_BUTTON_SIZE_Y - UI_BUTTON_GAP_X,
                                     UI_BUTTON_SIZE_X,
                                     UI_BUTTON_SIZE_Y);
            if (GUI.Button(m_hideAllRect, "<size=30>Hide All</size>"))
            {
                foreach (ARLocationMarker marker in GameObject.FindObjectsOfType<ARLocationMarker>())
                {
                    marker.SendMessage("Hide");
                }
            }
        }
        else
        {
            m_hideAllRect = new Rect(0, 0, 0, 0);
        }
    }
Exemple #5
0
    /// <summary>
    /// Update location marker state.
    /// </summary>
    private void _UpdateLocationMarker()
    {
        if (Input.touchCount == 1)
        {
            // Single tap -- place new location or select existing location.
            Touch      t           = Input.GetTouch(0);
            Vector2    guiPosition = new Vector2(t.position.x, Screen.height - t.position.y);
            Camera     cam         = m_arScreen.m_renderCamera;
            RaycastHit hitInfo;

            if (t.phase != TouchPhase.Began)
            {
                return;
            }

            if (m_selectedRect.Contains(guiPosition) || m_hideAllRect.Contains(guiPosition))
            {
                // do nothing, the button will handle it
            }
            else if (Physics.Raycast(cam.ScreenPointToRay(t.position), out hitInfo))
            {
                // Found a marker, select it (so long as it isn't disappearing)!
                GameObject tapped = hitInfo.collider.gameObject;
                if (tapped.GetComponent <ARLocationCharacter>())
                {
                    tapped.GetComponent <ARLocationCharacter>().beDamaged(55);
                }
                else if (tapped.GetComponent <ARLocationSpawnPoint>())
                {
                    tapped.GetComponent <ARLocationSpawnPoint>().beDamaged(55);
                }
                else
                {
                    Vector3 planeCenter;

                    // Ensure the location is always facing the camera.  This is like a LookRotation, but for the Y axis.
                    Vector3 up = new Vector3(0, 1, 0);
                    Vector3 forward;
                    if (Vector3.Angle(up, cam.transform.forward) < 175)
                    {
                        Vector3 right = Vector3.Cross(up, cam.transform.forward).normalized;
                        forward = Vector3.Cross(right, up).normalized;
                    }
                    else
                    {
                        // Normal is nearly parallel to camera look direction, the cross product would have too much
                        // floating point error in it.
                        forward = Vector3.Cross(up, cam.transform.right);
                    }
                    if (mode == MODE.ZOMBIE)
                    {
                        GameObject zombie = Instantiate(m_prefabLocation, hitInfo.point + new Vector3(0, 0.1f, 0), Quaternion.LookRotation(forward * -1, up)) as GameObject;
                        //zombie.GetComponent<Rigidbody>().velocity = (forward * -1 /2);
                    }
                    else if (mode == MODE.COFFIN)
                    {
                        Instantiate(coffin, hitInfo.point, Quaternion.LookRotation(forward * -1, up));
                    }
                    else if (mode == MODE.SHOOT)
                    {
                        GameObject ball = Instantiate(bullet, Camera.main.transform.position - (Camera.main.transform.up * bullet.transform.localScale.y), Quaternion.LookRotation(forward * -1, up)) as GameObject;
                        ball.GetComponent <Rigidbody>().velocity = (Camera.main.transform.forward * 5) + (Camera.main.transform.up * 5 / 2);
                    }
                    m_selectedMarker = null;
                }
            }
            else
            {
                // Place a new point at that location, clear selection
                Vector3 planeCenter;
                Plane   plane;
                if (!m_pointCloud.FindPlane(cam, t.position,
                                            TAP_PIXEL_TOLERANCE, MIN_PLANE_FIT_PERCENTAGE,
                                            out planeCenter, out plane))
                {
                    return;
                }

                // Ensure the location is always facing the camera.  This is like a LookRotation, but for the Y axis.
                Vector3 up = plane.normal;
                Vector3 forward;
                if (Vector3.Angle(plane.normal, cam.transform.forward) < 175)
                {
                    Vector3 right = Vector3.Cross(up, cam.transform.forward).normalized;
                    forward = Vector3.Cross(right, up).normalized;
                }
                else
                {
                    // Normal is nearly parallel to camera look direction, the cross product would have too much
                    // floating point error in it.
                    forward = Vector3.Cross(up, cam.transform.right);
                }
                if (mode == MODE.ZOMBIE)
                {
                    Instantiate(m_prefabLocation, planeCenter, Quaternion.LookRotation(forward * -1, up));
                }
                else if (mode == MODE.COFFIN)
                {
                    Instantiate(coffin, planeCenter, Quaternion.LookRotation(forward * -1, up));
                }
                else if (mode == MODE.SHOOT)
                {
                    GameObject ball = Instantiate(bullet, Camera.main.transform.position - (Camera.main.transform.up * bullet.transform.localScale.y), Quaternion.LookRotation(forward * -1, up)) as GameObject;
                    ball.GetComponent <Rigidbody>().velocity = (Camera.main.transform.forward * 5) + (Camera.main.transform.up * 5 / 2);
                }
                m_selectedMarker = null;
            }
        }
        if (Input.touchCount == 2)
        {
            // Two taps -- toggle debug text
            Touch t0 = Input.GetTouch(0);
            Touch t1 = Input.GetTouch(1);

            if (t0.phase != TouchPhase.Began && t1.phase != TouchPhase.Began)
            {
                return;
            }

            m_showDebug = !m_showDebug;
            return;
        }

        if (Input.touchCount != 1)
        {
            return;
        }
    }
Exemple #6
0
    /// <summary>
    /// Display simple GUI.
    /// </summary>
    public void OnGUI()
    {
        if (m_showDebug && m_tangoApplication.HasRequestedPermissions())
        {
            Color oldColor = GUI.color;
            GUI.color = Color.white;

            GUI.color = Color.black;
            GUI.Label(new Rect(UI_LABEL_START_X,
                               UI_LABEL_START_Y,
                               UI_LABEL_SIZE_X,
                               UI_LABEL_SIZE_Y),
                      UI_FONT_SIZE + String.Format(UX_TANGO_SERVICE_VERSION, m_tangoServiceVersion) + "</size>");

            GUI.Label(new Rect(UI_LABEL_START_X,
                               UI_FPS_LABEL_START_Y,
                               UI_LABEL_SIZE_X,
                               UI_LABEL_SIZE_Y),
                      UI_FONT_SIZE + m_fpsText + "</size>");

            // MOTION TRACKING
            GUI.Label(new Rect(UI_LABEL_START_X,
                               UI_POSE_LABEL_START_Y - UI_LABEL_OFFSET,
                               UI_LABEL_SIZE_X,
                               UI_LABEL_SIZE_Y),
                      UI_FONT_SIZE + String.Format(UX_TARGET_TO_BASE_FRAME, "Device", "Start") + "</size>");

            Vector3    pos            = m_arScreen.transform.position;
            Quaternion quat           = m_arScreen.transform.rotation;
            string     positionString = pos.x.ToString(UI_FLOAT_FORMAT) + ", " +
                                        pos.y.ToString(UI_FLOAT_FORMAT) + ", " +
                                        pos.z.ToString(UI_FLOAT_FORMAT);
            string rotationString = quat.x.ToString(UI_FLOAT_FORMAT) + ", " +
                                    quat.y.ToString(UI_FLOAT_FORMAT) + ", " +
                                    quat.z.ToString(UI_FLOAT_FORMAT) + ", " +
                                    quat.w.ToString(UI_FLOAT_FORMAT);
            string statusString = String.Format(UX_STATUS,
                                                _GetLoggingStringFromPoseStatus(m_arScreen.m_status),
                                                _GetLoggingStringFromFrameCount(m_arScreen.m_frameCount),
                                                positionString, rotationString);
            GUI.Label(new Rect(UI_LABEL_START_X,
                               UI_POSE_LABEL_START_Y,
                               UI_LABEL_SIZE_X,
                               UI_LABEL_SIZE_Y),
                      UI_FONT_SIZE + statusString + "</size>");
            GUI.color = oldColor;
        }

        if (m_selectedMarker != null)
        {
            Renderer selectedRenderer = m_selectedMarker.GetComponent <Renderer>();

            // GUI's Y is flipped from the mouse's Y
            Rect  screenRect = WorldBoundsToScreen(Camera.main, selectedRenderer.bounds);
            float yMin       = Screen.height - screenRect.yMin;
            float yMax       = Screen.height - screenRect.yMax;
            screenRect.yMin = Mathf.Min(yMin, yMax);
            screenRect.yMax = Mathf.Max(yMin, yMax);

            if (GUI.Button(screenRect, "<size=30>Hide</size>"))
            {
                m_selectedMarker.SendMessage("Hide");
                m_selectedMarker = null;
                m_selectedRect   = new Rect();
            }
            else
            {
                m_selectedRect = screenRect;
            }
        }
        else
        {
            m_selectedRect = new Rect();
        }

        if (GameObject.FindObjectOfType <ARLocationMarker>() != null)
        {
            m_hideAllRect = new Rect(Screen.width - UI_BUTTON_SIZE_X - UI_BUTTON_GAP_X,
                                     Screen.height - UI_BUTTON_SIZE_Y - UI_BUTTON_GAP_X,
                                     UI_BUTTON_SIZE_X,
                                     UI_BUTTON_SIZE_Y);
            if (GUI.Button(m_hideAllRect, "<size=30>Hide All</size>"))
            {
                foreach (ARLocationMarker marker in GameObject.FindObjectsOfType <ARLocationMarker>())
                {
                    marker.SendMessage("Hide");
                }
            }
        }
        else
        {
            m_hideAllRect = new Rect(0, 0, 0, 0);
        }
    }
Exemple #7
0
    /// <summary>
    /// Update location marker state.
    /// </summary>
    private void _UpdateLocationMarker()
    {
        if (Input.touchCount == 1)
        {
            // Single tap -- place new location or select existing location.
            Touch      t           = Input.GetTouch(0); // first finger
            Vector2    guiPosition = new Vector2(t.position.x, Screen.height - t.position.y);
            Camera     cam         = m_arScreen.m_renderCamera;
            RaycastHit hitInfo;

            if (t.phase != TouchPhase.Began)
            {
                return;
            }

            if (m_selectedRect.Contains(guiPosition) || m_hideAllRect.Contains(guiPosition))
            {
                // do nothing, the button will handle it
            }

            else if (Physics.Raycast(cam.ScreenPointToRay(t.position), out hitInfo))
            {
                // Found a marker, select it (so long as it isn't disappearing)!
                GameObject tapped = hitInfo.collider.gameObject;
                if (!tapped.GetComponent <Animation>().isPlaying)
                {
                    m_selectedMarker = tapped.GetComponent <ARLocationMarker>();
                }
            }
            else
            {
                // Place a new point at that location, clear selection
                Vector3 planeCenter;
                Plane   plane;
                if (!m_pointCloud.FindPlane(cam, t.position,
                                            TAP_PIXEL_TOLERANCE, MIN_PLANE_FIT_PERCENTAGE,
                                            out planeCenter, out plane))
                {
                    return;
                }

                // Ensure the location is always facing the camera.  This is like a LookRotation, but for the Y axis.
                Vector3 up = plane.normal;
                Vector3 forward;
                if (Vector3.Angle(plane.normal, cam.transform.forward) < 175)
                {
                    Vector3 right = Vector3.Cross(up, cam.transform.forward).normalized;
                    forward = Vector3.Cross(right, up).normalized;
                }
                else
                {
                    // Normal is nearly parallel to camera look direction, the cross product would have too much
                    // floating point error in it.
                    forward = Vector3.Cross(up, cam.transform.right);
                }
                if (!portalMade)
                {
                    Instructs.gameObject.SetActive(false);
                    portalMade = true;
                    portal.transform.position = planeCenter;
                    portal.SetActive(true);
                }
                m_selectedMarker = null;
            }
        }
        if (Input.touchCount == 2)
        {
            // Two taps -- toggle debug text
            Touch t0 = Input.GetTouch(0);
            Touch t1 = Input.GetTouch(1);

            if (t0.phase != TouchPhase.Began && t1.phase != TouchPhase.Began)
            {
                return;
            }

            m_showDebug = !m_showDebug;
            return;
        }

        if (Input.touchCount != 1)
        {
            return;
        }
    }
    /// <summary>
    /// Unity Update function.
    /// 
    /// Mainly handle the touch event and place mark in place.
    /// </summary>
    public void Update()
    {
        if (m_saveThread != null && m_saveThread.ThreadState != ThreadState.Running)
        {
            // After saving an Area Description or mark data, we reload the scene to restart the game.
            Application.LoadLevel(Application.loadedLevel);
        }

        if (!m_initialized)
        {
            return;
        }
        if (EventSystem.current.IsPointerOverGameObject(0) || GUIUtility.hotControl != 0)
        {
            return;
        }

        if (Input.touchCount == 1)
        {
            Touch t = Input.GetTouch(0);
            Vector2 guiPosition = new Vector2(t.position.x, Screen.height - t.position.y);
            Camera cam = Camera.main;
            RaycastHit hitInfo;

            if (m_selectedRect.Contains(guiPosition))
            {
                // do nothing, the button will handle it.
            }
            else if (Physics.Raycast(cam.ScreenPointToRay(t.position), out hitInfo))
            {
                if (t.phase == TouchPhase.Began)
                {
                    GameObject tapped = hitInfo.collider.gameObject;
                    if (tapped.tag != "Ground")
                    {
                        if (!tapped.GetComponent<Animation>().isPlaying)
                        {
                            m_selectedMarker = tapped.GetComponent<ARLocationMarker>();
                        }
                    }
                    else
                    {
                        // Instantiate marker object.
                        newMarkObject = Instantiate(m_markPrefabs[m_currentMarkType],
                                                    hitInfo.point,
                                                    Quaternion.identity) as GameObject;
                        ARLocationMarker markerScript = newMarkObject.GetComponent<ARLocationMarker>();

                        markerScript.m_type = m_currentMarkType;
                        markerScript.m_timestamp = m_deltaPoseController.m_poseTimestamp;

                        Matrix4x4 uwTDevice = Matrix4x4.TRS(m_deltaPoseController.m_tangoPosition,
                                                            m_deltaPoseController.m_tangoRotation,
                                                            Vector3.one);
                        Matrix4x4 uwTMarker = Matrix4x4.TRS(hitInfo.point,
                                                            Quaternion.identity,
                                                            Vector3.one);
                        markerScript.m_deviceTMarker = Matrix4x4.Inverse(uwTDevice) * uwTMarker;

                        m_markerList.Add(newMarkObject);
                    }
                }
                else if (t.phase == TouchPhase.Moved)
                {
                    // Move instantiate object
                    if (newMarkObject != null)
                    {
                        newMarkObject.transform.position = hitInfo.point;
                    }
                }
                else if (t.phase == TouchPhase.Ended)
                {
                    newMarkObject = null;
                }
            }
        }
    }
    /// <summary>
    /// Unity OnGUI function.
    /// 
    /// Mainly for removing markers.
    /// </summary>
    public void OnGUI()
    {
        if (m_selectedMarker != null)
        {
            Renderer selectedRenderer = m_selectedMarker.GetComponent<Renderer>();

            // GUI's Y is flipped from the mouse's Y
            Rect screenRect = _WorldBoundsToScreen(Camera.main, selectedRenderer.bounds);
            float yMin = Screen.height - screenRect.yMin;
            float yMax = Screen.height - screenRect.yMax;
            screenRect.yMin = Mathf.Min(yMin, yMax);
            screenRect.yMax = Mathf.Max(yMin, yMax);

            if (GUI.Button(screenRect, "<size=30>Hide</size>"))
            {
                m_markerList.Remove(m_selectedMarker.gameObject);
                m_selectedMarker.SendMessage("Hide");
                m_selectedMarker = null;
                m_selectedRect = new Rect();
            }
            else
            {
                m_selectedRect = screenRect;
            }
        }
        else
        {
            m_selectedRect = new Rect();
        }
    }
    /// <summary>
    /// Update location marker state.
    /// </summary>
    private void _UpdateLocationMarker()
    {
        if (Input.touchCount == 1)
        {
            // Single tap -- place new location or select existing location.
            Touch      t           = Input.GetTouch(0);
            Vector2    guiPosition = new Vector2(t.position.x, Screen.height - t.position.y);
            Camera     cam         = m_arScreen.m_renderCamera;
            RaycastHit hitInfo;

            if (t.phase != TouchPhase.Began)
            {
                return;
            }

            if (m_selectedRect.Contains(guiPosition) || m_hideAllRect.Contains(guiPosition))
            {
                // do nothing, the button will handle it
            }
            else if (Physics.Raycast(cam.ScreenPointToRay(t.position), out hitInfo))
            {
                // Found a marker, select it (so long as it isn't disappearing)!
                GameObject tapped = hitInfo.collider.gameObject;
                if (!tapped.GetComponent <Animation>().isPlaying)
                {
                    m_selectedMarker = tapped.GetComponent <ARLocationMarker>();
                }
            }
            else
            {
                // Place a new point at that location, clear selection
                Vector3 planeCenter;
                Plane   plane;
                if (!m_pointCloud.FindPlane(cam, t.position,
                                            TAP_PIXEL_TOLERANCE, MIN_PLANE_FIT_PERCENTAGE,
                                            out planeCenter, out plane))
                {
                    return;
                }
                Instantiate(m_prefabLocation, planeCenter, Quaternion.FromToRotation(Vector3.up, plane.normal));
                m_selectedMarker = null;
            }
        }
        if (Input.touchCount == 2)
        {
            // Two taps -- toggle debug text
            Touch t0 = Input.GetTouch(0);
            Touch t1 = Input.GetTouch(1);

            if (t0.phase != TouchPhase.Began && t1.phase != TouchPhase.Began)
            {
                return;
            }

            m_showDebug = !m_showDebug;
            return;
        }

        if (Input.touchCount != 1)
        {
            return;
        }
    }
    /// <summary>
    /// Unity Update function.
    ///
    /// Mainly handle the touch event and place mark in place.
    /// </summary>
    public void Update()
    {
        if (m_saveThread != null && m_saveThread.ThreadState != ThreadState.Running)
        {
            // After saving an Area Description or mark data, we reload the scene to restart the game.
            Application.LoadLevel(Application.loadedLevel);
        }

        if (!m_initialized)
        {
            return;
        }
        if (EventSystem.current.IsPointerOverGameObject(0) || GUIUtility.hotControl != 0)
        {
            return;
        }

        if (Input.touchCount == 1)
        {
            Touch      t           = Input.GetTouch(0);
            Vector2    guiPosition = new Vector2(t.position.x, Screen.height - t.position.y);
            Camera     cam         = Camera.main;
            RaycastHit hitInfo;

            if (m_selectedRect.Contains(guiPosition))
            {
                // do nothing, the button will handle it.
            }
            else if (Physics.Raycast(cam.ScreenPointToRay(t.position), out hitInfo))
            {
                if (t.phase == TouchPhase.Began)
                {
                    GameObject tapped = hitInfo.collider.gameObject;
                    if (tapped.tag != "Ground")
                    {
                        if (!tapped.GetComponent <Animation>().isPlaying)
                        {
                            m_selectedMarker = tapped.GetComponent <ARLocationMarker>();
                        }
                    }
                    else
                    {
                        // Instantiate marker object.
                        newMarkObject = Instantiate(m_markPrefabs[m_currentMarkType],
                                                    hitInfo.point,
                                                    Quaternion.identity) as GameObject;
                        ARLocationMarker markerScript = newMarkObject.GetComponent <ARLocationMarker>();

                        markerScript.m_type      = m_currentMarkType;
                        markerScript.m_timestamp = m_deltaPoseController.m_poseTimestamp;

                        Matrix4x4 uwTDevice = Matrix4x4.TRS(m_deltaPoseController.m_tangoPosition,
                                                            m_deltaPoseController.m_tangoRotation,
                                                            Vector3.one);
                        Matrix4x4 uwTMarker = Matrix4x4.TRS(hitInfo.point,
                                                            Quaternion.identity,
                                                            Vector3.one);
                        markerScript.m_deviceTMarker = Matrix4x4.Inverse(uwTDevice) * uwTMarker;

                        m_markerList.Add(newMarkObject);
                    }
                }
                else if (t.phase == TouchPhase.Moved)
                {
                    // Move instantiate object
                    if (newMarkObject != null)
                    {
                        newMarkObject.transform.position = hitInfo.point;
                    }
                }
                else if (t.phase == TouchPhase.Ended)
                {
                    newMarkObject = null;
                }
            }
        }
    }
    /// <summary>
    /// Update location marker state.
    /// </summary>
    private void _UpdateLocationMarker()
    {
        if (Input.touchCount == 1)
        {
            // Single tap -- place new location or select existing location.
            Touch t = Input.GetTouch(0);
            Vector2 guiPosition = new Vector2(t.position.x, Screen.height - t.position.y);
            Camera cam = m_arScreen.m_renderCamera;
            RaycastHit hitInfo;

            if (t.phase != TouchPhase.Began)
            {
                return;
            }

            if (m_selectedRect.Contains(guiPosition) || m_hideAllRect.Contains(guiPosition))
            {
                // do nothing, the button will handle it
            }
            else if (Physics.Raycast(cam.ScreenPointToRay(t.position), out hitInfo))
            {
                // Found a marker, select it (so long as it isn't disappearing)!
                GameObject tapped = hitInfo.collider.gameObject;
                if (!tapped.GetComponent<Animation>().isPlaying)
                {
                    m_selectedMarker = tapped.GetComponent<ARLocationMarker>();
                }
            }
            else
            {
                // Place a new point at that location, clear selection
                Vector3 planeCenter;
                Plane plane;
                if (!m_pointCloud.FindPlane(cam, t.position,
                                            TAP_PIXEL_TOLERANCE, MIN_PLANE_FIT_PERCENTAGE,
                                            out planeCenter, out plane))
                {
                    return;
                }
                Instantiate(m_prefabLocation, planeCenter, Quaternion.FromToRotation(Vector3.up, plane.normal));
                m_selectedMarker = null;
            }
        }
        if (Input.touchCount == 2)
        {
            // Two taps -- toggle debug text
            Touch t0 = Input.GetTouch(0);
            Touch t1 = Input.GetTouch(1);

            if (t0.phase != TouchPhase.Began && t1.phase != TouchPhase.Began)
            {
                return;
            }

            m_showDebug = !m_showDebug;
            return;
        }

        if (Input.touchCount != 1)
        {
            return;
        }
    }