/// <summary> /// Retrieves the PCF associated with the given CFUID. /// </summary> /// <param name="cfuid">The CFUID to look up the PCF type with.</param> /// <param name="pcf">Stores the resulting PCF.</param> /// <param name="update">Determines if the PCF should have it's pose and state updated.</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if a valid PCF was found. /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if failed due to an invalid input parameter. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to other internal error. /// MLResult.Result will be <c>MLResult.Code.PassableWorldLowMapQuality</c> if map quality is too low for content persistence. Continue building the map. /// MLResult.Result will be <c>MLResult.Code.PassableWorldUnableToLocalize</c> if currently unable to localize into any map. Continue building the map. /// </returns> public static MLResult FindPCFByCFUID(MagicLeapNativeBindings.MLCoordinateFrameUID cfuid, out PCF pcf, bool update = true) { pcf = null; if (MLPersistentCoordinateFrames.IsValidInstance()) { if (_instance.mapAllPCFs.ContainsKey(cfuid)) { pcf = _instance.mapAllPCFs[cfuid]; if (update) { MLResult updateResult = pcf.Update(); if (!updateResult.IsOk) { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed to update the found PCF. Reason: {0}", updateResult); } return(updateResult); } return(MLResult.Create(MLResult.Code.Ok)); } else { MLResult result = FindAllPCFs(out List <PCF> list, update: false); if (result.IsOk) { pcf = list.Find(PCF => PCF.CFUID == cfuid); if (update && pcf != null) { MLResult updateResult = pcf.Update(); if (!updateResult.IsOk) { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed to update the found PCF. Reason: {0}", updateResult); } return(updateResult); } } else { if (result.Result == MLResult.Code.PassableWorldLowMapQuality || result.Result == MLResult.Code.PassableWorldUnableToLocalize) { MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.FindPCFByCFUID. Reason: {0}", result); } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed. Reason: {0}", result); } } return(result); } } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed. Reason: No Instance for MLPersistentCoordinateFrames."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.FindPCFByCFUID failed. Reason: No Instance for MLPersistentCoordinateFrames.")); } }
/// <summary> /// Retrieves the PCF associated with the given CFUID. /// </summary> /// <param name="cfuid">The CFUID to look up the PCF type with.</param> /// <param name="callback">Delegate used to return the resulting MLResult.Result and the closest found PCF.</param> /// <param name="update">Determines if the PCF should have it's pose and state updated.</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if a valid PCF was found. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to no API instance being found. /// </returns> public static MLResult FindPCFByCFUID(MagicLeapNativeBindings.MLCoordinateFrameUID cfuid, OnFoundSinglePCFDelegate callback, bool update = true) { if (MLPersistentCoordinateFrames.IsValidInstance()) { if (_instance.mapAllPCFs.ContainsKey(cfuid)) { PCF pcf = _instance.mapAllPCFs[cfuid]; if (update) { MLResult updateResult = pcf.Update(); if (!updateResult.IsOk) { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed to update the found PCF. Reason: {0}", updateResult); callback(MLResult.Code.PassableWorldNotFound, pcf); return(updateResult); } } callback(MLResult.Code.Ok, pcf); return(MLResult.Create(MLResult.Code.Ok)); } else { QueryFilter queryFilter = QueryFilter.Create(); queryFilter.TypesMask = PCF.Types.SingleUserSingleSession | PCF.Types.SingleUserMultiSession | PCF.Types.MultiUserMultiSession; queryFilter.MaxResults = int.MaxValue; queryFilter.Sorted = false; FindPCFsByFilter(queryFilter, update: update, callback: (MLResult.Code resultCode, List <PCF> pcfList) => { PCF pcfWithCFUID = pcfList.Find(pcf => pcf.CFUID == cfuid); if (pcfWithCFUID != null) { if (update) { MLResult updateResult = pcfWithCFUID.Update(); if (!updateResult.IsOk) { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed to update the found PCF. Reason: {0}", updateResult); callback(MLResult.Code.PassableWorldNotFound, pcfWithCFUID); } } callback(MLResult.Code.Ok, pcfWithCFUID); } else { callback(resultCode, null); } }); return(MLResult.Create(MLResult.Code.Ok)); } } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed. Reason: No Instance for MLPersistentCoordinateFrames."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.FindPCFByCFUID failed. Reason: No Instance for MLPersistentCoordinateFrames.")); } }
// -- Utility methods to convert between MLCoordinateFrameUID and a strings. Will be replaced in future SDK updates with API -- // /// <summary> /// Returns the GUID based on the values of this MLCoordinateFrameUID. /// </summary> /// <returns>The calculated GUID.</returns> public static Guid PCFUIDToGuid(MagicLeapNativeBindings.MLCoordinateFrameUID frameUID) { byte[] high = BitConverter.GetBytes(frameUID.First); byte[] low = BitConverter.GetBytes(frameUID.Second); FlipGuidComponents(high); ulong newFirst = BitConverter.ToUInt64(high, 0); return(new Guid((int)(newFirst >> 32 & 0x00000000FFFFFFFF), (short)(newFirst >> 16 & 0x000000000000FFFF), (short)(newFirst & 0x000000000000FFFF), low)); }
/// <summary> /// Gets the object corresponding to the given ID or creates a new one. /// </summary> /// <param name="meshID">The ID of the mesh in question.</param> /// <returns>The newly generated mesh object.</returns> private MeshObject GetOrCreateGameObject(MagicLeapNativeBindings.MLCoordinateFrameUID meshID, out bool newMesh) { newMesh = !meshObjMap.TryGetValue(meshID, out MeshObject meshObj); if (newMesh) { meshObj = new MeshObject(); meshObj.Obj = Instantiate(MeshPrefab, MeshParent); meshObj.Obj.name = string.Format("Mesh {0}", meshID); meshObj.Obj.SetActive(true); meshObjMap.Add(meshID, meshObj); } return(meshObj); }
private IEnumerator Restore_Relocalize(string pcfCFUID) { MagicLeapNativeBindings.MLCoordinateFrameUID cfuid = SerializationUtilities.StringToCFUID(pcfCFUID); while (true) { MLPersistentCoordinateFrames.FindPCFByCFUID(cfuid, out pcfAnchor); if (pcfAnchor == null) { //we didn't find the pcf we needed this time: _restoreAttempt++; if (_restoreAttempt < _maxRestoreAttempts) { //retry: Debug.Log($"Previous PCF not located. Trying again. Attempt: {_restoreAttempt}/{_maxRestoreAttempts}"); yield return(new WaitForSeconds(_restoreRetryDelay)); } else { //failed: Debug.Log($"Failed to locate PCF attempt: {_restoreAttempt}/{_maxRestoreAttempts}. Creating new Playspace."); ChangeState(State.FindPCF); yield break; } yield return(null); } else { //deserialize meshes: string[] meshData = PlayerPrefs.GetString(_sessionMeshKey).Split('|'); Vector3[] wallVerts = SerializationUtilities.Deserialize <Vector3[]>(meshData[0]); int[] wallTris = SerializationUtilities.Deserialize <int[]>(meshData[1]); Vector3[] floorVerts = SerializationUtilities.Deserialize <Vector3[]>(meshData[2]); int[] floorTris = SerializationUtilities.Deserialize <int[]>(meshData[3]); Vector3[] ceilingVerts = SerializationUtilities.Deserialize <Vector3[]>(meshData[4]); BuildGeometry(wallVerts, wallTris, floorVerts, floorTris, ceilingVerts); ChangeState(State.ConfirmAreaReload); yield break; } } }
public static MagicLeapNativeBindings.MLCoordinateFrameUID PCFUIDFromString(string s) { Guid guid = Guid.Parse(s); string guidString = guid.ToString("N"); ulong flippedFirst = ulong.Parse(guidString.Substring(0, 16), System.Globalization.NumberStyles.HexNumber); ulong flippedSecond = ulong.Parse(guidString.Substring(16, 16), System.Globalization.NumberStyles.HexNumber); byte[] bytes = BitConverter.GetBytes(flippedFirst); FlipGuidComponents(bytes); ulong first = BitConverter.ToUInt64(bytes, 0); bytes = BitConverter.GetBytes(flippedSecond); FlipGuidComponents(bytes); ulong second = BitConverter.ToUInt64(bytes, 0); MagicLeapNativeBindings.MLCoordinateFrameUID cfuid = new MagicLeapNativeBindings.MLCoordinateFrameUID(); cfuid.First = first; cfuid.Second = second; return(cfuid); }
/// <summary> /// Retrieves the type of the PCF associated with the given CFUID. /// </summary> /// <param name="cfuid">The CFUID to look up the PCF type with.</param> /// <param name="type">Stores the type of PCF associated with the given CFUID.</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if a valid PCF was found. /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if failed due to an invalid input parameter. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to other internal error. /// MLResult.Result will be <c>MLResult.Code.PassableWorldLowMapQuality</c> if map quality is too low for content persistence. Continue building the map. /// MLResult.Result will be <c>MLResult.Code.PassableWorldNotFound</c> if the passed CFUID is not available. /// MLResult.Result will be <c>MLResult.Code.PassableWorldUnableToLocalize</c> if currently unable to localize into any map. Continue building the map. /// </returns> public static MLResult GetPCFTypeByCFUID(MagicLeapNativeBindings.MLCoordinateFrameUID cfuid, out PCF.Types type) { type = 0; if (MLPersistentCoordinateFrames.IsValidInstance()) { try { NativeBindings.FrameStateNative nativeState = NativeBindings.FrameStateNative.Create(); MLResult.Code resultCode = NativeBindings.MLPersistentCoordinateFramesGetFrameState(_instance.nativeTracker, in cfuid, ref nativeState); if (!MLResult.IsOK(resultCode)) { if (resultCode == MLResult.Code.PassableWorldLowMapQuality || resultCode == MLResult.Code.PassableWorldUnableToLocalize) { MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.GetPCFTypeByCFUID. Reason: {0}", MLResult.CodeToString(resultCode)); } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: {0}", MLResult.CodeToString(resultCode)); } return(MLResult.Create(resultCode, string.Format("MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: {0}", MLResult.CodeToString(resultCode)))); } else { type = nativeState.Type; return(MLResult.Create(resultCode)); } } catch (EntryPointNotFoundException) { MLPluginLog.Error("MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: API symbols not found."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: API symbols not found.")); } } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: No Instance for MLPersistentCoordinateFrames."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: No Instance for MLPersistentCoordinateFrames.")); } }
/// <summary> /// Initializes a new instance of the <see cref="PCF" /> class. /// </summary> /// <param name="id">The CFUID to give to the PCF.</param> public PCF(MagicLeapNativeBindings.MLCoordinateFrameUID id) { this.cfuid = id; }
private bool locateAndReBindToPCFAnchor() { bool result = false; /// /// Iterate the persisted bindings that are stored locally on the device /// TransformBinding.storage.LoadFromFile(); List <TransformBinding> storedBindings = TransformBinding.storage.Bindings; List <TransformBinding> staleBindings = new List <TransformBinding>(); foreach (TransformBinding storedBinding in storedBindings) { /// /// Get the Coordinate Frame Unique Identifier /// this.coordinateFrameUID = storedBinding.PCF.CFUID; /// /// Find the PCF (Persistent Coordinate Frame) aka "The Anchor" /// MLPersistentCoordinateFrames.FindPCFByCFUID(coordinateFrameUID, out MLPersistentCoordinateFrames.PCF pcf); /// Gets the MLResult from the last query for the PCF's pose. It could be one of the following: /// <c>MLResult.Code.Pending</c> - /// <c>MLResult.Code.Ok</c> - Position/Orientation is reliable. /// Otherwise - Position/Orientation is unreliable. switch (pcf.CurrentResultCode) { case MLResult.Code.Pending: // Position/Orientation does not exist. staleBindings.Add(storedBinding); break; case MLResult.Code.Ok: // Position/Orientation is reliable, but pcf may be null { if (pcf == null) { staleBindings.Add(storedBinding); continue; } else { print("Found stored PCF -- Rebinding"); this.transformBinding = storedBinding; this.transformBinding.Bind(pcf, this.transform, true); this.pcf = pcf; result = true; } } break; default: // Position/Orientation is unreliable. { staleBindings.Add(storedBinding); continue; } } } foreach (TransformBinding staleBinding in staleBindings) { staleBinding.UnBind(); } if (!result) { print("Failed to locate stored binding."); } return(result); }
/// <summary> /// Initializes a new instance of the <see cref="MLArucoTracker.Marker" /> class. /// </summary> /// <param name="id">The id of this marker.</param> /// <param name="cfuid">The CFUID associated with this marker.</param> public Marker(int id, MagicLeapNativeBindings.MLCoordinateFrameUID cfuid) { this.id = id; this.cfuid = cfuid; }
/// <summary> /// Returns filtered list of PCFs based on the parameters of the given queryFilter. /// </summary> /// <param name="queryFilter">Parameters used to curate the returned values.</param> /// <param name="pcfList">Stores the resulting list of PCFs.</param> /// <param name="update">Determines if the PCFs should have their pose updated.</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if all the PCFs from the current map have been found successfully. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to other internal error. /// MLResult.Result will be <c>MLResult.Code.PassableWorldLowMapQuality</c> if map quality is too low for content persistence. Continue building the map. /// MLResult.Result will be <c>MLResult.Code.PassableWorldUnableToLocalize</c> if currently unable to localize into any map. Continue building the map. /// </returns> public static MLResult FindPCFsByFilter(QueryFilter queryFilter, out List <PCF> pcfList, bool update = true) { pcfList = new List <PCF>(); if (MLPersistentCoordinateFrames.IsValidInstance()) { try { uint numPCFs = 0; MLResult.Code resultCode = NativeBindings.MLPersistentCoordinateFrameGetCount(_instance.nativeTracker, ref numPCFs); if (MLResult.IsOK(resultCode) && numPCFs > 0) { MagicLeapNativeBindings.MLCoordinateFrameUID[] cfuidArray = new MagicLeapNativeBindings.MLCoordinateFrameUID[numPCFs]; NativeBindings.QueryFilterNative queryFilterNative = NativeBindings.QueryFilterNative.Create(); queryFilterNative.Data = queryFilter; uint cfuidCount = 0; //// With these conditions the user is asking for all PCFs, no need to use the slower filtered query call. if (queryFilter.TypesMask == (PCF.Types.SingleUserSingleSession | PCF.Types.SingleUserMultiSession | PCF.Types.MultiUserMultiSession) && queryFilter.Radius <= 0 && !queryFilter.Sorted) { resultCode = NativeBindings.MLPersistentCoordinateFrameGetAllEx(_instance.nativeTracker, numPCFs, cfuidArray); cfuidCount = (uint)cfuidArray.Length; } else { resultCode = NativeBindings.MLPersistentCoordinateFrameQuery(_instance.nativeTracker, in queryFilterNative, cfuidArray, out cfuidCount); } if (MLResult.IsOK(resultCode)) { for (int i = 0; i < cfuidCount; ++i) { MagicLeapNativeBindings.MLCoordinateFrameUID pcfCFUID = cfuidArray[i]; if (!pcfCFUID.Equals(MagicLeapNativeBindings.MLCoordinateFrameUID.EmptyFrame)) { PCF pcf = null; if (_instance.mapAllPCFs.ContainsKey(pcfCFUID)) { pcf = _instance.mapAllPCFs[pcfCFUID]; } else { pcf = new PCF(pcfCFUID); _instance.mapAllPCFs.Add(pcfCFUID, pcf); } pcfList.Add(pcf); if (update) { MLResult result = pcf.Update(); if (!result.IsOk) { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFsByFilter failed to update the found PCF with CFUID {0}, Reason: {1}", pcf.CFUID, result); } } } } return(MLResult.Create(MLResult.Code.Ok)); } else { if (resultCode == MLResult.Code.PassableWorldLowMapQuality || resultCode == MLResult.Code.PassableWorldUnableToLocalize) { MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.FindPCFsByFilter. Reason: {0}", MLResult.CodeToString(resultCode)); } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: {0}", MLResult.CodeToString(resultCode)); } return(MLResult.Create(resultCode, string.Format("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: {0}", MLResult.CodeToString(resultCode)))); } } else { if (resultCode == MLResult.Code.PassableWorldLowMapQuality || resultCode == MLResult.Code.PassableWorldUnableToLocalize) { MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.FindPCFsByFilter. Reason: {0}", MLResult.CodeToString(resultCode)); } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: {0}", MLResult.IsOK(resultCode) ? "No PCFs could be found." : MLResult.CodeToString(resultCode)); } return(MLResult.Create(resultCode, string.Format("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: {0}", MLResult.IsOK(resultCode) ? "No PCFs could be found." : MLResult.CodeToString(resultCode)))); } } catch (EntryPointNotFoundException) { MLPluginLog.Error("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: API symbols not found."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: API symbols not found.")); } } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: No Instance for MLPersistentCoordinateFrames."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: No Instance for MLPersistentCoordinateFrames.")); } }