// creates boundary plane for mr headsets
    private void CreateBoundaryPlane(Transform planeParent, Material planeMat, bool isCollider, PhysicMaterial colliderMat)
    {
        //if(boundaryPlane == null)
        {
            boundaryPlane       = GameObject.CreatePrimitive(PrimitiveType.Plane);
            boundaryPlane.name  = "Boundary";
            boundaryPlane.layer = MultiARInterop.GetSurfaceLayer();
            boundaryPlane.transform.SetParent(planeParent);
        }

        MeshRenderer meshRenderer = boundaryPlane.GetComponent <MeshRenderer>();

        if (meshRenderer)
        {
            meshRenderer.enabled  = planeMat != null;
            meshRenderer.material = planeMat;
        }

        MeshCollider meshCollider = boundaryPlane.GetComponent <MeshCollider>();

        if (meshCollider)
        {
            meshCollider.enabled = isCollider;

            if (isCollider && colliderMat)
            {
                meshCollider.material = colliderMat;
            }
        }
    }
    void Update()
    {
//		// don't consider taps over the UI
//		if(UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
//			return;

        // check for click
        if (objectPrefab && arManager && arManager.IsInitialized() && arManager.IsInputAvailable(true))
        {
            MultiARInterop.InputAction action = arManager.GetInputAction();

            if (action == MultiARInterop.InputAction.Click)
            {
                // raycast world
                //Vector2 screenPos = Input.GetTouch(0).position;
                MultiARInterop.TrackableHit hit;

                if (arManager.RaycastToWorld(true, out hit))
                {
                    // instantiate the object and anchor it to the world position
                    GameObject spawnObj = Instantiate(objectPrefab, hit.point, !verticalModel ? hit.rotation : Quaternion.identity);
                    arManager.AnchorGameObjectToWorld(spawnObj, hit);

                    // look at the camera
                    if (modelLookingAtCamera)
                    {
                        Camera arCamera = arManager.GetMainCamera();
                        MultiARInterop.TurnObjectToCamera(spawnObj, arCamera, hit.point, hit.normal);
                    }
                }
            }
        }
    }
Exemple #3
0
    // sets the world position of the current model
    private bool SetModelWorldPos(Vector3 vNewPos, Quaternion qNewRot)
    {
        if (modelTransform)
        {
            // activate model if needed
            if (!modelTransform.gameObject.activeSelf)
            {
                modelTransform.gameObject.SetActive(true);
            }

            // set position and look at the camera
            modelTransform.position = vNewPos;
            modelTransform.rotation = qNewRot;

            if (modelLookingAtCamera)
            {
                Camera arCamera = arManager.GetMainCamera();
                MultiARInterop.TurnObjectToCamera(modelTransform.gameObject, arCamera, modelTransform.position, modelTransform.up);
            }

            return(true);
        }

        return(false);
    }
    // Updates overlay surface mesh. Returns true on success, false if the surface needs to be deleted
    private bool UpdateOverlaySurface(OverlaySurfaceUpdater overlaySurface, DetectedPlane trackedSurface)
    {
        // check for validity
        if (overlaySurface == null || trackedSurface == null)
        {
            return(false);
        }
        else if (trackedSurface.SubsumedBy != null)
        {
            return(false);
        }
        else if (trackedSurface.TrackingState != TrackingState.Tracking)
        {
            overlaySurface.SetEnabled(false);
            return(true);
        }

        // enable the surface
        overlaySurface.SetEnabled(true);

        // estimate mesh vertices
        List <Vector3> meshVertices = new List <Vector3>();

        // GetBoundaryPolygon returns points in clockwise order.
        trackedSurface.GetBoundaryPolygon(meshVertices);
        int verticeLength = meshVertices.Count;

        // surface position & rotation
        Vector3    surfacePos = trackedSurface.CenterPose.position;       // Vector3.zero; //
        Quaternion surfaceRot = trackedSurface.CenterPose.rotation;       // Quaternion.identity; //

        // estimate vertices relative to the center
        Quaternion invRot = Quaternion.Inverse(surfaceRot);

        for (int v = verticeLength - 1; v >= 0; v--)
        {
            meshVertices[v] -= surfacePos;
            meshVertices[v]  = invRot * meshVertices[v];

            if (Mathf.Abs(meshVertices[v].y) > 0.1f)
            {
                meshVertices.RemoveAt(v);
            }
        }

        // estimate mesh indices
        List <int> meshIndices = MultiARInterop.GetMeshIndices(meshVertices.Count);

        // update the surface mesh
        overlaySurface.UpdateSurfaceMesh(surfacePos, surfaceRot, meshVertices, meshIndices);

        return(true);
    }
    // invoked by AnchorAdded-event
    private void PlaneAnchorAdded(ARPlaneAnchor arPlaneAnchor)
    {
        Debug.Log("Plane added: " + arPlaneAnchor.identifier);

        GameObject go = null;
//		if(arManager.displayTrackedSurfaces)
//		{
//			go = UnityARUtility.CreatePlaneInScene(arPlaneAnchor);
//			go.AddComponent<DontDestroyOnLoad>();  // these GOs persist across scene loads
//		}

        ARPlaneAnchorGameObject arpag = new ARPlaneAnchorGameObject();

        arpag.planeAnchor = arPlaneAnchor;
        arpag.gameObject  = go;

        planeAnchorDict.Add(arPlaneAnchor.identifier, arpag);
        trackedPlanesTimestamp = GetLastFrameTimestamp();

        // create overlay surfaces as needed
        if (arManager.useOverlaySurface != MultiARManager.SurfaceRenderEnum.None)
        {
            // estimate the material
            Material surfaceMat   = arManager.GetSurfaceMaterial();
            int      surfaceLayer = MultiARInterop.GetSurfaceLayer();

            MultiARInterop.MultiARData arData = arManager.GetARData();

            string surfId = arPlaneAnchor.identifier;
            if (!arData.dictOverlaySurfaces.ContainsKey(surfId))
            {
                GameObject overlaySurfaceObj = new GameObject();
                overlaySurfaceObj.name = "surface-" + surfId;

                overlaySurfaceObj.layer = surfaceLayer;
                overlaySurfaceObj.transform.SetParent(arData.surfaceRendererRoot ? arData.surfaceRendererRoot.transform : null);

//				GameObject overlayCubeObj = GameObject.CreatePrimitive(PrimitiveType.Cube);
//				overlayCubeObj.name = "surface-cube-" + surfId;
//				overlayCubeObj.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);
//				overlayCubeObj.transform.SetParent(overlaySurfaceObj.transform);

                OverlaySurfaceUpdater overlaySurface = overlaySurfaceObj.AddComponent <OverlaySurfaceUpdater>();
                overlaySurface.SetSurfaceMaterial(surfaceMat);
                overlaySurface.SetSurfaceCollider(arManager.surfaceCollider, arManager.colliderMaterial);

                arData.dictOverlaySurfaces.Add(surfId, overlaySurface);
            }

            // update the surface mesh
            UpdateOverlaySurface(arData.dictOverlaySurfaces[surfId], arPlaneAnchor);
        }
    }
    /// <summary>
    /// Gets the currently tracked surfaces.
    /// </summary>
    /// <returns>The tracked surfaces.</returns>
    public MultiARInterop.TrackedSurface[] GetTrackedSurfaces(bool bGetPoints)
    {
        MultiARInterop.TrackedSurface[] trackedPlanes = new MultiARInterop.TrackedSurface[allTrackedPlanes.Count];

        for (int i = 0; i < allTrackedPlanes.Count; i++)
        {
            DetectedPlane surface = allTrackedPlanes[i];
            trackedPlanes[i] = new MultiARInterop.TrackedSurface();

            trackedPlanes[i].position = surface.CenterPose.position;
            trackedPlanes[i].rotation = surface.CenterPose.rotation;
            trackedPlanes[i].bounds   = new Vector3(surface.ExtentX, 0f, surface.ExtentZ);

            if (bGetPoints)
            {
                List <Vector3> alPoints = new List <Vector3>();
                surface.GetBoundaryPolygon(alPoints);

                int        vertexCount = alPoints.Count;
                Quaternion invRot      = Quaternion.Inverse(surface.CenterPose.rotation);
                Vector3    centerPos   = surface.CenterPose.position;

                for (int v = vertexCount - 1; v >= 0; v--)
                {
                    alPoints[v] -= centerPos;
                    alPoints[v]  = invRot * alPoints[v];

                    if (Mathf.Abs(alPoints[v].y) > 0.1f)
                    {
                        alPoints.RemoveAt(v);
                    }
                }

                // get mesh indices
                List <int> meshIndices = MultiARInterop.GetMeshIndices(vertexCount);

                trackedPlanes[i].points    = alPoints.ToArray();
                trackedPlanes[i].triangles = meshIndices.ToArray();
            }
        }

        return(trackedPlanes);
    }
    // sets the world position of the current model
    private bool SetModelWorldPos(Vector3 vNewPos, Quaternion qNewRot)
    {
        if (currentModel)
        {
            // set position and look at the camera
            currentModel.position = vNewPos;
            currentModel.rotation = qNewRot;

            if (modelLookingAtCamera)
            {
                Camera arCamera = arManager.GetMainCamera();
                MultiARInterop.TurnObjectToCamera(currentModel.gameObject, arCamera, currentModel.position, currentModel.up);
            }

            return(true);
        }

        return(false);
    }
    /// <summary>
    /// Raycasts from screen point or camera to the world.
    /// </summary>
    /// <returns><c>true</c>, if a plane was hit, <c>false</c> otherwise.</returns>
    /// <param name="screenPos">Screen position.</param>
    /// <param name="hit">Hit data.</param>
    public bool RaycastToWorld(bool fromInputPos, out MultiARInterop.TrackableHit hit)
    {
        hit = new MultiARInterop.TrackableHit();
        if (!isInitialized || !mainCamera)
        {
            return(false);
        }

        // ray-cast
        Ray camRay = GetCameraRay();

        hit.rayPos = camRay.origin;
        hit.rayDir = camRay.direction;

        int surfaceLayer = MultiARInterop.GetSurfaceLayer();          // LayerMask.NameToLayer("SpatialSurface");
        //Debug.Log("SpatialSurfaceLayer: " + surfaceLayer);
        int layerMask = 1 << surfaceLayer;

        RaycastHit[] rayHits = Physics.RaycastAll(camRay, MultiARInterop.MAX_RAYCAST_DIST, layerMask);

        for (int i = 0; i < rayHits.Length; i++)
        {
            RaycastHit rayHit = rayHits[i];

            // check for child of SpatialMappingCollider
            //if(rayHit.transform.GetComponentInParent<SpatialMappingCollider>() != null)
            if (rayHit.collider != null)
            {
                hit.point    = rayHit.point;
                hit.normal   = rayHit.normal;
                hit.distance = rayHit.distance;
                hit.rotation = Quaternion.FromToRotation(Vector3.up, rayHit.normal);

                hit.psObject = rayHit;
                //Debug.Log(string.Format("Hit {0} at position {1}.", rayHit.collider.gameObject, rayHit.point));

                return(true);
            }
        }

        return(false);
    }
