123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- /************************************************************************************
- Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
- Licensed under the Oculus Utilities SDK License Version 1.31 (the "License"); you may not use
- the Utilities SDK except in compliance with the License, which is provided at the time of installation
- or download, or which otherwise accompanies this software in either electronic or hard copy form.
- You may obtain a copy of the License at
- https://developer.oculus.com/licenses/utilities-1.31
- Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
- under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
- ANY KIND, either express or implied. See the License for the specific language governing
- permissions and limitations under the License.
- ************************************************************************************/
- using UnityEngine;
- using System.Collections;
- using System.IO;
- /// <summary>
- /// Helper script for capture cubemap and save it into PNG or JPG file
- /// </summary>
- /// <description>
- /// How it works:
- /// 1) This script can be attached to a existing game object, you can also use prefab Assets\OVR\Prefabs\OVRCubemapCaptureProbe
- /// There are 2 ways to trigger a capture if you attached this script to a game object.
- /// * Automatic capturing: if [autoTriggerAfterLaunch] is true, a automatic capturing will be triggered after [autoTriggerDelay] seconds.
- /// * Keyboard trigger: press key [triggeredByKey], a capturing will be triggered.
- /// 2) If you like to trigger the screen capture in your code logic, just call static function [OVRCubemapCapture.TriggerCubemapCapture] with proper input arguments.
- /// </description>
- public class OVRCubemapCapture : MonoBehaviour
- {
- /// <summary>
- /// Enable the automatic screenshot trigger, which will capture a cubemap after autoTriggerDelay (seconds)
- /// </summary>
- public bool autoTriggerAfterLaunch = true;
- public float autoTriggerDelay = 1.0f;
- private float autoTriggerElapse = 0.0f;
- /// <summary>
- /// Trigger cubemap screenshot if user pressed key triggeredByKey
- /// </summary>
- public KeyCode triggeredByKey = KeyCode.F8;
- /// <summary>
- /// The complete file path for saving the cubemap screenshot, including the filename and extension
- /// if pathName is blank, screenshots will be saved into %USERPROFILE%\Documents\OVR_ScreenShot360
- /// </summary>
- public string pathName;
- /// <summary>
- /// The cube face resolution
- /// </summary>
- public int cubemapSize = 2048;
- // Update is called once per frame
- void Update()
- {
- // Trigger after autoTriggerDelay
- if (autoTriggerAfterLaunch)
- {
- autoTriggerElapse += Time.deltaTime;
- if (autoTriggerElapse >= autoTriggerDelay)
- {
- autoTriggerAfterLaunch = false;
- TriggerCubemapCapture(transform.position, cubemapSize, pathName);
- }
- }
- // Trigger by press triggeredByKey
- if ( Input.GetKeyDown( triggeredByKey ) )
- {
- TriggerCubemapCapture(transform.position, cubemapSize, pathName);
- }
- }
- /// <summary>
- /// Generate unity cubemap at specific location and save into JPG/PNG
- /// </summary>
- /// <description>
- /// Default save folder: your app's persistentDataPath
- /// Default file name: using current time OVR_hh_mm_ss.png
- /// Note1: this will take a few seconds to finish
- /// Note2: if you only want to specify path not filename, please end [pathName] with "/"
- /// </description>
- public static void TriggerCubemapCapture(Vector3 capturePos, int cubemapSize = 2048, string pathName = null)
- {
- GameObject ownerObj = new GameObject("CubemapCamera", typeof(Camera));
- ownerObj.hideFlags = HideFlags.HideAndDontSave;
- ownerObj.transform.position = capturePos;
- ownerObj.transform.rotation = Quaternion.identity;
- Camera camComponent = ownerObj.GetComponent<Camera>();
- camComponent.farClipPlane = 10000.0f;
- camComponent.enabled = false;
- Cubemap cubemap = new Cubemap(cubemapSize, TextureFormat.RGB24, false);
- RenderIntoCubemap(camComponent, cubemap);
- SaveCubemapCapture(cubemap, pathName);
- DestroyImmediate(cubemap);
- DestroyImmediate(ownerObj);
- }
- public static void RenderIntoCubemap(Camera ownerCamera, Cubemap outCubemap)
- {
- int width = (int)outCubemap.width;
- int height = (int)outCubemap.height;
- CubemapFace[] faces = new CubemapFace[] { CubemapFace.PositiveX, CubemapFace.NegativeX, CubemapFace.PositiveY, CubemapFace.NegativeY, CubemapFace.PositiveZ, CubemapFace.NegativeZ };
- Vector3[] faceAngles = new Vector3[] { new Vector3(0.0f, 90.0f, 0.0f), new Vector3(0.0f, -90.0f, 0.0f), new Vector3(-90.0f, 0.0f, 0.0f), new Vector3(90.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 180.0f, 0.0f) };
- // Backup states
- RenderTexture backupRenderTex = RenderTexture.active;
- float backupFieldOfView = ownerCamera.fieldOfView;
- float backupAspect = ownerCamera.aspect;
- Quaternion backupRot = ownerCamera.transform.rotation;
- //RenderTexture backupRT = ownerCamera.targetTexture;
- // Enable 8X MSAA
- RenderTexture faceTexture = new RenderTexture(width, height, 24);
- faceTexture.antiAliasing = 8;
- faceTexture.dimension = UnityEngine.Rendering.TextureDimension.Tex2D;
- faceTexture.hideFlags = HideFlags.HideAndDontSave;
- // For intermediate saving
- Texture2D swapTex = new Texture2D(width, height, TextureFormat.RGB24, false);
- swapTex.hideFlags = HideFlags.HideAndDontSave;
- // Capture 6 Directions
- ownerCamera.targetTexture = faceTexture;
- ownerCamera.fieldOfView = 90;
- ownerCamera.aspect = 1.0f;
- Color[] mirroredPixels = new Color[swapTex.height * swapTex.width];
- for (int i = 0; i < faces.Length; i++)
- {
- ownerCamera.transform.eulerAngles = faceAngles[i];
- ownerCamera.Render();
- RenderTexture.active = faceTexture;
- swapTex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
- // Mirror vertically to meet the standard of unity cubemap
- Color[] OrignalPixels = swapTex.GetPixels();
- for (int y1 = 0; y1 < height; y1++)
- {
- for (int x1 = 0; x1 < width; x1++)
- {
- mirroredPixels[y1 * width + x1] = OrignalPixels[((height - 1 - y1) * width) + x1];
- }
- };
- outCubemap.SetPixels(mirroredPixels, faces[i]);
- }
- outCubemap.SmoothEdges();
- // Restore states
- RenderTexture.active = backupRenderTex;
- ownerCamera.fieldOfView = backupFieldOfView;
- ownerCamera.aspect = backupAspect;
- ownerCamera.transform.rotation = backupRot;
- ownerCamera.targetTexture = backupRenderTex;
- DestroyImmediate(swapTex);
- DestroyImmediate(faceTexture);
- }
- /// <summary>
- /// Save unity cubemap into NPOT 6x1 cubemap/texture atlas in the following format PX NX PY NY PZ NZ
- /// </summary>
- /// <description>
- /// Supported format: PNG/JPG
- /// Default file name: using current time OVR_hh_mm_ss.png
- /// </description>
- public static bool SaveCubemapCapture(Cubemap cubemap, string pathName = null)
- {
- string fileName;
- string dirName;
- int width = cubemap.width;
- int height = cubemap.height;
- int x = 0;
- int y = 0;
- bool saveToPNG = true;
- if (string.IsNullOrEmpty(pathName))
- {
- dirName = Application.persistentDataPath + "/OVR_ScreenShot360/";
- fileName = null;
- }
- else
- {
- dirName = Path.GetDirectoryName(pathName);
- fileName = Path.GetFileName(pathName);
- if (dirName[dirName.Length - 1] != '/' || dirName[dirName.Length - 1] != '\\')
- dirName += "/";
- }
- if (string.IsNullOrEmpty(fileName))
- fileName = "OVR_" + System.DateTime.Now.ToString("hh_mm_ss") + ".png";
- string extName = Path.GetExtension(fileName);
- if (extName == ".png")
- {
- saveToPNG = true;
- }
- else if (extName == ".jpg")
- {
- saveToPNG = false;
- }
- else
- {
- Debug.LogError("Unsupported file format" + extName);
- return false;
- }
- // Validate path
- try
- {
- System.IO.Directory.CreateDirectory(dirName);
- }
- catch (System.Exception e)
- {
- Debug.LogError("Failed to create path " + dirName + " since " + e.ToString());
- return false;
- }
- // Create the new texture
- Texture2D tex = new Texture2D(width * 6, height, TextureFormat.RGB24, false);
- if (tex == null)
- {
- Debug.LogError("[OVRScreenshotWizard] Failed creating the texture!");
- return false;
- }
- // Merge all the cubemap faces into the texture
- // Reference cubemap format: http://docs.unity3d.com/Manual/class-Cubemap.html
- CubemapFace[] faces = new CubemapFace[] { CubemapFace.PositiveX, CubemapFace.NegativeX, CubemapFace.PositiveY, CubemapFace.NegativeY, CubemapFace.PositiveZ, CubemapFace.NegativeZ };
- for (int i = 0; i < faces.Length; i++)
- {
- // get the pixels from the cubemap
- Color[] srcPixels = null;
- Color[] pixels = cubemap.GetPixels(faces[i]);
- // if desired, flip them as they are ordered left to right, bottom to top
- srcPixels = new Color[pixels.Length];
- for (int y1 = 0; y1 < height; y1++)
- {
- for (int x1 = 0; x1 < width; x1++)
- {
- srcPixels[y1 * width + x1] = pixels[((height - 1 - y1) * width) + x1];
- }
- }
- // Copy them to the dest texture
- tex.SetPixels(x, y, width, height, srcPixels);
- x += width;
- }
- try
- {
- // Encode the texture and save it to disk
- byte[] bytes = saveToPNG ? tex.EncodeToPNG() : tex.EncodeToJPG();
- System.IO.File.WriteAllBytes(dirName + fileName, bytes);
- Debug.Log("Cubemap file created " + dirName + fileName);
- }
- catch (System.Exception e)
- {
- Debug.LogError("Failed to save cubemap file since " + e.ToString());
- return false;
- }
- DestroyImmediate(tex);
- return true;
- }
- }
|