Skip to content

Commit

Permalink
Merge pull request #988 from malaybaku/develop
Browse files Browse the repository at this point in the history
v3.3.1
  • Loading branch information
malaybaku committed Sep 30, 2023
2 parents 5bab47d + 3a18639 commit ba2fbf8
Show file tree
Hide file tree
Showing 45 changed files with 722 additions and 199 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -39,6 +39,7 @@ sysinfo.txt
*.unitypackage

/VMagicMirror/Logs/
/VMagicMirror/UserSettings/

# Streaming Assets (now only include DlibFaceLandmarkDetector, so it must be ignored)
/VMagicMirror/Assets/StreamingAssets/
Expand Down
2 changes: 1 addition & 1 deletion Batches/build_unity.cmd
Expand Up @@ -5,7 +5,7 @@ REM example: `build_unity.cmd full dev`

REM use following instead, if editor is NOT from Hub
REM set UNITY_EXE="%ProgramFiles%\Unity\Editor\Unity.exe"
set UNITY_EXE="%ProgramFiles%\Unity\Hub\Editor\2020.3.22f1\Editor\Unity.exe"
set UNITY_EXE="%ProgramFiles%\Unity\Hub\Editor\2022.3.7f1\Editor\Unity.exe"

cd %~dp0

Expand Down
2 changes: 1 addition & 1 deletion Batches/version.txt
@@ -1 +1 @@
v3.3.0
v3.3.1
10 changes: 5 additions & 5 deletions README.md
Expand Up @@ -4,10 +4,10 @@

Logo: by [@otama_jacksy](https://twitter.com/otama_jacksy)

v3.3.0
v3.3.1

* 作成: 獏星(ばくすたー)
* 2023/08/31
* 2023/09/30

WindowsでVRMを表示し、追加のデバイスなしで動かせるアプリケーションです。

Expand Down Expand Up @@ -51,12 +51,12 @@ Windows 10/11環境でお使いいただけます。

適当なフォルダに本レポジトリを配置します。配置先について、空白文字を含むようなフォルダパスは避けて下さい。

Unity 2020.3系でUnityプロジェクト(本レポジトリの`VMagicMirror`フォルダ)を開き、Visual Studio 2022でWPFプロジェクトを開きます。
Unity 2022.3系でUnityプロジェクト(本レポジトリの`VMagicMirror`フォルダ)を開き、Visual Studio 2022でWPFプロジェクトを開きます。

メンテナの開発環境は以下の通りです。

* Unity 2020.3.22f1 Personal
* Visual Studio Community 2022 (17.0.0)
* Unity 2022.3.7f1 Personal
* Visual Studio Community 2022 (17.4.4)
* 「.NET Desktop」コンポーネントがインストール済みであること
* 「C++によるデスクトップ開発」コンポーネントがインストール済みであること
- UnityのBurstコンパイラ向けに必要なセットアップです。
Expand Down
10 changes: 5 additions & 5 deletions README_en.md
Expand Up @@ -5,10 +5,10 @@

Logo: by [@otama_jacksy](https://twitter.com/otama_jacksy)

v3.3.0
v3.3.1

* Author: Baxter
* 2023/Aug/31
* 2023/Sep/30

The VRM avatar application without any special device.

Expand Down Expand Up @@ -54,12 +54,12 @@ note: Contact in English or Japanese is very helpful for the author.

Put the repository on your local folder. folder path should not include space character.

Open Unity project with Unity 2020.3.x, and open WPF project with Visual Studio 2022.
Open Unity project with Unity 2022.3.x, and open WPF project with Visual Studio 2022.

Maintainer's environment is as following.

* Unity 2020.3.8f1 Personal
* Visual Studio Community 2022 17.0.0
* Unity 2022.3.7f1 Personal
* Visual Studio Community 2022 (17.4.4)
* Component ".NET Desktop Development" is required.
* Also Component "C++ Desktop Development" is required, for Unity Burst compiler.

Expand Down
Expand Up @@ -465,6 +465,12 @@ private void LateUpdate()
_arcadeStickHand.LateUpdate();
_penTablet.LateUpdate();
}

private void OnDestroy()
{
_vmcpHand.Dispose();
//NOTE: 他でもDisposeしたほうがいいものは追加してOK
}

private void UpdateLeftHand()
{
Expand Down Expand Up @@ -538,25 +544,48 @@ private void UpdateRightHand()
t
);
}
private void SetLeftHandState(IHandIkState state)

