1114 lines
34 KiB
C#
1114 lines
34 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using BitStrap;
|
|
using Oculus.Avatar;
|
|
using UnityEngine;
|
|
|
|
public class OvrAvatar : MonoBehaviour
|
|
{
|
|
public class PacketEventArgs : EventArgs
|
|
{
|
|
public readonly OvrAvatarPacket Packet;
|
|
|
|
public PacketEventArgs(OvrAvatarPacket packet)
|
|
{
|
|
Packet = packet;
|
|
}
|
|
}
|
|
|
|
public enum HandType
|
|
{
|
|
Right = 0,
|
|
Left = 1,
|
|
Max = 2
|
|
}
|
|
|
|
public enum HandJoint
|
|
{
|
|
HandBase = 0,
|
|
IndexBase = 1,
|
|
IndexTip = 2,
|
|
ThumbBase = 3,
|
|
ThumbTip = 4,
|
|
Max = 5
|
|
}
|
|
|
|
public OvrAvatarMaterialManager DefaultBodyMaterialManager;
|
|
|
|
public OvrAvatarMaterialManager DefaultHandMaterialManager;
|
|
|
|
public OvrAvatarDriver Driver;
|
|
|
|
internal OvrAvatarBase Base;
|
|
|
|
internal OvrAvatarTouchController ControllerLeft;
|
|
|
|
internal OvrAvatarTouchController ControllerRight;
|
|
|
|
internal OvrAvatarBody Body;
|
|
|
|
internal OvrAvatarHand HandLeft;
|
|
|
|
internal OvrAvatarHand HandRight;
|
|
|
|
[ReadOnly]
|
|
public Transform leftControllerAnchor;
|
|
|
|
[ReadOnly]
|
|
public Transform rightControllerAnchor;
|
|
|
|
[Header("Oculus User ID")]
|
|
public string oculusUserID;
|
|
|
|
internal ulong oculusUserIDInternal;
|
|
|
|
[Header("Capabilities")]
|
|
public bool EnableBody = true;
|
|
|
|
public bool EnableHands = true;
|
|
|
|
public bool EnableBase = true;
|
|
|
|
public bool EnableExpressive;
|
|
|
|
[Header("Network")]
|
|
public bool RecordPackets;
|
|
|
|
public bool UseSDKPackets = true;
|
|
|
|
public PacketRecordSettings PacketSettings = new PacketRecordSettings();
|
|
|
|
[Header("Other")]
|
|
public bool StartWithControllers;
|
|
|
|
public AvatarLayer FirstPersonLayer;
|
|
|
|
public AvatarLayer ThirdPersonLayer;
|
|
|
|
public bool ShowFirstPerson = true;
|
|
|
|
public bool ShowThirdPerson;
|
|
|
|
public bool CanOwnMicrophone = true;
|
|
|
|
internal ovrAvatarCapabilities Capabilities = ovrAvatarCapabilities.Body;
|
|
|
|
[Tooltip("Enable this to use transparent queue, disable to use for geometry queue. Requires restart to take effect.")]
|
|
[Header("Shaders")]
|
|
public bool UseTransparentRenderQueue = true;
|
|
|
|
public Shader Monochrome_SurfaceShader;
|
|
|
|
public Shader Monochrome_SurfaceShader_SelfOccluding;
|
|
|
|
public Shader Monochrome_SurfaceShader_PBS;
|
|
|
|
public Shader Skinshaded_SurfaceShader_SingleComponent;
|
|
|
|
public Shader Skinshaded_VertFrag_SingleComponent;
|
|
|
|
public Shader Skinshaded_VertFrag_CombinedMesh;
|
|
|
|
public Shader Skinshaded_Expressive_SurfaceShader_SingleComponent;
|
|
|
|
public Shader Skinshaded_Expressive_VertFrag_SingleComponent;
|
|
|
|
public Shader Skinshaded_Expressive_VertFrag_CombinedMesh;
|
|
|
|
public Shader Loader_VertFrag_CombinedMesh;
|
|
|
|
public Shader EyeLens;
|
|
|
|
private static readonly Vector3 MOUTH_HEAD_OFFSET;
|
|
|
|
private const string MOUTH_HELPER_NAME = "MouthAnchor";
|
|
|
|
private OVRLipSyncMicInput micInput;
|
|
|
|
private OVRLipSyncContext lipsyncContext;
|
|
|
|
private OVRLipSync.Frame currentFrame = new OVRLipSync.Frame();
|
|
|
|
private float[] visemes = new float[15];
|
|
|
|
private AudioSource audioSource;
|
|
|
|
private ONSPAudioSource spatializedSource;
|
|
|
|
private int renderPartCount;
|
|
|
|
private bool showLeftController;
|
|
|
|
private bool showRightController;
|
|
|
|
private List<float[]> voiceUpdates = new List<float[]>();
|
|
|
|
private bool CombineMeshes;
|
|
|
|
private bool ForceMobileTextureFormat;
|
|
|
|
private bool WaitingForCombinedMesh;
|
|
|
|
public IntPtr sdkAvatar = IntPtr.Zero;
|
|
|
|
private HashSet<ulong> assetLoadingIds = new HashSet<ulong>();
|
|
|
|
private Dictionary<string, OvrAvatarComponent> trackedComponents = new Dictionary<string, OvrAvatarComponent>();
|
|
|
|
private bool assetsFinishedLoading;
|
|
|
|
private static bool doneExpressiveGlobalInit;
|
|
|
|
[Header("Misc")]
|
|
public GameObject MouthAnchor;
|
|
|
|
public Transform LeftHandCustomPose;
|
|
|
|
public Transform RightHandCustomPose;
|
|
|
|
private Transform cachedLeftHandCustomPose;
|
|
|
|
private Transform[] cachedCustomLeftHandJoints;
|
|
|
|
private ovrAvatarTransform[] cachedLeftHandTransforms;
|
|
|
|
private Transform cachedRightHandCustomPose;
|
|
|
|
private Transform[] cachedCustomRightHandJoints;
|
|
|
|
private ovrAvatarTransform[] cachedRightHandTransforms;
|
|
|
|
private Vector4 clothingAlphaOffset = new Vector4(0f, 0f, 0f, 1f);
|
|
|
|
private ulong clothingAlphaTexture;
|
|
|
|
private OvrAvatarPacket CurrentUnityPacket;
|
|
|
|
private static string[,] HandJoints;
|
|
|
|
internal ovrAvatarAssetLevelOfDetail LevelOfDetail = ovrAvatarAssetLevelOfDetail.Highest;
|
|
|
|
internal ovrAvatarLookAndFeelVersion LookAndFeelVersion = ovrAvatarLookAndFeelVersion.Two;
|
|
|
|
internal ovrAvatarLookAndFeelVersion FallbackLookAndFeelVersion;
|
|
|
|
private static ovrAvatarVisemes RuntimeVisemes;
|
|
|
|
public EventHandler<PacketEventArgs> PacketRecorded;
|
|
|
|
private static Vector3 MOUTH_POSITION_OFFSET;
|
|
|
|
private static string VOICE_PROPERTY;
|
|
|
|
private static string MOUTH_POSITION_PROPERTY;
|
|
|
|
private static string MOUTH_DIRECTION_PROPERTY;
|
|
|
|
private static string MOUTH_SCALE_PROPERTY;
|
|
|
|
private static float MOUTH_SCALE_GLOBAL;
|
|
|
|
private static float MOUTH_MAX_GLOBAL;
|
|
|
|
private static string NECK_JONT;
|
|
|
|
public float VoiceAmplitude;
|
|
|
|
public bool EnableMouthVertexAnimation;
|
|
|
|
static OvrAvatar()
|
|
{
|
|
MOUTH_HEAD_OFFSET = new Vector3(0f, -0.085f, 0.09f);
|
|
doneExpressiveGlobalInit = false;
|
|
HandJoints = new string[2, 5]
|
|
{
|
|
{ "hands:r_hand_world", "hands:r_hand_world/hands:b_r_hand/hands:b_r_index1", "hands:r_hand_world/hands:b_r_hand/hands:b_r_index1/hands:b_r_index2/hands:b_r_index3/hands:b_r_index_ignore", "hands:r_hand_world/hands:b_r_hand/hands:b_r_thumb1/hands:b_r_thumb2", "hands:r_hand_world/hands:b_r_hand/hands:b_r_thumb1/hands:b_r_thumb2/hands:b_r_thumb3/hands:b_r_thumb_ignore" },
|
|
{ "hands:l_hand_world", "hands:l_hand_world/hands:b_l_hand/hands:b_l_index1", "hands:l_hand_world/hands:b_l_hand/hands:b_l_index1/hands:b_l_index2/hands:b_l_index3/hands:b_l_index_ignore", "hands:l_hand_world/hands:b_l_hand/hands:b_l_thumb1/hands:b_l_thumb2", "hands:l_hand_world/hands:b_l_hand/hands:b_l_thumb1/hands:b_l_thumb2/hands:b_l_thumb3/hands:b_l_thumb_ignore" }
|
|
};
|
|
MOUTH_POSITION_OFFSET = new Vector3(0f, -0.018f, 0.1051f);
|
|
VOICE_PROPERTY = "_Voice";
|
|
MOUTH_POSITION_PROPERTY = "_MouthPosition";
|
|
MOUTH_DIRECTION_PROPERTY = "_MouthDirection";
|
|
MOUTH_SCALE_PROPERTY = "_MouthEffectScale";
|
|
MOUTH_SCALE_GLOBAL = 0.007f;
|
|
MOUTH_MAX_GLOBAL = 0.007f;
|
|
NECK_JONT = "root_JNT/body_JNT/chest_JNT/neckBase_JNT/neck_JNT";
|
|
RuntimeVisemes.visemeParams = new float[32];
|
|
RuntimeVisemes.visemeParamCount = 15u;
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
if ((bool)VRControllersManager.Instance && (bool)ControllerRight)
|
|
{
|
|
VRControllersManager.Instance.ChangeAvatar(this);
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (sdkAvatar != IntPtr.Zero)
|
|
{
|
|
CAPI.ovrAvatar_Destroy(sdkAvatar);
|
|
}
|
|
}
|
|
|
|
public void AssetLoadedCallback(OvrAvatarAsset asset)
|
|
{
|
|
assetLoadingIds.Remove(asset.assetID);
|
|
}
|
|
|
|
public void CombinedMeshLoadedCallback(IntPtr assetPtr)
|
|
{
|
|
if (WaitingForCombinedMesh)
|
|
{
|
|
ulong[] array = CAPI.ovrAvatarAsset_GetCombinedMeshIDs(assetPtr);
|
|
ulong[] array2 = array;
|
|
foreach (ulong item in array2)
|
|
{
|
|
assetLoadingIds.Remove(item);
|
|
}
|
|
CAPI.ovrAvatar_GetCombinedMeshAlphaData(sdkAvatar, ref clothingAlphaTexture, ref clothingAlphaOffset);
|
|
WaitingForCombinedMesh = false;
|
|
}
|
|
}
|
|
|
|
private void AddAvatarComponent(GameObject componentObject, ovrAvatarComponent component)
|
|
{
|
|
OvrAvatarComponent ovrAvatarComponent2 = componentObject.AddComponent<OvrAvatarComponent>();
|
|
trackedComponents.Add(component.name, ovrAvatarComponent2);
|
|
if (ovrAvatarComponent2.name == "body")
|
|
{
|
|
ovrAvatarComponent2.ClothingAlphaOffset = clothingAlphaOffset;
|
|
ovrAvatarComponent2.ClothingAlphaTexture = clothingAlphaTexture;
|
|
}
|
|
AddRenderParts(ovrAvatarComponent2, component, componentObject.transform);
|
|
}
|
|
|
|
private OvrAvatarSkinnedMeshRenderComponent AddSkinnedMeshRenderComponent(GameObject gameObject, ovrAvatarRenderPart_SkinnedMeshRender skinnedMeshRender)
|
|
{
|
|
OvrAvatarSkinnedMeshRenderComponent ovrAvatarSkinnedMeshRenderComponent = gameObject.AddComponent<OvrAvatarSkinnedMeshRenderComponent>();
|
|
ovrAvatarSkinnedMeshRenderComponent.Initialize(skinnedMeshRender, Monochrome_SurfaceShader, Monochrome_SurfaceShader_SelfOccluding, ThirdPersonLayer.layerIndex, FirstPersonLayer.layerIndex, renderPartCount++);
|
|
return ovrAvatarSkinnedMeshRenderComponent;
|
|
}
|
|
|
|
private OvrAvatarSkinnedMeshRenderPBSComponent AddSkinnedMeshRenderPBSComponent(GameObject gameObject, ovrAvatarRenderPart_SkinnedMeshRenderPBS skinnedMeshRenderPBS)
|
|
{
|
|
OvrAvatarSkinnedMeshRenderPBSComponent ovrAvatarSkinnedMeshRenderPBSComponent = gameObject.AddComponent<OvrAvatarSkinnedMeshRenderPBSComponent>();
|
|
ovrAvatarSkinnedMeshRenderPBSComponent.Initialize(skinnedMeshRenderPBS, Monochrome_SurfaceShader_PBS, ThirdPersonLayer.layerIndex, FirstPersonLayer.layerIndex, renderPartCount++);
|
|
return ovrAvatarSkinnedMeshRenderPBSComponent;
|
|
}
|
|
|
|
private OvrAvatarSkinnedMeshPBSV2RenderComponent AddSkinnedMeshRenderPBSV2Component(IntPtr renderPart, GameObject go, ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2 skinnedMeshRenderPBSV2, OvrAvatarMaterialManager materialManager, bool isBodyPartZero, bool isControllerModel)
|
|
{
|
|
OvrAvatarSkinnedMeshPBSV2RenderComponent ovrAvatarSkinnedMeshPBSV2RenderComponent = go.AddComponent<OvrAvatarSkinnedMeshPBSV2RenderComponent>();
|
|
ovrAvatarSkinnedMeshPBSV2RenderComponent.Initialize(renderPart, skinnedMeshRenderPBSV2, materialManager, ThirdPersonLayer.layerIndex, FirstPersonLayer.layerIndex, renderPartCount++, isBodyPartZero && CombineMeshes, LevelOfDetail, isBodyPartZero && EnableExpressive, this, isControllerModel);
|
|
return ovrAvatarSkinnedMeshPBSV2RenderComponent;
|
|
}
|
|
|
|
private OvrAvatarProjectorRenderComponent AddProjectorRenderComponent(GameObject gameObject, ovrAvatarRenderPart_ProjectorRender projectorRender)
|
|
{
|
|
ovrAvatarComponent ovrAvatarComponent2 = CAPI.ovrAvatarComponent_Get(sdkAvatar, projectorRender.componentIndex);
|
|
OvrAvatarComponent value;
|
|
if (trackedComponents.TryGetValue(ovrAvatarComponent2.name, out value) && projectorRender.renderPartIndex < value.RenderParts.Count)
|
|
{
|
|
OvrAvatarRenderComponent target = value.RenderParts[(int)projectorRender.renderPartIndex];
|
|
OvrAvatarProjectorRenderComponent ovrAvatarProjectorRenderComponent = gameObject.AddComponent<OvrAvatarProjectorRenderComponent>();
|
|
ovrAvatarProjectorRenderComponent.InitializeProjectorRender(projectorRender, Monochrome_SurfaceShader, target);
|
|
return ovrAvatarProjectorRenderComponent;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static IntPtr GetRenderPart(ovrAvatarComponent component, uint renderPartIndex)
|
|
{
|
|
long num = Marshal.SizeOf(typeof(IntPtr)) * renderPartIndex;
|
|
IntPtr ptr = new IntPtr(component.renderParts.ToInt64() + num);
|
|
return (IntPtr)Marshal.PtrToStructure(ptr, typeof(IntPtr));
|
|
}
|
|
|
|
private void UpdateAvatarComponent(ovrAvatarComponent component)
|
|
{
|
|
OvrAvatarComponent value;
|
|
if (!trackedComponents.TryGetValue(component.name, out value))
|
|
{
|
|
throw new Exception(string.Format("trackedComponents didn't have {0}", component.name));
|
|
}
|
|
value.UpdateAvatar(component, this);
|
|
}
|
|
|
|
private static string GetRenderPartName(ovrAvatarComponent component, uint renderPartIndex)
|
|
{
|
|
return component.name + "_renderPart_" + (int)renderPartIndex;
|
|
}
|
|
|
|
internal static void ConvertTransform(ovrAvatarTransform transform, Transform target)
|
|
{
|
|
Vector3 position = transform.position;
|
|
position.z = 0f - position.z;
|
|
Quaternion orientation = transform.orientation;
|
|
orientation.x = 0f - orientation.x;
|
|
orientation.y = 0f - orientation.y;
|
|
target.localPosition = position;
|
|
target.localRotation = orientation;
|
|
target.localScale = transform.scale;
|
|
}
|
|
|
|
public static ovrAvatarTransform CreateOvrAvatarTransform(Vector3 position, Quaternion orientation)
|
|
{
|
|
return new ovrAvatarTransform
|
|
{
|
|
position = new Vector3(position.x, position.y, 0f - position.z),
|
|
orientation = new Quaternion(0f - orientation.x, 0f - orientation.y, orientation.z, orientation.w),
|
|
scale = Vector3.one
|
|
};
|
|
}
|
|
|
|
private static ovrAvatarGazeTarget CreateOvrGazeTarget(uint targetId, Vector3 targetPosition, ovrAvatarGazeTargetType targetType)
|
|
{
|
|
return new ovrAvatarGazeTarget
|
|
{
|
|
id = targetId,
|
|
worldPosition = new Vector3(targetPosition.x, targetPosition.y, 0f - targetPosition.z),
|
|
type = targetType
|
|
};
|
|
}
|
|
|
|
private void BuildRenderComponents()
|
|
{
|
|
ovrAvatarHandComponent? ovrAvatarHandComponent2 = CAPI.ovrAvatarPose_GetLeftHandComponent(sdkAvatar);
|
|
ovrAvatarHandComponent? ovrAvatarHandComponent3 = CAPI.ovrAvatarPose_GetRightHandComponent(sdkAvatar);
|
|
ovrAvatarBodyComponent? ovrAvatarBodyComponent2 = CAPI.ovrAvatarPose_GetBodyComponent(sdkAvatar);
|
|
ovrAvatarControllerComponent? ovrAvatarControllerComponent2 = CAPI.ovrAvatarPose_GetLeftControllerComponent(sdkAvatar);
|
|
ovrAvatarControllerComponent? ovrAvatarControllerComponent3 = CAPI.ovrAvatarPose_GetRightControllerComponent(sdkAvatar);
|
|
ovrAvatarBaseComponent? ovrAvatarBaseComponent2 = CAPI.ovrAvatarPose_GetBaseComponent(sdkAvatar);
|
|
uint num = CAPI.ovrAvatarComponent_Count(sdkAvatar);
|
|
for (uint num2 = 0u; num2 < num; num2++)
|
|
{
|
|
IntPtr intPtr = CAPI.ovrAvatarComponent_Get_Native(sdkAvatar, num2);
|
|
ovrAvatarComponent component = (ovrAvatarComponent)Marshal.PtrToStructure(intPtr, typeof(ovrAvatarComponent));
|
|
if (!trackedComponents.ContainsKey(component.name))
|
|
{
|
|
GameObject gameObject = new GameObject();
|
|
gameObject.name = component.name;
|
|
gameObject.transform.SetParent(base.transform);
|
|
AddAvatarComponent(gameObject, component);
|
|
if (ovrAvatarHandComponent2.HasValue && intPtr == ovrAvatarHandComponent2.Value.renderComponent)
|
|
{
|
|
HandLeft = gameObject.AddComponent<OvrAvatarHand>();
|
|
}
|
|
if (ovrAvatarHandComponent3.HasValue && intPtr == ovrAvatarHandComponent3.Value.renderComponent)
|
|
{
|
|
HandRight = gameObject.AddComponent<OvrAvatarHand>();
|
|
}
|
|
if (ovrAvatarBodyComponent2.HasValue && intPtr == ovrAvatarBodyComponent2.Value.renderComponent)
|
|
{
|
|
Body = gameObject.AddComponent<OvrAvatarBody>();
|
|
}
|
|
if (ovrAvatarControllerComponent2.HasValue && intPtr == ovrAvatarControllerComponent2.Value.renderComponent)
|
|
{
|
|
ControllerLeft = gameObject.AddComponent<OvrAvatarTouchController>();
|
|
}
|
|
if (ovrAvatarControllerComponent3.HasValue && intPtr == ovrAvatarControllerComponent3.Value.renderComponent)
|
|
{
|
|
ControllerRight = gameObject.AddComponent<OvrAvatarTouchController>();
|
|
}
|
|
if (ovrAvatarBaseComponent2.HasValue && intPtr == ovrAvatarBaseComponent2.Value.renderComponent)
|
|
{
|
|
Base = gameObject.AddComponent<OvrAvatarBase>();
|
|
}
|
|
}
|
|
}
|
|
Utilities.SetLayerRecursively(ControllerLeft.gameObject, "TransparentFX");
|
|
Utilities.SetLayerRecursively(ControllerRight.gameObject, "TransparentFX");
|
|
Body.gameObject.SetActive(false);
|
|
HandLeft.gameObject.SetActive(false);
|
|
HandRight.gameObject.SetActive(false);
|
|
if ((bool)VRControllersManager.Instance)
|
|
{
|
|
VRControllersManager.Instance.ChangeAvatar(this);
|
|
}
|
|
}
|
|
|
|
private void UpdateSDKAvatarUnityState()
|
|
{
|
|
uint num = CAPI.ovrAvatarComponent_Count(sdkAvatar);
|
|
for (uint num2 = 0u; num2 < num; num2++)
|
|
{
|
|
IntPtr ptr = CAPI.ovrAvatarComponent_Get_Native(sdkAvatar, num2);
|
|
ovrAvatarComponent component = (ovrAvatarComponent)Marshal.PtrToStructure(ptr, typeof(ovrAvatarComponent));
|
|
UpdateAvatarComponent(component);
|
|
}
|
|
UpdateVoiceBehavior();
|
|
}
|
|
|
|
private void UpdateCustomPoses()
|
|
{
|
|
if (UpdatePoseRoot(LeftHandCustomPose, ref cachedLeftHandCustomPose, ref cachedCustomLeftHandJoints, ref cachedLeftHandTransforms) && cachedLeftHandCustomPose == null && sdkAvatar != IntPtr.Zero)
|
|
{
|
|
CAPI.ovrAvatar_SetLeftHandGesture(sdkAvatar, ovrAvatarHandGesture.Default);
|
|
}
|
|
if (UpdatePoseRoot(RightHandCustomPose, ref cachedRightHandCustomPose, ref cachedCustomRightHandJoints, ref cachedRightHandTransforms) && cachedRightHandCustomPose == null && sdkAvatar != IntPtr.Zero)
|
|
{
|
|
CAPI.ovrAvatar_SetRightHandGesture(sdkAvatar, ovrAvatarHandGesture.Default);
|
|
}
|
|
if (sdkAvatar != IntPtr.Zero)
|
|
{
|
|
if (cachedLeftHandCustomPose != null && UpdateTransforms(cachedCustomLeftHandJoints, cachedLeftHandTransforms))
|
|
{
|
|
CAPI.ovrAvatar_SetLeftHandCustomGesture(sdkAvatar, (uint)cachedLeftHandTransforms.Length, cachedLeftHandTransforms);
|
|
}
|
|
if (cachedRightHandCustomPose != null && UpdateTransforms(cachedCustomRightHandJoints, cachedRightHandTransforms))
|
|
{
|
|
CAPI.ovrAvatar_SetRightHandCustomGesture(sdkAvatar, (uint)cachedRightHandTransforms.Length, cachedRightHandTransforms);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool UpdatePoseRoot(Transform poseRoot, ref Transform cachedPoseRoot, ref Transform[] cachedPoseJoints, ref ovrAvatarTransform[] transforms)
|
|
{
|
|
if (poseRoot == cachedPoseRoot)
|
|
{
|
|
return false;
|
|
}
|
|
if (!poseRoot)
|
|
{
|
|
cachedPoseRoot = null;
|
|
cachedPoseJoints = null;
|
|
transforms = null;
|
|
}
|
|
else
|
|
{
|
|
List<Transform> list = new List<Transform>();
|
|
OrderJoints(poseRoot, list);
|
|
cachedPoseRoot = poseRoot;
|
|
cachedPoseJoints = list.ToArray();
|
|
transforms = new ovrAvatarTransform[list.Count];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static bool UpdateTransforms(Transform[] joints, ovrAvatarTransform[] transforms)
|
|
{
|
|
bool result = false;
|
|
for (int i = 0; i < joints.Length; i++)
|
|
{
|
|
Transform transform = joints[i];
|
|
ovrAvatarTransform ovrAvatarTransform2 = CreateOvrAvatarTransform(transform.localPosition, transform.localRotation);
|
|
if (ovrAvatarTransform2.position != transforms[i].position || ovrAvatarTransform2.orientation != transforms[i].orientation)
|
|
{
|
|
transforms[i] = ovrAvatarTransform2;
|
|
result = true;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static void OrderJoints(Transform transform, List<Transform> joints)
|
|
{
|
|
joints.Add(transform);
|
|
for (int i = 0; i < transform.childCount; i++)
|
|
{
|
|
Transform child = transform.GetChild(i);
|
|
OrderJoints(child, joints);
|
|
}
|
|
}
|
|
|
|
private void AvatarSpecificationCallback(IntPtr avatarSpecification)
|
|
{
|
|
sdkAvatar = CAPI.ovrAvatar_Create(avatarSpecification, Capabilities);
|
|
ShowLeftController(showLeftController);
|
|
ShowRightController(showRightController);
|
|
uint num = CAPI.ovrAvatar_GetReferencedAssetCount(sdkAvatar);
|
|
for (uint num2 = 0u; num2 < num; num2++)
|
|
{
|
|
ulong num3 = CAPI.ovrAvatar_GetReferencedAsset(sdkAvatar, num2);
|
|
if (OvrAvatarSDKManager.Instance.GetAsset(num3) == null)
|
|
{
|
|
OvrAvatarSDKManager.Instance.BeginLoadingAsset(num3, LevelOfDetail, AssetLoadedCallback);
|
|
assetLoadingIds.Add(num3);
|
|
}
|
|
}
|
|
if (CombineMeshes)
|
|
{
|
|
OvrAvatarSDKManager.Instance.RegisterCombinedMeshCallback(sdkAvatar, CombinedMeshLoadedCallback);
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
if (CombineMeshes)
|
|
{
|
|
CombineMeshes = false;
|
|
}
|
|
try
|
|
{
|
|
oculusUserIDInternal = ulong.Parse(oculusUserID);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
oculusUserIDInternal = 0uL;
|
|
}
|
|
Capabilities = (ovrAvatarCapabilities)0;
|
|
if (EnableBody)
|
|
{
|
|
Capabilities |= ovrAvatarCapabilities.Body;
|
|
}
|
|
if (EnableHands)
|
|
{
|
|
Capabilities |= ovrAvatarCapabilities.Hands;
|
|
}
|
|
if (EnableBase && EnableBody)
|
|
{
|
|
Capabilities |= ovrAvatarCapabilities.Base;
|
|
}
|
|
if (EnableExpressive)
|
|
{
|
|
Capabilities |= ovrAvatarCapabilities.Expressive;
|
|
}
|
|
Capabilities |= ovrAvatarCapabilities.BodyTilt;
|
|
leftControllerAnchor = base.transform.parent.Find("LeftHandAnchor").Find("LeftControllerAnchor");
|
|
rightControllerAnchor = base.transform.parent.Find("RightHandAnchor").Find("RightControllerAnchor");
|
|
ShowLeftController(StartWithControllers);
|
|
ShowRightController(StartWithControllers);
|
|
OvrAvatarSDKManager.Instance.RequestAvatarSpecification(oculusUserIDInternal, AvatarSpecificationCallback, CombineMeshes, LevelOfDetail, ForceMobileTextureFormat, LookAndFeelVersion, FallbackLookAndFeelVersion, EnableExpressive);
|
|
WaitingForCombinedMesh = CombineMeshes;
|
|
if (Driver != null)
|
|
{
|
|
Driver.Mode = ((!UseSDKPackets) ? OvrAvatarDriver.PacketMode.Unity : OvrAvatarDriver.PacketMode.SDK);
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (sdkAvatar == IntPtr.Zero)
|
|
{
|
|
return;
|
|
}
|
|
if (Driver != null)
|
|
{
|
|
Driver.UpdateTransforms(sdkAvatar);
|
|
foreach (float[] voiceUpdate in voiceUpdates)
|
|
{
|
|
CAPI.ovrAvatarPose_UpdateVoiceVisualization(sdkAvatar, voiceUpdate);
|
|
}
|
|
voiceUpdates.Clear();
|
|
CAPI.ovrAvatarPose_Finalize(sdkAvatar, Time.deltaTime);
|
|
}
|
|
if (RecordPackets)
|
|
{
|
|
RecordFrame();
|
|
}
|
|
if (assetLoadingIds.Count == 0)
|
|
{
|
|
if (!assetsFinishedLoading)
|
|
{
|
|
BuildRenderComponents();
|
|
InitPostLoad();
|
|
assetsFinishedLoading = true;
|
|
}
|
|
UpdateSDKAvatarUnityState();
|
|
UpdateCustomPoses();
|
|
if (EnableExpressive)
|
|
{
|
|
UpdateExpressive();
|
|
}
|
|
}
|
|
}
|
|
|
|
public static ovrAvatarHandInputState CreateInputState(ovrAvatarTransform transform, OvrAvatarDriver.ControllerPose pose)
|
|
{
|
|
return new ovrAvatarHandInputState
|
|
{
|
|
transform = transform,
|
|
buttonMask = pose.buttons,
|
|
touchMask = pose.touches,
|
|
joystickX = pose.joystickPosition.x,
|
|
joystickY = pose.joystickPosition.y,
|
|
indexTrigger = pose.indexTrigger,
|
|
handTrigger = pose.handTrigger,
|
|
isActive = pose.isActive
|
|
};
|
|
}
|
|
|
|
public void ShowControllers(bool show)
|
|
{
|
|
ShowLeftController(show);
|
|
ShowRightController(show);
|
|
}
|
|
|
|
public void ShowLeftController(bool show)
|
|
{
|
|
if (sdkAvatar != IntPtr.Zero)
|
|
{
|
|
CAPI.ovrAvatar_SetLeftControllerVisibility(sdkAvatar, show);
|
|
}
|
|
showLeftController = show;
|
|
}
|
|
|
|
public void ShowRightController(bool show)
|
|
{
|
|
if (sdkAvatar != IntPtr.Zero)
|
|
{
|
|
CAPI.ovrAvatar_SetRightControllerVisibility(sdkAvatar, show);
|
|
}
|
|
showRightController = show;
|
|
}
|
|
|
|
public void UpdateVoiceVisualization(float[] voiceSamples)
|
|
{
|
|
voiceUpdates.Add(voiceSamples);
|
|
}
|
|
|
|
private void RecordFrame()
|
|
{
|
|
if (UseSDKPackets)
|
|
{
|
|
RecordSDKFrame();
|
|
}
|
|
else
|
|
{
|
|
RecordUnityFrame();
|
|
}
|
|
}
|
|
|
|
private void RecordUnityFrame()
|
|
{
|
|
float num = Time.deltaTime;
|
|
OvrAvatarDriver.PoseFrame currentPose = Driver.GetCurrentPose();
|
|
if (CurrentUnityPacket == null)
|
|
{
|
|
CurrentUnityPacket = new OvrAvatarPacket(currentPose);
|
|
num = 0f;
|
|
}
|
|
float num2 = 0f;
|
|
while (num2 < num)
|
|
{
|
|
float num3 = num - num2;
|
|
float num4 = PacketSettings.UpdateRate - CurrentUnityPacket.Duration;
|
|
if (num3 < num4)
|
|
{
|
|
CurrentUnityPacket.AddFrame(currentPose, num3);
|
|
num2 += num3;
|
|
continue;
|
|
}
|
|
OvrAvatarDriver.PoseFrame finalFrame = CurrentUnityPacket.FinalFrame;
|
|
OvrAvatarDriver.PoseFrame b = currentPose;
|
|
float t = num4 / num3;
|
|
OvrAvatarDriver.PoseFrame poseFrame = OvrAvatarDriver.PoseFrame.Interpolate(finalFrame, b, t);
|
|
CurrentUnityPacket.AddFrame(poseFrame, num4);
|
|
num2 += num4;
|
|
if (PacketRecorded != null)
|
|
{
|
|
PacketRecorded(this, new PacketEventArgs(CurrentUnityPacket));
|
|
}
|
|
CurrentUnityPacket = new OvrAvatarPacket(poseFrame);
|
|
}
|
|
}
|
|
|
|
private void RecordSDKFrame()
|
|
{
|
|
if (sdkAvatar == IntPtr.Zero)
|
|
{
|
|
return;
|
|
}
|
|
if (!PacketSettings.RecordingFrames)
|
|
{
|
|
CAPI.ovrAvatarPacket_BeginRecording(sdkAvatar);
|
|
PacketSettings.AccumulatedTime = 0f;
|
|
PacketSettings.RecordingFrames = true;
|
|
}
|
|
PacketSettings.AccumulatedTime += Time.deltaTime;
|
|
if (PacketSettings.AccumulatedTime >= PacketSettings.UpdateRate)
|
|
{
|
|
PacketSettings.AccumulatedTime = 0f;
|
|
IntPtr intPtr = CAPI.ovrAvatarPacket_EndRecording(sdkAvatar);
|
|
CAPI.ovrAvatarPacket_BeginRecording(sdkAvatar);
|
|
if (PacketRecorded != null)
|
|
{
|
|
PacketRecorded(this, new PacketEventArgs(new OvrAvatarPacket
|
|
{
|
|
ovrNativePacket = intPtr
|
|
}));
|
|
}
|
|
CAPI.ovrAvatarPacket_Free(intPtr);
|
|
}
|
|
}
|
|
|
|
private void AddRenderParts(OvrAvatarComponent ovrComponent, ovrAvatarComponent component, Transform parent)
|
|
{
|
|
bool flag = ovrComponent.name == "body";
|
|
bool flag2 = ovrComponent.name == "controller_left";
|
|
bool flag3 = ovrComponent.name == "controller_right";
|
|
for (uint num = 0u; num < component.renderPartCount; num++)
|
|
{
|
|
GameObject gameObject = new GameObject();
|
|
gameObject.name = GetRenderPartName(component, num);
|
|
gameObject.transform.SetParent(parent);
|
|
IntPtr renderPart = GetRenderPart(component, num);
|
|
ovrAvatarRenderPartType ovrAvatarRenderPartType2 = CAPI.ovrAvatarRenderPart_GetType(renderPart);
|
|
OvrAvatarRenderComponent item;
|
|
switch (ovrAvatarRenderPartType2)
|
|
{
|
|
case ovrAvatarRenderPartType.SkinnedMeshRender:
|
|
item = AddSkinnedMeshRenderComponent(gameObject, CAPI.ovrAvatarRenderPart_GetSkinnedMeshRender(renderPart));
|
|
break;
|
|
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS:
|
|
item = AddSkinnedMeshRenderPBSComponent(gameObject, CAPI.ovrAvatarRenderPart_GetSkinnedMeshRenderPBS(renderPart));
|
|
break;
|
|
case ovrAvatarRenderPartType.ProjectorRender:
|
|
item = AddProjectorRenderComponent(gameObject, CAPI.ovrAvatarRenderPart_GetProjectorRender(renderPart));
|
|
break;
|
|
case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2:
|
|
item = AddSkinnedMeshRenderPBSV2Component(renderPart, gameObject, CAPI.ovrAvatarRenderPart_GetSkinnedMeshRenderPBSV2(renderPart), (!flag) ? DefaultHandMaterialManager : DefaultBodyMaterialManager, flag && num == 0, flag2 || flag3);
|
|
break;
|
|
default:
|
|
throw new NotImplementedException(string.Format("Unsupported render part type: {0}", ovrAvatarRenderPartType2.ToString()));
|
|
}
|
|
ovrComponent.RenderParts.Add(item);
|
|
}
|
|
}
|
|
|
|
public void RefreshBodyParts()
|
|
{
|
|
if (!(Body != null))
|
|
{
|
|
return;
|
|
}
|
|
OvrAvatarComponent component = Body.GetComponent<OvrAvatarComponent>();
|
|
foreach (OvrAvatarRenderComponent renderPart in component.RenderParts)
|
|
{
|
|
UnityEngine.Object.Destroy(renderPart.gameObject);
|
|
}
|
|
component.RenderParts.Clear();
|
|
ovrAvatarBodyComponent? ovrAvatarBodyComponent2 = CAPI.ovrAvatarPose_GetBodyComponent(sdkAvatar);
|
|
if (ovrAvatarBodyComponent2.HasValue)
|
|
{
|
|
ovrAvatarComponent component2 = (ovrAvatarComponent)Marshal.PtrToStructure(ovrAvatarBodyComponent2.Value.renderComponent, typeof(ovrAvatarComponent));
|
|
AddRenderParts(component, component2, Body.gameObject.transform);
|
|
return;
|
|
}
|
|
throw new Exception("Destroyed the body component, but didn't find a new one in the SDK");
|
|
}
|
|
|
|
public ovrAvatarBodyComponent? GetBodyComponent()
|
|
{
|
|
return CAPI.ovrAvatarPose_GetBodyComponent(sdkAvatar);
|
|
}
|
|
|
|
public Transform GetHandTransform(HandType hand, HandJoint joint)
|
|
{
|
|
if (hand >= HandType.Max || joint >= HandJoint.Max)
|
|
{
|
|
return null;
|
|
}
|
|
OvrAvatarHand ovrAvatarHand = ((hand != HandType.Left) ? HandRight : HandLeft);
|
|
if (ovrAvatarHand != null)
|
|
{
|
|
OvrAvatarComponent component = ovrAvatarHand.GetComponent<OvrAvatarComponent>();
|
|
if (component != null && component.RenderParts.Count > 0)
|
|
{
|
|
OvrAvatarRenderComponent ovrAvatarRenderComponent = component.RenderParts[0];
|
|
return ovrAvatarRenderComponent.transform.Find(HandJoints[(int)hand, (int)joint]);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void GetPointingDirection(HandType hand, ref Vector3 forward, ref Vector3 up)
|
|
{
|
|
Transform handTransform = GetHandTransform(hand, HandJoint.HandBase);
|
|
if (handTransform != null)
|
|
{
|
|
forward = handTransform.forward;
|
|
up = handTransform.up;
|
|
}
|
|
}
|
|
|
|
public Transform GetMouthTransform()
|
|
{
|
|
OvrAvatarComponent value;
|
|
if (trackedComponents.TryGetValue("voice", out value) && value.RenderParts.Count > 0)
|
|
{
|
|
return value.RenderParts[0].transform;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void UpdateVoiceBehavior()
|
|
{
|
|
if (EnableMouthVertexAnimation && Body != null)
|
|
{
|
|
OvrAvatarComponent component = Body.GetComponent<OvrAvatarComponent>();
|
|
VoiceAmplitude = Mathf.Clamp(VoiceAmplitude, 0f, 1f);
|
|
if (component.RenderParts.Count > 0)
|
|
{
|
|
Material sharedMaterial = component.RenderParts[0].mesh.sharedMaterial;
|
|
Transform transform = component.RenderParts[0].mesh.transform.Find(NECK_JONT);
|
|
Vector3 vector = transform.TransformPoint(Vector3.up) - transform.position;
|
|
sharedMaterial.SetFloat(MOUTH_SCALE_PROPERTY, vector.magnitude);
|
|
sharedMaterial.SetFloat(VOICE_PROPERTY, Mathf.Min(vector.magnitude * MOUTH_MAX_GLOBAL, vector.magnitude * VoiceAmplitude * MOUTH_SCALE_GLOBAL));
|
|
sharedMaterial.SetVector(MOUTH_POSITION_PROPERTY, transform.TransformPoint(MOUTH_POSITION_OFFSET));
|
|
sharedMaterial.SetVector(MOUTH_DIRECTION_PROPERTY, transform.up);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool IsValidMic()
|
|
{
|
|
if (Microphone.devices.Length < 1)
|
|
{
|
|
return false;
|
|
}
|
|
string deviceName = Microphone.devices[0].ToString();
|
|
int minFreq;
|
|
int maxFreq;
|
|
Microphone.GetDeviceCaps(deviceName, out minFreq, out maxFreq);
|
|
if (maxFreq == 0)
|
|
{
|
|
maxFreq = 44100;
|
|
}
|
|
AudioClip audioClip = Microphone.Start(deviceName, true, 1, maxFreq);
|
|
if (audioClip == null)
|
|
{
|
|
return false;
|
|
}
|
|
Microphone.End(deviceName);
|
|
return true;
|
|
}
|
|
|
|
private void InitPostLoad()
|
|
{
|
|
ExpressiveGlobalInit();
|
|
ConfigureHelpers();
|
|
if (GetComponent<OvrAvatarLocalDriver>() != null)
|
|
{
|
|
lipsyncContext.audioLoopback = false;
|
|
if (CanOwnMicrophone && IsValidMic())
|
|
{
|
|
micInput = MouthAnchor.gameObject.AddComponent<OVRLipSyncMicInput>();
|
|
micInput.enableMicSelectionGUI = false;
|
|
micInput.MicFrequency = 44100f;
|
|
micInput.micControl = OVRLipSyncMicInput.micActivation.ConstantSpeak;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void ExpressiveGlobalInit()
|
|
{
|
|
if (doneExpressiveGlobalInit)
|
|
{
|
|
return;
|
|
}
|
|
doneExpressiveGlobalInit = true;
|
|
ovrAvatarLights lights = new ovrAvatarLights
|
|
{
|
|
ambientIntensity = RenderSettings.ambientLight.grayscale * 0.5f,
|
|
lights = new ovrAvatarLight[16]
|
|
};
|
|
Light[] array = UnityEngine.Object.FindObjectsOfType(typeof(Light)) as Light[];
|
|
int num = 0;
|
|
foreach (Light light in array)
|
|
{
|
|
if ((bool)light && light.enabled)
|
|
{
|
|
uint instanceID = (uint)light.transform.GetInstanceID();
|
|
switch (light.type)
|
|
{
|
|
case LightType.Directional:
|
|
lights.lights[num++] = CreateLightDirectional(instanceID, light.transform.forward, light.intensity);
|
|
break;
|
|
case LightType.Point:
|
|
lights.lights[num++] = CreateLightPoint(instanceID, light.transform.position, light.range, light.intensity);
|
|
break;
|
|
case LightType.Spot:
|
|
lights.lights[num++] = CreateLightSpot(instanceID, light.transform.position, light.transform.forward, light.spotAngle, light.range, light.intensity);
|
|
break;
|
|
}
|
|
}
|
|
if (num >= 16)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
lights.lightCount = (uint)num;
|
|
CAPI.ovrAvatar_UpdateLights(lights);
|
|
}
|
|
|
|
private static ovrAvatarLight CreateLightDirectional(uint id, Vector3 direction, float intensity)
|
|
{
|
|
return new ovrAvatarLight
|
|
{
|
|
id = id,
|
|
type = ovrAvatarLightType.Direction,
|
|
worldDirection = new Vector3(direction.x, direction.y, 0f - direction.z),
|
|
intensity = intensity
|
|
};
|
|
}
|
|
|
|
private static ovrAvatarLight CreateLightPoint(uint id, Vector3 position, float range, float intensity)
|
|
{
|
|
return new ovrAvatarLight
|
|
{
|
|
id = id,
|
|
type = ovrAvatarLightType.Point,
|
|
worldPosition = new Vector3(position.x, position.y, 0f - position.z),
|
|
range = range,
|
|
intensity = intensity
|
|
};
|
|
}
|
|
|
|
private static ovrAvatarLight CreateLightSpot(uint id, Vector3 position, Vector3 direction, float spotAngleDeg, float range, float intensity)
|
|
{
|
|
return new ovrAvatarLight
|
|
{
|
|
id = id,
|
|
type = ovrAvatarLightType.Spot,
|
|
worldPosition = new Vector3(position.x, position.y, 0f - position.z),
|
|
worldDirection = new Vector3(direction.x, direction.y, 0f - direction.z),
|
|
spotAngleDeg = spotAngleDeg,
|
|
range = range,
|
|
intensity = intensity
|
|
};
|
|
}
|
|
|
|
private void UpdateExpressive()
|
|
{
|
|
ovrAvatarTransform ovrAvatarTransform2 = CreateOvrAvatarTransform(base.transform.position, base.transform.rotation);
|
|
CAPI.ovrAvatar_UpdateWorldTransform(sdkAvatar, ovrAvatarTransform2);
|
|
UpdateFacewave();
|
|
}
|
|
|
|
private void ConfigureHelpers()
|
|
{
|
|
Transform transform = base.transform.Find("body/body_renderPart_0/root_JNT/body_JNT/chest_JNT/neckBase_JNT/neck_JNT/head_JNT");
|
|
if (transform == null)
|
|
{
|
|
transform = base.transform;
|
|
}
|
|
if (MouthAnchor == null)
|
|
{
|
|
MouthAnchor = CreateHelperObject(transform, MOUTH_HEAD_OFFSET, "MouthAnchor", string.Empty);
|
|
}
|
|
if (GetComponent<OvrAvatarLocalDriver>() != null)
|
|
{
|
|
if (audioSource == null)
|
|
{
|
|
audioSource = MouthAnchor.gameObject.AddComponent<AudioSource>();
|
|
}
|
|
spatializedSource = MouthAnchor.GetComponent<ONSPAudioSource>();
|
|
if (spatializedSource == null)
|
|
{
|
|
spatializedSource = MouthAnchor.gameObject.AddComponent<ONSPAudioSource>();
|
|
}
|
|
spatializedSource.UseInvSqr = true;
|
|
spatializedSource.EnableRfl = false;
|
|
spatializedSource.EnableSpatialization = true;
|
|
spatializedSource.Far = 100f;
|
|
spatializedSource.Near = 0.1f;
|
|
lipsyncContext = MouthAnchor.GetComponent<OVRLipSyncContext>();
|
|
if (lipsyncContext == null)
|
|
{
|
|
lipsyncContext = MouthAnchor.gameObject.AddComponent<OVRLipSyncContext>();
|
|
lipsyncContext.provider = OVRLipSync.ContextProviders.Enhanced;
|
|
lipsyncContext.skipAudioSource = !CanOwnMicrophone;
|
|
}
|
|
StartCoroutine(WaitForMouthAudioSource());
|
|
}
|
|
if (GetComponent<OvrAvatarRemoteDriver>() != null)
|
|
{
|
|
GazeTarget gazeTarget = transform.gameObject.AddComponent<GazeTarget>();
|
|
gazeTarget.Type = ovrAvatarGazeTargetType.AvatarHead;
|
|
Transform transform2 = base.transform.Find("hand_left");
|
|
if (!(transform2 == null))
|
|
{
|
|
GazeTarget gazeTarget2 = transform2.gameObject.AddComponent<GazeTarget>();
|
|
gazeTarget2.Type = ovrAvatarGazeTargetType.AvatarHand;
|
|
}
|
|
transform2 = base.transform.Find("hand_right");
|
|
if (!(transform2 == null))
|
|
{
|
|
GazeTarget gazeTarget3 = transform2.gameObject.AddComponent<GazeTarget>();
|
|
gazeTarget3.Type = ovrAvatarGazeTargetType.AvatarHand;
|
|
}
|
|
}
|
|
}
|
|
|
|
private IEnumerator WaitForMouthAudioSource()
|
|
{
|
|
while (MouthAnchor.GetComponent<AudioSource>() == null)
|
|
{
|
|
yield return new WaitForSeconds(0.1f);
|
|
}
|
|
AudioSource AS = MouthAnchor.GetComponent<AudioSource>();
|
|
AS.minDistance = 0.3f;
|
|
AS.maxDistance = 4f;
|
|
AS.rolloffMode = AudioRolloffMode.Logarithmic;
|
|
AS.loop = true;
|
|
AS.playOnAwake = true;
|
|
AS.spatialBlend = 1f;
|
|
AS.spatialize = true;
|
|
AS.spatializePostEffects = true;
|
|
}
|
|
|
|
public void DestroyHelperObjects()
|
|
{
|
|
if ((bool)MouthAnchor)
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(MouthAnchor.gameObject);
|
|
}
|
|
}
|
|
|
|
public GameObject CreateHelperObject(Transform parent, Vector3 localPositionOffset, string helperName, string helperTag = "")
|
|
{
|
|
GameObject gameObject = new GameObject();
|
|
gameObject.name = helperName;
|
|
if (helperTag != string.Empty)
|
|
{
|
|
gameObject.tag = helperTag;
|
|
}
|
|
gameObject.transform.SetParent(parent);
|
|
gameObject.transform.localRotation = Quaternion.identity;
|
|
gameObject.transform.localPosition = localPositionOffset;
|
|
return gameObject;
|
|
}
|
|
|
|
public void UpdateVoiceData(short[] pcmData, int numChannels)
|
|
{
|
|
if (lipsyncContext != null && micInput == null)
|
|
{
|
|
lipsyncContext.ProcessAudioSamplesRaw(pcmData, numChannels);
|
|
}
|
|
}
|
|
|
|
public void UpdateVoiceData(float[] pcmData, int numChannels)
|
|
{
|
|
if (lipsyncContext != null && micInput == null)
|
|
{
|
|
lipsyncContext.ProcessAudioSamplesRaw(pcmData, numChannels);
|
|
}
|
|
}
|
|
|
|
private void UpdateFacewave()
|
|
{
|
|
if (!(lipsyncContext != null) || (!(micInput != null) && CanOwnMicrophone))
|
|
{
|
|
return;
|
|
}
|
|
currentFrame = lipsyncContext.GetCurrentPhonemeFrame();
|
|
if (currentFrame.Visemes.Length != 15)
|
|
{
|
|
Debug.LogError("Unexpected number of visemes " + currentFrame.Visemes);
|
|
return;
|
|
}
|
|
currentFrame.Visemes.CopyTo(visemes, 0);
|
|
for (int i = 0; i < 15; i++)
|
|
{
|
|
RuntimeVisemes.visemeParams[i] = visemes[i];
|
|
}
|
|
CAPI.ovrAvatar_SetVisemes(sdkAvatar, RuntimeVisemes);
|
|
}
|
|
}
|