/// <summary>
        /// Create missing spongy anchors/edges and feed plugin with up-to-date input
        /// </summary>
        /// <returns>Boolean: Has the plugin received input to provide an adjustment?</returns>
        public virtual bool Update()
        {
            ErrorStatus = "";

            if (!IsTracking())
            {
                return(LostTrackingCleanup("Lost Tracking"));
            }

            // To communicate spongyHead and spongyAnchor poses to the FrozenWorld engine, they must all be expressed
            // in the same coordinate system. Here, we do not care where this coordinate
            // system is defined and how it fluctuates over time, as long as it can be used to express the
            // relative poses of all the spongy objects within each time step.
            //
            Pose spongyHead = headTracker.GetHeadPose();

            // place new anchors 1m below head
            Pose newSpongyAnchorPose = spongyHead;

            newSpongyAnchorPose.position.y -= 1;
            newSpongyAnchorPose.rotation    = Quaternion.identity;

            var activeAnchors        = new List <AnchorPose>();
            var innerSphereAnchorIds = new List <AnchorId>();
            var outerSphereAnchorIds = new List <AnchorId>();

            float    minDistSqr      = float.PositiveInfinity;
            AnchorId minDistAnchorId = 0;

            float        maxDistSq           = 0;
            AnchorId     maxDistAnchorId     = AnchorId.Invalid;
            SpongyAnchor maxDistSpongyAnchor = null;

            List <AnchorEdge> newEdges;
            AnchorId          newId = FinalizeNewAnchor(out newEdges);

            float innerSphereRadSqr = MinNewAnchorDistance * MinNewAnchorDistance;
            float outerSphereRadSqr = MaxAnchorEdgeLength * MaxAnchorEdgeLength;

            foreach (var keyval in spongyAnchors)
            {
                var id = keyval.anchorId;
                var a  = keyval.spongyAnchor;
                if (a.IsLocated)
                {
                    Pose  aSpongyPose = a.SpongyPose;
                    float distSqr     = (aSpongyPose.position - newSpongyAnchorPose.position).sqrMagnitude;
                    var   anchorPose  = new AnchorPose()
                    {
                        anchorId = id, pose = aSpongyPose
                    };
                    activeAnchors.Add(anchorPose);
                    if (distSqr < minDistSqr)
                    {
                        minDistSqr      = distSqr;
                        minDistAnchorId = id;
                    }
                    if (distSqr <= outerSphereRadSqr && id != newId)
                    {
                        outerSphereAnchorIds.Add(id);
                        if (distSqr <= innerSphereRadSqr)
                        {
                            innerSphereAnchorIds.Add(id);
                        }
                    }
                    if (distSqr > maxDistSq)
                    {
                        maxDistSq           = distSqr;
                        maxDistAnchorId     = id;
                        maxDistSpongyAnchor = a;
                    }
                }
            }

            if (newId == 0 && innerSphereAnchorIds.Count == 0)
            {
                if (Time.unscaledTime <= lastTrackingInactiveTime + TrackingStartDelayTime)
                {
#if WLT_EXTRA_LOGGING
                    // Tracking has become active only recently. We suppress creation of new anchors while
                    // new anchors may still be in transition due to SpatialAnchor easing.
                    Debug.Log($"Skip new anchor creation because only recently gained tracking {Time.unscaledTime - lastTrackingInactiveTime}");
#endif // WLT_EXTRA_LOGGING
                }
                else if (Time.unscaledTime < lastAnchorAddTime + AnchorAddOutTime)
                {
#if WLT_EXTRA_LOGGING
                    // short timeout after creating one anchor to prevent bursts of new, unlocatable anchors
                    // in case of problems in the anchor generation
                    Debug.Log($"Skip new anchor creation because waiting on recently made anchor "
                              + $"{Time.unscaledTime - lastAnchorAddTime} "
                              + $"- {(newSpongyAnchor != null ? newSpongyAnchor.name : "null")}");
#endif // WLT_EXTRA_LOGGING
                }
                else
                {
                    PrepareNewAnchor(newSpongyAnchorPose, outerSphereAnchorIds);
                    lastAnchorAddTime = Time.unscaledTime;
                }
            }

            if (activeAnchors.Count == 0)
            {
                ErrorStatus = "No active anchors";
                return(false);
            }

            // create edges between nearby existing anchors
            if (innerSphereAnchorIds.Count >= 2)
            {
                foreach (var i in innerSphereAnchorIds)
                {
                    if (i != minDistAnchorId)
                    {
                        newEdges.Add(new AnchorEdge()
                        {
                            anchorId1 = i, anchorId2 = minDistAnchorId
                        });
                    }
                }
            }

            CheckForCull(maxDistAnchorId, maxDistSpongyAnchor);

            plugin.ClearSpongyAnchors();
            plugin.Step_Init(spongyHead);
            plugin.AddSpongyAnchors(activeAnchors);
            plugin.SetMostSignificantSpongyAnchorId(minDistAnchorId);
            plugin.AddSpongyEdges(newEdges);
            plugin.Step_Finish();

            return(true);
        }
 /// <summary>
 /// Platform dependent disposal of local anchors.
 /// </summary>
 /// <param name="id">The id of the anchor to destroy.</param>
 /// <param name="spongyAnchor">Reference to the anchor to destroy.</param>
 /// <returns>Null</returns>
 /// <remarks>
 /// The id is used to delete from any stored lists. If the SpongyAnchor hasn't been
 /// added to any lists (is still initializing), id can be AnchorId.Invalid.
 /// </remarks>
 protected abstract SpongyAnchor DestroyAnchor(AnchorId id, SpongyAnchor spongyAnchor);
 protected virtual async Task LoadAnchors(IPlugin plugin, AnchorId firstId, Transform parent, List <SpongyAnchorWithId> spongyAnchors)
 {
     await Task.CompletedTask;
 }
 /// <summary>
 /// Search input list for reference pose with given id.
 /// </summary>
 /// <param name="poseList">The list to search.</param>
 /// <param name="id">The id to search for.</param>
 /// <returns>The index in the list if found, else -1.</returns>
 private static int FindReferencePoseById(List <ReferencePose> poseList, AnchorId id)
 {
     return(poseList.FindIndex(x => x.anchorId == id));
 }
 /// <summary>
 /// Platform dependent instantiation of a local anchor at given position.
 /// </summary>
 /// <param name="id">Anchor id to give new anchor.</param>
 /// <param name="parent">Object to hang anchor off of.</param>
 /// <param name="initialPose">Pose for the anchor.</param>
 /// <returns>The new anchor</returns>
 protected abstract SpongyAnchor CreateAnchor(AnchorId id, Transform parent, Pose initialPose);
