void ApplyRotations(float yaw, float pitch) { #pragma warning disable 0618 if (yaw < 0) { // Left blendShapeValues[1] = 0; blendShapeValues[0] = Mathf.Clamp(Horizontal.Map(-yaw), 0, 1.0f); } else { // Right blendShapeValues[0] = 0; blendShapeValues[1] = Mathf.Clamp(Horizontal.Map(yaw), 0, 1.0f); } if (pitch < 0) { // Down blendShapeValues[2] = 0; blendShapeValues[3] = Mathf.Clamp(VerticalDown.Map(-pitch), 0, 1.0f); } else { // Up blendShapeValues[3] = 0; blendShapeValues[2] = Mathf.Clamp(VerticalUp.Map(pitch), 0, 1.0f); } faceController.MixPresets(nameof(VMC_VRMLookAtBlendShapeApplyer), presets, blendShapeValues); #pragma warning restore 0618 }
void Update() { available = false; //全ノブを調べる if (faceController != null) { int valuecount = 0; for (int i = 0; i < MidiCCWrapper.KNOBS; i++) { //キーが登録されている場合 if (KnobToBlendShape[i] != null && KnobToBlendShape[i] != "") { //表情を反映する var key = KnobToBlendShape[i]; if (nameToValueDictionary.ContainsKey(key) == false) { UpdateDictionary(); } nameToValueDictionary[key] = midiCCWrapper.CCValue[i]; available = true; valuecount++; } } if (keyArray.Length != valuecount) { UpdateDictionary(); } if (valuecount > 0) { faceController.MixPresets(nameof(MIDICCBlendShape), keyArray, nameToValueDictionary.Values.ToArray()); } } }
void Update() { if (SRanipal_Lip_Framework.Status != SRanipal_Lip_Framework.FrameworkStatus.WORKING) { return; } if (LipWeightings == null) { if (!SRanipal_Lip_Framework.Instance.EnableLip) { enabled = false; return; } //Get All Shapes SRanipal_Lip_v2.GetLipWeightings(out LipWeightings); foreach (var weighting in LipWeightings) { if (Enum.IsDefined(typeof(LipShape_v2), weighting.Key)) { LipShapeNameToEnumMap[weighting.Key.ToString()] = weighting.Key; } } } SRanipal_Lip_v2.GetLipWeightings(out LipWeightings); var keyvalues = new Dictionary <string, float>(); foreach (var weighting in LipWeightings) { if (LipShapeToStringKeyMap.ContainsKey(weighting.Key)) { keyvalues[LipShapeToStringKeyMap[weighting.Key]] = weighting.Value; } } if (keyvalues.Any()) { faceController.MixPresets(nameof(LipTracking_Vive), keyvalues.Keys.ToArray(), keyvalues.Values.ToArray()); } }
void Update() { if (SRanipal_Lip_Framework.Status != SRanipal_Lip_Framework.FrameworkStatus.WORKING) { return; } SRanipal_Lip_v2.GetLipWeightings(out LipWeightings); var keyvalues = new Dictionary <BlendShapeKey, float>(); foreach (var weighting in LipWeightings) { if (LipShapeToBlendShapeMap.ContainsKey(weighting.Key)) { keyvalues[LipShapeToBlendShapeMap[weighting.Key]] = weighting.Value; } } if (keyvalues.Any()) { faceController.MixPresets(nameof(LipTracking_Vive), keyvalues.Keys.ToArray(), keyvalues.Values.ToArray()); } }
void OnDataReceived(uOSC.Message message) { //有効なとき以外処理しない if (this.isActiveAndEnabled) { //仮想コントローラー V2.3 if (message.address == "/VMC/Ext/Con/Pos" && (message.values[0] is string) && (message.values[1] is float) && (message.values[2] is float) && (message.values[3] is float) && (message.values[4] is float) && (message.values[5] is float) && (message.values[6] is float) && (message.values[7] is float) ) { string serial = (string)message.values[0]; var rigidTransform = SetTransform(ref pos, ref rot, ref message); lock (LockObject) { if (virtualController.ContainsKey(serial)) { virtualController[serial] = rigidTransform; } else { virtualController.Add(serial, rigidTransform); virtualControllerFiltered.Add(serial, rigidTransform); } } } //仮想トラッカー V2.3 else if ((message.address == "/VMC/Ext/Hmd/Pos" || message.address == "/VMC/Ext/Tra/Pos") && (message.values[0] is string) && (message.values[1] is float) && (message.values[2] is float) && (message.values[3] is float) && (message.values[4] is float) && (message.values[5] is float) && (message.values[6] is float) && (message.values[7] is float) ) { string serial = (string)message.values[0]; var rigidTransform = SetTransform(ref pos, ref rot, ref message); lock (LockObject) { if (virtualTracker.ContainsKey(serial)) { virtualTracker[serial] = rigidTransform; } else { virtualTracker.Add(serial, rigidTransform); virtualTrackerFiltered.Add(serial, rigidTransform); } } } //フレーム設定 V2.3 else if (message.address == "/VMC/Ext/Set/Period" && (message.values[0] is int) && (message.values[1] is int) && (message.values[2] is int) && (message.values[3] is int) && (message.values[4] is int) && (message.values[5] is int) ) { externalSender.periodStatus = (int)message.values[0]; externalSender.periodRoot = (int)message.values[1]; externalSender.periodBone = (int)message.values[2]; externalSender.periodBlendShape = (int)message.values[3]; externalSender.periodCamera = (int)message.values[4]; externalSender.periodDevices = (int)message.values[5]; } //Virtual MIDI CC V2.3 else if (message.address == "/VMC/Ext/Midi/CC/Val" && (message.values[0] is int) && (message.values[1] is float) ) { MIDICCWrapper.KnobUpdated(0, (int)message.values[0], (float)message.values[1]); } //Camera Control V2.3 else if (message.address == "/VMC/Ext/Cam" && (message.values[0] is string) && (message.values[1] is float) && (message.values[2] is float) && (message.values[3] is float) && (message.values[4] is float) && (message.values[5] is float) && (message.values[6] is float) && (message.values[7] is float) && (message.values[8] is float) ) { pos.x = (float)message.values[1]; pos.y = (float)message.values[2]; pos.z = (float)message.values[3]; rot.x = (float)message.values[4]; rot.y = (float)message.values[5]; rot.z = (float)message.values[6]; rot.w = (float)message.values[7]; float fov = (float)message.values[8]; //FreeCameraじゃなかったらFreeCameraにする if (ControlWPFWindow.CurrentSettings.CameraType != UnityMemoryMappedFile.CameraTypes.Free) { window.ChangeCamera(UnityMemoryMappedFile.CameraTypes.Free); } //カメラ制御を切る window.FreeCamera.GetComponent <CameraMouseControl>().enabled = false; //座標とFOVを適用 window.FreeCamera.transform.position = pos; window.FreeCamera.transform.rotation = rot; window.FreeCamera.fieldOfView = fov; } //ブレンドシェープ同期 else if (message.address == "/VMC/Ext/Blend/Val" && (message.values[0] is string) && (message.values[1] is float) ) { blendShapeBuffer[new BlendShapeKey((string)message.values[0])] = (float)message.values[1]; } //ブレンドシェープ適用 else if (message.address == "/VMC/Ext/Blend/Apply") { faceController.MixPresets(nameof(ExternalReceiverForVMC), blendShapeBuffer.Keys.ToArray(), blendShapeBuffer.Values.ToArray()); blendShapeBuffer.Clear(); }//外部アイトラ V2.3 else if (message.address == "/VMC/Ext/Set/Eye" && (message.values[0] is int) && (message.values[1] is float) && (message.values[2] is float) && (message.values[3] is float) ) { bool enable = ((int)message.values[0]) != 0; pos.x = (float)message.values[1]; pos.y = (float)message.values[2]; pos.z = (float)message.values[3]; if (enable) { //ターゲットが存在しなければ作る if (lookTargetOSC == null) { lookTargetOSC = new GameObject(); lookTargetOSC.transform.parent = null; lookTargetOSC.name = "lookTargetOSC"; } //位置を書き込む if (lookTargetOSC.transform != null) { lookTargetOSC.transform.position = pos; } //視線に書き込む if (vrmLookAtHead != null && setFaceApplyAction == false) { faceController.BeforeApply += beforeFaceApply; setFaceApplyAction = true; } } else { //視線を止める if (vrmLookAtHead != null && setFaceApplyAction == true) { faceController.BeforeApply -= beforeFaceApply; setFaceApplyAction = false; } } } //情報要求 V2.4 else if (message.address == "/VMC/Ext/Set/Req") { externalSender.SendPerLowRate(); //即時送信 } //情報表示 V2.4 else if (message.address == "/VMC/Ext/Set/Res" && (message.values[0] is string)) { statusString = (string)message.values[0]; } //キャリブレーション準備 V2.5 else if (message.address == "/VMC/Ext/Set/Calib/Ready") { if (File.Exists(ControlWPFWindow.CurrentSettings.VRMPath)) { window.ImportVRM(ControlWPFWindow.CurrentSettings.VRMPath, true, true, true); } } //キャリブレーション実行 V2.5 else if (message.address == "/VMC/Ext/Set/Calib/Exec" && (message.values[0] is int)) { PipeCommands.CalibrateType calibrateType = PipeCommands.CalibrateType.Default; switch ((int)message.values[0]) { case 0: calibrateType = PipeCommands.CalibrateType.Default; break; case 1: calibrateType = PipeCommands.CalibrateType.FixedHand; break; case 2: calibrateType = PipeCommands.CalibrateType.FixedHandWithGround; break; default: return; //無視 } StartCoroutine(window.Calibrate(calibrateType)); Invoke("EndCalibrate", 2f); } //設定読み込み V2.5 else if (message.address == "/VMC/Ext/Set/Config" && (message.values[0] is string)) { string path = (string)message.values[0]; if (File.Exists(path)) { //なぜか時間がかかる window.LoadSettings(path); } } } }
void OnDataReceived(uOSC.Message message) { //有効なとき以外処理しない if (this.isActiveAndEnabled) { //生存チェックのためのパケットカウンタ packets++; if (packets > int.MaxValue / 2) { packets = 0; } //仮想コントローラー V2.3 if (message.address == "/VMC/Ext/Con/Pos" && (message.values[0] is string) && (message.values[1] is float) && (message.values[2] is float) && (message.values[3] is float) && (message.values[4] is float) && (message.values[5] is float) && (message.values[6] is float) && (message.values[7] is float) ) { string serial = (string)message.values[0]; var rigidTransform = SetTransform(ref pos, ref rot, ref message); lock (LockObject) { if (virtualController.ContainsKey(serial)) { virtualController[serial] = rigidTransform; } else { virtualController.Add(serial, rigidTransform); virtualControllerFiltered.Add(serial, rigidTransform); } } } //仮想トラッカー V2.3 else if ((message.address == "/VMC/Ext/Hmd/Pos" || message.address == "/VMC/Ext/Tra/Pos") && (message.values[0] is string) && (message.values[1] is float) && (message.values[2] is float) && (message.values[3] is float) && (message.values[4] is float) && (message.values[5] is float) && (message.values[6] is float) && (message.values[7] is float) ) { string serial = (string)message.values[0]; var rigidTransform = SetTransform(ref pos, ref rot, ref message); lock (LockObject) { if (virtualTracker.ContainsKey(serial)) { virtualTracker[serial] = rigidTransform; } else { virtualTracker.Add(serial, rigidTransform); virtualTrackerFiltered.Add(serial, rigidTransform); } } } //フレーム設定 V2.3 else if (message.address == "/VMC/Ext/Set/Period" && (message.values[0] is int) && (message.values[1] is int) && (message.values[2] is int) && (message.values[3] is int) && (message.values[4] is int) && (message.values[5] is int) ) { externalSender.periodStatus = (int)message.values[0]; externalSender.periodRoot = (int)message.values[1]; externalSender.periodBone = (int)message.values[2]; externalSender.periodBlendShape = (int)message.values[3]; externalSender.periodCamera = (int)message.values[4]; externalSender.periodDevices = (int)message.values[5]; } //Virtual MIDI CC V2.3 else if (message.address == "/VMC/Ext/Midi/CC/Val" && (message.values[0] is int) && (message.values[1] is float) ) { MIDICCWrapper.KnobUpdated(0, (int)message.values[0], (float)message.values[1]); } //Camera Control V2.3 else if (message.address == "/VMC/Ext/Cam" && (message.values[0] is string) && (message.values[1] is float) && (message.values[2] is float) && (message.values[3] is float) && (message.values[4] is float) && (message.values[5] is float) && (message.values[6] is float) && (message.values[7] is float) && (message.values[8] is float) ) { pos.x = (float)message.values[1]; pos.y = (float)message.values[2]; pos.z = (float)message.values[3]; rot.x = (float)message.values[4]; rot.y = (float)message.values[5]; rot.z = (float)message.values[6]; rot.w = (float)message.values[7]; float fov = (float)message.values[8]; //FreeCameraじゃなかったらFreeCameraにする if (ControlWPFWindow.CurrentSettings.CameraType != UnityMemoryMappedFile.CameraTypes.Free) { window.ChangeCamera(UnityMemoryMappedFile.CameraTypes.Free); } //カメラ制御を切る window.FreeCamera.GetComponent <CameraMouseControl>().enabled = false; //座標とFOVを適用 window.FreeCamera.transform.localPosition = pos; window.FreeCamera.transform.localRotation = rot; window.ControlCamera.fieldOfView = fov; } //ブレンドシェープ同期 else if (message.address == "/VMC/Ext/Blend/Val" && (message.values[0] is string) && (message.values[1] is float) ) { blendShapeBuffer[(string)message.values[0]] = (float)message.values[1]; } //ブレンドシェープ適用 else if (message.address == "/VMC/Ext/Blend/Apply") { faceController.MixPresets(nameof(ExternalReceiverForVMC), blendShapeBuffer.Keys.ToArray(), blendShapeBuffer.Values.ToArray()); blendShapeBuffer.Clear(); }//外部アイトラ V2.3 else if (message.address == "/VMC/Ext/Set/Eye" && (message.values[0] is int) && (message.values[1] is float) && (message.values[2] is float) && (message.values[3] is float) ) { bool enable = ((int)message.values[0]) != 0; pos.x = (float)message.values[1]; pos.y = (float)message.values[2]; pos.z = (float)message.values[3]; if (enable) { //ターゲットが存在しなければ作る if (lookTargetOSC == null) { lookTargetOSC = new GameObject(); lookTargetOSC.name = "lookTargetOSC"; } //位置を書き込む if (lookTargetOSC.transform != null) { lookTargetOSC.transform.parent = headTransform; lookTargetOSC.transform.localPosition = pos; } //視線に書き込む if (vrmLookAtHead != null && setFaceApplyAction == false) { faceController.BeforeApply += beforeFaceApply; setFaceApplyAction = true; } } else { //視線を止める if (vrmLookAtHead != null && setFaceApplyAction == true) { faceController.BeforeApply -= beforeFaceApply; setFaceApplyAction = false; } } } //情報要求 V2.4 else if (message.address == "/VMC/Ext/Set/Req") { if (externalSender.isActiveAndEnabled && externalSender.uClient != null) { externalSender.SendPerLowRate(); //即時送信 } } //情報表示 V2.4 else if (message.address == "/VMC/Ext/Set/Res" && (message.values[0] is string)) { statusString = (string)message.values[0]; } //キャリブレーション準備 V2.5 else if (message.address == "/VMC/Ext/Set/Calib/Ready") { if (File.Exists(ControlWPFWindow.CurrentSettings.VRMPath)) { window.ImportVRM(ControlWPFWindow.CurrentSettings.VRMPath, true, true, true); } } //キャリブレーション実行 V2.5 else if (message.address == "/VMC/Ext/Set/Calib/Exec" && (message.values[0] is int)) { PipeCommands.CalibrateType calibrateType = PipeCommands.CalibrateType.Default; switch ((int)message.values[0]) { case 0: calibrateType = PipeCommands.CalibrateType.Default; break; case 1: calibrateType = PipeCommands.CalibrateType.FixedHand; break; case 2: calibrateType = PipeCommands.CalibrateType.FixedHandWithGround; break; default: return; //無視 } StartCoroutine(window.Calibrate(calibrateType)); Invoke("EndCalibrate", 2f); } //設定読み込み V2.5 else if (message.address == "/VMC/Ext/Set/Config" && (message.values[0] is string)) { string path = (string)message.values[0]; if (File.Exists(path)) { //なぜか時間がかかる window.LoadSettings(path); } } //スルー情報 V2.6 else if (message.address != null && message.address.StartsWith("/VMC/Thru/")) { //転送する if (externalSender.isActiveAndEnabled && externalSender.uClient != null) { externalSender.uClient.Send(message.address, message.values); } } //Directional Light V2.9 else if (message.address == "/VMC/Ext/Light" && (message.values[0] is string) && (message.values[1] is float) && (message.values[2] is float) && (message.values[3] is float) && (message.values[4] is float) && (message.values[5] is float) && (message.values[6] is float) && (message.values[7] is float) && (message.values[8] is float) && (message.values[9] is float) && (message.values[10] is float) && (message.values[11] is float) ) { pos.x = (float)message.values[1]; pos.y = (float)message.values[2]; pos.z = (float)message.values[3]; rot.x = (float)message.values[4]; rot.y = (float)message.values[5]; rot.z = (float)message.values[6]; rot.w = (float)message.values[7]; float r = (float)message.values[8]; float g = (float)message.values[9]; float b = (float)message.values[10]; float a = (float)message.values[11]; window.MainDirectionalLight.color = new Color(r, g, b, a); window.MainDirectionalLightTransform.position = pos; window.MainDirectionalLightTransform.rotation = rot; } //ボーン姿勢 else if (message.address == "/VMC/Ext/Bone/Pos" && (message.values[0] is string) && (message.values[1] is float) && (message.values[2] is float) && (message.values[3] is float) && (message.values[4] is float) && (message.values[5] is float) && (message.values[6] is float) && (message.values[7] is float) ) { string boneName = (string)message.values[0]; pos.x = (float)message.values[1]; pos.y = (float)message.values[2]; pos.z = (float)message.values[3]; rot.x = (float)message.values[4]; rot.y = (float)message.values[5]; rot.z = (float)message.values[6]; rot.w = (float)message.values[7]; //Humanoidボーンに該当するボーンがあるか調べる HumanBodyBones bone; if (HumanBodyBonesTryParse(ref boneName, out bone)) { //あれば位置と回転をキャッシュする if (HumanBodyBonesPositionTable.ContainsKey(bone)) { HumanBodyBonesPositionTable[bone] = pos; } else { HumanBodyBonesPositionTable.Add(bone, pos); } if (HumanBodyBonesRotationTable.ContainsKey(bone)) { HumanBodyBonesRotationTable[bone] = rot; } else { HumanBodyBonesRotationTable.Add(bone, rot); } } //受信と更新のタイミングは切り離した } } }
// Update is called once per frame void Update() { if (EnableLipSync) { if (Context != 0) { if (faceController == null) { return; } else { // get the current viseme frame OVRLipSync.Frame frame = GetCurrentPhonemeFrame(); if (frame != null) { //あ OVRLipSync.Viseme.aa; BlendShapePreset.A; //い OVRLipSync.Viseme.ih; BlendShapePreset.I; //う OVRLipSync.Viseme.ou; BlendShapePreset.U; //え OVRLipSync.Viseme.E; BlendShapePreset.E; //お OVRLipSync.Viseme.oh; BlendShapePreset.O; var presets = new BlendShapePreset[] { BlendShapePreset.A, BlendShapePreset.I, BlendShapePreset.U, BlendShapePreset.E, BlendShapePreset.O, }; var visemes = new float[] { frame.Visemes[(int)OVRLipSync.Viseme.aa], frame.Visemes[(int)OVRLipSync.Viseme.ih], frame.Visemes[(int)OVRLipSync.Viseme.ou], frame.Visemes[(int)OVRLipSync.Viseme.E], frame.Visemes[(int)OVRLipSync.Viseme.oh], }; int maxindex = 0; float maxvisemes = 0; for (int i = 0; i < presets.Length; i++) { if (visemes[i] < WeightThreashold) { visemes[i] = 0; } if (maxvisemes < visemes[i]) { maxindex = i; maxvisemes = visemes[i]; } } if (MaxWeightEmphasis) { visemes[maxindex] = Mathf.Clamp(visemes[maxindex] * 3, 0.0f, 1.0f); } if (MaxWeightEnable) { for (int i = 0; i < presets.Length; i++) { if (i != maxindex) { visemes[i] = 0.0f; } } } for (int i = 0; i < presets.Length; i++) { visemes[i] *= MaxLevel; } faceController.MixPresets(nameof(DynamicOVRLipSync), presets, visemes); //Debug.Log("Visemes:" + string.Join(",", frame.Visemes.Select(d => d.ToString()))); } } } if (string.IsNullOrEmpty(selectedDevice) == false) { audioSource.volume = (sourceVolume / 100); if (!Microphone.IsRecording(selectedDevice)) { StartMicrophone(); } if (EnableLowLatency) { var position = Microphone.GetPosition(selectedDevice); if (position < 0 || head == position) { return; } audioSource.clip.GetData(microphoneBuffer, 0); while (GetDataLength(microphoneBuffer.Length, head, position) > processBuffer.Length) { var remain = microphoneBuffer.Length - head; if (remain < processBuffer.Length) { Array.Copy(microphoneBuffer, head, processBuffer, 0, remain); Array.Copy(microphoneBuffer, 0, processBuffer, remain, processBuffer.Length - remain); } else { Array.Copy(microphoneBuffer, head, processBuffer, 0, processBuffer.Length); } OVRLipSync.ProcessFrame(Context, processBuffer, Frame, OVRLipSync.AudioDataType.F32_Mono); head += processBuffer.Length; if (head > microphoneBuffer.Length) { head -= microphoneBuffer.Length; } } } } } }