clean project
This commit is contained in:
@@ -0,0 +1,374 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided “AS IS” WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using System;
|
||||
|
||||
namespace OculusSampleFramework
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The rendering methods swappable via radio buttons
|
||||
/// </summary>
|
||||
public enum EUiDisplayType
|
||||
{
|
||||
EUDT_WorldGeoQuad,
|
||||
EUDT_OverlayQuad,
|
||||
EUDT_None,
|
||||
EUDT_MaxDislayTypes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Usage: demonstrate how to use overlay layers for a paneled UI system
|
||||
/// On Mobile, we support both Cylinder layer and Quad layer
|
||||
/// Press any button: it will cycle [world geometry Quad]->[overlay layer Quad]->[world geometry cylinder]->[overlay layer cylinder]
|
||||
/// On PC, only Quad layer is supported
|
||||
/// Press any button: it will cycle [world geometry Quad]->[overlay layer Quad]
|
||||
///
|
||||
/// You should be able to observe sharper and less aliased image when switch from world geometry to overlay layer.
|
||||
///
|
||||
/// </summary>
|
||||
public class OVROverlaySample : MonoBehaviour
|
||||
{
|
||||
|
||||
bool inMenu;
|
||||
|
||||
/// <summary>
|
||||
/// The string identifiers for DebugUI radio buttons
|
||||
/// </summary>
|
||||
const string ovrOverlayID = "OVROverlayID";
|
||||
const string applicationID = "ApplicationID";
|
||||
const string noneID = "NoneID";
|
||||
|
||||
/// <summary>
|
||||
/// Toggle references
|
||||
/// </summary>
|
||||
Toggle applicationRadioButton;
|
||||
Toggle noneRadioButton;
|
||||
|
||||
[Header("App vs Compositor Comparison Settings")]
|
||||
/// <summary>
|
||||
/// The main camera used to calculate reprojected OVROverlay quad
|
||||
/// </summary>
|
||||
public GameObject mainCamera;
|
||||
|
||||
/// <summary>
|
||||
/// The camera used to render UI panels
|
||||
/// </summary>
|
||||
public GameObject uiCamera;
|
||||
|
||||
/// <summary>
|
||||
/// The parents of grouped UI panels
|
||||
/// </summary>
|
||||
public GameObject uiGeoParent;
|
||||
public GameObject worldspaceGeoParent;
|
||||
|
||||
/// <summary>
|
||||
/// The OVROverlay component to pass the uiCamera rendered RT to
|
||||
/// </summary>
|
||||
public OVROverlay cameraRenderOverlay;
|
||||
|
||||
/// <summary>
|
||||
/// The OVROverlay component displaying which rendering mode is active
|
||||
/// </summary>
|
||||
public OVROverlay renderingLabelOverlay;
|
||||
|
||||
/// <summary>
|
||||
/// The quad textures to indicate the active rendering method
|
||||
/// </summary>
|
||||
public Texture applicationLabelTexture;
|
||||
public Texture compositorLabelTexture;
|
||||
|
||||
/// <summary>
|
||||
/// The resources & settings needed for the level loading simulation demo
|
||||
/// </summary>
|
||||
[Header("Level Loading Sim Settings")]
|
||||
public GameObject prefabForLevelLoadSim;
|
||||
public OVROverlay cubemapOverlay;
|
||||
public OVROverlay loadingTextQuadOverlay;
|
||||
public float distanceFromCamToLoadText;
|
||||
public float cubeSpawnRadius;
|
||||
public float heightBetweenItems;
|
||||
public int numObjectsPerLevel;
|
||||
public int numLevels;
|
||||
public int numLoopsTrigger = 500000000;
|
||||
List<GameObject> spawnedCubes = new List<GameObject>();
|
||||
|
||||
#region MonoBehaviour handler
|
||||
|
||||
void Start()
|
||||
{
|
||||
DebugUIBuilder.instance.AddLabel("OVROverlay Sample");
|
||||
DebugUIBuilder.instance.AddDivider();
|
||||
DebugUIBuilder.instance.AddLabel("Level Loading Example");
|
||||
DebugUIBuilder.instance.AddButton("Simulate Level Load", TriggerLoad);
|
||||
DebugUIBuilder.instance.AddButton("Destroy Cubes", TriggerUnload);
|
||||
DebugUIBuilder.instance.AddDivider();
|
||||
DebugUIBuilder.instance.AddLabel("OVROverlay vs. Application Render Comparison");
|
||||
DebugUIBuilder.instance.AddRadio("OVROverlay", "group", delegate (Toggle t) { RadioPressed(ovrOverlayID, "group", t); }).GetComponentInChildren<Toggle>();
|
||||
applicationRadioButton = DebugUIBuilder.instance.AddRadio("Application", "group", delegate (Toggle t) { RadioPressed(applicationID, "group", t); }).GetComponentInChildren<Toggle>();
|
||||
noneRadioButton = DebugUIBuilder.instance.AddRadio("None", "group", delegate (Toggle t) { RadioPressed(noneID, "group", t); }).GetComponentInChildren<Toggle>();
|
||||
|
||||
DebugUIBuilder.instance.Show();
|
||||
|
||||
// Start with Overlay Quad
|
||||
CameraAndRenderTargetSetup();
|
||||
cameraRenderOverlay.enabled = true;
|
||||
cameraRenderOverlay.currentOverlayShape = OVROverlay.OverlayShape.Quad;
|
||||
spawnedCubes.Capacity = numObjectsPerLevel * numLevels;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Switch ui display types
|
||||
if (OVRInput.GetDown(OVRInput.Button.Two) || OVRInput.GetDown(OVRInput.Button.Start))
|
||||
{
|
||||
if (inMenu) DebugUIBuilder.instance.Hide();
|
||||
else DebugUIBuilder.instance.Show();
|
||||
inMenu = !inMenu;
|
||||
}
|
||||
|
||||
// Trigger loading simulator via keyboard
|
||||
if (Input.GetKeyDown(KeyCode.A))
|
||||
{
|
||||
TriggerLoad();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Functions
|
||||
|
||||
/// <summary>
|
||||
/// Usage: Activate the world geometry and deactivate OVROverlay display
|
||||
/// </summary>
|
||||
void ActivateWorldGeo()
|
||||
{
|
||||
worldspaceGeoParent.SetActive(true);
|
||||
uiGeoParent.SetActive(false);
|
||||
uiCamera.SetActive(false);
|
||||
cameraRenderOverlay.enabled = false;
|
||||
renderingLabelOverlay.enabled = true;
|
||||
renderingLabelOverlay.textures[0] = applicationLabelTexture;
|
||||
Debug.Log("Switched to ActivateWorldGeo");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Usage: Activate OVROverlay display and deactivate the world geometry
|
||||
/// </summary>
|
||||
void ActivateOVROverlay()
|
||||
{
|
||||
worldspaceGeoParent.SetActive(false);
|
||||
uiCamera.SetActive(true);
|
||||
cameraRenderOverlay.enabled = true;
|
||||
uiGeoParent.SetActive(true);
|
||||
renderingLabelOverlay.enabled = true;
|
||||
renderingLabelOverlay.textures[0] = compositorLabelTexture;
|
||||
Debug.Log("Switched to ActivateOVROVerlay");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Usage: Deactivate both world geometry and OVROverlay display
|
||||
/// </summary>
|
||||
void ActivateNone()
|
||||
{
|
||||
worldspaceGeoParent.SetActive(false);
|
||||
uiCamera.SetActive(false);
|
||||
cameraRenderOverlay.enabled = false;
|
||||
uiGeoParent.SetActive(false);
|
||||
renderingLabelOverlay.enabled = false;
|
||||
Debug.Log("Switched to ActivateNone");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This function is to simulate a level load event in Unity
|
||||
/// The idea is to enable a cubemap overlay right before any action that will stall the main thread
|
||||
/// This cubemap overlay can be combined with other OVROverlay objects, such as animated textures to indicate "Loading..."
|
||||
/// </summary>
|
||||
void TriggerLoad()
|
||||
{
|
||||
StartCoroutine(WaitforOVROverlay());
|
||||
}
|
||||
|
||||
IEnumerator WaitforOVROverlay()
|
||||
{
|
||||
Transform camTransform = mainCamera.transform;
|
||||
Transform uiTextOverlayTrasnform = loadingTextQuadOverlay.transform;
|
||||
Vector3 newPos = camTransform.position + camTransform.forward * distanceFromCamToLoadText;
|
||||
newPos.y = camTransform.position.y;
|
||||
uiTextOverlayTrasnform.position = newPos;
|
||||
cubemapOverlay.enabled = true;
|
||||
loadingTextQuadOverlay.enabled = true;
|
||||
noneRadioButton.isOn = true;
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
ClearObjects();
|
||||
SimulateLevelLoad();
|
||||
cubemapOverlay.enabled = false;
|
||||
loadingTextQuadOverlay.enabled = false;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Usage: Destroy all loaded resources and switch back to world geometry rendering mode.
|
||||
/// </summary>
|
||||
void TriggerUnload()
|
||||
{
|
||||
ClearObjects();
|
||||
applicationRadioButton.isOn = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Usage: Recreate UI render target according overlay type and overlay size
|
||||
/// </summary>
|
||||
void CameraAndRenderTargetSetup()
|
||||
{
|
||||
float overlayWidth = cameraRenderOverlay.transform.localScale.x;
|
||||
float overlayHeight = cameraRenderOverlay.transform.localScale.y;
|
||||
float overlayRadius = cameraRenderOverlay.transform.localScale.z;
|
||||
|
||||
#if UNITY_ANDROID
|
||||
// Gear VR display panel resolution
|
||||
float hmdPanelResWidth = 2560;
|
||||
float hmdPanelResHeight = 1440;
|
||||
#else
|
||||
// Rift display panel resolution
|
||||
float hmdPanelResWidth = 2160;
|
||||
float hmdPanelResHeight = 1200;
|
||||
#endif
|
||||
|
||||
float singleEyeScreenPhysicalResX = hmdPanelResWidth * 0.5f;
|
||||
float singleEyeScreenPhysicalResY = hmdPanelResHeight;
|
||||
|
||||
// Calculate RT Height
|
||||
// screenSizeYInWorld : how much world unity the full screen can cover at overlayQuad's location vertically
|
||||
// pixelDensityY: pixels / world unit ( meter )
|
||||
|
||||
float halfFovY = mainCamera.GetComponent<Camera>().fieldOfView / 2;
|
||||
float screenSizeYInWorld = 2 * overlayRadius * Mathf.Tan(Mathf.Deg2Rad * halfFovY);
|
||||
float pixelDensityYPerWorldUnit = singleEyeScreenPhysicalResY / screenSizeYInWorld;
|
||||
float renderTargetHeight = pixelDensityYPerWorldUnit * overlayWidth;
|
||||
|
||||
// Calculate RT width
|
||||
float renderTargetWidth = 0.0f;
|
||||
|
||||
// screenSizeXInWorld : how much world unity the full screen can cover at overlayQuad's location horizontally
|
||||
// pixelDensityY: pixels / world unit ( meter )
|
||||
|
||||
float screenSizeXInWorld = screenSizeYInWorld * mainCamera.GetComponent<Camera>().aspect;
|
||||
float pixelDensityXPerWorldUnit = singleEyeScreenPhysicalResX / screenSizeXInWorld;
|
||||
renderTargetWidth = pixelDensityXPerWorldUnit * overlayWidth;
|
||||
|
||||
// Compute the orthographic size for the camera
|
||||
float orthographicSize = overlayHeight / 2.0f;
|
||||
float orthoCameraAspect = overlayWidth / overlayHeight;
|
||||
uiCamera.GetComponent<Camera>().orthographicSize = orthographicSize;
|
||||
uiCamera.GetComponent<Camera>().aspect = orthoCameraAspect;
|
||||
|
||||
if (uiCamera.GetComponent<Camera>().targetTexture != null)
|
||||
uiCamera.GetComponent<Camera>().targetTexture.Release();
|
||||
|
||||
RenderTexture overlayRT = new RenderTexture(
|
||||
(int)renderTargetWidth * 2,
|
||||
(int)renderTargetHeight * 2,
|
||||
0,
|
||||
RenderTextureFormat.ARGB32,
|
||||
RenderTextureReadWrite.sRGB);
|
||||
Debug.Log("Created RT of resolution w: " + renderTargetWidth + " and h: " + renderTargetHeight);
|
||||
|
||||
overlayRT.hideFlags = HideFlags.DontSave;
|
||||
overlayRT.useMipMap = true;
|
||||
overlayRT.filterMode = FilterMode.Trilinear;
|
||||
overlayRT.anisoLevel = 4;
|
||||
#if UNITY_5_5_OR_NEWER
|
||||
overlayRT.autoGenerateMips = true;
|
||||
#else
|
||||
overlayRT.generateMips = true;
|
||||
#endif
|
||||
uiCamera.GetComponent<Camera>().targetTexture = overlayRT;
|
||||
|
||||
cameraRenderOverlay.textures[0] = overlayRT;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Usage: block main thread with an empty for loop and generate a bunch of cubes around the player.
|
||||
/// </summary>
|
||||
void SimulateLevelLoad()
|
||||
{
|
||||
int numToPrint = 0;
|
||||
for (int p = 0; p < numLoopsTrigger; p++)
|
||||
{
|
||||
numToPrint++;
|
||||
}
|
||||
Debug.Log("Finished " + numToPrint + " Loops");
|
||||
Vector3 playerPos = mainCamera.transform.position;
|
||||
playerPos.y = 0.5f;
|
||||
// Generate a bunch of blocks, "blocking" the mainthread ;)
|
||||
for (int j = 0; j < numLevels; j++)
|
||||
{
|
||||
for (var i = 0; i < numObjectsPerLevel; i++)
|
||||
{
|
||||
var angle = i * Mathf.PI * 2 / numObjectsPerLevel;
|
||||
float stagger = (i % 2 == 0) ? 1.5f : 1.0f;
|
||||
var pos = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * cubeSpawnRadius * stagger;
|
||||
pos.y = j * heightBetweenItems;
|
||||
var newInst = Instantiate(prefabForLevelLoadSim, pos + playerPos, Quaternion.identity);
|
||||
var newObjTransform = newInst.transform;
|
||||
newObjTransform.LookAt(playerPos);
|
||||
Vector3 newAngle = newObjTransform.rotation.eulerAngles;
|
||||
newAngle.x = 0.0f;
|
||||
newObjTransform.rotation = Quaternion.Euler(newAngle);
|
||||
spawnedCubes.Add(newInst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Usage: destroy all created cubes and garbage collect.
|
||||
/// </summary>
|
||||
void ClearObjects()
|
||||
{
|
||||
for (int i = 0; i < spawnedCubes.Count; i++)
|
||||
{
|
||||
DestroyImmediate(spawnedCubes[i]);
|
||||
}
|
||||
spawnedCubes.Clear();
|
||||
GC.Collect();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Debug UI Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Usage: radio button handler.
|
||||
/// </summary>
|
||||
public void RadioPressed(string radioLabel, string group, Toggle t)
|
||||
{
|
||||
if (string.Compare(radioLabel, ovrOverlayID) == 0)
|
||||
{
|
||||
ActivateOVROverlay();
|
||||
}
|
||||
else if (string.Compare(radioLabel, applicationID) == 0)
|
||||
{
|
||||
ActivateWorldGeo();
|
||||
}
|
||||
else if (string.Compare(radioLabel, noneID) == 0)
|
||||
{
|
||||
ActivateNone();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d75ad87b4f70d345becda5841f29b7a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user