C API wrapper for the Tango area description interface.
Esempio n. 1
0
        /// <summary>
        /// Raise a Tango Area Description event if there is new data.
        /// </summary>
        internal static void SendIfAvailable()
        {
            if (!m_isCallbackSet)
            {
                return;
            }

            if (m_onTangoAreaDescriptionExported != null && m_onTangoAreaDescriptionImported != null)
            {
                lock (m_lockObject)
                {
                    if (m_isImportFinished)
                    {
                        m_onTangoAreaDescriptionImported(m_isSuccessful, AreaDescription.ForUUID(m_eventString));
                        m_isImportFinished = false;
                        m_eventString      = string.Empty;
                    }

                    if (m_isExportFinished)
                    {
                        m_onTangoAreaDescriptionExported(m_isSuccessful);
                        m_isExportFinished = false;
                    }
                }
            }
        }
        /// <summary>
        /// Inits the emulation for a given area description UUID and set of Tango Application settings.
        /// </summary>
        /// <param name="uuid">UUID of the Area Description that
        /// TangoApplication.Startup() was called with.</param>
        /// <param name="haveAreaDescriptionPermissions">If set to <c>true</c>, assume area description
        /// permissions have been requested and 'granted'.</param>
        /// <param name="learningMode">If set to <c>true</c>, service is in learning mode.</param>
        /// <param name="artificialOffset">Artificial offset fom Start of Service to Area Description.</param>
        public static void InitEmulationForUUID(string uuid, bool haveAreaDescriptionPermissions,
                                                bool learningMode, Vector3 artificialOffset)
        {
            m_usingEmulatedDescriptionFrames = false;
            m_currentUUID = uuid;

            if (haveAreaDescriptionPermissions)
            {
                if (!string.IsNullOrEmpty(uuid))
                {
                    if (AreaDescription.ForUUID(uuid).GetMetadata() != null)
                    {
                        m_usingEmulatedDescriptionFrames = true;
                    }
                    else
                    {
                        m_currentUUID = string.Empty;
                        Debug.LogError("Requested Area Description UUID does not exist.");
                    }
                }
                else if (learningMode)
                {
                    m_usingEmulatedDescriptionFrames = true;
                }
            }

            m_emulationAreaOffset = artificialOffset;
        }
Esempio n. 3
0
        /// <summary>
        /// Saves the current area description, returning the area description saved.
        ///
        /// You can only save an area description while connected to the Tango Service and if you have enabled Area
        /// Learning mode. If you loaded an ADF before connecting, then calling this method appends any new learned
        /// areas to that ADF and returns the same UUID. If you did not load an ADF, this method creates a new ADF and
        /// a new UUID for that ADF.
        /// </summary>
        /// <returns>
        /// AreaDescription instance for the newly saved area description if saved successfully, <c>null</c> otherwise.
        ///
        /// See logcat for details of why the saved failed.
        /// </returns>
        public static AreaDescription SaveCurrent()
        {
            byte[] rawUUID = new byte[Common.UUID_LENGTH];
            if (AreaDescriptionAPI.TangoService_saveAreaDescription(rawUUID) != Common.ErrorType.TANGO_SUCCESS)
            {
                Debug.Log("Could not save area description.\n" + Environment.StackTrace);
                return(null);
            }

            string uuid = Encoding.UTF8.GetString(rawUUID);

            return(AreaDescription.ForUUID(uuid));
        }
        /// <summary>
        /// Get a list of all the area descriptions on the device.
        /// </summary>
        /// <returns>A list of area descriptions, or <c>null</c> if the list could not be queried.</returns>
        public static AreaDescription[] GetList()
        {
            string[] uuids = _GetUUIDList();
            if (uuids == null || uuids.Length == 0)
            {
                return(null);
            }

            AreaDescription[] adfs = new AreaDescription[uuids.Length];
            for (int it = 0; it < uuids.Length; ++it)
            {
                adfs[it] = new AreaDescription(uuids[it]);
            }

            return(adfs);
        }
