123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- /*===============================================================================
- Copyright (C) 2022 Immersal - Part of Hexagon. All Rights Reserved.
- This file is part of the Immersal SDK.
- The Immersal SDK cannot be copied, distributed, or made available to
- third-parties for commercial purposes without written permission of Immersal Ltd.
- Contact sdk@immersal.com for licensing requests.
- ===============================================================================*/
- using UnityEngine;
- using UnityEngine.Events;
- using Unity.Collections;
- using UnityEngine.XR.ARFoundation;
- using System;
- using System.Net.Http;
- using Immersal.AR;
- using UnityEngine.XR.ARSubsystems;
- namespace Immersal
- {
- public class ImmersalSDK : MonoBehaviour
- {
- public static string sdkVersion = "1.18.1";
- public static bool isHWAR = false;
- public static readonly string DefaultServer = "https://api.immersal.com";
-
- public enum CameraResolution { Default, HD, FullHD, Max }; // With Huawei AR Engine SDK, only Default (640x480) and Max (1440x1080) are supported.
- private static ImmersalSDK instance = null;
- [Tooltip("SDK developer token")]
- public string developerToken;
- [SerializeField]
- [Tooltip("Application target frame rate")]
- private int m_TargetFrameRate = 60;
- [SerializeField]
- [Tooltip("Android resolution")]
- private CameraResolution m_AndroidResolution = CameraResolution.FullHD;
- [SerializeField]
- [Tooltip("iOS resolution")]
- private CameraResolution m_iOSResolution = CameraResolution.Default;
- [Tooltip("Downsample image to HD resolution")]
- [SerializeField]
- private bool m_Downsample = true;
- public UnityEvent onPoseLost = null;
- public UnityEvent onPoseFound = null;
- public int secondsToDecayPose = 10;
- public LocalizerBase Localizer { get; private set; }
- public int TrackingQuality { get; private set; }
- private ARCameraManager m_CameraManager;
- private ARSession m_ARSession;
- private bool m_bCamConfigDone = false;
- private string m_LocalizationServer = DefaultServer;
- private int m_PreviousResults = 0;
- private int m_CurrentResults = 0;
- private int q = 0;
- private float m_LatestPoseUpdated = 0f;
- private int m_SLAMTrackingQuality = 0;
- private bool m_HasPose = false;
- private XRCameraConfiguration? m_InitialConfig;
- public static HttpClient client;
- public int targetFrameRate
- {
- get { return m_TargetFrameRate; }
- set
- {
- m_TargetFrameRate = value;
- SetFrameRate();
- }
- }
- public CameraResolution androidResolution
- {
- get { return m_AndroidResolution; }
- set
- {
- m_AndroidResolution = value;
- ConfigureCamera();
- }
- }
- public CameraResolution iOSResolution
- {
- get { return m_iOSResolution; }
- set
- {
- m_iOSResolution = value;
- ConfigureCamera();
- }
- }
- public bool downsample
- {
- get { return m_Downsample; }
- set
- {
- m_Downsample = value;
- SetDownsample();
- }
- }
- public string localizationServer
- {
- get { return m_LocalizationServer; }
- set
- {
- m_LocalizationServer = value;
- }
- }
- public ARCameraManager cameraManager
- {
- get
- {
- if (m_CameraManager == null)
- {
- m_CameraManager = UnityEngine.Object.FindObjectOfType<ARCameraManager>();
- }
- return m_CameraManager;
- }
- }
- public ARSession arSession
- {
- get
- {
- if (m_ARSession == null)
- {
- m_ARSession = UnityEngine.Object.FindObjectOfType<ARSession>();
- }
- return m_ARSession;
- }
- }
- public static ImmersalSDK Instance
- {
- get
- {
- #if UNITY_EDITOR
- if (instance == null && !Application.isPlaying)
- {
- instance = UnityEngine.Object.FindObjectOfType<ImmersalSDK>();
- }
- #endif
- if (instance == null)
- {
- Debug.LogError("No ImmersalSDK instance found. Ensure one exists in the scene.");
- }
- return instance;
- }
- }
- void Awake()
- {
- if (instance == null)
- {
- instance = this;
- }
- if (instance != this)
- {
- Debug.LogError("There must be only one ImmersalSDK object in a scene.");
- UnityEngine.Object.DestroyImmediate(this);
- return;
- }
- HttpClientHandler handler = new HttpClientHandler();
- handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
- client = new HttpClient(handler);
- client.DefaultRequestHeaders.ExpectContinue = false;
-
- if (developerToken != null && developerToken.Length > 0)
- {
- PlayerPrefs.SetString("token", developerToken);
- }
- }
- void Start()
- {
- SetFrameRate();
- #if !UNITY_EDITOR
- SetDownsample();
- #endif
-
- onPoseLost?.Invoke();
- }
- private void SetFrameRate()
- {
- switch (DeviceType.type)
- {
- case "A01":
- Application.targetFrameRate = 300;
- break;
- default:
- Application.targetFrameRate = targetFrameRate ;
- break;
- }
-
- }
- private void SetDownsample()
- {
- if (downsample)
- {
- Immersal.Core.SetInteger("LocalizationMaxPixels", 1280*720);
- }
- else
- {
- Immersal.Core.SetInteger("LocalizationMaxPixels", 0);
- }
- }
- private void Update()
- {
- bool trackingQualityAvailable = false;
- if (ImmersalSDK.isHWAR)
- {
- #if HWAR
- trackingQualityAvailable = HWARHelper.TryGetTrackingQuality(out m_SLAMTrackingQuality);
- #endif
- }
- else
- {
- trackingQualityAvailable = ARHelper.TryGetTrackingQuality(out m_SLAMTrackingQuality);
- }
- if (trackingQualityAvailable && Localizer != null)
- {
- LocalizerStats stats = Localizer.stats;
- if (stats.localizationAttemptCount > 0)
- {
- q = CurrentResults(stats.localizationSuccessCount);
-
- if (!m_HasPose && q > 1)
- {
- m_HasPose = true;
- onPoseFound?.Invoke();
- }
- if (m_HasPose && q < 1 && m_SLAMTrackingQuality <= 1)
- {
- m_HasPose = false;
- Localizer.Reset();
- m_PreviousResults = 0;
- m_CurrentResults = 0;
- onPoseLost?.Invoke();
- }
- TrackingQuality = q;
- }
- }
-
- if (!isHWAR)
- {
- if (!m_bCamConfigDone && cameraManager != null)
- ConfigureCamera();
- }
- }
- private void ConfigureCamera()
- {
- #if !UNITY_EDITOR && (UNITY_ANDROID || UNITY_IOS)
- var cameraSubsystem = cameraManager.subsystem;
- if (cameraSubsystem == null || !cameraSubsystem.running)
- return;
- var configurations = cameraSubsystem.GetConfigurations(Allocator.Temp);
- if (!configurations.IsCreated || (configurations.Length <= 0))
- return;
- int bestError = int.MaxValue;
- var currentConfig = cameraSubsystem.currentConfiguration;
- int dw = (int)currentConfig?.width;
- int dh = (int)currentConfig?.height;
- if (dw == 0 && dh == 0)
- return;
- #if UNITY_ANDROID
- CameraResolution reso = androidResolution;
- #else
- CameraResolution reso = iOSResolution;
- #endif
- if (!m_bCamConfigDone)
- {
- m_InitialConfig = currentConfig;
- }
- switch (reso)
- {
- case CameraResolution.Default:
- dw = (int)currentConfig?.width;
- dh = (int)currentConfig?.height;
- break;
- case CameraResolution.HD:
- dw = 1280;
- dh = 720;
- break;
- case CameraResolution.FullHD:
- dw = 1920;
- dh = 1080;
- break;
- case CameraResolution.Max:
- dw = 80000;
- dh = 80000;
- break;
- }
- foreach (var config in configurations)
- {
- int perror = config.width * config.height - dw * dh;
- if (Math.Abs(perror) < bestError)
- {
- bestError = Math.Abs(perror);
- currentConfig = config;
- }
- }
- if (reso != CameraResolution.Default) {
- Debug.Log("resolution = " + (int)currentConfig?.width + "x" + (int)currentConfig?.height);
- cameraSubsystem.currentConfiguration = currentConfig;
- }
- else
- {
- cameraSubsystem.currentConfiguration = m_InitialConfig;
- }
- #endif
- m_bCamConfigDone = true;
- }
- int CurrentResults(int localizationResults) {
- int diffResults = localizationResults - m_PreviousResults;
- m_PreviousResults = localizationResults;
- if (diffResults > 0)
- {
- m_LatestPoseUpdated = Time.time;
- m_CurrentResults += diffResults;
- if (m_CurrentResults > 3)
- {
- m_CurrentResults = 3;
- }
- }
- else if (Time.time - m_LatestPoseUpdated > secondsToDecayPose)
- {
- m_LatestPoseUpdated = Time.time;
- if (m_CurrentResults > 0)
- {
- m_CurrentResults--;
- }
- }
-
- return m_CurrentResults;
- }
- public void RegisterLocalizer(LocalizerBase localizer)
- {
- Localizer = localizer;
- Localizer.OnReset += OnLocalizerReset;
- }
-
- public void UnRegisterLocalizer()
- {
- Localizer.OnReset -= OnLocalizerReset;
- Localizer = null;
- }
- private void OnLocalizerReset()
- {
- m_CurrentResults = m_PreviousResults = 0;
- m_HasPose = false;
- }
- }
- }
|