Modified the way OpenSeeVRMDriver animates the jaw bone.
This commit is contained in:
parent
95d698a7ce
commit
e2d2ed700f
3 changed files with 8299 additions and 17 deletions
8243
Examples/Animations/JawOpen.anim
Normal file
8243
Examples/Animations/JawOpen.anim
Normal file
File diff suppressed because it is too large
Load diff
8
Examples/Animations/JawOpen.anim.meta
Normal file
8
Examples/Animations/JawOpen.anim.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 697b139e69dcb414498dcd93210620ff
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -22,8 +22,12 @@ public class OpenSeeVRMDriver : MonoBehaviour {
|
||||||
public OpenSeeIKTarget openSeeIKTarget;
|
public OpenSeeIKTarget openSeeIKTarget;
|
||||||
[Tooltip("This is the target VRM avatar's blend shape proxy.")]
|
[Tooltip("This is the target VRM avatar's blend shape proxy.")]
|
||||||
public VRMBlendShapeProxy vrmBlendShapeProxy;
|
public VRMBlendShapeProxy vrmBlendShapeProxy;
|
||||||
[Tooltip("When this is enabled, no blend shapes are applied.")]
|
[Tooltip("When this is enabled, no blendshapes are applied.")]
|
||||||
public bool skipApply = false;
|
public bool skipApply = false;
|
||||||
|
[Tooltip("When this is enabled, no gaze tracking (bone or blendshape) is applied.")]
|
||||||
|
public bool skipApplyEyes = false;
|
||||||
|
[Tooltip("When this is enabled, no jaw bone animation is applied.")]
|
||||||
|
public bool skipApplyJaw = false;
|
||||||
[Tooltip("When this is enabled in addition to skipApply, expressions from hotkeys or expression detection are still applied.")]
|
[Tooltip("When this is enabled in addition to skipApply, expressions from hotkeys or expression detection are still applied.")]
|
||||||
public bool stillApplyExpressions = false;
|
public bool stillApplyExpressions = false;
|
||||||
[Tooltip("This needs to be enabled when tracking with the fast 30 point model.")]
|
[Tooltip("This needs to be enabled when tracking with the fast 30 point model.")]
|
||||||
|
|
@ -106,6 +110,8 @@ public class OpenSeeVRMDriver : MonoBehaviour {
|
||||||
public bool maximizeLipSync = false;
|
public bool maximizeLipSync = false;
|
||||||
[Tooltip("When enabled and the animator of the avatar has a float parameter called JawMovement, this parameter will be set to values from 0 to 1, corresponding to a closed to open mouth. This can be used for animating jaw bones.")]
|
[Tooltip("When enabled and the animator of the avatar has a float parameter called JawMovement, this parameter will be set to values from 0 to 1, corresponding to a closed to open mouth. This can be used for animating jaw bones.")]
|
||||||
public bool animateJawBone = false;
|
public bool animateJawBone = false;
|
||||||
|
[Tooltip("This should be set to the included mecanim animation, which sets the jaw bone to closed on the first frame and to open on the second frame.")]
|
||||||
|
public AnimationClip jawBoneAnimation;
|
||||||
[Tooltip("This is the mouth tracking smoothing factor, with 0 being no smoothing and 1 being a fixed mouth.")]
|
[Tooltip("This is the mouth tracking smoothing factor, with 0 being no smoothing and 1 being a fixed mouth.")]
|
||||||
[Range(0, 1)]
|
[Range(0, 1)]
|
||||||
public float mouthSmoothing = 0.6f;
|
public float mouthSmoothing = 0.6f;
|
||||||
|
|
@ -210,7 +216,11 @@ public class OpenSeeVRMDriver : MonoBehaviour {
|
||||||
|
|
||||||
private OpenSeeBlendShapeProxy proxy = new OpenSeeBlendShapeProxy();
|
private OpenSeeBlendShapeProxy proxy = new OpenSeeBlendShapeProxy();
|
||||||
private Animator animator;
|
private Animator animator;
|
||||||
private bool haveJawParameter;
|
private Transform jawBone;
|
||||||
|
private Quaternion jawRotation = Quaternion.identity;
|
||||||
|
private HumanBodyBones[] humanBodyBones;
|
||||||
|
private Transform[] humanBodyBoneTransforms;
|
||||||
|
private Quaternion[] humanBodyBoneRotations;
|
||||||
|
|
||||||
private VRMBlendShapeProxy lastAvatar = null;
|
private VRMBlendShapeProxy lastAvatar = null;
|
||||||
private int eyebrowIsMoving = 0;
|
private int eyebrowIsMoving = 0;
|
||||||
|
|
@ -511,16 +521,31 @@ public class OpenSeeVRMDriver : MonoBehaviour {
|
||||||
else
|
else
|
||||||
proxy.AccumulateValue(visemePresetMap[i], result);
|
proxy.AccumulateValue(visemePresetMap[i], result);
|
||||||
}
|
}
|
||||||
if (i == lastIdx && haveJawParameter) {
|
if (i == lastIdx) {
|
||||||
if (animateJawBone)
|
if (animateJawBone)
|
||||||
animator.SetFloat("JawMovement", result * 0.99999f);
|
SetJaw(result * 0.99999f);
|
||||||
else
|
else
|
||||||
animator.SetFloat("JawMovement", 0f);
|
SetJaw(0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetJaw(float v) {
|
||||||
|
if (jawBoneAnimation == null || jawBone == null)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < humanBodyBones.Length; i++) {
|
||||||
|
if (humanBodyBoneTransforms[i] != null)
|
||||||
|
humanBodyBoneRotations[i] = humanBodyBoneTransforms[i].localRotation;
|
||||||
|
}
|
||||||
|
jawBoneAnimation.SampleAnimation(lastAvatar.gameObject, v / jawBoneAnimation.frameRate);
|
||||||
|
jawRotation = jawBone.localRotation;
|
||||||
|
for (int i = 0; i < humanBodyBones.Length; i++) {
|
||||||
|
if (humanBodyBoneTransforms[i] != null)
|
||||||
|
humanBodyBoneTransforms[i].localRotation = humanBodyBoneRotations[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ApplyMouthShape(bool fadeOnly) {
|
void ApplyMouthShape(bool fadeOnly) {
|
||||||
if (vrmBlendShapeProxy == null)
|
if (vrmBlendShapeProxy == null)
|
||||||
return;
|
return;
|
||||||
|
|
@ -550,11 +575,11 @@ public class OpenSeeVRMDriver : MonoBehaviour {
|
||||||
float result = interpolated * expressionFactor * visemeFactor;
|
float result = interpolated * expressionFactor * visemeFactor;
|
||||||
if (i < 5 && result > 0f)
|
if (i < 5 && result > 0f)
|
||||||
proxy.AccumulateValue(visemePresetMap[i], result);
|
proxy.AccumulateValue(visemePresetMap[i], result);
|
||||||
if (i == 5 && haveJawParameter) {
|
if (i == 5) {
|
||||||
if (animateJawBone)
|
if (animateJawBone)
|
||||||
animator.SetFloat("JawMovement", result * 0.99999f);
|
SetJaw(result * 0.99999f);
|
||||||
else
|
else
|
||||||
animator.SetFloat("JawMovement", 0f);
|
SetJaw(0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -750,19 +775,19 @@ public class OpenSeeVRMDriver : MonoBehaviour {
|
||||||
InitCatsData();
|
InitCatsData();
|
||||||
lastAvatar = vrmBlendShapeProxy;
|
lastAvatar = vrmBlendShapeProxy;
|
||||||
animator = lastAvatar.gameObject.GetComponent<Animator>();
|
animator = lastAvatar.gameObject.GetComponent<Animator>();
|
||||||
|
|
||||||
proxy.UpdateAvatar(lastAvatar, animator);
|
|
||||||
|
|
||||||
haveJawParameter = false;
|
|
||||||
if (animator != null) {
|
if (animator != null) {
|
||||||
for (int i = 0; i < animator.parameterCount; i++) {
|
jawBone = animator.GetBoneTransform(HumanBodyBones.Jaw);
|
||||||
if (animator.parameters[i].name == "JawMovement") {
|
for (int i = 0; i < humanBodyBones.Length; i++) {
|
||||||
haveJawParameter = true;
|
if (humanBodyBones[i] >= 0 && humanBodyBones[i] < HumanBodyBones.LastBone)
|
||||||
break;
|
humanBodyBoneTransforms[i] = animator.GetBoneTransform(humanBodyBones[i]);
|
||||||
}
|
else
|
||||||
|
humanBodyBoneTransforms[i] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proxy.UpdateAvatar(lastAvatar, animator);
|
||||||
|
|
||||||
faceMesh = null;
|
faceMesh = null;
|
||||||
faceType = -1;
|
faceType = -1;
|
||||||
browUpIndex = -1;
|
browUpIndex = -1;
|
||||||
|
|
@ -1628,6 +1653,9 @@ public class OpenSeeVRMDriver : MonoBehaviour {
|
||||||
|
|
||||||
void Start() {
|
void Start() {
|
||||||
InitExpressionMap();
|
InitExpressionMap();
|
||||||
|
humanBodyBones = (HumanBodyBones[])Enum.GetValues(typeof(HumanBodyBones));
|
||||||
|
humanBodyBoneTransforms = new Transform[humanBodyBones.Length];
|
||||||
|
humanBodyBoneRotations = new Quaternion[humanBodyBones.Length];
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunUpdates() {
|
void RunUpdates() {
|
||||||
|
|
@ -1661,10 +1689,13 @@ public class OpenSeeVRMDriver : MonoBehaviour {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LateUpdate() {
|
void LateUpdate() {
|
||||||
if (!skipApply && gazeTracking && !only30Points) {
|
if (!skipApplyEyes && gazeTracking && !only30Points) {
|
||||||
UpdateGaze();
|
UpdateGaze();
|
||||||
proxy.Apply();
|
proxy.Apply();
|
||||||
}
|
}
|
||||||
|
if (!skipApplyJaw && jawBone != null && jawBoneAnimation != null) {
|
||||||
|
jawBone.localRotation = jawRotation;
|
||||||
|
}
|
||||||
// If blendshapes are received over VMC, apply expressions afterwards if they should be applied
|
// If blendshapes are received over VMC, apply expressions afterwards if they should be applied
|
||||||
if (skipApply && stillApplyExpressions) {
|
if (skipApply && stillApplyExpressions) {
|
||||||
proxy.SetSkip(false);
|
proxy.SetSkip(false);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue