/// <inheritdocs /> public AnchorId AddAlignmentAnchor(string uniqueName, Pose virtualPose, Pose lockedPose) { FragmentId fragmentId = CurrentFragmentId; AnchorId anchorId = ClaimAnchorId(); if (IsGlobal) { /// Bake in current snapshot of any application imposed transform (teleport). virtualPose = manager.PinnedFromFrozen.Multiply(virtualPose); } else { /// For subtree, applied adjustment transform is LockedFromPinned. Remove existing /// adjustment here by premultiplying PinnedFromLocked. virtualPose = PinnedFromLocked.Multiply(virtualPose); } #if WLT_EXTRA_LOGGING string label = "AddAlign1"; Debug.Log($"F{Time.frameCount} {label} {uniqueName} vp={virtualPose.ToString("F3")} lp={lockedPose.ToString("F3")} sp={manager.SpongyFromLocked.Multiply(lockedPose).ToString("F3")}"); #endif // WLT_EXTRA_LOGGING ReferencePose refPose = new ReferencePose() { name = uniqueName, fragmentId = fragmentId, anchorId = anchorId, virtualPose = virtualPose }; refPose.LockedPose = lockedPose; referencePoses.Add(refPose); QueueForSave(refPose); return(anchorId); }
/// <summary> /// Update is called by the update proxy. /// </summary> private void Update() { ErrorStatus = ""; if (hasPendingLoadTask) { ErrorStatus = "pending background load task"; return; } if (AdjustmentFrame == null) { Debug.Log("No WLM update because no adjustment frame set"); ErrorStatus = "no adjustment frame"; return; } // AnchorManager.Update takes care of creating anchors&edges and feeding the up-to-date state // into the FrozenWorld engine bool hasSpongyAnchors = AnchorManager.Update(); //#if UNITY_WSA if (!hasSpongyAnchors) { // IFragmentManager.Pause() will set all fragments to disconnected. ErrorStatus = AnchorManager.ErrorStatus; FragmentManager.Pause(); return; } //#endif // UNITY_WSA try { DiagnosticRecordings.Update(); } catch (Exception exception) { Debug.LogErrorFormat("Error writing WorldLocking diagnostics record: {0}", exception); } // The basic output from the FrozenWorld engine (current fragment and its alignment) // are applied to the unity scene FragmentManager.Update(AutoRefreeze, AutoMerge); /// The following assumes a camera hierarchy like this: /// Nodes_A => AdjustmentFrame => Nodes_B => camera /// The cumulative effect of Nodes_B is to transform from Spongy space to playspace. /// Spongy space is the space that the camera moves about in, and is the space that /// coordinates coming from scene agnostic APIs like XR are in. /// (Note the MRTK APIs are in Unity's global space, not Spongy space. /// The internal structure of that graph is inconsequential here, the only dependency /// is on the cumulative transform, PlayspaceFromSpongy. /// Likewise, the cumulative effect of Nodes_A is to transform from alignment space (described below) /// to Unity's global space, referred to here as FrozenSpace. /// The AdjustmentFrame's transform is composed of two transforms. /// The first comes from the FrozenWorld engine DLL as the inverse of Plugin.GetAlignment(), /// and transforms from Playspace to the base stable world locked space, labeled as /// LockedFromPlayspace. /// The second transforms from this stable but arbitrary space to a space locked /// to a finite set of real world markers. This transform is labeled PinnedFromLocked. /// The transform chain equivalent of the above camera hierarchy is: /// FrozenFromPinned * [PinnedFromLocked * LockedFromPlayspace] * PlayspaceFromSpongy * SpongyFromCamera /// /// FrozenFromSpongy and its inverse are useful for converting between the coordinates of scene agnostic APIs (e.g. XR) /// and Frozen coordinates, i.e. Unity's global space. /// FrozenFromLocked is convenient for converting between the "frozen" coordinates of the FrozenWorld engine DLL /// and Unity's global space, i.e. Frozen coordinate. if (Enabled) { Pose playspaceFromLocked = Plugin.GetAlignment(); LockedFromPlayspace = playspaceFromLocked.Inverse(); SpongyFromCamera = Plugin.GetSpongyHead(); Pose lockedHeadPose = LockedFromPlayspace.Multiply(PlayspaceFromSpongy.Multiply(SpongyFromCamera)); alignmentManager.ComputePinnedPose(lockedHeadPose); PinnedFromLocked = alignmentManager.PinnedFromLocked; } else { SpongyFromCamera = Camera.main.transform.GetLocalPose(); /// Note leave adjustment and pinning transforms alone, to facilitate /// comparison of behavior when toggling FW enabled. } AdjustmentFrame.SetLocalPose(PinnedFromLocked.Multiply(LockedFromPlayspace)); #if false && WLT_ARSUBSYSTEMS_PRESENT if ((AdjustmentFrame.GetGlobalPose().position != Vector3.zero) || (AdjustmentFrame.GetGlobalPose().rotation != Quaternion.identity)) { Debug.Log($"WLT: Adj{AnchorManagerXR.DebugVector3("O=", AdjustmentFrame.GetGlobalPose().position)}, {AnchorManagerXR.DebugEuler("R=", AdjustmentFrame.GetGlobalPose().rotation.eulerAngles)}"); } #endif // WLT_ARSUBSYSTEMS_PRESENT AutoSaveTriggerHook(); }