Esempio n. 6
0
 public void SetMostSignificantSpongyAnchorId(AnchorId anchorId)
 {
     mostSignificantAnchorId = anchorId;
     checkError();
 }
Esempio n. 7
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="contextAnchorId"></param>
 /// <param name="contextLocationFromAnchor"></param>
 /// <param name="frozenPosition"></param>
 /// <param name="anchorId"></param>
 /// <param name="locationFromAnchor"></param>
 /// <remarks>
 /// This noop version ignores the context/spawner hint.
 /// </remarks>
 unsafe public void CreateAttachmentPointFromSpawner(AnchorId contextAnchorId, Vector3 contextLocationFromAnchor, Vector3 frozenPosition,
                                                     out AnchorId anchorId, out Vector3 locationFromAnchor)
 {
     CreateAttachmentPointFromHead(frozenPosition, out anchorId, out locationFromAnchor);
 }
Esempio n. 8
0
 unsafe public void MoveFrozenAnchor(AnchorId id, Pose frozenPose)
 {
     SetFrozenAnchorTransform(id, frozenPose);
     checkError();
 }
Esempio n. 9
0
 public void SetMostSignificantSpongyAnchorId(AnchorId anchorId)
 {
     FrozenWorld_SetMostSignificantAnchorId(FrozenWorld_Snapshot.SPONGY, (FrozenWorld_AnchorId)anchorId);
     checkError();
 }
Esempio n. 10
0
 public void RemoveFrozenEdge(AnchorId anchorId1, AnchorId anchorId2)
 {
     FrozenWorld_RemoveEdge(FrozenWorld_Snapshot.FROZEN, (FrozenWorld_AnchorId)anchorId1, (FrozenWorld_AnchorId)anchorId2);
     checkError();
 }
Esempio n. 11
0
 public void RemoveFrozenAnchor(AnchorId anchorId)
 {
     FrozenWorld_RemoveAnchor(FrozenWorld_Snapshot.FROZEN, (FrozenWorld_AnchorId)anchorId);
     checkError();
 }
Esempio n. 12
0
 /// <summary>
 /// Check that an id is valid and refers to a known anchor.
 /// </summary>
 /// <param name="id"></param>
 /// <returns></returns>
 public static bool IsKnown(this AnchorId id)
 {
     return(id != AnchorId.Invalid && id != AnchorId.Unknown);
 }