Skip to content

Commit 7fa7ebc

Browse files
committed
[Automated] Merged dev into main
2 parents 190575d + 26150b6 commit 7fa7ebc

File tree

10 files changed

+327
-5
lines changed

10 files changed

+327
-5
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## [72.0.0]
2+
- Updated sample scenes to use OpenXRHands.
3+
- Fixed readme, documentation links and UI path.
4+
- Changed Normal recalculator to run independently by default.
5+
- Added `VisemeDriver.cs` to allow using visemes.
6+
17
## [71.0.0]
28
- Normal recalculator has been fixed to run on submeshes with index greater than zero.
39
- New networking sample shows how to efficiently network body movement by compressing the joint-related movement information for transmission and is compatible with common network providers.

Editor/Tracking/Viseme.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Copyright (c) Meta Platforms, Inc. and affiliates.
2+
3+
using UnityEditor;
4+
using UnityEditor.SceneManagement;
5+
using UnityEngine;
6+
7+
namespace Meta.XR.Movement.FaceTracking
8+
{
9+
/// <summary>
10+
/// Custom Editor for <see cref="VisemeDriver">.
11+
/// </summary>
12+
/// <remarks>
13+
/// Custom Editor for <see cref="VisemeDriver"> that:
14+
/// - Allows users to access and modify <see cref="SkinnedMeshRenderer"/> <see cref="FaceViseme[]"/> <see cref="OVRFaceExpressions"/> in <see cref="VisemeDriver"/>.
15+
/// - Creates buttons to auto-generate and clear blendshape mappings.
16+
/// - Allows users to modify the <see cref="FaceViseme"> for the blendshapes in the <see cref="SkinnedMeshRenderer"/>.
17+
/// </remarks>
18+
[CustomEditor(typeof(VisemeDriver))]
19+
public class VisemeDriverEditor : UnityEditor.Editor
20+
{
21+
private SerializedProperty _mappings;
22+
private SerializedProperty _mesh;
23+
private SerializedProperty _ovrExpressions;
24+
private bool _showBlendshapes = true;
25+
private bool _logErrorShown = false;
26+
private VisemeDriver _visemeDriver;
27+
28+
protected virtual void OnEnable()
29+
{
30+
_visemeDriver = (VisemeDriver)target;
31+
_visemeDriver.VisemeMesh = _visemeDriver.GetComponent<SkinnedMeshRenderer>();
32+
33+
_mappings = serializedObject.FindProperty("_visemeMapping");
34+
_mesh = serializedObject.FindProperty("_mesh");
35+
_ovrExpressions = serializedObject.FindProperty("_ovrFaceExpressions");
36+
}
37+
38+
/// <inheritdoc/>
39+
public override void OnInspectorGUI()
40+
{
41+
var renderer = _visemeDriver.VisemeMesh;
42+
43+
EditorGUILayout.PropertyField(_ovrExpressions, new GUIContent(nameof(OVRFaceExpressions)));
44+
EditorGUILayout.PropertyField(_mesh, new GUIContent(nameof(SkinnedMeshRenderer)));
45+
46+
if (renderer.sharedMesh == null || renderer.sharedMesh.blendShapeCount == 0)
47+
{
48+
if (_logErrorShown == false)
49+
{
50+
Debug.LogError($"The mesh renderer on {target.name} must have blendshapes.");
51+
_logErrorShown = true;
52+
}
53+
return;
54+
}
55+
else
56+
{
57+
if (_logErrorShown == true)
58+
{
59+
_logErrorShown = false;
60+
}
61+
}
62+
63+
if (_mappings.arraySize != renderer.sharedMesh.blendShapeCount)
64+
{
65+
_mappings.ClearArray();
66+
_mappings.arraySize = renderer.sharedMesh.blendShapeCount;
67+
for (int i = 0; i < renderer.sharedMesh.blendShapeCount; ++i)
68+
{
69+
_mappings.GetArrayElementAtIndex(i).intValue = (int)OVRFaceExpressions.FaceViseme.Invalid;
70+
}
71+
}
72+
73+
_showBlendshapes = EditorGUILayout.BeginFoldoutHeaderGroup(_showBlendshapes, "Blendshapes");
74+
75+
if (_showBlendshapes)
76+
{
77+
if (GUILayout.Button("Auto Generate Mapping"))
78+
{
79+
_visemeDriver.AutoMapBlendshapes();
80+
Refresh(_visemeDriver);
81+
}
82+
83+
if (GUILayout.Button("Clear Mapping"))
84+
{
85+
_visemeDriver.ClearBlendshapes();
86+
Refresh(_visemeDriver);
87+
}
88+
89+
EditorGUILayout.Space();
90+
91+
for (int i = 0; i < renderer.sharedMesh.blendShapeCount; ++i)
92+
{
93+
EditorGUILayout.PropertyField(_mappings.GetArrayElementAtIndex(i),
94+
new GUIContent(renderer.sharedMesh.GetBlendShapeName(i)));
95+
}
96+
}
97+
serializedObject.ApplyModifiedProperties();
98+
serializedObject.Update();
99+
100+
static void Refresh(VisemeDriver face)
101+
{
102+
EditorUtility.SetDirty(face);
103+
PrefabUtility.RecordPrefabInstancePropertyModifications(face);
104+
EditorSceneManager.MarkSceneDirty(face.gameObject.scene);
105+
}
106+
}
107+
}
108+
}

