using System ;
using UnityEngine ;
using UnityEngine.Rendering ;
/// A sensor that wraps a Camera object to generate visual observations for an agent.
/// </summary>
public class CameraSensor : ISensor , IBuiltInSensor
public class CameraSensor : ISensor , IBuiltInSensor , IDisposable
{
Camera m_Camera ;
int m_Width ;
private ObservationSpec m_ObservationSpec ;
SensorCompressionType m_CompressionType ;
Texture2D m_Texture ;
/// <summary>
/// The Camera used for rendering the sensor observations.
set { m_CompressionType = value ; }
}
/// <summary>
/// Creates and returns the camera sensor.
/// </summary>
var channels = grayscale ? 1 : 3 ;
m_ObservationSpec = ObservationSpec . Visual ( height , width , channels , observationType ) ;
m_CompressionType = compression ;
m_Texture = new Texture2D ( width , height , TextureFormat . RGB24 , false ) ;
}
/// <summary>
{
using ( TimerStack . Instance . Scoped ( "CameraSensor.GetCompressedObservation" ) )
{
var texture = ObservationToTexture ( m_Camera , m_Width , m_Height ) ;
ObservationToTexture ( m_Camera , m_Texture , m_Width , m_Height ) ;
var compressed = texture . EncodeToPNG ( ) ;
DestroyTexture ( texture ) ;
var compressed = m_Texture . EncodeToPNG ( ) ;
return compressed ;
}
}
{
using ( TimerStack . Instance . Scoped ( "CameraSensor.WriteToTensor" ) )
{
var texture = ObservationToTexture ( m_Camera , m_Width , m_Height ) ;
var numWritten = writer . WriteTexture ( texture , m_Grayscale ) ;
DestroyTexture ( texture ) ;
ObservationToTexture ( m_Camera , m_Texture , m_Width , m_Height ) ;
var numWritten = writer . WriteTexture ( m_Texture , m_Grayscale ) ;
return numWritten ;
}
}
/// <summary>
/// Renders a Camera instance to a 2D texture at the corresponding resolution.
/// </summary>
/// <returns>The 2D texture.</returns>
/// <param name="texture2D">Texture2D to render to.</param>
/// <returns name="texture2D">Texture2D to render to.</returns>
public static Texture2D ObservationToTexture ( Camera obsCamera , int width , int height )
public static void ObservationToTexture ( Camera obsCamera , Texture2D texture2D , int width , int height )
{
if ( SystemInfo . graphicsDeviceType = = GraphicsDeviceType . Null )
{
var texture2D = new Texture2D ( width , height , TextureFormat . RGB24 , false ) ;
var oldRec = obsCamera . rect ;
obsCamera . rect = new Rect ( 0f , 0f , 1f , 1f ) ;
var depth = 2 4 ;
obsCamera . rect = oldRec ;
RenderTexture . active = prevActiveRt ;
RenderTexture . ReleaseTemporary ( tempRt ) ;
return texture2D ;
/// <summary>
/// Computes the observation shape for a camera sensor based on the height, width
/// and grayscale flag.
/// </summary>
/// <param name="width">Width of the image captures from the camera.</param>
/// <param name="height">Height of the image captures from the camera.</param>
/// <param name="grayscale">Whether or not to convert the image to grayscale.</param>
/// <returns>The observation shape.</returns>
internal static int [ ] GenerateShape ( int width , int height , bool grayscale )
/// <inheritdoc/>
public BuiltInSensorType GetBuiltInSensorType ( )
return new [ ] { height , width , grayscale ? 1 : 3 } ;
return BuiltInSensorType . CameraSensor ;
static void DestroyTexture ( Texture2D texture )
/// <summary>
/// Clean up the owned Texture2D.
/// </summary>
public void Dispose ( )
if ( Application . isEditor )
if ( ! ReferenceEquals ( null , m_Texture ) )
// Edit Mode tests complain if we use Destroy()
// TODO move to extension methods for UnityEngine.Object?
Object . DestroyImmediate ( texture ) ;
}
else
{
Object . Destroy ( texture ) ;
Utilities . DestroyTexture ( m_Texture ) ;
m_Texture = null ;
}
/// <inheritdoc/>
public BuiltInSensorType GetBuiltInSensorType ( )
{
return BuiltInSensorType . CameraSensor ;
}
}
}