private void LateUpdate() { //モデルロードの前 if (!IsInitialized) { return; } AdjustEyeRotation(); //パーフェクトシンクが動いてるとき、眉は眉単体で動かせるため、このスクリプトの仕事はない if (_exTracker.Connected && _config.ShouldStopEyeDownOnBlink) { //自前で動かしたぶんは直しておく: // パーフェクトシンクの最初のLateUpdateが走る前にここを通すと破綻を防げるはず if (_hasAppliedEyebrowBlendShape) { EyebrowBlendShape.UpdateEyebrowBlendShape(0, 0); _hasAppliedEyebrowBlendShape = false; } } else { AdjustEyebrow(); } }
private void AdjustEyebrow() { //プレビューやクリップで指定されたモーフの実行時: 眉毛が動いてるとジャマなので戻してから放置。 //毎フレームやるとクリップ指定動作を上書きしてしまうため、それを防ぐべく最初の1回だけリセットするのがポイント //if (wordToMotion.EnablePreview || wordToMotion.IsPlayingBlendShape) if (!_config.ShouldSkipNonMouthBlendShape) { if (_hasAppliedEyebrowBlendShape) { EyebrowBlendShape.UpdateEyebrowBlendShape(0, 0); _hasAppliedEyebrowBlendShape = false; } return; } //NOTE: ここもともとは顔トラッキングで入れた値が入ってたんだけど、まあ要らんだろ…と思って書き換えた、という経緯でこのような実装です。 //まばたき量に応じた値を足していく: こちらはまばたき側の計算時にすでにローパスされてるから、そのまま足してOK //weightToAssignのオフセット項は後付けの補正なので速度の計算基準に使わないよう、計算から外している float blinkLeft = _blendShapeProxy.GetValue(BlinkLKey); float weightLeftToAssign = defaultOffset - blinkLeft * eyeBrowDownOffsetWhenEyeClosed; float blinkRight = _blendShapeProxy.GetValue(BlinkRKey); float weightRightToAssign = defaultOffset - blinkRight * eyeBrowDownOffsetWhenEyeClosed; EyebrowBlendShape.UpdateEyebrowBlendShape(weightLeftToAssign, weightRightToAssign); _hasAppliedEyebrowBlendShape = true; }
private void AdjustEyebrow() { //NOTE: ここスケールファクタないと非常に小さい値しか入らないのでは??? float left = _leftEyeBrowValue - _faceTracker.CalibrationData.eyeBrowPosition; float right = _rightEyeBrowValue - _faceTracker.CalibrationData.eyeBrowPosition; //顔トラッキングしない場合、つねに0が入るようにしとく if (!_faceTracker.HasInitDone || !_faceTracker.FaceDetectedAtLeastOnce || PreferAutoBlink) { left = 0; right = 0; } float goalLeft = left; float idealLeft = (goalLeft - _prevLeftEyeBrowWeight) / timeScaleFactor; float speedLeft = Mathf.Lerp(_prevLeftEyeBrowSpeed, idealLeft, speedLerpFactor); float weightLeft = _prevLeftEyeBrowWeight + Time.deltaTime * speedLeft; weightLeft = Mathf.Clamp(weightLeft, -1, 1); float goalRight = right; float idealRight = (goalRight - _prevRightEyeBrowWeight) / timeScaleFactor; float speedRight = Mathf.Lerp(_prevRightEyeBrowSpeed, idealRight, speedLerpFactor); float weightRight = _prevRightEyeBrowWeight + Time.deltaTime * speedRight; weightRight = Mathf.Clamp(weightRight, -1, 1); if (PreferAutoBlink) { speedLeft = 0; weightLeft = 0; speedRight = 0; weightRight = 0; } //まばたき量に応じた値も足す: こちらはまばたき側の計算時にすでにローパスされてるから、そのまま足してOK //weightToAssignのオフセット項は後付けの補正なので速度の計算基準に使わないよう、計算から外している float blinkLeft = _blendShapeProxy.GetValue(BlinkLKey); float weightLeftToAssign = weightLeft + defaultOffset - blinkLeft * eyeBrowDownOffsetWhenEyeClosed; float blinkRight = _blendShapeProxy.GetValue(BlinkRKey); float weightRightToAssign = weightRight + defaultOffset - blinkRight * eyeBrowDownOffsetWhenEyeClosed; EyebrowBlendShape.UpdateEyebrowBlendShape(weightLeftToAssign, weightRightToAssign); _hasAppliedEyebrowBlendShape = true; _prevLeftEyeBrowWeight = weightLeft; _prevLeftEyeBrowSpeed = speedLeft; _prevRightEyeBrowWeight = weightRight; _prevRightEyeBrowSpeed = speedRight; }
private void AdjustEyebrow() { //プレビューやクリップで指定されたモーフの実行時: 眉毛が動いてるとジャマなので戻してから放置。 //毎フレームやるとクリップ指定動作を上書きしてしまうため、それを防ぐべく最初の1回だけリセットするのがポイント //if (wordToMotion.EnablePreview || wordToMotion.IsPlayingBlendShape) if (!_config.ShouldSkipNonMouthBlendShape) { if (_hasAppliedEyebrowBlendShape) { EyebrowBlendShape.UpdateEyebrowBlendShape(0, 0); _hasAppliedEyebrowBlendShape = false; } return; } //NOTE: ここスケールファクタないと非常に小さい値しか入らないのでは??? float left = _leftEyeBrowValue - _faceTracker.CalibrationData.eyeBrowPosition; float right = _rightEyeBrowValue - _faceTracker.CalibrationData.eyeBrowPosition; //顔トラッキングしない場合、つねに0が入るようにしとく if (!_faceTracker.HasInitDone || !_faceTracker.FaceDetectedAtLeastOnce || PreferAutoBlink) { left = 0; right = 0; } float goalLeft = left; float idealLeft = (goalLeft - _prevLeftEyeBrowWeight) / timeScaleFactor; float speedLeft = Mathf.Lerp(_prevLeftEyeBrowSpeed, idealLeft, speedLerpFactor); float weightLeft = _prevLeftEyeBrowWeight + Time.deltaTime * speedLeft; weightLeft = Mathf.Clamp(weightLeft, -1, 1); float goalRight = right; float idealRight = (goalRight - _prevRightEyeBrowWeight) / timeScaleFactor; float speedRight = Mathf.Lerp(_prevRightEyeBrowSpeed, idealRight, speedLerpFactor); float weightRight = _prevRightEyeBrowWeight + Time.deltaTime * speedRight; weightRight = Mathf.Clamp(weightRight, -1, 1); if (PreferAutoBlink) { speedLeft = 0; weightLeft = 0; speedRight = 0; weightRight = 0; } //まばたき量に応じた値も足す: こちらはまばたき側の計算時にすでにローパスされてるから、そのまま足してOK //weightToAssignのオフセット項は後付けの補正なので速度の計算基準に使わないよう、計算から外している float blinkLeft = _blendShapeProxy.GetValue(BlinkLKey); float weightLeftToAssign = weightLeft + defaultOffset - blinkLeft * eyeBrowDownOffsetWhenEyeClosed; float blinkRight = _blendShapeProxy.GetValue(BlinkRKey); float weightRightToAssign = weightRight + defaultOffset - blinkRight * eyeBrowDownOffsetWhenEyeClosed; EyebrowBlendShape.UpdateEyebrowBlendShape(weightLeftToAssign, weightRightToAssign); _hasAppliedEyebrowBlendShape = true; _prevLeftEyeBrowWeight = weightLeft; _prevLeftEyeBrowSpeed = speedLeft; _prevRightEyeBrowWeight = weightRight; _prevRightEyeBrowSpeed = speedRight; }