using System;
using UnityEngine.Rendering;
using UnityEngine.XR.ARSubsystems;
using Object = UnityEngine.Object;
namespace UnityEngine.XR.ARFoundation
{
///
/// A GameObject component to manage the reflection probe settings as the environment probe changes are applied.
///
[RequireComponent(typeof(ReflectionProbe))]
[DisallowMultipleComponent]
[DefaultExecutionOrder(ARUpdateOrder.k_EnvironmentProbe)]
[HelpURL(HelpUrls.ApiWithNamespace + nameof(AREnvironmentProbe) + ".html")]
public class AREnvironmentProbe : ARTrackable
{
///
/// The reflection probe component attached to the GameObject.
///
///
/// The reflection probe component attached to the GameObject.
///
ReflectionProbe m_ReflectionProbe;
///
/// The current environment texture data wrapping the reflection probe environment texture.
///
///
/// The current environment texture data wrapping the reflection probe environment texture.
///
XRTextureDescriptor m_CurrentTextureDescriptor;
///
/// The texture info of the custom baked texture from the reflection probe.
///
///
/// The texture info of the custom baked texture from the reflection probe.
///
ARTextureInfo m_CustomBakedTextureInfo;
///
/// Specifies the texture filter mode to be used with the environment texture.
///
///
/// The texture filter mode to be used with the environment texture.
///
public FilterMode environmentTextureFilterMode
{
get => m_EnvironmentTextureFilterMode;
set
{
m_EnvironmentTextureFilterMode = value;
if ((m_ReflectionProbe != null) && (m_ReflectionProbe.customBakedTexture != null))
{
m_ReflectionProbe.customBakedTexture.filterMode = m_EnvironmentTextureFilterMode;
}
}
}
FilterMode m_EnvironmentTextureFilterMode = FilterMode.Trilinear;
///
/// The placement type (for example, manual or automatic). If manual, this probe was created by .
///
public AREnvironmentProbePlacementType placementType { get; internal set; }
///
/// The size (dimensions) of the environment probe.
///
public Vector3 size => sessionRelativeData.size;
///
/// The extents of the environment probe. This is always half the .
///
public Vector3 extents => size * .5f;
///
/// A native pointer associated with this environment probe.
/// The data pointed to by this pointer is implementation defined.
/// While the lifetime is also implementation defined, it should be valid at
/// least until the next frame.
///
public IntPtr nativePtr => sessionRelativeData.nativePtr;
///
/// The XRTextureDescriptor associated with this environment probe. This is used to generate the cubemap texture on the reflection probe component.
///
public XRTextureDescriptor textureDescriptor => m_CurrentTextureDescriptor;
///
/// Initializes the GameObject transform and reflection probe component from the scene.
///
void Awake()
{
m_ReflectionProbe = GetComponent();
// Set the reflection probe mode to use a custom baked texture.
m_ReflectionProbe.mode = ReflectionProbeMode.Custom;
}
Transform GetTrackablesParent()
{
if (AREnvironmentProbeManager.instance is AREnvironmentProbeManager manager)
{
return manager.GetComponent().trackablesParent;
}
return null;
}
internal protected override void OnAfterSetSessionRelativeData()
{
var trackablesParent = GetTrackablesParent();
if (trackablesParent && transform.parent != trackablesParent)
{
var pose = sessionRelativeData.pose;
// Compute the desired world space transform matrix for the environment probe
var desiredLocalToWorld = trackablesParent.localToWorldMatrix * Matrix4x4.TRS(pose.position, pose.rotation, sessionRelativeData.scale);
if (transform.parent)
{
// If the probe has a parent (i.e., it is not at the root), then we need to compute
// its localScale such that its final world-space scale will match what it would be
// if it were under the ARSessionOrigin.
var localToParent = transform.parent.worldToLocalMatrix * desiredLocalToWorld;
transform.localScale = localToParent.lossyScale;
}
else
{
// Otherwise, it is at the scene root, so just set its localScale is its world-space scale.
transform.localScale = desiredLocalToWorld.lossyScale;
}
}
else
{
transform.localScale = sessionRelativeData.scale;
}
// Update the environment texture if the environment texture is valid.
m_ReflectionProbe.enabled = sessionRelativeData.textureDescriptor.valid;
if (sessionRelativeData.textureDescriptor.valid)
{
UpdateEnvironmentTexture(sessionRelativeData.textureDescriptor);
}
// Update the reflection probe box.
m_ReflectionProbe.center = Vector3.zero;
m_ReflectionProbe.size = sessionRelativeData.size;
m_ReflectionProbe.boxProjection = !float.IsInfinity(m_ReflectionProbe.size.x);
// Manual placement is set by the manager. Unknown means it must have been added automatically.
if (placementType == AREnvironmentProbePlacementType.Unknown)
{
placementType = AREnvironmentProbePlacementType.Automatic;
}
}
///
/// Applies the texture data in the XRTextureDescriptor to the reflection probe settings.
///
/// The environment texture data to apply to the reflection probe baked
/// texture.
void UpdateEnvironmentTexture(XRTextureDescriptor textureDescriptor)
{
if(m_ReflectionProbe.customBakedTexture == null)
{
m_CustomBakedTextureInfo = new ARTextureInfo(textureDescriptor);
}
else
{
m_CustomBakedTextureInfo = ARTextureInfo.GetUpdatedTextureInfo(m_CustomBakedTextureInfo, textureDescriptor);
}
m_CustomBakedTextureInfo.texture.filterMode = m_EnvironmentTextureFilterMode;
m_ReflectionProbe.customBakedTexture = m_CustomBakedTextureInfo.texture as Cubemap;
// Update the current environment texture metadata.
m_CurrentTextureDescriptor = textureDescriptor;
}
///
/// Generates a string representation of this .
///
/// A string representation of this .
public override string ToString() => $"{name} [trackableId:{trackableId.ToString()}]";
void OnEnable()
{
if (AREnvironmentProbeManager.instance is AREnvironmentProbeManager manager)
{
manager.TryAddEnvironmentProbe(this);
}
else
{
pending = true;
}
}
void Update()
{
if (trackableId.Equals(TrackableId.invalidId) && AREnvironmentProbeManager.instance is AREnvironmentProbeManager manager)
{
manager.TryAddEnvironmentProbe(this);
}
}
void OnDisable()
{
if (AREnvironmentProbeManager.instance is AREnvironmentProbeManager manager)
{
manager.TryRemoveEnvironmentProbe(this);
}
}
}
}