Editor/Tracking/Viseme/VisemeDriverEditor.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ The Unity-Movement package is released under the [Oculus License](https://github
99
- 2021.3.26f1 (2021 LTS or newer)
1010
- 2022.3.11f2 (2022 LTS or newer)
1111
- Unity 6 or newer
12-
- v71.0 or newer of the Meta XR SDK. You will need the [Meta XR Core SDK](https://assetstore.unity.com/packages/tools/integration/meta-xr-core-sdk-269169) and the [Meta XR Interaction SDK](https://assetstore.unity.com/packages/tools/integration/meta-xr-interaction-sdk-265014) packages found [on this page](https://assetstore.unity.com/publishers/25353).
12+
- v72.0 or newer of the Meta XR SDK. You will need the [Meta XR Core SDK](https://assetstore.unity.com/packages/tools/integration/meta-xr-core-sdk-269169) and the [Meta XR Interaction SDK](https://assetstore.unity.com/packages/tools/integration/meta-xr-interaction-sdk-265014) packages found [on this page](https://assetstore.unity.com/publishers/25353).
1313
- A project set up with these [steps](https://developers.meta.com/horizon/documentation/unity/move-unity-getting-started#unity-project-setup).
1414

1515

Runtime/Scripts/Tooltips.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,4 +2031,14 @@ public static class TargetOffsetCorrectionTooltips
20312031
public const string GroundingConstraint =
20322032
"Foot grounding constraint.";
20332033
}
2034+
2035+
public static class VisemeDriverTooltips
2036+
{
2037+
public const string OvrFaceExpression =
2038+
"OvrFaceExpression component in the scene.";
2039+
public const string VisemeMapping =
2040+
"The mapping between the blendshapes and the FaceViseme.";
2041+
public const string Mesh =
2042+
"The mesh with viseme-compatible blendshapes.";
2043+
}
20342044
}

Runtime/Scripts/Tracking/Viseme.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Copyright (c) Meta Platforms, Inc. and affiliates.
2+
3+
using Oculus.Movement;
4+
using System;
5+
using UnityEngine;
6+
using UnityEngine.Assertions;
7+
using static OVRFaceExpressions;
8+
9+
namespace Meta.XR.Movement.FaceTracking
10+
{
11+
/// <summary>
12+
/// This component drives the blendshapes from the <see cref="SkinnedMeshRenderer"/>
13+
/// based on the weights that we we get for each visemes using <see cref="OVRFaceExpressions"/>.
14+
/// The blendshapes are mapped with an array of Visemes via <see cref="FaceViseme"/>.
15+
/// The fields are accessible with the help of <see cref="VisemeDriverEditor"/>.
16+
/// </summary>
17+
[RequireComponent(typeof(SkinnedMeshRenderer))]
18+
public class VisemeDriver : MonoBehaviour
19+
{
20+
/// <summary>
21+
/// This mesh is accessed and set on enable in the <see cref="VisemeDriverEditor"/>
22+
/// </summary>
23+
public SkinnedMeshRenderer VisemeMesh
24+
{
25+
get { return _mesh; }
26+
set { _mesh = value; }
27+
}
28+
29+
/// <summary>
30+
/// Checks if visemes are valid and gets the weights received from the visemes.
31+
/// </summary>
32+
[SerializeField]
33+
[Tooltip(VisemeDriverTooltips.OvrFaceExpression)]
34+
protected OVRFaceExpressions _ovrFaceExpressions;
35+
36+
/// <summary>
37+
/// The array is populated based on the number of blendshapes in the <see cref="SkinnedMeshRenderer"/>.
38+
/// The blendshapes get assigned to the closest <see cref="FaceViseme"/> based on the
39+
/// blendshape name using <see cref="GetClosestViseme(string)"/>.
40+
/// </summary>
41+
[SerializeField]
42+
[Tooltip(VisemeDriverTooltips.VisemeMapping)]
43+
protected FaceViseme[] _visemeMapping;
44+
45+
/// <summary>
46+
/// The mesh that should contain viseme-compatible blendshapes.
47+
/// </summary>
48+
[SerializeField]
49+
[Tooltip(VisemeDriverTooltips.Mesh)]
50+
protected SkinnedMeshRenderer _mesh;
51+
52+
private const string _VISEME_PREFIX = "viseme_";
53+
54+
private void Awake()
55+
{
56+
Assert.IsNotNull(_mesh);
57+
Assert.IsNotNull(_ovrFaceExpressions);
58+
}
59+
60+
private void Update()
61+
{
62+
if (_ovrFaceExpressions.AreVisemesValid)
63+
{
64+
UpdateVisemes();
65+
}
66+
}
67+
68+
/// <summary>
69+
/// Map the <see cref="FaceViseme"/> to the blendshapes in the <see cref="SkinnedMeshRenderer"/>
70+
/// after pressing the "Auto Generate Mapping" button in the <see cref="VisemeDriverEditor"/>.
71+
/// </summary>
72+
public void AutoMapBlendshapes()
73+
{
74+
_visemeMapping = new FaceViseme[_mesh.sharedMesh.blendShapeCount];
75+
76+
for (int i = 0; i < _mesh.sharedMesh.blendShapeCount; i++)
77+
{
78+
_visemeMapping[i] = GetClosestViseme(_mesh.sharedMesh.GetBlendShapeName(i).ToLower());
79+
}
80+
}
81+
82+
/// <summary>
83+
/// Clears blendshapes by turning all the <see cref="_visemeMapping"/> to <see cref=" OVRFaceExpressions.FaceViseme.Invalid"/>.
84+
/// </summary>
85+
public void ClearBlendshapes()
86+
{
87+
if (_mesh == null || _mesh.sharedMesh.blendShapeCount == 0)
88+
{
89+
return;
90+
}
91+
92+
for (int i = 0; i < _mesh.sharedMesh.blendShapeCount; ++i)
93+
{
94+
_visemeMapping[i] = OVRFaceExpressions.FaceViseme.Invalid;
95+
}
96+
}
97+
98+
private FaceViseme GetClosestViseme(string blendshapeName)
99+
{
100+
foreach (FaceViseme viseme in Enum.GetValues(typeof(FaceViseme)))
101+
{
102+
if (viseme == FaceViseme.Invalid || viseme == FaceViseme.Count)
103+
{
104+
continue;
105+
}
106+
107+
string visemeName = viseme.ToString().ToLower();
108+
109+
if (blendshapeName == visemeName)
110+
{
111+
return viseme;
112+
}
113+
114+
string prefixedName = _VISEME_PREFIX + visemeName;
115+
116+
if (blendshapeName == prefixedName)
117+
{
118+
return viseme;
119+
}
120+
121+
char firstChar = visemeName[0];
122+
prefixedName = _VISEME_PREFIX + firstChar;
123+
if (blendshapeName == prefixedName)
124+
{
125+
return viseme;
126+
}
127+
128+
if (visemeName.Length > 1 && visemeName.Length <= 2)
129+
{
130+
char secondChar = visemeName[1];
131+
prefixedName = _VISEME_PREFIX + secondChar;
132+
if (blendshapeName == prefixedName)
133+
{
134+
return viseme;
135+
}
136+
}
137+
}
138+
return OVRFaceExpressions.FaceViseme.Invalid;
139+
}
140+
141+
private void UpdateVisemes()
142+
{
143+
if (_mesh == null || _visemeMapping.Length == 0 || _ovrFaceExpressions != null)
144+
{
145+
return;
146+
}
147+
148+
for (int i = 0; i < _visemeMapping.Length; i++)
149+
{
150+
if (_visemeMapping[i] == FaceViseme.Invalid || _visemeMapping[i] == FaceViseme.Count)
151+
{
152+
continue;
153+
}
154+
155+
_ovrFaceExpressions.TryGetFaceViseme(_visemeMapping[i], out float visemeWeight);
156+
_mesh.SetBlendShapeWeight(i, visemeWeight);
157+
}
158+
}
159+
}
160+
}

Runtime/Scripts/Tracking/Viseme/VisemeDriver.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "com.meta.movement",
33
"displayName": "Meta Movement",
4-
"version": "71.0.1",
4+
"version": "72.0.0",
55
"description": "Contains sample scenes, prefabs, scripts, and art assets for Movement SDK.",
66
"unity": "2021.3",
77
"unityRelease": "26f1",
@@ -39,9 +39,9 @@
3939
"XR"
4040
],
4141
"dependencies": {
42-
"com.meta.xr.sdk.core": "71.0.0",
43-
"com.meta.xr.sdk.interaction": "71.0.0",
44-
"com.meta.xr.sdk.interaction.ovr": "71.0.0",
42+
"com.meta.xr.sdk.core": "72.0.0",
43+
"com.meta.xr.sdk.interaction": "72.0.0",
44+
"com.meta.xr.sdk.interaction.ovr": "72.0.0",
4545
"com.unity.textmeshpro": "3.0.6",
4646
"com.unity.animation.rigging": "1.2.1",
4747
"com.unity.burst": "1.4.1"

0 commit comments

Comments
 (0)