using System;
using System.Runtime.InteropServices;
using UnityEngine.XR.ARSubsystems;
namespace UnityEngine.XR.MagicLeap
{
///
/// Contains information necessary to report on XRAnchors.
///
internal struct ReferenceFrame
{
///
/// Information necessary to construct a reference frame
///
public struct Cinfo
{
///
/// The closet coordinate frame to the requested point
///
public Pose closetCoordinateFrame;
///
/// The closest coordinate frame's UID. Necessary so we can
/// update the anchor in the future.
///
public Native.MagicLeapNativeBindings.MLCoordinateFrameUID cfuid;
///
/// The tracking state of the anchor. Necessary so we can
/// report an update if the tracking state changes.
///
public TrackingState trackingState;
///
/// The initial pose of the anchor. Necessary so we can compute
/// the transform between and the
/// anchor.
///
public Pose initialAnchorPose;
}
public ReferenceFrame(Cinfo cinfo)
{
trackableId = GenerateTrackableId();
coordinateFrame = cinfo.closetCoordinateFrame;
cfuid = cinfo.cfuid;
trackingState = cinfo.trackingState;
// Compute the delta transform between the closet coordinate frame and the anchor
m_AnchorFromCoordinateFrame = Pose.identity;
ComputeDelta(cinfo.initialAnchorPose);
}
///
/// A pose which describes the delta beteen the anchor and the closest MLCoordinateFrame.
///
Pose m_AnchorFromCoordinateFrame;
///
/// The anchor's trackable id.
///
public TrackableId trackableId { get; private set; }
///
/// The pose of the coordinate frame used as the origin when calculating the .
///
public Pose coordinateFrame { get; set; }
///
/// The UID of the closest coordinate frame
///
public Native.MagicLeapNativeBindings.MLCoordinateFrameUID cfuid { get; private set; }
///
/// The tracking state associated with the anchor
///
///
public TrackingState trackingState { get; set; }
///
/// Compute the pose of the anchor.
///
public Pose anchorPose
{
get
{
return m_AnchorFromCoordinateFrame.GetTransformedBy(coordinateFrame);
}
}
///
/// Get the reference frame as a refernce point
///
public XRAnchor anchor
{
get
{
return new XRAnchor(
trackableId,
anchorPose,
trackingState,
IntPtr.Zero);
}
}
///
/// Sets a new coordinate frame. This is different from simply setting
/// the . This method causes the anchor
/// to be computed relative to a different coordinate frame entirely.
///
/// The UID of the new coordinate frame
/// The pose of the new coordinate frame
public void SetCoordinateFrame(Native.MagicLeapNativeBindings.MLCoordinateFrameUID cfuid, Pose coordinateFrame)
{
// Compute the current anchor pose
var pose = anchorPose;
// Set new coordinate frame
this.cfuid = cfuid;
this.coordinateFrame = coordinateFrame;
// Recompute the delta transform based on the new coordinate frame
ComputeDelta(pose);
}
///
/// Sets the tracking state and returns true if the state changed.
///
/// The new tracking state
/// true if the tracking state changed.
public bool SetTrackingState(TrackingState trackingState)
{
var oldTrackingState = this.trackingState;
this.trackingState = trackingState;
return oldTrackingState != trackingState;
}
void ComputeDelta(Pose pose)
{
var invRotation = Quaternion.Inverse(coordinateFrame.rotation);
m_AnchorFromCoordinateFrame = new Pose(
invRotation * (pose.position - coordinateFrame.position),
invRotation * pose.rotation);
}
static unsafe TrackableId GenerateTrackableId()
{
var guid = Guid.NewGuid();
void* guidPtr = &guid;
return Marshal.PtrToStructure((IntPtr)guidPtr);
}
}
}