150 lines
3.9 KiB
C#
150 lines
3.9 KiB
C#
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
public class OVRLipSyncContextMorphTarget : MonoBehaviour
|
|
{
|
|
[Tooltip("Skinned Mesh Rendered target to be driven by Oculus Lipsync")]
|
|
public SkinnedMeshRenderer skinnedMeshRenderer;
|
|
|
|
[Tooltip("Blendshape index to trigger for each viseme.")]
|
|
public int[] visemeToBlendTargets = Enumerable.Range(0, OVRLipSync.VisemeCount).ToArray();
|
|
|
|
[Tooltip("Enable using the test keys defined below to manually trigger each viseme.")]
|
|
public bool enableVisemeTestKeys;
|
|
|
|
[Tooltip("Test keys used to manually trigger an individual viseme - by default the QWERTY row of a US keyboard.")]
|
|
public KeyCode[] visemeTestKeys = new KeyCode[15]
|
|
{
|
|
KeyCode.BackQuote,
|
|
KeyCode.Tab,
|
|
KeyCode.Q,
|
|
KeyCode.W,
|
|
KeyCode.E,
|
|
KeyCode.R,
|
|
KeyCode.T,
|
|
KeyCode.Y,
|
|
KeyCode.U,
|
|
KeyCode.I,
|
|
KeyCode.O,
|
|
KeyCode.P,
|
|
KeyCode.LeftBracket,
|
|
KeyCode.RightBracket,
|
|
KeyCode.Backslash
|
|
};
|
|
|
|
[Tooltip("Test key used to manually trigger laughter and visualise the results")]
|
|
public KeyCode laughterKey = KeyCode.CapsLock;
|
|
|
|
[Tooltip("Blendshape index to trigger for laughter")]
|
|
public int laughterBlendTarget = OVRLipSync.VisemeCount;
|
|
|
|
[Tooltip("Laughter probability threshold above which the laughter blendshape will be activated")]
|
|
[Range(0f, 1f)]
|
|
public float laughterThreshold = 0.5f;
|
|
|
|
[Tooltip("Laughter animation linear multiplier, the final output will be clamped to 1.0")]
|
|
[Range(0f, 3f)]
|
|
public float laughterMultiplier = 1.5f;
|
|
|
|
[Tooltip("Smoothing of 1 will yield only the current predicted viseme, 100 will yield an extremely smooth viseme response.")]
|
|
[Range(1f, 100f)]
|
|
public int smoothAmount = 70;
|
|
|
|
private OVRLipSyncContextBase lipsyncContext;
|
|
|
|
private void Start()
|
|
{
|
|
if (skinnedMeshRenderer == null)
|
|
{
|
|
Debug.LogError("LipSyncContextMorphTarget.Start Error: Please set the target Skinned Mesh Renderer to be controlled!");
|
|
return;
|
|
}
|
|
lipsyncContext = GetComponent<OVRLipSyncContextBase>();
|
|
if (lipsyncContext == null)
|
|
{
|
|
Debug.LogError("LipSyncContextMorphTarget.Start Error: No OVRLipSyncContext component on this object!");
|
|
}
|
|
else
|
|
{
|
|
lipsyncContext.Smoothing = smoothAmount;
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (lipsyncContext != null && skinnedMeshRenderer != null)
|
|
{
|
|
OVRLipSync.Frame currentPhonemeFrame = lipsyncContext.GetCurrentPhonemeFrame();
|
|
if (currentPhonemeFrame != null)
|
|
{
|
|
SetVisemeToMorphTarget(currentPhonemeFrame);
|
|
SetLaughterToMorphTarget(currentPhonemeFrame);
|
|
}
|
|
CheckForKeys();
|
|
if (smoothAmount != lipsyncContext.Smoothing)
|
|
{
|
|
lipsyncContext.Smoothing = smoothAmount;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckForKeys()
|
|
{
|
|
if (enableVisemeTestKeys)
|
|
{
|
|
for (int i = 0; i < OVRLipSync.VisemeCount; i++)
|
|
{
|
|
CheckVisemeKey(visemeTestKeys[i], i, 100);
|
|
}
|
|
}
|
|
CheckLaughterKey();
|
|
}
|
|
|
|
private void SetVisemeToMorphTarget(OVRLipSync.Frame frame)
|
|
{
|
|
for (int i = 0; i < visemeToBlendTargets.Length; i++)
|
|
{
|
|
if (visemeToBlendTargets[i] != -1)
|
|
{
|
|
skinnedMeshRenderer.SetBlendShapeWeight(visemeToBlendTargets[i], frame.Visemes[i] * 100f);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetLaughterToMorphTarget(OVRLipSync.Frame frame)
|
|
{
|
|
if (laughterBlendTarget != -1)
|
|
{
|
|
float laughterScore = frame.laughterScore;
|
|
laughterScore = ((!(laughterScore < laughterThreshold)) ? (laughterScore - laughterThreshold) : 0f);
|
|
laughterScore = Mathf.Min(laughterScore * laughterMultiplier, 1f);
|
|
laughterScore *= 1f / laughterThreshold;
|
|
skinnedMeshRenderer.SetBlendShapeWeight(laughterBlendTarget, laughterScore * 100f);
|
|
}
|
|
}
|
|
|
|
private void CheckVisemeKey(KeyCode key, int viseme, int amount)
|
|
{
|
|
if (Input.GetKeyDown(key))
|
|
{
|
|
lipsyncContext.SetVisemeBlend(visemeToBlendTargets[viseme], amount);
|
|
}
|
|
if (Input.GetKeyUp(key))
|
|
{
|
|
lipsyncContext.SetVisemeBlend(visemeToBlendTargets[viseme], 0);
|
|
}
|
|
}
|
|
|
|
private void CheckLaughterKey()
|
|
{
|
|
if (Input.GetKeyDown(laughterKey))
|
|
{
|
|
lipsyncContext.SetLaughterBlend(100);
|
|
}
|
|
if (Input.GetKeyUp(laughterKey))
|
|
{
|
|
lipsyncContext.SetLaughterBlend(0);
|
|
}
|
|
}
|
|
}
|