diff --git a/Assets/External/Ifacialmocap/UnityRecieve_FACEMOTION3D_and_iFacialMocap.cs b/Assets/External/Ifacialmocap/UnityRecieve_FACEMOTION3D_and_iFacialMocap.cs index 1d7c0992..7cb3d3c8 100644 --- a/Assets/External/Ifacialmocap/UnityRecieve_FACEMOTION3D_and_iFacialMocap.cs +++ b/Assets/External/Ifacialmocap/UnityRecieve_FACEMOTION3D_and_iFacialMocap.cs @@ -14,6 +14,16 @@ public class UnityRecieve_FACEMOTION3D_and_iFacialMocap : MonoBehaviour public bool gameStartWithConnect = true; public string iOS_IPAddress = "255.255.255.255"; public bool mirrorMode = false; // 좌우 반전 모드 설정 + + [Header("BlendShape 보정")] + [Tooltip("세로 방향 BlendShape 보정 비율 (입 벌림, 눈 위아래 등)")] + [Range(0.5f, 2.0f)] + public float verticalScale = 1.28f; + + [Tooltip("가로 방향 BlendShape 보정 비율 (입 좌우, 볼 등)")] + [Range(0.5f, 2.0f)] + public float horizontalScale = 1.0f; + private UdpClient client; private bool StartFlag = true; @@ -40,6 +50,33 @@ public class UnityRecieve_FACEMOTION3D_and_iFacialMocap : MonoBehaviour private readonly char[] splitHash = new char[] { '#' }; private readonly char[] splitComma = new char[] { ',' }; + // 세로 방향 BlendShape (위아래 움직임) - verticalScale 적용 + private static readonly HashSet VerticalBlendShapes = new HashSet(StringComparer.OrdinalIgnoreCase) { + // 입 세로 + "jawopen", "mouthclose", "mouthfunnel", "mouthpucker", + // 눈 위아래 + "eyelookupleft", "eyelookupright", "eyelookdownleft", "eyelookdownright", + "eyewideleft", "eyewideright", "eyesquintleft", "eyesquintright", + "eyeblinkleft", "eyeblinkright", + // 눈썹 위아래 + "browinnerup", "browdownleft", "browdownright", "browouterupright", "browouterupleft" + }; + + // 가로 방향 BlendShape (좌우 움직임) - horizontalScale 적용 + private static readonly HashSet HorizontalBlendShapes = new HashSet(StringComparer.OrdinalIgnoreCase) { + // 입 좌우 + "mouthsmileleft", "mouthsmileright", "mouthfrownleft", "mouthfrownright", + "mouthdimpleleft", "mouthdimpleright", "mouthstretchleft", "mouthstretchright", + "mouthpressleft", "mouthpressright", "mouthlowerdownleft", "mouthlowerdownright", + "mouthupperupleft", "mouthupperupright", + "mouthleft", "mouthright", + // 눈 좌우 + "eyelookinleft", "eyelookinright", "eyelookoutleft", "eyelookoutright", + // 볼/코 + "cheekpuff", "cheeksquintleft", "cheeksquintright", + "nosesneerleft", "nosesneerright" + }; + // Mirror mode용 정적 매핑 테이블 private static readonly Dictionary EyeMirrorMap = new Dictionary() { {"eyelookupleft", "EyeLookUpRight"}, @@ -238,6 +275,9 @@ public class UnityRecieve_FACEMOTION3D_and_iFacialMocap : MonoBehaviour // 정규화된 이름으로 캐시 검색 string normalizedName = NormalizeBlendShapeName(shapeName).ToLowerInvariant(); + // 세로/가로 방향에 따라 보정 비율 적용 + weight = ApplyScaleCorrection(normalizedName, weight); + if (blendShapeCache.TryGetValue(normalizedName, out List mappings)) { // 캐시에서 찾은 모든 매핑에 대해 weight 설정 @@ -251,6 +291,32 @@ public class UnityRecieve_FACEMOTION3D_and_iFacialMocap : MonoBehaviour } } + // 세로/가로 방향에 따른 BlendShape 보정 비율 적용 + // 곡선 보정으로 0~100 범위를 유지하면서 민감도 조절 + float ApplyScaleCorrection(string normalizedName, float weight) + { + float scale = 1.0f; + + if (VerticalBlendShapes.Contains(normalizedName)) + { + scale = verticalScale; + } + else if (HorizontalBlendShapes.Contains(normalizedName)) + { + scale = horizontalScale; + } + + if (Mathf.Approximately(scale, 1.0f)) + return weight; + + // 0~100 범위 유지하면서 곡선 보정 + // scale > 1: 작은 입력에서 더 빠르게 반응 (눌린 화면 보정) + // scale < 1: 작은 입력에서 더 느리게 반응 + float normalized = weight / 100f; + float corrected = Mathf.Pow(normalized, 1f / scale); + return corrected * 100f; + } + // BlendShape 이름 정규화 함수 string NormalizeBlendShapeName(string name) {