private bool CanChangeState(HandTargetType current, HandTargetType target)
{
var targetType = state.TargetType;

//書いてる通りだが、
// - 同じ状態には遷移できない
// - 手下げモード、ないしVMCProtocolのときは拍手以外に遷移できない
// - 拍手は実行優先度がすごく高い
if (_leftTargetType.Value == targetType ||
AlwaysHandDown.Value && targetType != HandTargetType.AlwaysDown && targetType != HandTargetType.ClapMotion ||
_vmcpHand.IsActive.Value && targetType != HandTargetType.VMCPReceiveResult && targetType != HandTargetType.ClapMotion ||
_leftTargetType.Value == HandTargetType.ClapMotion && ClapMotion.ClapMotionRunning
// - 拍手は実行優先度がすごく高いので、他の状態に遷移できない
// - 手下げモード有効時は手下げ or 拍手にしか遷移できない
// - VMCProtocolが有効だとVMCP or 手下げ or 拍手にしか遷移できない

if (current == target)
{
return false;
}

if (current == HandTargetType.ClapMotion && ClapMotion.ClapMotionRunning)
{
return false;
}

if (AlwaysHandDown.Value && target != HandTargetType.AlwaysDown &&
target != HandTargetType.ClapMotion)
{
return false;
}

if (_vmcpHand.IsActive.Value && target != HandTargetType.VMCPReceiveResult &&
target != HandTargetType.ClapMotion && target != HandTargetType.AlwaysDown
)
{
return false;
}
return true;
}

private void SetLeftHandState(IHandIkState state)
{
if (!CanChangeState(_leftTargetType.Value, state.TargetType))
{
return;
}

_leftTargetType.Value = targetType;
_leftTargetType.Value = state.TargetType;
_prevLeftHand = _currentLeftHand;
_currentLeftHand = state;

Expand All @@ -574,19 +603,12 @@ private void SetLeftHandState(IHandIkState state)

private void SetRightHandState(IHandIkState state)
{
var targetType = state.TargetType;

// 優先度の効かせ方はLeftHandと同じ
if (_rightTargetType.Value == targetType ||
_vmcpHand.IsActive.Value && targetType != HandTargetType.VMCPReceiveResult && targetType != HandTargetType.ClapMotion ||
AlwaysHandDown.Value && targetType != HandTargetType.AlwaysDown && targetType != HandTargetType.ClapMotion ||
_rightTargetType.Value == HandTargetType.ClapMotion && ClapMotion.ClapMotionRunning
)
if (!CanChangeState(_rightTargetType.Value, state.TargetType))
{
return;
}

_rightTargetType.Value = targetType;
_rightTargetType.Value = state.TargetType;
_prevRightHand = _currentRightHand;
_currentRightHand = state;

Expand Down
@@ -1,9 +1,10 @@
using System.Collections;
using System;
using System.Collections;
using UnityEngine;

namespace Baku.VMagicMirror.IK
{
public abstract class HandIkGeneratorBase
public abstract class HandIkGeneratorBase : IDisposable
{
public HandIkGeneratorBase(HandIkGeneratorDependency dependency)
{
Expand Down Expand Up @@ -32,6 +33,10 @@ public virtual void LateUpdate()
{
}

public virtual void Dispose()
{
}

protected Coroutine StartCoroutine(IEnumerator i) => Dependency.Component.StartCoroutine(i);
protected void StopCoroutine(Coroutine coroutine) => Dependency.Component.StopCoroutine(coroutine);
}
Expand Down
Expand Up @@ -106,15 +106,15 @@ private void Update()

var offset = _vmcpHeadPose.PositionOffset;

var goal = _vmcpHeadPose.Connected.Value
var goal = _vmcpHeadPose.IsConnected.Value
? new Vector3(
Mathf.Clamp(offset.x * _scale.x, _min.x, _max.x),
Mathf.Clamp(offset.y * _scale.y, _min.y, _max.y),
Mathf.Clamp(offset.z * _scale.z, _min.z, _max.z)
)
: Vector3.zero;

if (_vmcpHeadPose.Connected.Value)
if (_vmcpHeadPose.IsConnected.Value)
{
var addedLerp =
_currentLerpFactor +
Expand Down
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Baku.VMagicMirror.VMCP;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UniVRM10;
Expand All @@ -16,6 +17,8 @@ public class WordToMotionRunner : PresenterBase
private readonly IWordToMotionPlayer[] _players;
private readonly WordToMotionBlendShape _blendShape;
private readonly TaskBasedIkWeightFader _ikWeightCrossFade;
//NOTE: IKじゃないけどIKと同じくweight fadeの概念がある
private readonly VMCPNaiveBoneTransfer _vmcpNaiveBoneTransfer;
private readonly FingerController _fingerController;
private readonly WordToMotionAccessoryRequest _accessoryRequest;

Expand All @@ -24,13 +27,15 @@ public class WordToMotionRunner : PresenterBase
IEnumerable<IWordToMotionPlayer> players,
WordToMotionBlendShape blendShape,
TaskBasedIkWeightFader ikWeightCrossFade,
VMCPNaiveBoneTransfer vmcpNaiveBoneTransfer,
FingerController fingerController,
WordToMotionAccessoryRequest accessoryRequest)
{
_vrmLoadable = vrmLoadable;
_players = players.ToArray();
_blendShape = blendShape;
_ikWeightCrossFade = ikWeightCrossFade;
_vmcpNaiveBoneTransfer = vmcpNaiveBoneTransfer;
_fingerController = fingerController;
_accessoryRequest = accessoryRequest;
}
Expand Down Expand Up @@ -110,12 +115,14 @@ public void Run(MotionRequest request)
// 直前モーションでIKオフにしてない場合、オフにしたいので実際そうする
_fingerController.FadeOutWeight(IkFadeDuration);
_ikWeightCrossFade.SetUpperBodyIkWeight(0f, IkFadeDuration);
_vmcpNaiveBoneTransfer.FadeOutWeight(IkFadeDuration);
}
else if (!playablePlayer.UseIkAndFingerFade && _restoreIkOnMotionEnd)
{
// IKオフのモーション中にIK有効が期待されたモーションを行う場合、IKがオンになる
_fingerController.FadeInWeight(IkFadeDuration);
_ikWeightCrossFade.SetUpperBodyIkWeight(1f, IkFadeDuration);
_vmcpNaiveBoneTransfer.FadeInWeight(IkFadeDuration);
}
}

Expand Down Expand Up @@ -188,11 +195,13 @@ public void RunAsPreview(MotionRequest request)
{
_fingerController.FadeOutWeight(IkFadeDuration);
_ikWeightCrossFade.SetUpperBodyIkWeight(0f, IkFadeDuration);
_vmcpNaiveBoneTransfer.FadeOutWeight(IkFadeDuration);
}
else
{
_fingerController.FadeInWeight(IkFadeDuration);
_ikWeightCrossFade.SetUpperBodyIkWeight(1f, IkFadeDuration);
_vmcpNaiveBoneTransfer.FadeInWeight(IkFadeDuration);
}
}

Expand Down Expand Up @@ -226,6 +235,7 @@ public void Stop()
}
_fingerController.FadeInWeight(0f);
_ikWeightCrossFade.SetUpperBodyIkWeight(1f, 0f);
_vmcpNaiveBoneTransfer.FadeInWeight(0f);
_restoreIkOnMotionEnd = false;
}

