从本文开始,介绍Unity版本的Qcom VR SDK中另一个比较重要的脚本SvrEye。 在之前的系列中讲到,SvrEye脚本是在程序运行后SvrManager动态添加到左右眼物体上的。具体SvrEye代码如下,后面章节中将具体介绍SvrEye中的属性和方法的作用。
public static List
Instances = new List
();
public enum eSide
{
Left = 1,
Right = 2,
Both = 3,
[HideInInspector]
Count = Both
};
public enum eType
{
RenderTexture = 0,
StandardTexture = 1,
EglTexture = 2,
};
public delegate void OnPostRenderCallback();
public OnPostRenderCallback OnPostRenderListener;
public delegate void OnPreRenderCallback();
public OnPreRenderCallback OnPreRenderListener;
[Tooltip("Layer depth stack")]
public int layerDepth = 0;
[Tooltip("Image display transform")]
public Camera imageCamera;
[Tooltip("Image type: 0/Camera render target, 1/Texture 2d, 2/External egl")]
public eType imageType = eType.RenderTexture;
[Tooltip("Image texture used when ImageType is StandardTexture")]
public Texture imageTexture;
[Tooltip("Image transform for scale, rotation and position (optional)")]
public Transform imageTransform;
[Tooltip("Image display region (camera clip space)")]
public Vector4 clipLowerLeft = new Vector4(-1, -1, 0, 1);
public Vector4 clipUpperLeft = new Vector4(-1, 1, 0, 1);
public Vector4 clipUpperRight = new Vector4(1, 1, 0, 1);
public Vector4 clipLowerRight = new Vector4(1, -1, 0, 1);
[Tooltip("Image source region (texture uv space)")]
public Vector2 uvLowerLeft = new Vector2(0, 0);
public Vector2 uvUpperLeft = new Vector2(0, 1);
public Vector2 uvUpperRight = new Vector2(1, 1);
public Vector2 uvLowerRight = new Vector2(1, 0);
[Tooltip("Render target scale factor")]
public float resolutionScaleFactor = 1.0f;
[Tooltip("Side mask")]
public eSide side = eSide.Both;
private float fovMargin = 0f;
private RenderTextureFormat format = RenderTextureFormat.Default;
private Vector2 resolution = new Vector2(1024.0f, 1024.0f);
private int antiAliasing = 1;
private int depth = 24;
private int frustumType = 0;
private const int bufferCount = 3;
private RenderTexture[] eyeTextures = new RenderTexture[bufferCount];
private int[] eyeTextureIds = new int[bufferCount];
private int currentTextureIndex = 0;
private Camera[] mainCameras = null;
private bool dirty = false;
private Coroutine recreateBuffersCoroutine = null;
public int CompareTo(SvrEye that)
{
return this.layerDepth.CompareTo(that.layerDepth);
}
public float FovMargin
{
get { return fovMargin; }
set { fovMargin = value; }
}
public int FrustumType
{
get { return frustumType; }
set { frustumType = value; }
}
public void SetImage(Texture2D texture)
{
imageTexture = texture;
InitializeBuffers();
}
public eType ImageType
{
get { return imageType; }
set { imageType = value; }
}
public eSide Side
{
get { return side; }
set { side = value; }
}
public RenderTextureFormat Format
{
get { return format; }
set { SetDirty(format != value); format = value; }
}
public int AntiAliasing
{
get { return antiAliasing; }
set { SetDirty(antiAliasing != value); antiAliasing = value; }
}
public int Depth
{
get { return depth; }
set { SetDirty(depth != value); depth = value; }
}
public Vector2 Resolution
{
get { return resolution; }
set { SetDirty(!Mathf.Approximately(resolution.x, value.x) || !Mathf.Approximately(resolution.y, value.y)); resolution = value; }
}
public float ResolutionScaleFactor
{
get { return resolutionScaleFactor; }
set { SetDirty(!Mathf.Approximately(resolutionScaleFactor, value)); resolutionScaleFactor = value; }
}
void SetDirty(bool value)
{
dirty = dirty == true ? true : value;
}
public int TextureId
{
get { return eyeTextureIds[currentTextureIndex]; }
set { eyeTextureIds[currentTextureIndex] = value; }
}
public Texture TexturePtr
{
get { return (imageTexture != null ? imageTexture : (Texture)eyeTextures[currentTextureIndex]); }
}
void Awake()
{
Instances.Add(this);
AcquireComponents();
InitializeCoords();
}
void OnDestroy()
{
Instances.Remove(this);
}
void AcquireComponents()
{
if (imageCamera == null) imageCamera = gameObject.GetComponent
();
Debug.Assert(imageCamera != null, "ImageCamera object required");
mainCameras = imageCamera.GetComponentsInChildren
();
}
void Start()
{
//Initialize(); Called by SvrManager.InitializeEyes()
}
void LateUpdate()
{
UpdateCoords();
}
public void Initialize()
{
InitializeBuffers();
InitializeCameras();
}
void InitializeBuffers()
{
for (int i = 0; i < bufferCount; ++i)
{
if (eyeTextures
!= null) eyeTextures.Release(); switch(imageType) { case eType.RenderTexture: eyeTextures= new RenderTexture((int)(resolution.x * resolutionScaleFactor), (int)(resolution.y * resolutionScaleFactor), depth, format); eyeTextures.antiAliasing = antiAliasing; eyeTextures.Create(); eyeTextureIds= eyeTextures.GetNativeTexturePtr().ToInt32(); Debug.Log("Create Render Texture with ID: " + eyeTextureIds+ " Width: " + eyeTextures.width + " Height: " + eyeTextures.height + " AA: " + eyeTextures.antiAliasing); break; case eType.StandardTexture: if (imageTexture) eyeTextureIds= imageTexture.GetNativeTexturePtr().ToInt32(); break; case eType.EglTexture: eyeTextureIds= 0; break; } } dirty = false; } void InitializeCameras() { ... } void InitializeCoords() { ... } void UpdateCoords() { if (imageTransform == null) return; var viewCamera = mainCameras[0]; if (viewCamera == null) return; var extents = 0.5f * Vector3.one; var center = Vector3.zero; var worldLowerLeft = new Vector4(center.x - extents.x, center.y - extents.y, 0, 1); var worldUpperLeft = new Vector4(center.x - extents.x, center.y + extents.y, 0, 1); var worldUpperRight = new Vector4(center.x + extents.x, center.y + extents.y, 0, 1); var worldLowerRight = new Vector4(center.x + extents.x, center.y - extents.y, 0, 1); Matrix4x4 MVP = viewCamera.projectionMatrix * viewCamera.worldToCameraMatrix * imageTransform.localToWorldMatrix; clipLowerLeft = MVP * worldLowerLeft; clipUpperLeft = MVP * worldUpperLeft; clipUpperRight = MVP * worldUpperRight; clipLowerRight = MVP * worldLowerRight; } void OnPreRender() { ... } void SwapBuffers() { if (imageType != eType.RenderTexture) return; currentTextureIndex = ++currentTextureIndex % bufferCount; var targetTexture = eyeTextures[currentTextureIndex]; if (targetTexture == null) return; for (int i = 0; i < mainCameras.Length; i++) { mainCameras.targetTexture = targetTexture; } targetTexture.DiscardContents(); } void OnPostRender() { RecreateBuffersIfDirty(); if (OnPostRenderListener != null) { OnPostRenderListener(); } }
void RecreateBuffersIfDirty() { if (dirty) { if (recreateBuffersCoroutine != null) { StopCoroutine(recreateBuffersCoroutine); recreateBuffersCoroutine = null; } recreateBuffersCoroutine = StartCoroutine(RecreateBuffersDeferred()); dirty = false; } }
IEnumerator RecreateBuffersDeferred() { int i = 0; while (i < bufferCount) { int index = currentTextureIndex - 1; index = index >= 0 ? index : bufferCount - 1; if (eyeTextures[index] != null) eyeTextures[index].Release(); switch (imageType) { case eType.RenderTexture: eyeTextures[index] = new RenderTexture((int)(resolution.x * resolutionScaleFactor), (int)(resolution.y * resolutionScaleFactor), depth, format); eyeTextures[index].antiAliasing = antiAliasing; eyeTextures[index].Create(); eyeTextureIds[index] = eyeTextures[index].GetNativeTexturePtr().ToInt32(); Debug.Log("Re-create Render Texture with ID: " + eyeTextureIds[index] + " Width: " + eyeTextures[index].width + " Height: " + eyeTextures[index].height + " AA: " + eyeTextures[index].antiAliasing); break; case eType.StandardTexture: if (imageTexture) eyeTextureIds[index] = imageTexture.GetNativeTexturePtr().ToInt32(); break; case eType.EglTexture: eyeTextureIds[index] = 0; break; } int prevTextureIndex = currentTextureIndex; yield return new WaitUntil(() => currentTextureIndex != prevTextureIndex); i++; } yield break; }
|