/// <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);
public void SetMostSignificantSpongyAnchorId(AnchorId anchorId) { mostSignificantAnchorId = anchorId; checkError(); }
/// <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); }
unsafe public void MoveFrozenAnchor(AnchorId id, Pose frozenPose) { SetFrozenAnchorTransform(id, frozenPose); checkError(); }
public void SetMostSignificantSpongyAnchorId(AnchorId anchorId) { FrozenWorld_SetMostSignificantAnchorId(FrozenWorld_Snapshot.SPONGY, (FrozenWorld_AnchorId)anchorId); checkError(); }
public void RemoveFrozenEdge(AnchorId anchorId1, AnchorId anchorId2) { FrozenWorld_RemoveEdge(FrozenWorld_Snapshot.FROZEN, (FrozenWorld_AnchorId)anchorId1, (FrozenWorld_AnchorId)anchorId2); checkError(); }
public void RemoveFrozenAnchor(AnchorId anchorId) { FrozenWorld_RemoveAnchor(FrozenWorld_Snapshot.FROZEN, (FrozenWorld_AnchorId)anchorId); checkError(); }
/// <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); }