123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- #if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN
- #define UNITY_PLATFORM_SUPPORTS_LINEAR
- #elif UNITY_IOS || UNITY_ANDROID
- #if UNITY_5_5_OR_NEWER || (UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 && !UNITY_5_3 && !UNITY_5_4)
- #define UNITY_PLATFORM_SUPPORTS_LINEAR
- #endif
- #endif
- #if UNITY_5_4_OR_NEWER || (UNITY_5 && !UNITY_5_0)
- #define UNITY_HELPATTRIB
- #endif
- using UnityEngine;
- //-----------------------------------------------------------------------------
- // Copyright 2015-2020 RenderHeads Ltd. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace RenderHeads.Media.AVProVideo
- {
- /// <summary>
- /// Builds a cube mesh for displaying a 360 degree "Cubemap 3x2 facebook layout" texture in VR
- /// </summary>
- [RequireComponent(typeof(MeshRenderer))]
- [RequireComponent(typeof(MeshFilter))]
- //[ExecuteInEditMode]
- [AddComponentMenu("AVPro Video/Cubemap Cube (VR)", 400)]
- #if UNITY_HELPATTRIB
- [HelpURL("http://renderheads.com/products/avpro-video/")]
- #endif
- public class CubemapCube : MonoBehaviour
- {
- public enum Layout
- {
- FacebookTransform32, // Layout for Facebooks FFMPEG Transform plugin with 3:2 layout
- Facebook360Capture, // Layout for Facebooks 360-Capture-SDK
- }
- private Mesh _mesh;
- protected MeshRenderer _renderer;
- [SerializeField]
- protected Material _material = null;
- [SerializeField]
- private MediaPlayer _mediaPlayer = null;
- // This value comes from the facebook transform ffmpeg filter and is used to prevent seams appearing along the edges due to bilinear filtering
- [SerializeField]
- private float expansion_coeff = 1.01f;
- [SerializeField]
- private Layout _layout = Layout.FacebookTransform32;
- private Texture _texture;
- private bool _verticalFlip;
- private int _textureWidth;
- private int _textureHeight;
- private static int _propApplyGamma;
- private static int _propStereo;
- private static int _propUseYpCbCr;
- private const string PropChromaTexName = "_ChromaTex";
- private static int _propChromaTex;
- private const string PropYpCbCrTransformName = "_YpCbCrTransform";
- private static int _propYpCbCrTransform;
- public MediaPlayer Player
- {
- set { _mediaPlayer = value; }
- get { return _mediaPlayer; }
- }
- void Awake()
- {
- if (_propStereo == 0)
- {
- _propStereo = Shader.PropertyToID("Stereo");
- }
- if (_propApplyGamma == 0)
- {
- _propApplyGamma = Shader.PropertyToID("_ApplyGamma");
- }
- if (_propUseYpCbCr == 0)
- _propUseYpCbCr = Shader.PropertyToID("_UseYpCbCr");
- if (_propChromaTex == 0)
- _propChromaTex = Shader.PropertyToID(PropChromaTexName);
- if (_propYpCbCrTransform == 0)
- _propYpCbCrTransform = Shader.PropertyToID(PropYpCbCrTransformName);
- }
- void Start()
- {
- if (_mesh == null)
- {
- _mesh = new Mesh();
- _mesh.MarkDynamic();
- MeshFilter filter = this.GetComponent<MeshFilter>();
- if (filter != null)
- {
- filter.mesh = _mesh;
- }
- _renderer = this.GetComponent<MeshRenderer>();
- if (_renderer != null)
- {
- _renderer.material = _material;
- }
- BuildMesh();
- }
- }
- void OnDestroy()
- {
- if (_mesh != null)
- {
- MeshFilter filter = this.GetComponent<MeshFilter>();
- if (filter != null)
- {
- filter.mesh = null;
- }
- #if UNITY_EDITOR
- Mesh.DestroyImmediate(_mesh);
- #else
- Mesh.Destroy(_mesh);
- #endif
- _mesh = null;
- }
- if (_renderer != null)
- {
- _renderer.material = null;
- _renderer = null;
- }
- }
- // We do a LateUpdate() to allow for any changes in the texture that may have happened in Update()
- void LateUpdate()
- {
- if (Application.isPlaying)
- {
- Texture texture = null;
- bool requiresVerticalFlip = false;
- if (_mediaPlayer != null && _mediaPlayer.Control != null)
- {
- if (_mediaPlayer.TextureProducer != null)
- {
- Texture resamplerTex = _mediaPlayer.FrameResampler == null || _mediaPlayer.FrameResampler.OutputTexture == null ? null : _mediaPlayer.FrameResampler.OutputTexture[0];
- texture = _mediaPlayer.m_Resample ? resamplerTex : _mediaPlayer.TextureProducer.GetTexture();
- requiresVerticalFlip = _mediaPlayer.TextureProducer.RequiresVerticalFlip();
- // Detect changes that we need to apply to the material/mesh
- if (_texture != texture ||
- _verticalFlip != requiresVerticalFlip ||
- (texture != null && (_textureWidth != texture.width || _textureHeight != texture.height))
- )
- {
- _texture = texture;
- if (texture != null)
- {
- UpdateMeshUV(texture.width, texture.height, requiresVerticalFlip);
- }
- }
- #if UNITY_PLATFORM_SUPPORTS_LINEAR
- // Apply gamma
- if (_renderer.material.HasProperty(_propApplyGamma) && _mediaPlayer.Info != null)
- {
- Helper.SetupGammaMaterial(_renderer.material, _mediaPlayer.Info.PlayerSupportsLinearColorSpace());
- }
- #endif
- // Apply changes for stereo videos
- if (_renderer.material.HasProperty(_propStereo))
- {
- Helper.SetupStereoMaterial(_renderer.material, _mediaPlayer.m_StereoPacking, _mediaPlayer.m_DisplayDebugStereoColorTint);
- }
- if (_renderer.material.HasProperty(_propUseYpCbCr) && _mediaPlayer.TextureProducer.GetTextureCount() == 2)
- {
- _renderer.material.EnableKeyword("USE_YPCBCR");
- Texture resamplerTexYCRCB = _mediaPlayer.FrameResampler == null || _mediaPlayer.FrameResampler.OutputTexture == null ? null : _mediaPlayer.FrameResampler.OutputTexture[1];
- _renderer.material.SetTexture(_propChromaTex, _mediaPlayer.m_Resample ? resamplerTexYCRCB : _mediaPlayer.TextureProducer.GetTexture(1));
- _renderer.material.SetMatrix(_propYpCbCrTransform, _mediaPlayer.TextureProducer.GetYpCbCrTransform());
- }
- }
- _renderer.material.mainTexture = _texture;
- }
- else
- {
- _renderer.material.mainTexture = null;
- }
- }
- }
- private void BuildMesh()
- {
- Vector3 offset = new Vector3(-0.5f, -0.5f, -0.5f);
- Vector3[] v = new Vector3[]
- {
- // Left
- new Vector3(0f,-1f,0f) - offset,
- new Vector3(0f,0f,0f) - offset,
- new Vector3(0f,0f,-1f) - offset,
- new Vector3(0f,-1f,-1f) - offset,
- // Front
- new Vector3(0f,0f,0f) - offset,
- new Vector3(-1f,0f,0f) - offset,
- new Vector3(-1f,0f,-1f) - offset,
- new Vector3(0f,0f,-1f) - offset,
- // Right
- new Vector3(-1f,0f,0f) - offset,
- new Vector3(-1f,-1f,0f) - offset,
- new Vector3(-1f,-1f,-1f) - offset,
- new Vector3(-1f,0f,-1f) - offset,
- // Back
- new Vector3(-1f,-1f,0f) - offset,
- new Vector3(0f,-1f,0f) - offset,
- new Vector3(0f,-1f,-1f) - offset,
- new Vector3(-1f,-1f,-1f) - offset,
- // Bottom
- new Vector3(0f,-1f,-1f) - offset,
- new Vector3(0f,0f,-1f) - offset,
- new Vector3(-1f,0f,-1f) - offset,
- new Vector3(-1f,-1f,-1f) - offset,
- // Top
- new Vector3(-1f,-1f,0f) - offset,
- new Vector3(-1f,0f,0f) - offset,
- new Vector3(0f,0f,0f) - offset,
- new Vector3(0f,-1f,0f) - offset,
- };
- Matrix4x4 rot = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(-90f, Vector3.right), Vector3.one);
- for (int i = 0; i < v.Length; i++)
- {
- v[i] = rot.MultiplyPoint(v[i]);
- }
- _mesh.vertices = v;
- _mesh.triangles = new int[]
- {
- 0,1,2,
- 0,2,3,
- 4,5,6,
- 4,6,7,
- 8,9,10,
- 8,10,11,
- 12,13,14,
- 12,14,15,
- 16,17,18,
- 16,18,19,
- 20,21,22,
- 20,22,23,
- };
- _mesh.normals = new Vector3[]
- {
- // Left
- new Vector3(-1f,0f,0f),
- new Vector3(-1f,0f,0f),
- new Vector3(-1f,0f,0f),
- new Vector3(-1f,0f,0f),
- // Front
- new Vector3(0f,-1f,0f),
- new Vector3(0f,-1f,0f),
- new Vector3(0f,-1f,0f),
- new Vector3(0f,-1f,0f),
- // Right
- new Vector3(1f,0f,0f),
- new Vector3(1f,0f,0f),
- new Vector3(1f,0f,0f),
- new Vector3(1f,0f,0f),
- // Back
- new Vector3(0f,1f,0f),
- new Vector3(0f,1f,0f),
- new Vector3(0f,1f,0f),
- new Vector3(0f,1f,0f),
- // Bottom
- new Vector3(0f,0f,1f),
- new Vector3(0f,0f,1f),
- new Vector3(0f,0f,1f),
- new Vector3(0f,0f,1f),
- // Top
- new Vector3(0f,0f,-1f),
- new Vector3(0f,0f,-1f),
- new Vector3(0f,0f,-1f),
- new Vector3(0f,0f,-1f)
- };
- UpdateMeshUV(512, 512, false);
- }
- private void UpdateMeshUV(int textureWidth, int textureHeight, bool flipY)
- {
- _textureWidth = textureWidth;
- _textureHeight = textureHeight;
- _verticalFlip = flipY;
- float texWidth = textureWidth;
- float texHeight = textureHeight;
- float blockWidth = texWidth / 3f;
- float pixelOffset = Mathf.Floor(((expansion_coeff * blockWidth) - blockWidth) / 2f);
- float wO = pixelOffset / texWidth;
- float hO = pixelOffset / texHeight;
- const float third = 1f / 3f;
- const float half = 0.5f;
- Vector2[] uv = null;
- if (_layout == Layout.Facebook360Capture)
- {
- uv = new Vector2[]
- {
- //front (texture middle top) correct left
- new Vector2(third+wO, half-hO),
- new Vector2((third*2f)-wO, half-hO),
- new Vector2((third*2f)-wO, 0f+hO),
- new Vector2(third+wO, 0f+hO),
-
- //left (texture middle bottom) correct front
- new Vector2(third+wO,1f-hO),
- new Vector2((third*2f)-wO, 1f-hO),
- new Vector2((third*2f)-wO, half+hO),
- new Vector2(third+wO, half+hO),
- //bottom (texture left top) correct right
- new Vector2(0f+wO, half-hO),
- new Vector2(third-wO, half-hO),
- new Vector2(third-wO, 0f+hO),
- new Vector2(0f+wO, 0f+hO),
- //top (texture right top) correct rear
- new Vector2((third*2f)+wO, 1f-hO),
- new Vector2(1f-wO, 1f-hO),
- new Vector2(1f-wO, half+hO),
- new Vector2((third*2f)+wO, half+hO),
- //back (texture right bottom) correct ground
- new Vector2((third*2f)+wO, 0f+hO),
- new Vector2((third*2f)+wO, half-hO),
- new Vector2(1f-wO, half-hO),
- new Vector2(1f-wO, 0f+hO),
- //right (texture left bottom) correct sky
- new Vector2(third-wO, 1f-hO),
- new Vector2(third-wO, half+hO),
- new Vector2(0f+wO, half+hO),
- new Vector2(0f+wO, 1f-hO),
- };
- }
- else if (_layout == Layout.FacebookTransform32)
- {
- uv = new Vector2[]
- {
- //left
- new Vector2(third+wO,1f-hO),
- new Vector2((third*2f)-wO, 1f-hO),
- new Vector2((third*2f)-wO, half+hO),
- new Vector2(third+wO, half+hO),
- //front
- new Vector2(third+wO, half-hO),
- new Vector2((third*2f)-wO, half-hO),
- new Vector2((third*2f)-wO, 0f+hO),
- new Vector2(third+wO, 0f+hO),
- //right
- new Vector2(0f+wO, 1f-hO),
- new Vector2(third-wO, 1f-hO),
- new Vector2(third-wO, half+hO),
- new Vector2(0f+wO, half+hO),
- //back
- new Vector2((third*2f)+wO, half-hO),
- new Vector2(1f-wO, half-hO),
- new Vector2(1f-wO, 0f+hO),
- new Vector2((third*2f)+wO, 0f+hO),
- //bottom
- new Vector2(0f+wO, 0f+hO),
- new Vector2(0f+wO, half-hO),
- new Vector2(third-wO, half-hO),
- new Vector2(third-wO, 0f+hO),
- //top
- new Vector2(1f-wO, 1f-hO),
- new Vector2(1f-wO, half+hO),
- new Vector2((third*2f)+wO, half+hO),
- new Vector2((third*2f)+wO, 1f-hO)
- };
- }
- if (flipY)
- {
- for (int i = 0; i < uv.Length; i++)
- {
- uv[i].y = 1f - uv[i].y;
- }
- }
- _mesh.uv = uv;
- _mesh.UploadMeshData(false);
- }
- }
- }
|