2021년 4학년 1학기 기업연계프로젝트2 컴퓨터소프트웨어공학과 <원광투어팀> 팀장 : 송유진 팀원 : 김나영, 이경희, 한유진
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

891 lines
39 KiB

//========= Copyright 2016-2020, HTC Corporation. All rights reserved. ===========
#pragma warning disable 0649
using HTC.UnityPlugin.Utility;
using HTC.UnityPlugin.VRModuleManagement;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
#if VIU_OCULUSVR_AVATAR
using Oculus.Avatar;
#endif
namespace HTC.UnityPlugin.Vive.OculusVRExtension
{
// Only works in playing mode
public class VIUOculusVRRenderModel : MonoBehaviour
{
private struct ChildTransforms
{
public Transform root;
public Transform attach;
}
// Name of the sub-object which represents the "local" coordinate space for each component.
public const string LOCAL_TRANSFORM_NAME = "attach";
public const string MODEL_OVERRIDE_WARNNING = "Model override is really only meant to be used in " +
"the scene view for lining things up. Use tracked device " +
"index instead to ensure the correct model is displayed for all users.";
private const uint LEFT_INDEX = 1;
private const uint RIGHT_INDEX = 2;
[Tooltip(MODEL_OVERRIDE_WARNNING)]
[SerializeField]
private string m_modelOverride;
[Tooltip("Shader to apply to model.")]
[SerializeField]
private Shader m_shaderOverride;
[Tooltip("Update transforms of components at runtime to reflect user action.")]
[SerializeField]
private bool m_updateDynamically = true;
private uint m_deviceIndex = VRModule.INVALID_DEVICE_INDEX;
private MeshFilter m_meshFilter;
private MeshRenderer m_meshRenderer;
private IndexedTable<string, ChildTransforms> m_chilTransforms = new IndexedTable<string, ChildTransforms>();
private IndexedTable<int, Material> m_materials = new IndexedTable<int, Material>();
private HashSet<string> m_loadingRenderModels = new HashSet<string>();
private bool m_isAppQuit;
#if (VIU_OCULUSVR_1_32_0_OR_NEWER || VIU_OCULUSVR_1_36_0_OR_NEWER || VIU_OCULUSVR_1_37_0_OR_NEWER) && VIU_OCULUSVR_AVATAR
private IntPtr sdkAvatar = IntPtr.Zero;
private HashSet<UInt64> assetLoadingIds = new HashSet<UInt64>();
private Dictionary<string, OvrAvatarComponent> trackedComponents =
new Dictionary<string, OvrAvatarComponent>();
private OvrAvatarTouchController ovrController;
private int renderPartCount = 0;
private Shader SurfaceShader;
private Shader SurfaceShaderSelfOccluding;
private List<OvrAvatarRenderComponent> RenderParts = new List<OvrAvatarRenderComponent>();
private ovrAvatarHandInputState inputStateLeft;
private ovrAvatarHandInputState inputStateRight;
private bool firstSkinnedUpdate = true;
private bool assetsFinishedLoading = false;
private bool isMaterialInitilized = false;
private bool isMeshInitilized = false;
private ovrAvatarControllerType m_controllerType = ovrAvatarControllerType.Quest;
#endif
private string preferedModelName
{
get
{
if (!string.IsNullOrEmpty(m_modelOverride)) { return m_modelOverride; }
#if UNITY_EDITOR
if (!Application.isPlaying)
{
return string.Empty;
}
else
#endif
{
return VRModule.GetCurrentDeviceState(m_deviceIndex).renderModelName;
}
}
}
private Shader preferedShader { get { return m_shaderOverride == null ? Shader.Find("Standard") : m_shaderOverride; } }
public bool updateDynamically { get { return m_updateDynamically; } set { m_updateDynamically = value; } }
public bool isLoadingModel { get { return m_loadingRenderModels.Count > 0; } }
public string loadedModelName { get; private set; }
public bool isModelLoaded { get { return !string.IsNullOrEmpty(loadedModelName); } }
public Shader loadedShader { get; private set; }
public string modelOverride
{
get
{
return m_modelOverride;
}
set
{
m_modelOverride = value;
LoadPreferedModel();
}
}
public Shader shaderOverride
{
get
{
return m_shaderOverride;
}
set
{
m_shaderOverride = value;
SetPreferedShader();
}
}
#if UNITY_EDITOR
private void OnValidate()
{
if (Application.isPlaying)
{
UnityEditor.EditorApplication.delayCall += () =>
{
if (!m_isAppQuit && this != null && isActiveAndEnabled)
{
LoadPreferedModel();
SetPreferedShader();
}
};
}
}
#endif
private void Update()
{
if (m_updateDynamically)
{
#if (VIU_OCULUSVR_1_32_0_OR_NEWER || VIU_OCULUSVR_1_36_0_OR_NEWER || VIU_OCULUSVR_1_37_0_OR_NEWER) && VIU_OCULUSVR_AVATAR
if (sdkAvatar == IntPtr.Zero)
{
return;
}
if (m_deviceIndex == LEFT_INDEX)
{
inputStateLeft.transform.position = transform.position;
inputStateLeft.transform.orientation = transform.rotation;
inputStateLeft.transform.scale = transform.localScale;
inputStateLeft.buttonMask = 0;
inputStateLeft.touchMask = ovrAvatarTouch.Pointing | ovrAvatarTouch.ThumbUp;
if (ViveInput.GetPress(HandRole.LeftHand, ControllerButton.AKey))
{
inputStateLeft.buttonMask |= ovrAvatarButton.One;
}
if (ViveInput.GetPress(HandRole.LeftHand, ControllerButton.BKey))
{
inputStateLeft.buttonMask |= ovrAvatarButton.Two;
}
if (ViveInput.GetPress(HandRole.LeftHand, ControllerButton.System))
{
inputStateLeft.buttonMask |= ovrAvatarButton.Three;
}
if (ViveInput.GetPress(HandRole.LeftHand, ControllerButton.Pad))
{
inputStateLeft.buttonMask |= ovrAvatarButton.Joystick;
}
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.AKeyTouch))
{
inputStateLeft.touchMask &= ~ovrAvatarTouch.ThumbUp;
inputStateLeft.touchMask |= ovrAvatarTouch.One;
}
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.BkeyTouch))
{
inputStateLeft.touchMask &= ~ovrAvatarTouch.ThumbUp;
inputStateLeft.touchMask |= ovrAvatarTouch.Two;
}
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.PadTouch))
{
inputStateLeft.touchMask &= ~ovrAvatarTouch.ThumbUp;
inputStateLeft.touchMask |= ovrAvatarTouch.Joystick;
}
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.TriggerTouch))
{
inputStateLeft.touchMask &= ~ovrAvatarTouch.Pointing;
inputStateLeft.touchMask |= ovrAvatarTouch.Index;
}
inputStateLeft.joystickX = ViveInput.GetAxis(HandRole.LeftHand, ControllerAxis.JoystickX);
inputStateLeft.joystickY = ViveInput.GetAxis(HandRole.LeftHand, ControllerAxis.JoystickY);
inputStateLeft.indexTrigger = ViveInput.GetAxis(HandRole.LeftHand, ControllerAxis.Trigger);
inputStateLeft.handTrigger = ViveInput.GetAxis(HandRole.LeftHand, ControllerAxis.CapSenseGrip);
inputStateLeft.isActive = true;
}
else if (m_deviceIndex == RIGHT_INDEX)
{
inputStateRight.transform.position = transform.position;
inputStateRight.transform.orientation = transform.rotation;
inputStateRight.transform.scale = transform.localScale;
inputStateRight.buttonMask = 0;
inputStateRight.touchMask = ovrAvatarTouch.Pointing | ovrAvatarTouch.ThumbUp;
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.AKey))
{
inputStateRight.buttonMask |= ovrAvatarButton.One;
}
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.BKey))
{
inputStateRight.buttonMask |= ovrAvatarButton.Two;
}
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.Pad))
{
inputStateRight.buttonMask |= ovrAvatarButton.Joystick;
}
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.AKeyTouch))
{
inputStateRight.touchMask &= ~ovrAvatarTouch.ThumbUp;
inputStateRight.touchMask |= ovrAvatarTouch.One;
}
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.BkeyTouch))
{
inputStateRight.touchMask &= ~ovrAvatarTouch.ThumbUp;
inputStateRight.touchMask |= ovrAvatarTouch.Two;
}
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.PadTouch))
{
inputStateRight.touchMask &= ~ovrAvatarTouch.ThumbUp;
inputStateRight.touchMask |= ovrAvatarTouch.Joystick;
}
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.TriggerTouch))
{
inputStateRight.touchMask &= ~ovrAvatarTouch.Pointing;
inputStateRight.touchMask |= ovrAvatarTouch.Index;
}
inputStateRight.joystickX = ViveInput.GetAxis(HandRole.RightHand, ControllerAxis.JoystickX);
inputStateRight.joystickY = ViveInput.GetAxis(HandRole.RightHand, ControllerAxis.JoystickY);
inputStateRight.indexTrigger = ViveInput.GetAxis(HandRole.RightHand, ControllerAxis.Trigger);
inputStateRight.handTrigger = ViveInput.GetAxis(HandRole.RightHand, ControllerAxis.CapSenseGrip);
inputStateRight.isActive = true;
}
CAPI.ovrAvatarPose_UpdateHandsWithType(sdkAvatar, inputStateLeft, inputStateRight, m_controllerType);
CAPI.ovrAvatarPose_Finalize(sdkAvatar, Time.deltaTime);
#endif
UpdateComponents();
#if VIU_OCULUSVR_1_37_0_OR_NEWER && VIU_OCULUSVR_AVATAR
if (m_deviceIndex == LEFT_INDEX)
{
ovrAvatarControllerComponent component = new ovrAvatarControllerComponent();
if (CAPI.ovrAvatarPose_GetLeftControllerComponent(sdkAvatar, ref component))
{
UpdateAvatarComponent(component.renderComponent);
}
}
else if (m_deviceIndex == RIGHT_INDEX)
{
ovrAvatarControllerComponent component = new ovrAvatarControllerComponent();
if (CAPI.ovrAvatarPose_GetRightControllerComponent(sdkAvatar, ref component))
{
UpdateAvatarComponent(component.renderComponent);
}
}
#endif
}
}
private void OnEnable()
{
LoadPreferedModel();
}
private void OnDestroy()
{
ClearModel();
}
private void OnApplicationQuit()
{
m_isAppQuit = true;
}
public void ClearModel()
{
if (!isModelLoaded) { return; }
if (m_meshRenderer != null) { Destroy(m_meshRenderer); }
if (m_meshFilter != null) { Destroy(m_meshFilter); }
for (int i = 0, imax = m_chilTransforms.Count; i < imax; ++i)
{
var c = m_chilTransforms.GetValueByIndex(i);
if (c.root == null) { continue; }
Destroy(c.root.gameObject);
}
m_chilTransforms.Clear();
m_materials.Clear();
loadedModelName = string.Empty;
loadedShader = null;
}
private void SetPreferedShader()
{
SetShader(preferedShader);
}
private void SetShader(Shader newShader)
{
if (loadedShader == newShader) { return; }
loadedShader = newShader;
if (m_materials == null) { return; }
for (int i = 0, imax = m_materials.Count; i < imax; ++i)
{
var mat = m_materials.GetValueByIndex(i);
if (mat != null)
{
mat.shader = newShader;
}
}
}
private void LoadPreferedModel()
{
LoadModel(preferedModelName);
}
private void LoadModel(string renderModelName)
{
//Debug.Log(transform.parent.parent.name + " Try LoadModel " + renderModelName);
#if UNITY_EDITOR
if (!Application.isPlaying)
{
Debug.LogWarning("LoadModel failed! This function only works in playing mode");
return;
}
#endif
if (string.IsNullOrEmpty(loadedModelName) && string.IsNullOrEmpty(renderModelName)) { return; }
if (loadedModelName == renderModelName) { return; }
if (m_loadingRenderModels.Contains(renderModelName)) { return; }
ClearModel();
if (!m_isAppQuit && !string.IsNullOrEmpty(renderModelName))
{
//Debug.Log(transform.parent.parent.name + " LoadModel " + renderModelName);
m_loadingRenderModels.Add(renderModelName);
#if VIU_OCULUSVR_1_37_0_OR_NEWER && VIU_OCULUSVR_AVATAR
OvrAvatarSDKManager.AvatarSpecRequestParams avatarSpecRequest = new OvrAvatarSDKManager.AvatarSpecRequestParams(
0,
this.AvatarSpecificationCallback,
false,
ovrAvatarAssetLevelOfDetail.Highest,
false,
ovrAvatarLookAndFeelVersion.Two,
ovrAvatarLookAndFeelVersion.One,
false);
OvrAvatarSDKManager.Instance.RequestAvatarSpecification(avatarSpecRequest);
#elif VIU_OCULUSVR_1_36_0_OR_NEWER && VIU_OCULUSVR_AVATAR
OvrAvatarSDKManager.Instance.RequestAvatarSpecification(
0,
this.AvatarSpecificationCallback,
false,
ovrAvatarAssetLevelOfDetail.Highest,
false,
ovrAvatarLookAndFeelVersion.Two,
ovrAvatarLookAndFeelVersion.One,
false);
#elif VIU_OCULUSVR_1_32_0_OR_NEWER && VIU_OCULUSVR_AVATAR
OvrAvatarSDKManager.Instance.RequestAvatarSpecification(
0,
this.AvatarSpecificationCallback,
false,
ovrAvatarAssetLevelOfDetail.Highest,
false);
#endif
}
}
private void AvatarSpecificationCallback(IntPtr avatarSpecification)
{
#if (VIU_OCULUSVR_1_32_0_OR_NEWER || VIU_OCULUSVR_1_36_0_OR_NEWER || VIU_OCULUSVR_1_37_0_OR_NEWER) && VIU_OCULUSVR_AVATAR
sdkAvatar = CAPI.ovrAvatar_Create(avatarSpecification, ovrAvatarCapabilities.All);
CAPI.ovrAvatar_SetLeftControllerVisibility(sdkAvatar, true);
CAPI.ovrAvatar_SetRightControllerVisibility(sdkAvatar, true);
//Fetch all the assets that this avatar uses.
UInt32 assetCount = CAPI.ovrAvatar_GetReferencedAssetCount(sdkAvatar);
for (UInt32 i = 0; i < assetCount; ++i)
{
UInt64 id = CAPI.ovrAvatar_GetReferencedAsset(sdkAvatar, i);
if (OvrAvatarSDKManager.Instance.GetAsset(id) == null)
{
OvrAvatarSDKManager.Instance.BeginLoadingAsset(
id,
ovrAvatarAssetLevelOfDetail.Highest,
AssetLoadedCallback);
assetLoadingIds.Add(id);
}
}
#endif
}
#if (VIU_OCULUSVR_1_32_0_OR_NEWER || VIU_OCULUSVR_1_36_0_OR_NEWER || VIU_OCULUSVR_1_37_0_OR_NEWER) && VIU_OCULUSVR_AVATAR
private void AssetLoadedCallback(OvrAvatarAsset asset)
{
assetLoadingIds.Remove(asset.assetID);
}
#endif
private void OnLoadModelComplete(string renderModelName)
{
m_loadingRenderModels.Remove(renderModelName);
if (loadedModelName == renderModelName) { return; }
if (preferedModelName != renderModelName) { return; }
if (!isActiveAndEnabled) { return; }
//Debug.Log(transform.parent.parent.name + " OnLoadModelComplete " + renderModelName);
ClearModel();
loadedModelName = renderModelName;
}
private void UpdateComponents()
{
#if (VIU_OCULUSVR_1_32_0_OR_NEWER || VIU_OCULUSVR_1_36_0_OR_NEWER || VIU_OCULUSVR_1_37_0_OR_NEWER) && VIU_OCULUSVR_AVATAR
if (assetLoadingIds.Count == 0)
{
if (!assetsFinishedLoading)
{
UpdateSDKAvatarUnityState();
assetsFinishedLoading = true;
}
}
#endif
}
#if (VIU_OCULUSVR_1_32_0_OR_NEWER || VIU_OCULUSVR_1_36_0_OR_NEWER || VIU_OCULUSVR_1_37_0_OR_NEWER) && VIU_OCULUSVR_AVATAR
private void UpdateSDKAvatarUnityState()
{
#if VIU_OCULUSVR_1_37_0_OR_NEWER && VIU_OCULUSVR_AVATAR
ovrAvatarControllerComponent controllerComponent = new ovrAvatarControllerComponent();
ovrAvatarComponent dummyComponent = new ovrAvatarComponent();
OvrAvatarTouchController controller = null;
if (m_deviceIndex == LEFT_INDEX)
{
if (CAPI.ovrAvatarPose_GetLeftControllerComponent(sdkAvatar, ref controllerComponent))
{
CAPI.ovrAvatarComponent_Get(controllerComponent.renderComponent, true, ref dummyComponent);
AddAvatarComponent(ref controller, dummyComponent);
controller.isLeftHand = true;
}
}
else if (m_deviceIndex == RIGHT_INDEX)
{
if (CAPI.ovrAvatarPose_GetRightControllerComponent(sdkAvatar, ref controllerComponent))
{
CAPI.ovrAvatarComponent_Get(controllerComponent.renderComponent, true, ref dummyComponent);
AddAvatarComponent(ref controller, dummyComponent);
controller.isLeftHand = false;
}
}
#elif (VIU_OCULUSVR_1_32_0_OR_NEWER || VIU_OCULUSVR_1_36_0_OR_NEWER) && VIU_OCULUSVR_AVATAR
//Iterate through all the render components
UInt32 componentCount = CAPI.ovrAvatarComponent_Count(sdkAvatar);
for (UInt32 i = 0; i < componentCount; i++)
{
IntPtr ptr = CAPI.ovrAvatarComponent_Get_Native(sdkAvatar, i);
ovrAvatarComponent component = (ovrAvatarComponent)Marshal.PtrToStructure(ptr, typeof(ovrAvatarComponent));
if (!trackedComponents.ContainsKey(component.name))
{
GameObject componentObject = null;
Type specificType = null;
if (specificType == null && (ovrAvatarCapabilities.All & ovrAvatarCapabilities.Hands) != 0)
{
if (m_deviceIndex == LEFT_INDEX)
{
ovrAvatarControllerComponent? controllerComponent = CAPI.ovrAvatarPose_GetLeftControllerComponent(sdkAvatar);
if (specificType == null && controllerComponent.HasValue && ptr == controllerComponent.Value.renderComponent)
{
specificType = typeof(OvrAvatarTouchController);
if (ovrController != null)
{
componentObject = ovrController.gameObject;
}
}
}
else if (m_deviceIndex == RIGHT_INDEX)
{
ovrAvatarControllerComponent? controllerComponent = CAPI.ovrAvatarPose_GetRightControllerComponent(sdkAvatar);
if (specificType == null && controllerComponent.HasValue && ptr == controllerComponent.Value.renderComponent)
{
specificType = typeof(OvrAvatarTouchController);
if (ovrController != null)
{
componentObject = ovrController.gameObject;
}
}
}
}
if (componentObject != null)
{
AddAvatarComponent(componentObject, component);
}
}
UpdateAvatarComponent(component);
}
#endif
}
#if VIU_OCULUSVR_1_37_0_OR_NEWER && VIU_OCULUSVR_AVATAR
private void AddAvatarComponent<T>(ref T root, ovrAvatarComponent nativeComponent) where T : OvrAvatarComponent
{
GameObject componentObject = new GameObject();
componentObject.name = nativeComponent.name;
componentObject.transform.SetParent(transform);
root = componentObject.AddComponent<T>();
AddRenderParts(root, nativeComponent, componentObject.transform);
}
#elif VIU_OCULUSVR_1_32_0_OR_NEWER || VIU_OCULUSVR_1_36_0_OR_NEWER
private void AddAvatarComponent(GameObject componentObject, ovrAvatarComponent component)
{
OvrAvatarComponent ovrComponent = componentObject.AddComponent<OvrAvatarComponent>();
trackedComponents.Add(component.name, ovrComponent);
AddRenderParts(ovrComponent, component, componentObject.transform);
}
#endif
private void AddRenderParts(
OvrAvatarComponent ovrComponent,
ovrAvatarComponent component,
Transform parent)
{
for (UInt32 renderPartIndex = 0; renderPartIndex < component.renderPartCount; renderPartIndex++)
{
GameObject renderPartObject = new GameObject();
renderPartObject.name = GetRenderPartName(component, renderPartIndex);
renderPartObject.transform.SetParent(parent);
renderPartObject.transform.localPosition = Vector2.zero;
renderPartObject.transform.localRotation = Quaternion.identity;
IntPtr renderPart = GetRenderPart(component, renderPartIndex);
ovrAvatarRenderPartType type = CAPI.ovrAvatarRenderPart_GetType(renderPart);
OvrAvatarRenderComponent ovrRenderPart = null;
switch (type)
{
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS:
ovrRenderPart = AddSkinnedMeshRenderPBSComponent(renderPartObject, CAPI.ovrAvatarRenderPart_GetSkinnedMeshRenderPBS(renderPart));
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2:
ovrRenderPart = AddSkinnedMeshRenderPBSV2Component(renderPartObject, CAPI.ovrAvatarRenderPart_GetSkinnedMeshRenderPBSV2(renderPart));
break;
default:
break;// throw new NotImplementedException(string.Format("Unsupported render part type: {0}", type.ToString()));
}
if (ovrRenderPart != null)
{
ovrComponent.RenderParts.Add(ovrRenderPart);
RenderParts.Add(ovrRenderPart);
}
}
}
private OvrAvatarSkinnedMeshRenderPBSComponent AddSkinnedMeshRenderPBSComponent(GameObject gameObject, ovrAvatarRenderPart_SkinnedMeshRenderPBS skinnedMeshRenderPBS)
{
OvrAvatarSkinnedMeshRenderPBSComponent skinnedMeshRenderer = gameObject.AddComponent<OvrAvatarSkinnedMeshRenderPBSComponent>();
OvrAvatarAssetMesh meshAsset = (OvrAvatarAssetMesh)OvrAvatarSDKManager.Instance.GetAsset(skinnedMeshRenderPBS.meshAssetID);
SkinnedMeshRenderer renderer = meshAsset.CreateSkinnedMeshRendererOnObject(gameObject);
#if UNITY_ANDROID
renderer.quality = SkinQuality.Bone2;
#else
renderer.quality = SkinQuality.Bone4;
#endif
renderer.updateWhenOffscreen = true;
skinnedMeshRenderer.mesh = renderer;
transform.GetChild(0).localPosition = Vector2.zero;
transform.GetChild(0).localRotation = Quaternion.identity;
transform.GetChild(0).GetComponentInChildren<OvrAvatarSkinnedMeshRenderPBSComponent>().gameObject.SetActive(false);
var shader = Shader.Find("OvrAvatar/AvatarSurfaceShaderPBS");
renderer.sharedMaterial = CreateAvatarMaterial(gameObject.name + "_material", shader);
SetMaterialOpaque(renderer.sharedMaterial);
skinnedMeshRenderer.bones = renderer.bones;
return skinnedMeshRenderer;
}
private OvrAvatarSkinnedMeshPBSV2RenderComponent AddSkinnedMeshRenderPBSV2Component(GameObject gameObject, ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2 skinnedMeshRenderPBSV2)
{
OvrAvatarSkinnedMeshPBSV2RenderComponent skinnedMeshRenderer = gameObject.AddComponent<OvrAvatarSkinnedMeshPBSV2RenderComponent>();
OvrAvatarAssetMesh meshAsset = (OvrAvatarAssetMesh)OvrAvatarSDKManager.Instance.GetAsset(skinnedMeshRenderPBSV2.meshAssetID);
SkinnedMeshRenderer renderer = meshAsset.CreateSkinnedMeshRendererOnObject(gameObject);
#if UNITY_ANDROID
renderer.quality = SkinQuality.Bone2;
#else
renderer.quality = SkinQuality.Bone4;
#endif
renderer.updateWhenOffscreen = true;
skinnedMeshRenderer.mesh = renderer;
transform.GetChild(0).localPosition = Vector2.zero;
transform.GetChild(0).localRotation = Quaternion.identity;
transform.GetChild(0).GetComponentInChildren<OvrAvatarSkinnedMeshPBSV2RenderComponent>().gameObject.SetActive(false);
var shader = Shader.Find("OvrAvatar/AvatarPBRV2Simple");
renderer.sharedMaterial = CreateAvatarMaterial(gameObject.name + "_material", shader);
SetMaterialOpaque(renderer.sharedMaterial);
skinnedMeshRenderer.bones = renderer.bones;
return skinnedMeshRenderer;
}
private Material CreateAvatarMaterial(string name, Shader shader)
{
if (shader == null)
{
throw new Exception("No shader provided for avatar material.");
}
Material mat = new Material(shader);
mat.name = name;
return mat;
}
private void SetMaterialOpaque(Material mat)
{
// Initialize shader to use geometry render queue with no blending
mat.SetOverrideTag("Queue", "Geometry");
mat.SetOverrideTag("RenderType", "Opaque");
mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
mat.DisableKeyword("_ALPHATEST_ON");
mat.DisableKeyword("_ALPHABLEND_ON");
mat.DisableKeyword("_ALPHAPREMULTIPLY_ON");
mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry;
}
private static string GetRenderPartName(ovrAvatarComponent component, uint renderPartIndex)
{
return component.name + "_renderPart_" + (int)renderPartIndex;
}
static public IntPtr GetRenderPart(ovrAvatarComponent component, UInt32 renderPartIndex)
{
long offset = Marshal.SizeOf(typeof(IntPtr)) * renderPartIndex;
IntPtr marshalPtr = new IntPtr(component.renderParts.ToInt64() + offset);
return (IntPtr)Marshal.PtrToStructure(marshalPtr, typeof(IntPtr));
}
#if VIU_OCULUSVR_1_37_0_OR_NEWER
private void UpdateAvatarComponent(IntPtr nativeComponent)
{
ovrAvatarComponent nativeAvatarComponent = new ovrAvatarComponent();
CAPI.ovrAvatarComponent_Get(nativeComponent, false, ref nativeAvatarComponent);
ConvertTransform(nativeAvatarComponent.transform, transform);
for (UInt32 renderPartIndex = 0; renderPartIndex < nativeAvatarComponent.renderPartCount; renderPartIndex++)
{
if (RenderParts.Count <= renderPartIndex)
{
break;
}
OvrAvatarRenderComponent renderComponent = RenderParts[(int)renderPartIndex];
IntPtr renderPart = OvrAvatar.GetRenderPart(nativeAvatarComponent, renderPartIndex);
ovrAvatarRenderPartType type = CAPI.ovrAvatarRenderPart_GetType(renderPart);
ovrAvatarTransform localTransform;
ovrAvatarVisibilityFlags visibilityMask;
var mesh = renderComponent.mesh;
var bones = renderComponent.bones;
switch (type)
{
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS:
visibilityMask = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetVisibilityMask(renderPart);
localTransform = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetTransform(renderPart);
if ((visibilityMask & ovrAvatarVisibilityFlags.FirstPerson) != 0)
{
renderComponent.gameObject.SetActive(true);
mesh.enabled = true;
}
UpdateSkinnedMesh(localTransform, renderPart, bones);
UInt64 albedoTextureID = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetAlbedoTextureAssetID(renderPart);
UInt64 surfaceTextureID = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetSurfaceTextureAssetID(renderPart);
mesh.sharedMaterial.SetTexture("_Albedo", OvrAvatarComponent.GetLoadedTexture(albedoTextureID));
mesh.sharedMaterial.SetTexture("_Surface", OvrAvatarComponent.GetLoadedTexture(surfaceTextureID));
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2:
visibilityMask = CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetVisibilityMask(renderPart);
localTransform = CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetTransform(renderPart);
if ((visibilityMask & ovrAvatarVisibilityFlags.FirstPerson) != 0)
{
renderComponent.gameObject.SetActive(true);
mesh.enabled = true;
}
UpdateSkinnedMesh(localTransform, renderPart, bones);
ovrAvatarPBSMaterialState materialState =
CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetPBSMaterialState(renderPart);
Texture2D diffuseTexture = OvrAvatarComponent.GetLoadedTexture(materialState.albedoTextureID);
Texture2D normalTexture = OvrAvatarComponent.GetLoadedTexture(materialState.normalTextureID);
Texture2D metallicTexture = OvrAvatarComponent.GetLoadedTexture(materialState.metallicnessTextureID);
mesh.materials[0].SetTexture("_MainTex", diffuseTexture);
mesh.materials[0].SetTexture("_NormalMap", normalTexture);
mesh.materials[0].SetTexture("_RoughnessMap", metallicTexture);
break;
default:
break;
}
}
}
#elif VIU_OCULUSVR_1_32_0_OR_NEWER || VIU_OCULUSVR_1_36_0_OR_NEWER
private void UpdateAvatarComponent(ovrAvatarComponent component)
{
for (UInt32 renderPartIndex = 0; renderPartIndex < component.renderPartCount; renderPartIndex++)
{
if (RenderParts.Count <= renderPartIndex)
{
break;
}
OvrAvatarRenderComponent renderComponent = RenderParts[(int)renderPartIndex];
IntPtr renderPart = OvrAvatar.GetRenderPart(component, renderPartIndex);
ovrAvatarRenderPartType type = CAPI.ovrAvatarRenderPart_GetType(renderPart);
switch (type)
{
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS:
var mat = renderComponent.mesh.sharedMaterial;
var bones = renderComponent.bones;
ovrAvatarVisibilityFlags visibilityMask = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetVisibilityMask(renderPart);
ovrAvatarTransform localTransform = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetTransform(renderPart);
UpdateSkinnedMesh(localTransform, renderPart, bones);
UInt64 albedoTextureID = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetAlbedoTextureAssetID(renderPart);
UInt64 surfaceTextureID = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetSurfaceTextureAssetID(renderPart);
mat.SetTexture("_Albedo", OvrAvatarComponent.GetLoadedTexture(albedoTextureID));
mat.SetTexture("_Surface", OvrAvatarComponent.GetLoadedTexture(surfaceTextureID));
break;
default:
break;
}
}
}
#endif
private void UpdateSkinnedMesh(ovrAvatarTransform localTransform, IntPtr renderPart, Transform[] bones)
{
ConvertTransform(localTransform, transform);
ovrAvatarRenderPartType type = CAPI.ovrAvatarRenderPart_GetType(renderPart);
UInt64 dirtyJoints;
switch (type)
{
case ovrAvatarRenderPartType.SkinnedMeshRender:
dirtyJoints = CAPI.ovrAvatarSkinnedMeshRender_GetDirtyJoints(renderPart);
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS:
dirtyJoints = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetDirtyJoints(renderPart);
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2:
dirtyJoints = CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetDirtyJoints(renderPart);
break;
default:
throw new Exception("Unhandled render part type: " + type);
}
for (UInt32 i = 0; i < 64; i++)
{
UInt64 dirtyMask = (ulong)1 << (int)i;
// We need to make sure that we fully update the initial position of
// Skinned mesh renderers, then, thereafter, we can only update dirty joints
if ((firstSkinnedUpdate && i < bones.Length) ||
(dirtyMask & dirtyJoints) != 0)
{
//This joint is dirty and needs to be updated
Transform targetBone = bones[i];
ovrAvatarTransform transform;
switch (type)
{
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS:
transform = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetJointTransform(renderPart, i);
break;
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2:
transform = CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetJointTransform(renderPart, i);
break;
default:
throw new Exception("Unhandled render part type: " + type);
}
ConvertTransform(transform, targetBone);
}
}
firstSkinnedUpdate = false;
}
private void ConvertTransform(ovrAvatarTransform transform, Transform target)
{
Vector3 position = transform.position;
position.z = -position.z;
Quaternion orientation = transform.orientation;
orientation.x = -orientation.x;
orientation.y = -orientation.y;
target.localPosition = position;
target.localRotation = orientation;
target.localScale = transform.scale;
}
#endif
public void SetDeviceIndex(uint index)
{
//Debug.Log(transform.parent.parent.name + " SetDeviceIndex " + index);
m_deviceIndex = index;
#if (VIU_OCULUSVR_1_32_0_OR_NEWER || VIU_OCULUSVR_1_36_0_OR_NEWER) && VIU_OCULUSVR_AVATAR
ovrController = this.GetComponent<OvrAvatarTouchController>();
#endif
#if VIU_OCULUSVR && VIU_OCULUSVR_AVATAR
var headsetType = OVRPlugin.GetSystemHeadsetType();
switch (headsetType)
{
#if !VIU_OCULUSVR_19_0_OR_NEWER
case OVRPlugin.SystemHeadset.GearVR_R320:
case OVRPlugin.SystemHeadset.GearVR_R321:
case OVRPlugin.SystemHeadset.GearVR_R322:
case OVRPlugin.SystemHeadset.GearVR_R323:
case OVRPlugin.SystemHeadset.GearVR_R324:
case OVRPlugin.SystemHeadset.GearVR_R325:
m_controllerType = ovrAvatarControllerType.Malibu;
break;
case OVRPlugin.SystemHeadset.Oculus_Go:
m_controllerType = ovrAvatarControllerType.Go;
break;
#endif
#if VIU_OCULUSVR_16_0_OR_NEWER
case OVRPlugin.SystemHeadset.Oculus_Link_Quest:
#endif
case OVRPlugin.SystemHeadset.Oculus_Quest:
#if VIU_OCULUSVR_1_37_0_OR_NEWER
case OVRPlugin.SystemHeadset.Rift_S:
m_controllerType = ovrAvatarControllerType.Quest;
break;
#endif
case OVRPlugin.SystemHeadset.Rift_DK1:
case OVRPlugin.SystemHeadset.Rift_DK2:
case OVRPlugin.SystemHeadset.Rift_CV1:
default:
m_controllerType = ovrAvatarControllerType.Touch;
break;
}
#endif
LoadPreferedModel();
}
}
}