Expand All @@ -239,6 +249,7 @@ private async UniTaskVoid ResetMotionAsync(float delay, bool fadeIkAndFinger, Ca
{
_fingerController.FadeInWeight(IkFadeDuration);
_ikWeightCrossFade.SetUpperBodyIkWeight(1f, IkFadeDuration);
_vmcpNaiveBoneTransfer.FadeInWeight(IkFadeDuration);
}
_restoreIkOnMotionEnd = false;
}
Expand Down
Expand Up @@ -9,6 +9,7 @@
using OpenCVForUnity.ImgprocModule;
using OpenCVForUnity.UtilsModule;
using UnityEngine;
using Range = OpenCVForUnity.CoreModule.Range;
using Rect = UnityEngine.Rect;
#endif

Expand Down
Expand Up @@ -11,7 +11,8 @@ public class VMCPHandIkGenerator : HandIkGeneratorBase
// NOTE: 「未受信」はBarracudaHandとかのトラッキングロスよりは起きにくいのであまり凝った処理はしない。
// 送信元自体がトラッキングロスすることはあるが、その場合のモーション補間は送信元が頑張ってるはずなので信じる
private const float ConnectedBlendRate = 2f;

private const float RaiseRequestInterval = 0.2f;

public VMCPHandIkGenerator(
HandIkGeneratorDependency dependency,
VMCPHandPose vmcpHandPose,
Expand All @@ -24,15 +25,24 @@ public class VMCPHandIkGenerator : HandIkGeneratorBase
_leftHandState = new VMCPHandIkState(ReactedHand.Left, downHand.LeftHand);
_rightHandState = new VMCPHandIkState(ReactedHand.Right, downHand.RightHand);

//オフ -> オンへの切り替え時だけリクエストが出るが、それ以上にバシバシ送ったほうが良ければ頻度を上げてもOK
//NOTE: 定期的にリクエストを飛ばすのは手下げモードのon/offの切り替わりに配慮している
vmcpHandPose.IsActive
.Subscribe(active =>
{
if (active)
{
_leftHandState.RaiseRequest();
_rightHandState.RaiseRequest();
}
_raiseRequestDisposable.Disposable = Observable
.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(RaiseRequestInterval))
.Subscribe(_ =>
{
_leftHandState.RaiseRequest();
_rightHandState.RaiseRequest();
});
}
else
{
_raiseRequestDisposable.Disposable = Disposable.Empty;
}
})
.AddTo(dependency.Component);

Expand Down Expand Up @@ -64,10 +74,13 @@ public override void Update()
}
}

public override void Dispose()
{
_raiseRequestDisposable.Dispose();
}

private void LateUpdateCallback()
{


//指を適用する: FingerController経由じゃないことには注意
if (_vmcpHandPose.IsActive.Value)
{
Expand All @@ -82,7 +95,8 @@ private void LateUpdateCallback()
private readonly VMCPHandIkState _rightHandState;
public override IHandIkState RightHandState => _rightHandState;
public IReadOnlyReactiveProperty<bool> IsActive => _vmcpHandPose.IsActive;


private readonly SerialDisposable _raiseRequestDisposable = new SerialDisposable();
private float _connectedRate = 0f;

class VMCPHandIkState : IHandIkState
Expand Down

0 comments on commit ba2fbf8

Please sign in to comment.