251 lines
10 KiB
C#
251 lines
10 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.XR.ARSubsystems;
|
|
using UnityEngine.Rendering;
|
|
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace UnityEngine.XR.ARFoundation
|
|
{
|
|
/// <summary>
|
|
/// Container that pairs a <see cref="Unity.XR.ARSubsystems.XRTextureDescriptor"/> wrapping a native texture
|
|
/// object with a <c>Texture</c> that is created for the native texture object.
|
|
/// </summary>
|
|
internal struct ARTextureInfo : IEquatable<ARTextureInfo>, IDisposable
|
|
{
|
|
/// <summary>
|
|
/// Constant for whether the texture is in a linear color space.
|
|
/// </summary>
|
|
/// <value>
|
|
/// Constant for whether the texture is in a linear color space.
|
|
/// </value>
|
|
const bool k_TextureHasLinearColorSpace = false;
|
|
|
|
/// <summary>
|
|
/// The texture descriptor describing the metadata for the native texture object.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The texture descriptor describing the metadata for the native texture object.
|
|
/// </value>
|
|
public XRTextureDescriptor descriptor
|
|
{
|
|
get { return m_Descriptor; }
|
|
}
|
|
XRTextureDescriptor m_Descriptor;
|
|
|
|
/// <summary>
|
|
/// The Unity <c>Texture</c> object for the native texture.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The Unity <c>Texture</c> object for the native texture.
|
|
/// </value>
|
|
public Texture texture
|
|
{
|
|
get { return m_Texture; }
|
|
}
|
|
Texture m_Texture;
|
|
|
|
/// <summary>
|
|
/// Constructs the texture info with the given descriptor and material.
|
|
/// </summary>
|
|
/// <param name="descriptor">The texture descriptor wrapping a native texture object.</param>
|
|
public ARTextureInfo(XRTextureDescriptor descriptor)
|
|
{
|
|
m_Descriptor = descriptor;
|
|
m_Texture = CreateTexture(m_Descriptor);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resets the texture info back to the default state destroying the texture GameObject, if one exists.
|
|
/// </summary>
|
|
public void Reset()
|
|
{
|
|
m_Descriptor.Reset();
|
|
DestroyTexture();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Destroys the texture and sets the property to <c>null</c>.
|
|
/// </summary>
|
|
void DestroyTexture()
|
|
{
|
|
if (m_Texture != null)
|
|
{
|
|
UnityEngine.Object.Destroy(m_Texture);
|
|
m_Texture = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the current descriptor and creates/updates the associated texture as appropriate.
|
|
/// </summary>
|
|
/// <param name="textureInfo">The texture info to update.</param>
|
|
/// <param name="descriptor">The texture descriptor wrapping a native texture object.</param>
|
|
/// <returns>
|
|
/// The updated texture information.
|
|
/// </returns>
|
|
public static ARTextureInfo GetUpdatedTextureInfo(ARTextureInfo textureInfo, XRTextureDescriptor descriptor)
|
|
{
|
|
// If the current and given descriptors are equal, exit early from this method.
|
|
if (textureInfo.m_Descriptor.Equals(descriptor))
|
|
{
|
|
return textureInfo;
|
|
}
|
|
|
|
// If the given descriptor is invalid, destroy any existing texture, and return the default texture
|
|
// info.
|
|
if (!descriptor.valid)
|
|
{
|
|
textureInfo.DestroyTexture();
|
|
return default(ARTextureInfo);
|
|
}
|
|
|
|
DebugWarn.WhenFalse(textureInfo.m_Descriptor.dimension == TextureDimension.None || textureInfo.m_Descriptor.dimension == descriptor.dimension)?.
|
|
WithMessage($"Texture descriptor dimension should not change from {textureInfo.m_Descriptor.dimension} to {descriptor.dimension}.");
|
|
|
|
// If there is a texture already and if the descriptors have identical texture metadata, we only need
|
|
// to update the existing texture with the given native texture object.
|
|
if ((textureInfo.m_Texture != null) && textureInfo.m_Descriptor.hasIdenticalTextureMetadata(descriptor))
|
|
{
|
|
// Update the current descriptor with the given descriptor.
|
|
textureInfo.m_Descriptor = descriptor;
|
|
|
|
// Update the current texture with the native texture object.
|
|
switch(descriptor.dimension)
|
|
{
|
|
case TextureDimension.Tex3D:
|
|
((Texture3D)textureInfo.m_Texture).UpdateExternalTexture(textureInfo.m_Descriptor.nativeTexture);
|
|
break;
|
|
case TextureDimension.Tex2D:
|
|
((Texture2D)textureInfo.m_Texture).UpdateExternalTexture(textureInfo.m_Descriptor.nativeTexture);
|
|
break;
|
|
case TextureDimension.Cube:
|
|
((Cubemap)textureInfo.m_Texture).UpdateExternalTexture(textureInfo.m_Descriptor.nativeTexture);
|
|
break;
|
|
default:
|
|
throw new NotSupportedException($"'{descriptor.dimension.ToString()}' is not a supported texture type.");
|
|
}
|
|
}
|
|
// Else, we need to destroy the existing texture object and create a new texture object.
|
|
else
|
|
{
|
|
// Update the current descriptor with the given descriptor.
|
|
textureInfo.m_Descriptor = descriptor;
|
|
|
|
// Replace the current texture with a newly created texture, and update the material.
|
|
textureInfo.DestroyTexture();
|
|
textureInfo.m_Texture = CreateTexture(textureInfo.m_Descriptor);
|
|
}
|
|
|
|
return textureInfo;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create the texture object for the native texture wrapped by the valid descriptor.
|
|
/// </summary>
|
|
/// <param name="descriptor">The texture descriptor wrapping a native texture object.</param>
|
|
/// <returns>
|
|
/// If the descriptor is valid, the <c>Texture</c> object created from the texture descriptor. Otherwise,
|
|
/// <c>null</c>.
|
|
/// </returns>
|
|
static Texture CreateTexture(XRTextureDescriptor descriptor)
|
|
{
|
|
if (!descriptor.valid)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
switch(descriptor.dimension)
|
|
{
|
|
case TextureDimension.Tex3D:
|
|
return Texture3D.CreateExternalTexture(descriptor.width, descriptor.height,
|
|
descriptor.depth, descriptor.format,
|
|
(descriptor.mipmapCount != 0), descriptor.nativeTexture);
|
|
case TextureDimension.Tex2D:
|
|
var texture = Texture2D.CreateExternalTexture(descriptor.width, descriptor.height,
|
|
descriptor.format, (descriptor.mipmapCount != 0),
|
|
k_TextureHasLinearColorSpace,
|
|
descriptor.nativeTexture);
|
|
// NB: SetWrapMode needs to be the first call here, and the value passed
|
|
// needs to be kTexWrapClamp - this is due to limitations of what
|
|
// wrap modes are allowed for external textures in OpenGL (which are
|
|
// used for ARCore), as Texture::ApplySettings will eventually hit
|
|
// an assert about an invalid enum (see calls to glTexParameteri
|
|
// towards the top of ApiGLES::TextureSampler)
|
|
// reference: "3.7.14 External Textures" section of
|
|
// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
|
|
// (it shouldn't ever matter what the wrap mode is set to normally, since
|
|
// this is for a pass-through video texture, so we shouldn't ever need to
|
|
// worry about the wrap mode as textures should never "wrap")
|
|
texture.wrapMode = TextureWrapMode.Clamp;
|
|
texture.filterMode = FilterMode.Bilinear;
|
|
texture.hideFlags = HideFlags.HideAndDontSave;
|
|
return texture;
|
|
case TextureDimension.Cube:
|
|
return Cubemap.CreateExternalTexture(descriptor.width,
|
|
descriptor.format,
|
|
(descriptor.mipmapCount != 0),
|
|
descriptor.nativeTexture);
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static bool IsSupported(XRTextureDescriptor descriptor)
|
|
{
|
|
if(descriptor.dimension == TextureDimension.Tex3D)
|
|
{
|
|
return true;
|
|
}
|
|
else if(descriptor.dimension == TextureDimension.Tex2D)
|
|
{
|
|
return true;
|
|
}
|
|
else if(descriptor.dimension == TextureDimension.Cube)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
DestroyTexture();
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
int hash = 486187739;
|
|
unchecked
|
|
{
|
|
hash = hash * 486187739 + m_Descriptor.GetHashCode();
|
|
hash = hash * 486187739 + ((m_Texture == null) ? 0 : m_Texture.GetHashCode());
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
public bool Equals(ARTextureInfo other)
|
|
{
|
|
return m_Descriptor.Equals(other) && (m_Texture == other.m_Texture);
|
|
}
|
|
|
|
public override bool Equals(System.Object obj)
|
|
{
|
|
return ((obj is ARTextureInfo) && Equals((ARTextureInfo)obj));
|
|
}
|
|
|
|
public static bool operator ==(ARTextureInfo lhs, ARTextureInfo rhs)
|
|
{
|
|
return lhs.Equals(rhs);
|
|
}
|
|
|
|
public static bool operator !=(ARTextureInfo lhs, ARTextureInfo rhs)
|
|
{
|
|
return !lhs.Equals(rhs);
|
|
}
|
|
}
|
|
}
|