Esempio n. 5
0
 /// <summary>
 /// Raise a Tango Area Description event if there is new data.
 /// </summary>
 internal void SendEventIfAvailable()
 {
     if (OnTangoAreaDescriptionExported != null && OnTangoAreaDescriptionImported != null)
     {
         lock (m_lockObject)
         {
             if (m_isImportFinished)
             {
                 OnTangoAreaDescriptionImported(m_isSuccessful, AreaDescription.ForUUID(m_eventString));
                 m_isImportFinished = false;
                 m_eventString      = string.Empty;
             }
             if (m_isExportFinished)
             {
                 OnTangoAreaDescriptionExported(m_isSuccessful);
                 m_isExportFinished = false;
             }
         }
     }
 }
 /// <summary>
 /// Called every time an Area Description toggle changes state.
 /// </summary>
 /// <param name="areaDescription">Area Description the toggle is for.</param>
 /// <param name="value">The new state of the toggle.</param>
 private void _OnAreaDescriptionToggleChanged(AreaDescription areaDescription, bool value)
 {
     if (value)
     {
         _SelectAreaDescription(areaDescription);
     }
     else
     {
         _SelectAreaDescription(null);
     }
 }
    /// <summary>
    /// Actually do the Area description export.
    /// 
    /// This runs over multiple frames, so a Unity coroutine is used.
    /// </summary>
    /// <returns>Coroutine IEnumerator.</returns>
    /// <param name="areaDescription">Area Description to export.</param>
    private IEnumerator _DoExportAreaDescription(AreaDescription areaDescription)
    {
        if (TouchScreenKeyboard.visible)
        {
            yield break;
        }

        TouchScreenKeyboard kb = TouchScreenKeyboard.Open("/sdcard/", TouchScreenKeyboardType.Default, false);
        while (!kb.done && !kb.wasCanceled)
        {
            yield return null;
        }

        if (kb.done)
        {
            areaDescription.ExportToFile(kb.text);
        }
    }
 /// <summary>
 /// Callback function when toggle button is selected.
 /// </summary>
 /// <param name="item">Caller item object.</param>
 /// <param name="value">Selected value of the toggle button.</param>
 private void _OnToggleChanged(AreaDescription item, bool value)
 {
     if (value)
     {
         Globals.m_curAreaDescription = item;
     }
 }
Esempio n. 9
0
        /// <summary>
        /// Manual initalization step 2: Call this to connect to the Tango service.
        /// 
        /// After connecting to the Tango service, you will get updates for Motion Tracking, Depth Sensing, and Area
        /// Learning.  If you have a specific Area Description you want to localize too, pass that Area Description in
        /// here.
        /// </summary>
        /// <param name="areaDescription">If not null, the Area Description to localize to.</param>
        public void Startup(AreaDescription areaDescription)
        {
            // Make sure all required permissions have been granted.
            if (m_requiredPermissions != PermissionsTypes.NONE)
            {
                Debug.Log("TangoApplication.Startup() -- ERROR: Not all required permissions were accepted yet.");
                return;
            }

            _CheckTangoVersion();

            if (m_enableVideoOverlay && m_useExperimentalVideoOverlay)
            {
                int yTextureWidth = 0;
                int yTextureHeight = 0;
                int uvTextureWidth = 0;
                int uvTextureHeight = 0;
                
                m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_Y_TEXTURE_WIDTH, ref yTextureWidth);
                m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_Y_TEXTURE_HEIGHT, ref yTextureHeight);
                m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_UV_TEXTURE_WIDTH, ref uvTextureWidth);
                m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_UV_TEXTURE_HEIGHT, ref uvTextureHeight);
                
                if (yTextureWidth == 0 || yTextureHeight == 0 || uvTextureWidth == 0 || uvTextureHeight == 0)
                {
                    Debug.Log("Video overlay texture sizes were not set properly");
                }
                
                m_yuvTexture.ResizeAll(yTextureWidth, yTextureHeight, uvTextureWidth, uvTextureHeight);
            }

            if (areaDescription != null)
            {
                _InitializeMotionTracking(areaDescription.m_uuid);
            }
            else
            {
                _InitializeMotionTracking(null);
            }

            if (m_tangoConfig.SetBool(TangoConfig.Keys.ENABLE_DEPTH_PERCEPTION_BOOL, m_enableDepth) && m_enableDepth)
            {
                _SetDepthCallbacks();
            }

            if (m_enableVideoOverlay)
            {
                _SetVideoOverlayCallbacks();
            }

            _SetEventCallbacks();

            _TangoConnect();
        }