Exemple #9
0
    // checks if the input action ray-casts UI element or not
    private bool CheckForCanvasInputAction()
    {
        if (uiRaycasters != null && arInterface != null)
        {
            Vector2 inputPos = arInterface.GetInputScreenPos(false);

            foreach (UnityEngine.UI.GraphicRaycaster gr in uiRaycasters)
            {
                GameObject rayHit = MultiARInterop.RaycastUI(gr, inputPos);
                if (rayHit != null)
                {
                    // check for UI text
                    UnityEngine.UI.Text uiText = rayHit.gameObject.GetComponent <UnityEngine.UI.Text>();
                    return(uiText == null);
                }
            }
        }

        return(false);
    }
    // saves the current screen shot
    public bool SaveScreenShot(string saveFilePath)
    {
        if (saveFilePath == string.Empty)
        {
            return(false);
        }

        MultiARManager marManager    = MultiARManager.Instance;
        Texture2D      texScreenshot = MultiARInterop.MakeScreenShot(marManager != null ? marManager.GetMainCamera() : null);

        if (texScreenshot)
        {
            byte[] btScreenShot = texScreenshot.EncodeToJPG();
            GameObject.Destroy(texScreenshot);

            File.WriteAllBytes(saveFilePath, btScreenShot);

            return(true);
        }

        return(false);
    }
    // initializes the AR-Core components
    private void InitArCore()
    {
        //Debug.Log("InitArCore started.");

        // disable the main camera, if any
        Camera currentCamera = MultiARInterop.GetMainCamera();

        if (currentCamera)
        {
            currentCamera.gameObject.SetActive(false);
        }

        // create ARCore-Device in the scene
        arCoreDeviceObj      = Instantiate(arCoreDevicePrefab, Vector3.zero, Quaternion.identity);
        arCoreDeviceObj.name = "ARCore Device";
        DontDestroyOnLoad(arCoreDeviceObj);

        // get background material
        arCodeRenderer = FindObjectOfType <ARCoreBackgroundRenderer>();
        if (arCodeRenderer)
        {
            backgroundMat = arCodeRenderer.BackgroundMaterial;
        }

        // update the session config, if needed
        ARCoreSession arSession = arCoreDeviceObj.GetComponent <ARCoreSession>();

        if (arSession != null && arSession.SessionConfig != null && arImageDatabase != null)
        {
            arSession.SessionConfig.AugmentedImageDatabase = arImageDatabase;
        }

        // reference to the AR main camera
        mainCamera = arCoreDeviceObj.GetComponentInChildren <Camera>();

//		// disable directional light, if any
//		Light currentLight = MultiARInterop.GetDirectionalLight();
//		if(currentLight)
//		{
//			currentLight.gameObject.SetActive(false);
//		}
//
//		// create AR environmental light
//		GameObject envLight = new GameObject("Evironmental Light");
//		//envLight.transform.position = Vector3.zero;
//		//envLight.transform.rotation = Quaternion.identity;
//		envLight.AddComponent<EnvironmentalLight>();
//
//		// reference to the AR directional light
//		//directionalLight = envLight.GetComponent<Light>();

        // modify the directional light
        Light currentLight = MultiARInterop.GetDirectionalLight();

        if (!currentLight)
        {
            GameObject currentLightObj = new GameObject("Directional light");

            currentLight      = currentLightObj.AddComponent <Light>();
            currentLight.type = LightType.Directional;
        }

        // reset light position & rotation
        currentLight.transform.position = Vector3.zero;
        currentLight.transform.rotation = Quaternion.Euler(40f, 40f, 0f);
        DontDestroyOnLoad(currentLight.gameObject);

        // set light parameters
        //currentLight.lightmapBakeType = LightmapBakeType.Mixed;
        currentLight.color = new Color32(255, 254, 244, 255);

        // add the ar-light component
        currentLight.gameObject.AddComponent <MultiARDirectionalLight>();

        // get ar-data
        MultiARInterop.MultiARData arData = arManager ? arManager.GetARData() : null;

        if (arManager && arManager.usePointCloudData)
        {
            arData.pointCloudData      = new Vector3[MultiARInterop.MAX_POINT_COUNT];
            arData.pointCloudLength    = 0;
            arData.pointCloudTimestamp = 0.0;
        }

        // create surface renderer
        if (arManager && arData != null)
        {
            arData.surfaceRendererRoot      = new GameObject();
            arData.surfaceRendererRoot.name = "SurfaceRenderer";
            DontDestroyOnLoad(arData.surfaceRendererRoot);
        }

        // interface is initialized
        isInitialized = true;

        //Debug.Log("InitArCore finished.");
    }
Exemple #12
0
    void Update()
    {
        if (arInterface != null)
        {
            // get last frame timestamp and tracking state
            lastFrameTimestamp  = arInterface.GetLastFrameTimestamp();
            cameraTrackingState = arInterface.GetCameraTrackingState();
        }

        // show the tracking state
        if (infoText)
        {
            int numSurfaces = GetTrackedSurfacesCount();
            int numAnchors  = GetAnchorsCount();
            int numObjects  = GetAnchoredObjectsCount();

            infoText.text = "Tracker: " + arInterface.GetCameraTrackingState() + " " + arInterface.GetTrackingErrorMessage() +
                            string.Format("\nLight: {0:F3}", arInterface.GetLightIntensity()) + ", Surfaces: " + numSurfaces + ", Anchors: " + numAnchors + ", Objects: " + numObjects;
            //+ "\nTimestamp: " + lastFrameTimestamp.ToString();
        }

        // check the tracking state
        if (arInterface == null || cameraTrackingState != MultiARInterop.CameraTrackingState.NormalTracking)
        {
            const int LOST_TRACKING_SLEEP_TIMEOUT = 15;
            Screen.sleepTimeout = LOST_TRACKING_SLEEP_TIMEOUT;
            //return;
        }
        else
        {
            // normal trackin
            Screen.sleepTimeout = SleepTimeout.NeverSleep;
        }

        // display the point cloud
        if (pointCloudPrefab && arData.pointCloudTimestamp > lastPointCloudTimestamp)
        {
            lastPointCloudTimestamp = arData.pointCloudTimestamp;
            int pointCloudLen = arData.pointCloudLength < MultiARInterop.MAX_POINT_COUNT ? arData.pointCloudLength : MultiARInterop.MAX_POINT_COUNT;

            int[] indices = new int[pointCloudLen];
            for (int i = 0; i < pointCloudLen; i++)
            {
                indices[i] = i;
            }

            pointCloudMesh.Clear();
            pointCloudMesh.vertices = arData.pointCloudData;
            pointCloudMesh.SetIndices(indices, MeshTopology.Points, 0, false);
        }

        // show cursor if needed
        if (cursorObject && showCursor != ShowCursorEnum.Never)
        {
            MultiARInterop.TrackableHit hit;
            hit.point = Vector3.zero;

            // check how to raycast
            bool isFromInputPos = IsInputAvailable(false);

            if (showCursor == ShowCursorEnum.OnSurfacesOnly)
            {
                RaycastToWorld(isFromInputPos, out hit);
            }
            else
            {
                if (!RaycastToScene(isFromInputPos, out hit))
                {
                    RaycastToWorld(isFromInputPos, out hit);
                }
            }

//			if (infoText)
//			{
//				string hitObjName = string.Empty;
//				if (hit.psObject != null)
//				{
//					if (hit.psObject is RaycastHit)
//						hitObjName = ((RaycastHit)hit.psObject).transform.gameObject.name;
//					else
//						hitObjName = hit.psObject.ToString();
//				}
//
//				infoText.text += "\ninputPos: " + isFromInputPos + ", hit: " + hit.point + ", obj: " + hitObjName;
//			}

            if (showCursor == ShowCursorEnum.Always || hit.point != Vector3.zero)
            {
                MultiARInterop.ShowCursor(cursorObject, hit, 0.03f, 2f, 50f);
            }
        }
    }
    void Update()
    {
        // check for click
        if (objectPrefab && arManager && arManager.IsInitialized() && arManager.IsInputAvailable(true))
        {
            MultiARInterop.InputAction action = arManager.GetInputAction();

            if (action == MultiARInterop.InputAction.Click && (Time.time - lastInstanceTime) >= 1.5f)
            {
                // dont allow too often instance creation
                lastInstanceTime = Time.time;

                // remove current object, if any
                if (objectInstance)
                {
                    DestroyObjectInstance();
                }

                // raycast world
                MultiARInterop.TrackableHit hit;
                if (arManager.RaycastToWorld(true, out hit))
                {
                    // instantiate the object and anchor it to the world position
                    objectInstance = Instantiate(objectPrefab, hit.point, !verticalModel ? hit.rotation : Quaternion.identity);
                    arManager.AnchorGameObjectToWorld(objectInstance, hit);

                    // get object renderer & initial scale
                    objectRenderer = GetObjectRenderer(objectInstance);
                    objectScale    = objectInstance.transform.localScale;

                    // look at the camera
                    if (modelLookingAtCamera)
                    {
                        Camera arCamera = arManager.GetMainCamera();
                        MultiARInterop.TurnObjectToCamera(objectInstance, arCamera, hit.point, hit.normal);
                    }

                    if (infoText)
                    {
                        infoText.text = string.Format("{0} placed at {1}", objectPrefab.name, hit.point);
                    }
                }
            }
            else if (objectInstance && action == MultiARInterop.InputAction.Grip)
            {
                // get nav coordinates
                Vector3 navCoords = arManager.GetInputNavCoordinates();
                lastInstanceTime = Time.time;

                // estimate the scale change and target scale
                Vector3 scaleChange = navCoords.x >= 0 ? (objectScale * navCoords.x) : ((objectScale / 2f) * navCoords.x);
                targetScale = objectScale + scaleChange;

                objectInstance.transform.localScale = Vector3.Lerp(objectInstance.transform.localScale, targetScale, smoothFactor * Time.deltaTime);

                if (infoText)
                {
                    float fScaleChange = 1f + (navCoords.x >= 0 ? navCoords.x : (0.5f * navCoords.x));
                    infoText.text = string.Format("Scale change: {0:F2}", fScaleChange);
                }

                // outline object bounds
                if (objectRenderer && boundsPrefab)
                {
                    Bounds objectBounds = objectRenderer.bounds;

                    // instantiate bounds-cube, if needed
                    if (boundsInstance == null)
                    {
                        boundsInstance = GameObject.Instantiate(boundsPrefab);
                        boundsInstance.transform.SetParent(objectInstance.transform);
                    }

                    // set the bounds-cube tras=nsform
                    boundsInstance.transform.position = objectBounds.center;
                    boundsInstance.transform.rotation = objectInstance.transform.rotation;

                    Vector3 objScale    = objectInstance.transform.localScale;
                    Vector3 boundsScale = new Vector3(objectBounds.size.x / objScale.x, objectBounds.size.y / objScale.y, objectBounds.size.z / objScale.z);
                    boundsInstance.transform.localScale = boundsScale;
                }
            }
            else if (action == MultiARInterop.InputAction.Release)
            {
                // instantiate bounds-cube, if needed
                if (boundsInstance != null)
                {
                    Destroy(boundsInstance);
                    boundsInstance = null;
                }

                if (infoText)
                {
                    infoText.text = "Tap to place the object, then drag right or left, to scale it up or down.";
                }
            }
        }
    }
    // Update is called once per frame
    void Update()
    {
        // check for tap
        if (portalPrefab && arManager && arManager.IsInitialized() && arManager.IsInputAvailable(true))
        {
            MultiARInterop.InputAction action = arManager.GetInputAction();

            if (action == MultiARInterop.InputAction.Click)
            {
                // raycast to world
                MultiARInterop.TrackableHit hit;
                if (arManager.RaycastToWorld(true, out hit))
                {
                    // create the portal object, if needed
                    if (!portalObj)
                    {
                        portalObj = Instantiate(portalPrefab);
                    }

                    // set its position and rotation
                    portalObj.transform.position = hit.point;
                    portalObj.transform.rotation = !verticalPortal ? hit.rotation : Quaternion.identity;

                    // look at the camera
                    if (portalLookingAtCamera)
                    {
                        Camera arCamera = arManager.GetMainCamera();
                        MultiARInterop.TurnObjectToCamera(portalObj, arCamera, hit.point, hit.normal);
                    }

                    // remove object anchor, if it was anchored before
                    string anchorId = arManager.GetObjectAnchorId(portalObj);
                    if (anchorId != string.Empty)
                    {
                        arManager.RemoveGameObjectAnchor(anchorId, true);
                    }

                    // anchor it to the new world position
                    arManager.AnchorGameObjectToWorld(portalObj, hit);

                    // apply the vertical offset
                    if (verticalOffset != 0f)
                    {
                        Vector3 objPos = portalObj.transform.position;
                        //objPos.y += verticalOffset;
                        objPos += portalObj.transform.up * verticalOffset;
                        portalObj.transform.position = objPos;
                    }

                    // play portal-open animation
                    if (playAnimation != string.Empty)
                    {
                        // get reference to the portal animator
                        if (!animator)
                        {
                            animator = portalObj.GetComponent <Animator>();
                        }

                        if (animator)
                        {
                            animator.Play(playAnimation, 0, 0f);
                        }
                    }

                    // create camera rigidbody (no gravity) & box-collider, if needed
                    if (cameraBoxCollider != Vector3.zero)
                    {
                        Camera arCamera = arManager.GetMainCamera();

                        Rigidbody camRigidbody = arCamera.gameObject.GetComponent <Rigidbody>();
                        if (camRigidbody == null)
                        {
                            camRigidbody            = arCamera.gameObject.AddComponent <Rigidbody>();
                            camRigidbody.useGravity = false;
                        }

                        BoxCollider camBoxCollider = arCamera.gameObject.GetComponent <BoxCollider>();
                        if (camBoxCollider == null)
                        {
                            camBoxCollider           = arCamera.gameObject.AddComponent <BoxCollider>();
                            camBoxCollider.size      = cameraBoxCollider;
                            camBoxCollider.isTrigger = true;
                        }
                    }
                }
            }
        }
    }
    // -- // -- // -- // -- // -- // -- // -- // -- // -- // -- //

    void Start()
    {
        if (!isInterfaceEnabled)
        {
            return;
        }

        // determine if display is opaque or transparent
        isDisplayOpaque = HolographicSettings.IsDisplayOpaque;
        Debug.Log("Display: " + (isDisplayOpaque ? "Opaque" : "Transparent"));

        // modify the main camera in the scene
        Camera currentCamera = MultiARInterop.GetMainCamera();

        if (!currentCamera)
        {
            GameObject currentCameraObj = new GameObject("Main Camera");
            currentCameraObj.tag = "MainCamera";

            currentCamera = currentCameraObj.AddComponent <Camera>();
        }

        // reset camera position & rotation
        //currentCamera.transform.position = Vector3.zero;
        currentCamera.transform.rotation = Quaternion.identity;

        // set camera parameters
        currentCamera.clearFlags      = CameraClearFlags.SolidColor;
        currentCamera.backgroundColor = new Color(0f, 0f, 0f, 0f);
        currentCamera.nearClipPlane   = 0.5f;        // HoloLens recommended
        currentCamera.farClipPlane    = 100f;

        if (isDisplayOpaque)
        {
            currentCamera.clearFlags = CameraClearFlags.Skybox;
        }

        // set the fastest quality setting
        QualitySettings.SetQualityLevel((int)qualityLevel);
        Debug.Log("QualityLevel: " + QualitySettings.names[(int)qualityLevel]);

        // reference to the AR main camera
        mainCamera = currentCamera;

        // don't destroy the light between scenes
        DontDestroyOnLoad(currentCamera.gameObject);

//		// add camera parent
//		if(currentCamera.transform.parent == null)
//		{
//			GameObject cameraParent = new GameObject("CameraParent");
//			currentCamera.transform.SetParent(cameraParent.transform);
//		}

        // modify the directional light
        Light currentLight = MultiARInterop.GetDirectionalLight();

        if (!currentLight)
        {
            GameObject currentLightObj = new GameObject("Directional light");

            currentLight      = currentLightObj.AddComponent <Light>();
            currentLight.type = LightType.Directional;
        }

        // reset light position & rotation
        currentLight.transform.position = Vector3.zero;
        currentLight.transform.rotation = Quaternion.Euler(40f, 40f, 0f);

        // set light parameters
        currentLight.color = new Color32(255, 254, 244, 255);

        // add the ar-light component
        //currentLight.gameObject.AddComponent<MultiARDirectionalLight>();

        // reference to the AR directional light
        //directionalLight = currentLight;

        // don't destroy the light between scenes
        DontDestroyOnLoad(currentLight.gameObject);

        // there is no point cloud in WinMR
        MultiARInterop.MultiARData arData = arManager.GetARData();

        // check for point cloud getter
        if (arManager.pointCloudPrefab != null)
        {
            arData.pointCloudData      = new Vector3[0];
            arData.pointCloudLength    = 0;
            arData.pointCloudTimestamp = 0.0;
        }

        // set tracking state
        cameraTrackingState = WorldManager.state;
        WorldManager.OnPositionalLocatorStateChanged += WorldManager_OnPositionalLocatorStateChanged;

//		// set tracking space type
//		Debug.Log("Before: " + XRDevice.GetTrackingSpaceType());
//		if(XRDevice.GetTrackingSpaceType() != TrackingSpaceType.Stationary)
//		{
//			if(!XRDevice.SetTrackingSpaceType(TrackingSpaceType.Stationary))
//			{
//				Debug.LogError("Cannot set stationary space type!");
//			}
//		}

        // create gesture input
        if (!isDisplayOpaque)
        {
            gestureRecognizer = new GestureRecognizer();
            gestureRecognizer.SetRecognizableGestures(GestureSettings.Tap | GestureSettings.Hold |
                                                      GestureSettings.NavigationX | GestureSettings.NavigationY | GestureSettings.NavigationZ);

            gestureRecognizer.Tapped += GestureRecognizer_Tapped;

//			gestureRecognizer.HoldStarted += GestureRecognizer_HoldStarted;
//			gestureRecognizer.HoldCompleted += GestureRecognizer_HoldCompleted;
//			gestureRecognizer.HoldCanceled += GestureRecognizer_HoldCanceled;

            gestureRecognizer.NavigationStarted   += GestureRecognizer_NavigationStarted;
            gestureRecognizer.NavigationUpdated   += GestureRecognizer_NavigationUpdated;
            gestureRecognizer.NavigationCompleted += GestureRecognizer_NavigationCompleted;
            gestureRecognizer.NavigationCanceled  += GestureRecognizer_NavigationCanceled;

            gestureRecognizer.StartCapturingGestures();
            Debug.Log("Gesture recognizer inited and started.");
        }
        //else
        {
            // init interaction manager
//			InteractionManager.InteractionSourcePressed += InteractionManager_InteractionSourcePressed;
//			InteractionManager.InteractionSourceUpdated += InteractionManager_InteractionSourceUpdated;
//			InteractionManager.InteractionSourceReleased += InteractionManager_InteractionSourceReleased;

            InteractionManager.InteractionSourceDetected += InteractionManager_InteractionSourceDetected;
            InteractionManager.InteractionSourceLost     += InteractionManager_InteractionSourceLost;
            InteractionManager.InteractionSourceUpdated  += InteractionManager_InteractionSourceUpdated;

            Debug.Log("Interaction manager inited.");
        }

        // create surface renderer
        if (arManager.useOverlaySurface != MultiARManager.SurfaceRenderEnum.None)
        {
            GameObject objRenderer = new GameObject();
            objRenderer.name           = "SurfaceRenderer";
            objRenderer.layer          = MultiARInterop.GetSurfaceLayer();
            arData.surfaceRendererRoot = objRenderer;

            surfaceRootTransform = objRenderer.transform;
            DontDestroyOnLoad(objRenderer);

            if (!isDisplayOpaque)
            {
                // hololens
                surfaceRenderer = objRenderer.AddComponent <SpatialMappingRenderer>();
                surfaceRenderer.surfaceParent = objRenderer;

                switch (arManager.useOverlaySurface)
                {
                case MultiARManager.SurfaceRenderEnum.None:
                    surfaceRenderer.renderState = SpatialMappingRenderer.RenderState.None;
                    break;

                case MultiARManager.SurfaceRenderEnum.Visualization:
                    surfaceRenderer.renderState = SpatialMappingRenderer.RenderState.Visualization;
                    break;

                case MultiARManager.SurfaceRenderEnum.Occlusion:
                case MultiARManager.SurfaceRenderEnum.OcclusionWithShadows:
                    surfaceRenderer.renderState = SpatialMappingRenderer.RenderState.Occlusion;
                    break;
                }

                if (arManager.useOverlaySurface != MultiARManager.SurfaceRenderEnum.None)
                {
                    surfaceRenderer.visualMaterial    = arManager.surfaceVisualizationMaterial;
                    surfaceRenderer.occlusionMaterial = arManager.useOverlaySurface == MultiARManager.SurfaceRenderEnum.OcclusionWithShadows ?
                                                        arManager.surfaceOcclusionWithShadowsMaterial : arManager.surfaceOcclusionMaterial;
                }
            }
            else
            {
                // use special surface material on opaque displays
                Material visualMaterial = arManager.GetSurfaceMaterial();
                if (arManager.useOverlaySurface == MultiARManager.SurfaceRenderEnum.Visualization && vrSurfaceMaterial)
                {
                    visualMaterial = vrSurfaceMaterial;
                }

                // mr headsets
                CreateBoundaryPlane(objRenderer.transform, visualMaterial, arManager.surfaceCollider, arManager.colliderMaterial);

                boundaryMgr           = objRenderer.AddComponent <HoloToolkit.Unity.Boundary.BoundaryManager>();
                boundaryMgr.FloorQuad = boundaryPlane;
                boundaryMgr.AwakeBoundaryManager();
            }
        }

        // create surface collider
        if (arManager.surfaceCollider)
        {
            GameObject objCollider = new GameObject();
            objCollider.name  = "SurfaceCollider";
            objCollider.layer = MultiARInterop.GetSurfaceLayer();
            DontDestroyOnLoad(objCollider);

            if (!isDisplayOpaque)
            {
                // hololens
                surfaceCollider = objCollider.AddComponent <SpatialMappingCollider>();
                surfaceCollider.surfaceParent = objCollider;

                surfaceCollider.lodType = SpatialMappingBase.LODType.Low;
                surfaceCollider.layer   = MultiARInterop.GetSurfaceLayer();

                if (arManager.colliderMaterial)
                {
                    surfaceCollider.material = arManager.colliderMaterial;
                }
            }
            else
            {
                // mr headsets
                if (boundaryPlane == null)
                {
                    // there was no boundary rendering
                    CreateBoundaryPlane(objCollider.transform, null, true, arManager.colliderMaterial);

                    boundaryMgr           = objCollider.AddComponent <HoloToolkit.Unity.Boundary.BoundaryManager>();
                    boundaryMgr.FloorQuad = boundaryPlane;
                    boundaryMgr.AwakeBoundaryManager();
                }
            }
        }

//		// if camera is too near to the floor, lower the floor 1.5 meter below the camera
//		if(currentCamera && boundaryMgr)
//		{
//			if(currentCamera.transform.position.y < 0.1f)
//			{
//				boundaryMgr.CurrentFloorHeightOffset = currentCamera.transform.position.y - 1.5f;
//				Debug.Log(string.Format("FloorHeightOffset set below the camera at {0:F2}m.", boundaryMgr.CurrentFloorHeightOffset));
//			}
//		}

        // starts co-routine to check rendered surfaces
        StartCoroutine(CheckSurfacesRoutine());

        Debug.Log("TrackingSpaceType: " + XRDevice.GetTrackingSpaceType());
        Debug.Log("Screen size: " + Screen.width + " x " + Screen.height);

        int surfaceLayer = MultiARInterop.GetSurfaceLayer();          // LayerMask.NameToLayer("SpatialSurface");

        Debug.Log("SpatialSurfaceLayer: " + surfaceLayer);

        // interface is initialized
        isInitialized = true;
    }
    void Update()
    {
        if (!isInitialized)
        {
            return;
        }

        // check for errors
        _QuitOnConnectionErrors();

        // check for input (touch)
        CheckForInputAction();

        // estimate the tracking state
        SessionStatus status = Session.Status;

        if (status.IsError() || status.IsNotInitialized())
        {
            cameraTrackingState = TrackingState.Stopped;
            return;
        }
        else if (status == SessionStatus.Tracking)
        {
            cameraTrackingState = TrackingState.Tracking;
        }
        else
        {
            cameraTrackingState = TrackingState.Paused;
        }

        // get frame timestamp and light intensity
        lastFrameTimestamp = GetCurrentTimestamp();

        if (Frame.LightEstimate.State == LightEstimateState.Valid)
        {
            // Normalize pixel intensity by middle gray in gamma space.
            const float middleGray = 0.466f;
            currentLightIntensity = Frame.LightEstimate.PixelIntensity / middleGray;
        }

        // get point cloud, if needed
        MultiARInterop.MultiARData arData = arManager.GetARData();

        if (arManager.usePointCloudData)
        {
            if (Frame.PointCloud.PointCount > 0 && Frame.PointCloud.IsUpdatedThisFrame)
            {
                // Copy the point cloud points
                for (int i = 0; i < Frame.PointCloud.PointCount; i++)
                {
                    PointCloudPoint point = Frame.PointCloud.GetPointAsStruct(i);
                    arData.pointCloudData[i] = new Vector3(point.Position.x, point.Position.y, point.Position.z);
                }

                arData.pointCloudLength    = Frame.PointCloud.PointCount;
                arData.pointCloudTimestamp = lastFrameTimestamp;
            }
        }

//		// display the tracked planes if needed
//		if(arManager.displayTrackedSurfaces && trackedPlanePrefab)
//		{
//			// get the new planes
//			Frame.GetNewPlanes(ref newTrackedPlanes);
//
//			// Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
//			for (int i = 0; i < newTrackedPlanes.Count; i++)
//			{
//				// Instantiate a plane visualization prefab and set it to track the new plane.
//				GameObject planeObject = Instantiate(trackedPlanePrefab, Vector3.zero, Quaternion.identity);
//				planeObject.GetComponent<GoogleARCore.HelloAR.TrackedPlaneVisualizer>().SetTrackedPlane(newTrackedPlanes[i]);
//
//				// Apply a random color and grid rotation.
//				planeObject.GetComponent<Renderer>().material.SetColor("_GridColor", planeColors[Random.Range(0, planeColors.Length - 1)]);
//				planeObject.GetComponent<Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));
//			}
//		}

        // get all tracked planes
        Session.GetTrackables <DetectedPlane>(allTrackedPlanes, TrackableQueryFilter.All);

        // create overlay surfaces as needed
        if (arManager.useOverlaySurface != MultiARManager.SurfaceRenderEnum.None)
        {
            alSurfacesToDelete.Clear();
            alSurfacesToDelete.AddRange(arData.dictOverlaySurfaces.Keys);

            // estimate the material
            Material surfaceMat   = arManager.GetSurfaceMaterial();
            int      surfaceLayer = MultiARInterop.GetSurfaceLayer();

            for (int i = 0; i < allTrackedPlanes.Count; i++)
            {
                string surfId = allTrackedPlanes[i].m_TrackableNativeHandle.ToString();

                if (!arData.dictOverlaySurfaces.ContainsKey(surfId))
                {
                    GameObject overlaySurfaceObj = new GameObject();
                    overlaySurfaceObj.name = "surface-" + surfId;

                    overlaySurfaceObj.layer = surfaceLayer;
                    overlaySurfaceObj.transform.SetParent(arData.surfaceRendererRoot ? arData.surfaceRendererRoot.transform : null);

//					GameObject overlayCubeObj = GameObject.CreatePrimitive(PrimitiveType.Cube);
//					overlayCubeObj.name = "surface-cube-" + surfId;
//					overlayCubeObj.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);
//					overlayCubeObj.transform.SetParent(overlaySurfaceObj.transform);

                    OverlaySurfaceUpdater overlaySurface = overlaySurfaceObj.AddComponent <OverlaySurfaceUpdater>();
                    overlaySurface.SetSurfaceMaterial(surfaceMat);
                    overlaySurface.SetSurfaceCollider(arManager.surfaceCollider, arManager.colliderMaterial);

                    arData.dictOverlaySurfaces.Add(surfId, overlaySurface);
                }

                // update the surface mesh
                bool bValidSurface = UpdateOverlaySurface(arData.dictOverlaySurfaces[surfId], allTrackedPlanes[i]);

                if (bValidSurface && alSurfacesToDelete.Contains(surfId))
                {
                    alSurfacesToDelete.Remove(surfId);
                }
            }

            // delete not tracked surfaces
            foreach (string surfId in alSurfacesToDelete)
            {
                OverlaySurfaceUpdater overlaySurface = arData.dictOverlaySurfaces[surfId];
                arData.dictOverlaySurfaces.Remove(surfId);

                Destroy(overlaySurface.gameObject);
            }
        }

        // check status of the anchors
        List <string> alAnchorsToRemove = new List <string>();

        foreach (string anchorId in arData.allAnchorsDict.Keys)
        {
            List <GameObject> anchoredObjs = arData.allAnchorsDict[anchorId];

            foreach (GameObject anchoredObj in anchoredObjs)
            {
                Transform parentTrans = anchoredObj.transform.parent;

                if (parentTrans == null)
                {
                    if (!alAnchorsToRemove.Contains(anchorId))
                    {
                        alAnchorsToRemove.Add(anchorId);
                    }
                    anchoredObj.SetActive(false);
                }
                else
                {
                    Anchor anchor = parentTrans.GetComponent <Anchor>();

                    if (anchor == null || anchor.TrackingState == TrackingState.Stopped)
                    {
                        if (!alAnchorsToRemove.Contains(anchorId))
                        {
                            alAnchorsToRemove.Add(anchorId);
                        }

                        anchoredObj.transform.parent = null;
                        anchoredObj.SetActive(false);
                    }
                }
            }
        }

        // remove the stopped anchors from our list
        foreach (string anchorId in alAnchorsToRemove)
        {
            arData.allAnchorsDict.Remove(anchorId);
        }

        // clean up
        alAnchorsToRemove.Clear();

        // look for image anchors, if enabled
        if (arData.imageAnchorsEnabled)
        {
            // Get updated augmented images for this frame.
            Session.GetTrackables <AugmentedImage>(alTrackedAugmentedImages, TrackableQueryFilter.Updated);

            foreach (var image in alTrackedAugmentedImages)
            {
                string sImageName      = image.Name;
                bool   wasImageTracked = dictImageAnchors.ContainsKey(sImageName);

                if (!wasImageTracked && image.TrackingState == TrackingState.Tracking)
                {
                    // Create an anchor to ensure that ARCore keeps tracking this augmented image.
                    Anchor anchor = image.CreateAnchor(image.CenterPose);
                    anchor.gameObject.name = "ImageAnchor-" + sImageName;
                    DontDestroyOnLoad(anchor.gameObject);

                    alImageAnchorNames.Add(sImageName);
                    dictImageAnchors.Add(sImageName, anchor.gameObject);
                }
                else if (wasImageTracked && image.TrackingState == TrackingState.Stopped)
                {
                    // remove the anchor
                    GameObject anchorObj = dictImageAnchors[sImageName];

                    alImageAnchorNames.Remove(sImageName);
                    dictImageAnchors.Remove(sImageName);

                    GameObject.Destroy(anchorObj);
                }
            }
        }
    }
    // -- // -- // -- // -- // -- // -- // -- // -- // -- // -- //

    void Start()
    {
        if (!isInterfaceEnabled)
        {
            return;
        }

        if (!yuvMaterial)
        {
            Debug.LogError("ARKit-interface cannot start: YuvMaterial is not set.");
            return;
        }

        // modify the main camera in the scene
        Camera currentCamera = MultiARInterop.GetMainCamera();

        if (!currentCamera)
        {
            GameObject currentCameraObj = new GameObject("Main Camera");
            currentCameraObj.tag = "MainCamera";

            currentCamera = currentCameraObj.AddComponent <Camera>();
        }

        // reset camera position & rotation
        currentCamera.transform.position = Vector3.zero;
        currentCamera.transform.rotation = Quaternion.identity;

        // set camera parameters
        currentCamera.clearFlags    = CameraClearFlags.Depth;
        currentCamera.nearClipPlane = 0.1f;
        currentCamera.farClipPlane  = 30f;

        // reference to the AR main camera
        mainCamera = currentCamera;

        // add camera parent
        if (currentCamera.transform.parent == null)
        {
            GameObject cameraParent = new GameObject("CameraParent");
            currentCamera.transform.SetParent(cameraParent.transform);
            DontDestroyOnLoad(cameraParent);
        }
        else
        {
            DontDestroyOnLoad(currentCamera.transform.root.gameObject);
        }

        // add the needed camera components
        arVideoRenderer = currentCamera.gameObject.AddComponent <UnityARVideo>();
        arVideoRenderer.m_ClearMaterial = yuvMaterial;
        backgroundMat = yuvMaterial;

        currentCamera.gameObject.AddComponent <UnityARCameraNearFar>();

        // modify the directional light
        Light currentLight = MultiARInterop.GetDirectionalLight();

        if (!currentLight)
        {
            GameObject currentLightObj = new GameObject("Directional light");

            currentLight      = currentLightObj.AddComponent <Light>();
            currentLight.type = LightType.Directional;
        }

        // reset light position & rotation
        currentLight.transform.position = Vector3.zero;
        currentLight.transform.rotation = Quaternion.Euler(40f, 40f, 0f);
        DontDestroyOnLoad(currentLight.gameObject);

        // set light parameters
        //currentLight.lightmapBakeType = LightmapBakeType.Mixed;
        currentLight.color = new Color32(255, 254, 244, 255);

        // add the ar-light component
        currentLight.gameObject.AddComponent <MultiARDirectionalLight>();

        // reference to the AR directional light
        //directionalLight = currentLight;

        // create camera manager
        GameObject camManagerObj = new GameObject("ARCameraManager");

        DontDestroyOnLoad(camManagerObj);

        UnityARCameraManager camManager = camManagerObj.AddComponent <UnityARCameraManager>();

        camManager.m_camera = currentCamera;

        camManager.startAlignment = cameraAlignment;
        camManager.planeDetection = UnityARPlaneDetection.HorizontalAndVertical;

        //Debug.Log("arImageDatabase: " + (arImageDatabase != null ? arImageDatabase.resourceGroupName : "-"));
        if (arImageDatabase != null)
        {
            camManager.detectionImages = arImageDatabase;
            Debug.Log("camManager.detectionImages set to: " + arImageDatabase);
        }

        // allow relocalization after session interruption
        UnityARSessionNativeInterface.ARSessionShouldAttemptRelocalization = true;

        // get ar-data
        MultiARInterop.MultiARData arData = arManager ? arManager.GetARData() : null;

        // check for point cloud getter
        if (arManager && arManager.pointCloudPrefab != null)
        {
            arData.pointCloudData      = new Vector3[0];
            arData.pointCloudLength    = 0;
            arData.pointCloudTimestamp = 0.0;
        }

        // create surface renderer
        if (arManager && arData != null)
        {
            arData.surfaceRendererRoot      = new GameObject();
            arData.surfaceRendererRoot.name = "SurfaceRenderer";
            DontDestroyOnLoad(arData.surfaceRendererRoot);
        }

//		// check for tracked plane display
//		if(arManager.displayTrackedSurfaces && trackedPlanePrefab)
//		{
//			UnityARUtility.InitializePlanePrefab(trackedPlanePrefab);
//		}

        // add needed events
        UnityARSessionNativeInterface.ARFrameUpdatedEvent           += ARFrameUpdated;
        UnityARSessionNativeInterface.ARSessionTrackingChangedEvent += ARSessionTrackingChanged;

        UnityARSessionNativeInterface.ARAnchorAddedEvent   += PlaneAnchorAdded;
        UnityARSessionNativeInterface.ARAnchorUpdatedEvent += PlaneAnchorUpdated;
        UnityARSessionNativeInterface.ARAnchorRemovedEvent += PlaneAnchorRemoved;

        UnityARSessionNativeInterface.ARUserAnchorAddedEvent   += UserAnchorAdded;
        UnityARSessionNativeInterface.ARUserAnchorRemovedEvent += UserAnchorRemoved;

        // create ARCoreSession component, if the cloud functionality is used
        GoogleARCore.ARCoreSession arCoreSession = gameObject.GetComponent <GoogleARCore.ARCoreSession>();
        if (arCoreSession == null)
        {
            TextAsset cloudApiKey = Resources.Load("RuntimeSettings/CloudServicesApiKey") as TextAsset;

            if (cloudApiKey != null)
            {
                arCoreSession = gameObject.AddComponent <GoogleARCore.ARCoreSession>();
            }
        }

        // interface is initialized
        isInitialized = true;
    }
    // -- // -- // -- // -- // -- // -- // -- // -- // -- // -- //

    void Start()
    {
        if (!isInterfaceEnabled)
        {
            return;
        }

        if (!metaCameraRigPrefab)
        {
            Debug.LogError("Meta2-interface cannot start: MetaCameraRig-prefab is not set.");
            return;
        }

        // disable the main camera, if any
        Camera currentCamera = MultiARInterop.GetMainCamera();

        if (currentCamera)
        {
            currentCamera.gameObject.SetActive(false);
        }

        // create ARCore-Device in the scene
        GameObject arCoreDeviceObj = Instantiate(metaCameraRigPrefab, Vector3.zero, Quaternion.identity);

        arCoreDeviceObj.name = "ARCore Device";
        DontDestroyOnLoad(arCoreDeviceObj);

        // reference to the AR main camera
        mainCamera = arCoreDeviceObj.GetComponentInChildren <Camera>();

//		// add camera parent
//		if(currentCamera.transform.parent == null)
//		{
//			GameObject cameraParent = new GameObject("CameraParent");
//			currentCamera.transform.SetParent(cameraParent.transform);
//		}

        // modify the directional light
        Light currentLight = MultiARInterop.GetDirectionalLight();

        if (!currentLight)
        {
            GameObject currentLightObj = new GameObject("Directional light");

            currentLight      = currentLightObj.AddComponent <Light>();
            currentLight.type = LightType.Directional;
        }

        // reset light position & rotation
        currentLight.transform.position = Vector3.zero;
        currentLight.transform.rotation = Quaternion.Euler(40f, 40f, 0f);

        // set light parameters
        currentLight.color = new Color32(255, 254, 244, 255);

        // add the ar-light component
        //currentLight.gameObject.AddComponent<MultiARDirectionalLight>();

        // reference to the AR directional light
        //directionalLight = currentLight;

        // don't destroy the light between scenes
        DontDestroyOnLoad(currentLight.gameObject);

        // there is no point cloud in WinMR
        MultiARInterop.MultiARData arData = arManager.GetARData();

        // check for point cloud getter
        if (arManager.pointCloudPrefab != null)
        {
            arData.pointCloudData      = new Vector3[0];
            arData.pointCloudLength    = 0;
            arData.pointCloudTimestamp = 0.0;
        }

        // set tracking state
        cameraTrackingState = WorldManager.state;
        WorldManager.OnPositionalLocatorStateChanged += WorldManager_OnPositionalLocatorStateChanged;

//		// set tracking space type
//		Debug.Log("Before: " + XRDevice.GetTrackingSpaceType());
//		if(XRDevice.GetTrackingSpaceType() != TrackingSpaceType.Stationary)
//		{
//			if(!XRDevice.SetTrackingSpaceType(TrackingSpaceType.Stationary))
//			{
//				Debug.LogError("Cannot set stationary space type!");
//			}
//		}

        // create gesture input
        if (!isDisplayOpaque)
        {
            gestureRecognizer = new GestureRecognizer();
            gestureRecognizer.SetRecognizableGestures(GestureSettings.Tap | GestureSettings.Hold |
                                                      GestureSettings.NavigationX | GestureSettings.NavigationY | GestureSettings.NavigationZ);

            gestureRecognizer.Tapped += GestureRecognizer_Tapped;

//			gestureRecognizer.HoldStarted += GestureRecognizer_HoldStarted;
//			gestureRecognizer.HoldCompleted += GestureRecognizer_HoldCompleted;
//			gestureRecognizer.HoldCanceled += GestureRecognizer_HoldCanceled;

            gestureRecognizer.NavigationStarted   += GestureRecognizer_NavigationStarted;
            gestureRecognizer.NavigationUpdated   += GestureRecognizer_NavigationUpdated;
            gestureRecognizer.NavigationCompleted += GestureRecognizer_NavigationCompleted;
            gestureRecognizer.NavigationCanceled  += GestureRecognizer_NavigationCanceled;

            gestureRecognizer.StartCapturingGestures();
            Debug.Log("Gesture recognizer inited and started.");
        }
        else
        {
            InteractionManager.InteractionSourcePressed  += InteractionManager_InteractionSourcePressed;
            InteractionManager.InteractionSourceUpdated  += InteractionManager_InteractionSourceUpdated;
            InteractionManager.InteractionSourceReleased += InteractionManager_InteractionSourceReleased;
            Debug.Log("Interaction manager inited.");
        }

        // create surface renderer
        if (arManager.useOverlaySurface != MultiARManager.SurfaceRenderEnum.None)
        {
            GameObject objRenderer = new GameObject();
            objRenderer.name           = "SurfaceRenderer";
            objRenderer.layer          = MultiARInterop.GetSurfaceLayer();
            arData.surfaceRendererRoot = objRenderer;

            surfaceRootTransform = objRenderer.transform;
            DontDestroyOnLoad(objRenderer);

            if (!isDisplayOpaque)
            {
                // hololens
                surfaceRenderer = objRenderer.AddComponent <SpatialMappingRenderer>();
                surfaceRenderer.surfaceParent = objRenderer;

                surfaceRenderer.renderState = (SpatialMappingRenderer.RenderState)arManager.useOverlaySurface;

                if (arManager.useOverlaySurface != MultiARManager.SurfaceRenderEnum.None)
                {
                    surfaceRenderer.visualMaterial    = arManager.surfaceVisualizationMaterial;
                    surfaceRenderer.occlusionMaterial = arManager.surfaceOcclusionMaterial;
                }
            }
            else
            {
                // mr headsets
                CreateBoundaryPlane(objRenderer.transform, arManager.GetSurfaceMaterial(),
                                    arManager.surfaceCollider, arManager.colliderMaterial);

                boundaryMgr           = objRenderer.AddComponent <HoloToolkit.Unity.Boundary.BoundaryManager>();
                boundaryMgr.FloorQuad = boundaryPlane;
                boundaryMgr.AwakeBoundaryManager();
            }
        }

        // create surface collider
        if (arManager.surfaceCollider)
        {
            GameObject objCollider = new GameObject();
            objCollider.name  = "SurfaceCollider";
            objCollider.layer = MultiARInterop.GetSurfaceLayer();
            DontDestroyOnLoad(objCollider);

            if (!isDisplayOpaque)
            {
                // hololens
                surfaceCollider = objCollider.AddComponent <SpatialMappingCollider>();
                surfaceCollider.surfaceParent = objCollider;

                surfaceCollider.lodType = SpatialMappingBase.LODType.Low;
                surfaceCollider.layer   = MultiARInterop.GetSurfaceLayer();

                if (arManager.colliderMaterial)
                {
                    surfaceCollider.material = arManager.colliderMaterial;
                }
            }
            else
            {
                // mr headsets
                if (boundaryPlane == null)
                {
                    // there was no boundary rendering
                    CreateBoundaryPlane(objCollider.transform, null, true, arManager.colliderMaterial);

                    boundaryMgr           = objCollider.AddComponent <HoloToolkit.Unity.Boundary.BoundaryManager>();
                    boundaryMgr.FloorQuad = boundaryPlane;
                    boundaryMgr.AwakeBoundaryManager();
                }
            }
        }

//		// if camera is too near to the floor, lower the floor 1.5 meter below the camera
//		if(currentCamera && boundaryMgr)
//		{
//			if(currentCamera.transform.position.y < 0.1f)
//			{
//				boundaryMgr.CurrentFloorHeightOffset = currentCamera.transform.position.y - 1.5f;
//				Debug.Log(string.Format("FloorHeightOffset set below the camera at {0:F2}m.", boundaryMgr.CurrentFloorHeightOffset));
//			}
//		}

        // starts co-routine to check rendered surfaces
        StartCoroutine(CheckSurfacesRoutine());

        Debug.Log("TrackingSpaceType: " + XRDevice.GetTrackingSpaceType());
        Debug.Log("Screen size: " + Screen.width + " x " + Screen.height);

        int surfaceLayer = MultiARInterop.GetSurfaceLayer();          // LayerMask.NameToLayer("SpatialSurface");

        Debug.Log("SpatialSurfaceLayer: " + surfaceLayer);

        // interface is initialized
        isInitialized = true;
    }