Esempio n. 10
0
        /// <summary>
        /// Get a list of all the area descriptions on the device.
        /// </summary>
        /// <returns>A list of area descriptions, or <c>null</c> if the list could not be queried.</returns>
        public static AreaDescription[] GetList()
        {
            string[] uuids = _GetUUIDList();
            if (uuids == null || uuids.Length == 0)
            {
                return null;
            }

            AreaDescription[] adfs = new AreaDescription[uuids.Length];
            for (int it = 0; it < uuids.Length; ++it)
            {
                adfs[it] = new AreaDescription(uuids[it]);
            }

            return adfs;
        }
Esempio n. 11
0
    /// <summary>
    /// Actually do the Area Description save.
    /// </summary>
    /// <returns>Coroutine IEnumerator.</returns>
    private IEnumerator _DoSaveCurrentAreaDescription()
    {
        if (TouchScreenKeyboard.visible || m_saveThread != null)
        {
            yield break;
        }
        
        TouchScreenKeyboard kb = TouchScreenKeyboard.Open("Unnamed");
        while (!kb.done && !kb.wasCanceled)
        {
            yield return null;
        }

        if (kb.done)
        {
            // Disable interaction before saving.
            m_initialized = false;
            m_savingText.gameObject.SetActive(true);
            if (m_tangoApplication.m_enableAreaLearning)
            {
                m_saveThread = new Thread(delegate()
                {
                    // Start saving process in another thread.
                    m_curAreaDescription = AreaDescription.SaveCurrent();
                    AreaDescription.Metadata metadata = m_curAreaDescription.GetMetadata();
                    metadata.m_name = kb.text;
                    m_curAreaDescription.SaveMetadata(metadata);
                });
                m_saveThread.Start();
            }
            else
            {
                _SaveMarkerToDisk();
                Application.LoadLevel(Application.loadedLevel);
            }
        }
    }
 /// <summary>
 /// Callback function when toggle button is selected.
 /// </summary>
 /// <param name="item">Caller item object.</param>
 /// <param name="value">Selected value of the toggle button.</param>
 private void _OnToggleChanged(AreaDescription item, bool value)
 {
     if (value)
     {
         m_savedUUID = item.m_uuid;
         m_createSelectedButton.interactable = true;
         if (File.Exists(m_meshSavePath + "/" + item.m_uuid))
         {
             m_startGameButton.interactable = true;
         }
         else
         {
             m_startGameButton.interactable = false;
         }
     }
     else
     {
         m_savedUUID = null;
         m_createSelectedButton.interactable = false;
         m_startGameButton.interactable = false;
     }
 }
 /// <summary>
 /// This is called when the Area Description import operation completes.
 /// 
 /// Please note that the Tango Service can only load Area Description file from internal storage.
 /// </summary>
 /// <param name="isSuccessful">If the import operation completed successfully.</param>
 /// <param name="areaDescription">The imported Area Description.</param>
 public void OnAreaDescriptionImported(bool isSuccessful, AreaDescription areaDescription)
 {
     if (!isSuccessful)
     {
         AndroidHelper.ShowAndroidToastMessage("Area Description import failed, unable to join game.");
         _QuitGame();
         return;
     }
     
     // Only non-master client will run this part of code.
     m_loadedAreaDescription = areaDescription;
     m_tangoApplication.Startup(m_loadedAreaDescription);
     _StartPlayer();
 }
        /// <summary>
        /// Saves the current area description, returning the area description saved.
        ///
        /// You can only save an area description while connected to the Tango Service and if you have enabled Area
        /// Learning mode. If you loaded an area description before connecting, then calling this method appends any
        /// new learned areas to that area description and returns an area description with the same UUID. If you did
        /// not load an area description, this method creates a new area description and a new UUID for that area
        /// description.
        /// </summary>
        /// <returns>
        /// AreaDescription instance for the newly saved area description if saved successfully, <c>null</c> otherwise.
        ///
        /// See logcat for details of why a saved failed.
        /// </returns>
        public static AreaDescription SaveCurrent()
        {
#if UNITY_EDITOR
            if (!EmulatedAreaDescriptionHelper.m_usingEmulatedDescriptionFrames)
            {
                Debug.LogError("Error in Area Description save emulation:\nNo current emulated area description.");
                return(null);
            }

            // If we don't have an existing UUID, this is a 'new' Area Description, so we'll have to create it.
            if (string.IsNullOrEmpty(EmulatedAreaDescriptionHelper.m_currentUUID))
            {
                // Just use a .net GUID for the UUID.
                string uuid = Guid.NewGuid().ToString();

                EmulatedAreaDescriptionHelper.m_currentUUID = uuid;

                try
                {
                    Directory.CreateDirectory(EMULATED_ADF_SAVE_PATH);

                    using (StreamWriter streamWriter =
                               new StreamWriter(File.Open(EMULATED_ADF_SAVE_PATH + uuid + EMULATED_ADF_EXTENSION,
                                                          FileMode.Create)))
                    {
                        Metadata metadata = new Metadata();
                        metadata.m_name     = "Unnamed";
                        metadata.m_dateTime = DateTime.Now;
                        metadata.m_transformationPosition = new double[3];
                        metadata.m_transformationRotation = new double[] { 0, 0, 0, 1 };
                        metadataXmlSerializer.Serialize(streamWriter, metadata);
                    }
                }
                catch (IOException ioException)
                {
                    Debug.LogError("IO error in Area Description save/load emulation:\n"
                                   + ioException.Message);
                    return(null);
                }

                return(AreaDescription.ForUUID(uuid));
            }
            else
            {
                // Since we don't actually save any description of the area in emulation,
                // if we're using an existing UUID, we don't have to do anything but return it.
                return(AreaDescription.ForUUID(EmulatedAreaDescriptionHelper.m_currentUUID));
            }
#else
            byte[] rawUUID = new byte[Common.UUID_LENGTH];
            if (AreaDescriptionAPI.TangoService_saveAreaDescription(rawUUID) != Common.ErrorType.TANGO_SUCCESS)
            {
                Debug.Log("Could not save area description.\n" + Environment.StackTrace);
                return(null);
            }

            // Don't want to include the null terminator in the C# string.
            string uuid = Encoding.UTF8.GetString(rawUUID, 0, Common.UUID_LENGTH - 1);

            return(AreaDescription.ForUUID(uuid));
#endif
        }
        /// <summary>
        /// Manual initalization step 2: Call this to connect to the Tango service.
        /// 
        /// After connecting to the Tango service, you will get updates for Motion Tracking, Depth Sensing, and Area
        /// Learning.  If you have a specific Area Description you want to localize too, pass that Area Description in
        /// here.
        /// </summary>
        /// <param name="areaDescription">If not null, the Area Description to localize to.</param>
        public void Startup(AreaDescription areaDescription)
        {
            // Make sure all required permissions have been granted.
            if (m_requiredPermissions != PermissionsTypes.NONE)
            {
                Debug.Log("TangoApplication.Startup() -- ERROR: Not all required permissions were accepted yet.");
                return;
            }

            InitApplication();
            if (areaDescription != null)
            {
                InitProviders(areaDescription.m_uuid);
            }
            else
            {
                InitProviders(null);
            }
            ConnectToService();
        }
    /// <summary>
    /// Thread method to save an Area Description and marker data.  Make this the ThreadFunc.
    /// </summary>
    /// <param name="xmlDataList">The marker's data list.</param>
    private void _AsyncDataSaving(List<MarkerData> xmlDataList)
    {
        if (xmlDataList == null)
        {
            Debug.Log("AndroidInGameController._AsyncDataSaving(): xmlDataList is null");
        }

        if (m_tangoApplication.m_enableAreaLearning)
        {
            m_curAreaDescription = AreaDescription.SaveCurrent();
        }
        _WriteToXml(m_curAreaDescription.m_uuid + ".xml", xmlDataList);
    }
    /// <summary>
    /// Actually do the Area Description save.
    /// </summary>
    /// <returns>Coroutine IEnumerator.</returns>
    private IEnumerator _DoSaveAreaDescriptionAndMesh()
    {
        if (m_saveThread != null)
        {
            yield break;
        }

        // Disable interaction before saving.
        m_initialized = false;
        m_savingText.text = "Saving Area Description...";

        if (string.IsNullOrEmpty(m_savedUUID)) 
        {
            m_saveThread = new Thread(delegate()
            {
                // Save the Area Description to file.
                m_curAreaDescription = AreaDescription.SaveCurrent();
                AreaDescription.Metadata metadata = m_curAreaDescription.GetMetadata();
                m_savedUUID = m_curAreaDescription.m_uuid;    
                metadata.m_name = metadata.m_dateTime.ToLongTimeString();
                m_curAreaDescription.SaveMetadata(metadata);

                // Save the tango dynamic mesh to file.
                StartCoroutine(_DoSaveTangoDynamicMesh());
            });
            m_saveThread.Start();
        }
        else
        {
            StartCoroutine(_DoSaveTangoDynamicMesh());
        }
    }
    /// <summary>
    /// Select a specific Area Description to show details.
    /// </summary>
    /// <param name="areaDescription">Area Description to show details for, or <c>null</c> if details should be hidden.</param>
    private void _SelectAreaDescription(AreaDescription areaDescription)
    {
        m_selectedAreaDescription = areaDescription;

        if (areaDescription != null)
        {
            m_selectedMetadata = areaDescription.GetMetadata();
            m_detailsParent.gameObject.SetActive(true);

            m_detailsDate.text = m_selectedMetadata.m_dateTime.ToLongDateString() + ", " + m_selectedMetadata.m_dateTime.ToLongTimeString();

            m_detailsEditableName.text = m_selectedMetadata.m_name;
            m_detailsEditablePosX.text = m_selectedMetadata.m_transformationPosition[0].ToString();
            m_detailsEditablePosY.text = m_selectedMetadata.m_transformationPosition[1].ToString();
            m_detailsEditablePosZ.text = m_selectedMetadata.m_transformationPosition[2].ToString();
            m_detailsEditableRotQX.text = m_selectedMetadata.m_transformationRotation[0].ToString();
            m_detailsEditableRotQY.text = m_selectedMetadata.m_transformationRotation[1].ToString();
            m_detailsEditableRotQZ.text = m_selectedMetadata.m_transformationRotation[2].ToString();
            m_detailsEditableRotQW.text = m_selectedMetadata.m_transformationRotation[3].ToString();
        }
        else
        {
            m_selectedMetadata = null;
            m_detailsParent.gameObject.SetActive(false);
        }
    }
    /// <summary>
    /// From button press: start creating a mesh for occlusion.
    /// 
    /// If an Area Description has been selected, use it and link it to the dynamic mesh.
    /// If no Area Description selected, create one while meshing.
    /// </summary>
    /// <param name="createNew">If set to <c>true</c> create new mesh and new Area Description.</param>
    public void Button_CreateAreaDescriptionMesh(bool createNew)
    {
        m_3dReconstruction = true;
        m_menuOpen = false;

        // Enable the pose controller, but disable the AR screen.
        m_arPoseController.gameObject.SetActive(true);
        m_arPoseController.gameObject.GetComponent<TangoARScreen>().enabled = false;

        // Need to enable depth to build the mesh.
        m_tangoApplication.m_enableDepth = true;

        // Set UI panel to the mesh construction panel.
        m_areaDescriptionLoaderPanel.SetActive(false);
        m_meshBuildPanel.SetActive(true);
        m_meshInteractionPanel.SetActive(false);

        // Initialize tango application and pose controller depending on whether Area Description has been selected.
        if (createNew)
        {
            m_curAreaDescription = null;
            m_tangoApplication.m_areaDescriptionLearningMode = true;
            m_arPoseController.m_useAreaDescriptionPose = false;
            m_relocalizeImage.gameObject.SetActive(false);
            m_tangoApplication.Startup(null);
        }
        else
        {
            if (!string.IsNullOrEmpty(m_savedUUID))
            {
                m_curAreaDescription = AreaDescription.ForUUID(m_savedUUID);
                m_tangoApplication.m_areaDescriptionLearningMode = false;
                m_arPoseController.m_useAreaDescriptionPose = true;
                m_relocalizeImage.gameObject.SetActive(true);
                m_tangoApplication.Startup(m_curAreaDescription);
            }
            else
            {
                Debug.LogError("No Area Description loaded.");
            }
        }
    }
    /// <summary>
    /// Called when entering a room (by creating or joining it). Called on all clients (including the Master Client).
    /// </summary>
    /// <remarks>This method is commonly used to instantiate player characters.
    /// If a match has to be started "actively", you can call an [PunRPC](@ref PhotonView.RPC) triggered by a user's
    /// button-press or a timer.
    /// 
    /// When this is called, you can usually already access the existing players in the room via 
    /// PhotonNetwork.playerList. Also, all custom properties should be already available as Room.customProperties.
    /// Check Room.playerCount to find out if enough players are in the room to start playing.</remarks>
    public override void OnJoinedRoom()
    {
#if UNITY_EDITOR
        m_tangoApplication.Startup(null);
        _StartPlayer();
#else
        if (Globals.m_curAreaDescription != null)
        {
            Directory.CreateDirectory(TEMP_FILE_PATH);
            Globals.m_curAreaDescription.ExportToFile(TEMP_FILE_PATH);
        }
#endif
        m_loadedAreaDescription = Globals.m_curAreaDescription;
    }
    /// <summary>
    /// From button press: start the game by loading the mesh and the Area Description.
    /// 
    /// Generate a new mesh from the saved area definition mesh data linked to the selected Area Description.
    /// </summary>
    public void Button_StartAreaDescriptionMesh()
    {
        if (string.IsNullOrEmpty(m_savedUUID))
        {
            AndroidHelper.ShowAndroidToastMessage("Please choose an Area Description.");
            return;
        }

        if (!File.Exists(m_meshSavePath + "/" + m_savedUUID))
        {
            AndroidHelper.ShowAndroidToastMessage("Please choose an Area Description with mesh data.");
            return;
        }

        m_3dReconstruction = false;
        m_menuOpen = false;

        // Enable objects needed to use Area Description and mesh for occlusion.
        m_arPoseController.gameObject.SetActive(true);
        m_arPoseController.m_useAreaDescriptionPose = true;

        // Disable unused components in tango application.
        m_tangoApplication.m_areaDescriptionLearningMode = false;
        m_tangoApplication.m_enableDepth = false;

        // Set UI panel to the mesh interaction panel.
        m_relocalizeImage.gameObject.SetActive(true);
        m_areaDescriptionLoaderPanel.SetActive(false);
        m_meshBuildPanel.SetActive(false);
        m_meshInteractionPanel.SetActive(true);

        // Load mesh.
        AreaDescriptionMesh mesh = _DeserializeAreaDescriptionMesh(m_savedUUID);
        if (mesh == null)
        {
            return;
        }
        
        // Create GameObject container with mesh components for the loaded mesh.
        m_meshFromFile = new GameObject();
        MeshFilter mf = m_meshFromFile.AddComponent<MeshFilter>();
        mf.mesh = _AreaDescriptionMeshToUnityMesh(mesh);
        MeshRenderer mr = m_meshFromFile.AddComponent<MeshRenderer>();
        mr.material = m_depthMaskMat;
        m_meshFromFile.AddComponent<MeshCollider>();
        m_meshFromFile.layer = LayerMask.NameToLayer("Occlusion");

        // Load Area Description file.
        m_curAreaDescription = AreaDescription.ForUUID(m_savedUUID);

        m_tangoApplication.Startup(m_curAreaDescription);
    }
 /// <summary>
 /// Callback function when toggle button is selected.
 /// </summary>
 /// <param name="item">Caller item object.</param>
 /// <param name="value">Selected value of the toggle button.</param>
 private void _OnToggleChanged(AreaDescription item, bool value)
 {
     if (value)
     {
         m_curAreaDescriptionUUID = item.m_uuid;
     }
 }
        /// <summary>
        /// Manual initialization step 2: Call this to connect to the Tango service.
        /// 
        /// After connecting to the Tango service, you will get updates for Motion Tracking, Depth Sensing, and Area
        /// Learning.  If you have a specific Area Description you want to localize too, pass that Area Description in
        /// here.
        /// </summary>
        /// <param name="areaDescription">If not null, the Area Description to localize to.</param>
        public void Startup(AreaDescription areaDescription)
        {
            // Make sure all required permissions have been granted.
            if (m_requiredPermissions != PermissionsTypes.NONE)
            {
                Debug.Log("TangoApplication.Startup() -- ERROR: Not all required permissions were accepted yet.");
                return;
            }

            if (!_CheckTangoVersion())
            {
                // Error logged in _CheckTangoVersion function.
                return;
            }

            // Setup configs.
            m_tangoConfig = new TangoConfig(TangoEnums.TangoConfigType.TANGO_CONFIG_DEFAULT);
            m_tangoRuntimeConfig = new TangoConfig(TangoEnums.TangoConfigType.TANGO_CONFIG_RUNTIME);

            if (m_enableVideoOverlay && m_videoOverlayUseYUVTextureIdMethod)
            {
                int yTextureWidth = 0;
                int yTextureHeight = 0;
                int uvTextureWidth = 0;
                int uvTextureHeight = 0;
                
                m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_Y_TEXTURE_WIDTH, ref yTextureWidth);
                m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_Y_TEXTURE_HEIGHT, ref yTextureHeight);
                m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_UV_TEXTURE_WIDTH, ref uvTextureWidth);
                m_tangoConfig.GetInt32(TangoConfig.Keys.EXPERIMENTAL_UV_TEXTURE_HEIGHT, ref uvTextureHeight);
                
                if (yTextureWidth == 0 || yTextureHeight == 0 || uvTextureWidth == 0 || uvTextureHeight == 0)
                {
                    Debug.Log("Video overlay texture sizes were not set properly");
                }
                
                m_yuvTexture.ResizeAll(yTextureWidth, yTextureHeight, uvTextureWidth, uvTextureHeight);
            }

            if (areaDescription != null)
            {
                _InitializeMotionTracking(areaDescription.m_uuid);
            }
            else
            {
                _InitializeMotionTracking(null);
            }

            if (m_tangoConfig.SetBool(TangoConfig.Keys.ENABLE_DEPTH_PERCEPTION_BOOL, m_enableDepth) 
                && m_tangoConfig.SetInt32(TangoConfig.Keys.DEPTH_MODE, (int)TangoConfig.DepthMode.XYZC)
                && m_enableDepth)
            {
                DepthListener.SetCallback();
            }

            if (m_tangoConfig.SetBool(TangoConfig.Keys.ENABLE_COLOR_CAMERA_BOOL, m_enableVideoOverlay) && 
                m_enableVideoOverlay)
            {
                _SetVideoOverlayCallbacks();
            }

            TangoEventListener.SetCallback();

            if (m_enable3DReconstruction)
            {
                Register(m_tango3DReconstruction);
            }

            _TangoConnect();
        }