From c73c7cbc184e723e3bd7e6919947b8871006b726 Mon Sep 17 00:00:00 2001 From: "qsxft258@gmail.com" Date: Fri, 22 Aug 2025 07:02:00 +0900 Subject: [PATCH] =?UTF-8?q?Add=20:=20=EB=AA=A8=EC=85=98=20=EB=85=B9?= =?UTF-8?q?=ED=99=94=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=ED=8C=A8=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scripts/MotionDataRecorder.cs | 4 +- .../BaseAvatar - OptiTrack ver 2.prefab | 4 +- .../OptiTrack/BaseAvatar ver 2/Hand Data.meta | 8 + .../Hand Data/Hand Data.Avatar.meta | 8 + .../Hand Data.Avatar/VrmAvatar.asset | 3 + .../Hand Data.Avatar/VrmAvatar.asset.meta | 8 + .../Hand Data/Hand Data.Materials.meta | 8 + .../Hand Data.Materials/newton.asset | 3 + .../Hand Data.Materials/newton.asset.meta | 8 + .../Hand Data/Hand Data.Meshes.meta | 8 + .../Hand Data.Meshes/newton.baked.asset | 3 + .../Hand Data.Meshes/newton.baked.asset.meta | 8 + .../Hand Data/Hand Data.prefab | 3 + .../Hand Data/Hand Data.prefab.meta | 7 + .../BaseAvatar - OptiTrack Last.prefab | 3 + .../BaseAvatar - OptiTrack Last.prefab.meta | 7 + .../Prefabs/Client - OptiTrack.prefab | 4 +- .../OptitrackSkeletonAnimator_Mingle.cs | 44 +--- .../Prefeb/이벤트 컨트롤러 - 녹화 세팅.prefab | 4 +- .../Project/250821_모션촬영/모션.meta | 8 + .../250822_모션촬영/250822_모션촬영.unity | 4 +- .../Scripts/KindRetargeting/OffsetTransfer.cs | 192 ++++++++++++++++++ .../KindRetargeting/OffsetTransfer.cs.meta | 2 + 23 files changed, 304 insertions(+), 47 deletions(-) create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data.meta create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar.meta create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar/VrmAvatar.asset create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar/VrmAvatar.asset.meta create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials.meta create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials/newton.asset create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials/newton.asset.meta create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes.meta create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes/newton.baked.asset create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes/newton.baked.asset.meta create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.prefab create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.prefab.meta create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack Last.prefab create mode 100644 Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack Last.prefab.meta create mode 100644 Assets/ResourcesData/Project/250821_모션촬영/모션.meta create mode 100644 Assets/Scripts/KindRetargeting/OffsetTransfer.cs create mode 100644 Assets/Scripts/KindRetargeting/OffsetTransfer.cs.meta diff --git a/Assets/External/EasyMotionRecorder/Scripts/MotionDataRecorder.cs b/Assets/External/EasyMotionRecorder/Scripts/MotionDataRecorder.cs index dbf63f4b..d93d0efb 100644 --- a/Assets/External/EasyMotionRecorder/Scripts/MotionDataRecorder.cs +++ b/Assets/External/EasyMotionRecorder/Scripts/MotionDataRecorder.cs @@ -267,7 +267,7 @@ namespace Entum FrameIndex++; } - private void RecordStart() + public void RecordStart() { if (_recording) { @@ -421,7 +421,7 @@ namespace Entum Debug.Log("T-포즈 데이터가 저장되었습니다."); } - private void RecordEnd() + public void RecordEnd() { if (!_recording) { diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.prefab b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.prefab index b46dd531..fe21f047 100644 --- a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.prefab +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d426caa5686dcc01231edb83fcd338cb97ef3c81185b8a25d57f285ff9167fa8 -size 93393 +oid sha256:3636a534c8134d2addbc1b8783d0e33fa300024650366654bab15af370c3eaa9 +size 88075 diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data.meta b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data.meta new file mode 100644 index 00000000..bdf470d0 --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6f705ffb70fa1a140bf73185aef44529 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar.meta b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar.meta new file mode 100644 index 00000000..f0980e3a --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4b1499ea416adce4daaed7b0b3b2b001 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar/VrmAvatar.asset b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar/VrmAvatar.asset new file mode 100644 index 00000000..5e366b04 --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar/VrmAvatar.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ffbb281926810d322481acf6ed4506b0853fa1ca64f4edfb1fe5d7c528e36d4 +size 89653 diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar/VrmAvatar.asset.meta b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar/VrmAvatar.asset.meta new file mode 100644 index 00000000..9a7d4d71 --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Avatar/VrmAvatar.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3c4b192ca3a426b48819a1106d1d927b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 9000000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials.meta b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials.meta new file mode 100644 index 00000000..18334dfa --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9a46274a4e01e9d45bc0a3f2c25d5d02 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials/newton.asset b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials/newton.asset new file mode 100644 index 00000000..e01f65b4 --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials/newton.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bee63dd69600ec22f0eaa6c4c3a0eb4d0a2a8643cd723b4c2805667661ad0c97 +size 45440 diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials/newton.asset.meta b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials/newton.asset.meta new file mode 100644 index 00000000..20ae006d --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Materials/newton.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f5c6e42d92f8225488a96dfaf88b9051 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes.meta b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes.meta new file mode 100644 index 00000000..fce2cff9 --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d1094b1299f0ba44b9f618231c354db5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes/newton.baked.asset b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes/newton.baked.asset new file mode 100644 index 00000000..b11da0bd --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes/newton.baked.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1129516b4c03432a8d25550dd17d204fa72c6100b9527a01f78289039e45eef9 +size 3201114 diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes/newton.baked.asset.meta b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes/newton.baked.asset.meta new file mode 100644 index 00000000..a16f4f05 --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.Meshes/newton.baked.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 23aa04f3a9d0bb84bba05888737ec16e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 4300000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.prefab b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.prefab new file mode 100644 index 00000000..6dd93d8c --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca5166aeddce10c2dbb39a2b5ba75bb04853c8ae08d0a99ca6bfeea27c99611f +size 65261 diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.prefab.meta b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.prefab.meta new file mode 100644 index 00000000..d5490cbc --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/Hand Data/Hand Data.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e40a686a525bda34ebf267268d8b2616 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack Last.prefab b/Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack Last.prefab new file mode 100644 index 00000000..0977d2f1 --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack Last.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a97d4eb39cde31131b51f2f67670d4c93f7a9581d80b1540dae7bc00638aca8 +size 8648 diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack Last.prefab.meta b/Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack Last.prefab.meta new file mode 100644 index 00000000..cb1d0f90 --- /dev/null +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack Last.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c470e4106f9329048b690874ec8ef603 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/Client - OptiTrack.prefab b/Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/Client - OptiTrack.prefab index 79665c42..452a1240 100644 --- a/Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/Client - OptiTrack.prefab +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/Client - OptiTrack.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d2f437a992991a631d660888ea19054064d375285ac3f35a9b174623d3c6ab0 -size 3407 +oid sha256:2fb017b136c4553ec6b32b9b57342eaf9f73750826fddc427c566ab8f64a2cb1 +size 1689 diff --git a/Assets/External/OptiTrack Unity Plugin/OptiTrack/Scripts/OptitrackSkeletonAnimator_Mingle.cs b/Assets/External/OptiTrack Unity Plugin/OptiTrack/Scripts/OptitrackSkeletonAnimator_Mingle.cs index a40e48a2..c1f45a62 100644 --- a/Assets/External/OptiTrack Unity Plugin/OptiTrack/Scripts/OptitrackSkeletonAnimator_Mingle.cs +++ b/Assets/External/OptiTrack Unity Plugin/OptiTrack/Scripts/OptitrackSkeletonAnimator_Mingle.cs @@ -21,7 +21,7 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour [Tooltip("Motive의 스켈레톤 에셋 이름")] public string SkeletonAssetName = "Skeleton1"; - private Animator TargetAnimator; + public Animator TargetAnimator; [Header("모션 적용 범위")] [Tooltip("모션 캡처 데이터를 적용할 범위 선택")] @@ -37,18 +37,8 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour private float updateInterval = 0.1f; - // Actor 컴포넌트 참조 (Rokoko Actor와 동기화용) - private Rokoko.Inputs.Actor m_actor; - void Start() { - TargetAnimator = GetComponent(); - if (TargetAnimator == null) - { - //Debug.LogError("이 게임오브젝트에서 Animator 컴포넌트를 찾을 수 없습니다.", this); - enabled = false; - return; - } InitializeStreamingClient(); @@ -61,9 +51,6 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour InitializeBoneMapping(); - // Actor 컴포넌트 찾기 및 프로파일 이름 동기화 - SyncActorProfileName(); - // 주기적으로 스켈레톤 연결 상태를 확인하는 코루틴 시작 StartCoroutine(CheckSkeletonConnectionPeriodically()); } @@ -136,8 +123,12 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour { if (skelState.BonePoses.TryGetValue(bone.Id, out OptitrackPose bonePose)) { - // 위치는 항상 업데이트 (Hip 등 루트 본의 경우) - boneTransform.localPosition = bonePose.Position; + // 손가락의 경우 로컬 포지션 데이터를 받지 않음 + if (!IsFingerBone(optitrackBoneName)) + { + // 위치는 항상 업데이트 (Hip 등 루트 본의 경우) + boneTransform.localPosition = bonePose.Position; + } // 회전 업데이트 boneTransform.localRotation = bonePose.Orientation; @@ -178,27 +169,6 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour // 스켈레톤 에셋 이름을 제외한 기본 매핑 설정 SetupBoneNameMapping(); } - - /// - /// Actor 컴포넌트의 프로파일 이름을 OptiTrack 스켈레톤 이름과 동기화 - /// - private void SyncActorProfileName() - { - // 같은 게임오브젝트에서 Actor 컴포넌트 찾기 - m_actor = GetComponent(); - - if (m_actor != null) - { - // Actor의 프로파일 이름을 OptiTrack 스켈레톤 이름으로 설정 - m_actor.profileName = this.SkeletonAssetName; - Debug.Log($"[OptiTrack] Actor 프로파일 이름을 '{SkeletonAssetName}'으로 동기화했습니다.", this); - } - else - { - Debug.LogWarning("[OptiTrack] 같은 게임오브젝트에서 Actor 컴포넌트를 찾을 수 없습니다.", this); - } - } - private void SetupBoneNameMapping() { // 기본 본 매핑 (스켈레톤 에셋 이름 없이) diff --git a/Assets/Prefeb/이벤트 컨트롤러 - 녹화 세팅.prefab b/Assets/Prefeb/이벤트 컨트롤러 - 녹화 세팅.prefab index 9eb2c4fe..c6ad74e3 100644 --- a/Assets/Prefeb/이벤트 컨트롤러 - 녹화 세팅.prefab +++ b/Assets/Prefeb/이벤트 컨트롤러 - 녹화 세팅.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cbc146a4d31d4a1e6d8059017290fa3e10ad3a6dc150edc8c33314e986707bf -size 7725 +oid sha256:02686289571e295bc465ea87c68b6c93bcf47ccf37a65610e6addf7a587ba2ed +size 7519 diff --git a/Assets/ResourcesData/Project/250821_모션촬영/모션.meta b/Assets/ResourcesData/Project/250821_모션촬영/모션.meta new file mode 100644 index 00000000..7dc9f67e --- /dev/null +++ b/Assets/ResourcesData/Project/250821_모션촬영/모션.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e0123bef6b5bef14abc800ff6ed2ded4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ResourcesData/Project/250822_모션촬영/250822_모션촬영.unity b/Assets/ResourcesData/Project/250822_모션촬영/250822_모션촬영.unity index 723cd940..65370637 100644 --- a/Assets/ResourcesData/Project/250822_모션촬영/250822_모션촬영.unity +++ b/Assets/ResourcesData/Project/250822_모션촬영/250822_모션촬영.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0254b75e3483bc26a43f73449e4e0d30ed546ad3174cdf8a44f12fbda2fd6aba -size 47406 +oid sha256:c44a34af9c1555d9e83a4b74a44386295ebd02ecbe71320230f35526d63ee325 +size 47795 diff --git a/Assets/Scripts/KindRetargeting/OffsetTransfer.cs b/Assets/Scripts/KindRetargeting/OffsetTransfer.cs new file mode 100644 index 00000000..762d963b --- /dev/null +++ b/Assets/Scripts/KindRetargeting/OffsetTransfer.cs @@ -0,0 +1,192 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace KindRetargeting +{ + /// + /// 아바타 간의 회전 오프셋을 계산하고 포즈 데이터를 복사하는 기능을 제공합니다. + /// + public class OffsetTransfer : MonoBehaviour + { + [Header("아바타 설정")] + [SerializeField] public Animator sourceAnimator; // 원본 아바타의 Animator + [SerializeField] public Animator targetAnimator; // 대상 아바타의 Animator + + [Header("오프셋 설정")] + [SerializeField] private bool autoCalculateOnStart = true; // 시작 시 자동 계산 여부 + [SerializeField] private bool autoCopyPose = true; // 매 프레임마다 자동으로 포즈 복사 여부 + + // 본별 회전 오프셋을 저장하는 딕셔너리 + private Dictionary rotationOffsets = new Dictionary(); + + #region 프로퍼티 + + /// + /// 계산된 회전 오프셋 딕셔너리를 반환합니다. + /// + public Dictionary RotationOffsets => rotationOffsets; + + #endregion + + #region 초기화 + + private void Start() + { + if (autoCalculateOnStart) + { + CalculateRotationOffsets(); + } + } + + #endregion + + #region 업데이트 + + private void Update() + { + if (autoCopyPose) + { + CopyPoseToTarget(); + } + } + + private void LateUpdate() + { + if (autoCopyPose) + { + CopyPoseToTarget(); + } + } + + #endregion + + #region 오프셋 계산 + + /// + /// 원본과 대상 아바타의 각 본 간 회전 오프셋을 계산하여 저장합니다. + /// + public void CalculateRotationOffsets() + { + if (sourceAnimator == null || targetAnimator == null) + { + Debug.LogError("소스 또는 타겟 Animator가 설정되지 않았습니다."); + return; + } + + // Dictionary가 null이면 초기화 + if (rotationOffsets == null) + { + rotationOffsets = new Dictionary(); + } + + // 모든 본에 대해 오프셋 계산 (기본 몸체 본 + 손가락 본 + UpperChest) + for (int i = 0; i <= 54; i++) + { + HumanBodyBones bone = (HumanBodyBones)i; + Transform sourceBone = sourceAnimator.GetBoneTransform(bone); + Transform targetBone = targetAnimator.GetBoneTransform(bone); + + if (sourceBone != null && targetBone != null) + { + Quaternion offset = Quaternion.Inverse(sourceBone.rotation) * targetBone.rotation; + + if (rotationOffsets.ContainsKey(bone)) + { + rotationOffsets[bone] = offset; + } + else + { + rotationOffsets.Add(bone, offset); + } + } + } + + Debug.Log($"회전 오프셋 계산 완료: {rotationOffsets.Count}개 본"); + } + + /// + /// 특정 본의 회전 오프셋을 반환합니다. + /// + /// 본 타입 + /// 회전 오프셋 (없으면 Identity) + public Quaternion GetRotationOffset(HumanBodyBones bone) + { + if (rotationOffsets.ContainsKey(bone)) + { + return rotationOffsets[bone]; + } + return Quaternion.identity; + } + + /// + /// 특정 본에 회전 오프셋을 적용합니다. + /// + /// 본 타입 + /// 원본 회전값 + /// 오프셋이 적용된 회전값 + public Quaternion ApplyRotationOffset(HumanBodyBones bone, Quaternion originalRotation) + { + if (rotationOffsets.ContainsKey(bone)) + { + return originalRotation * rotationOffsets[bone]; + } + return originalRotation; + } + + #endregion + + #region 포즈 복사 + + /// + /// 원본 아바타의 포즈를 대상 아바타에 복사합니다. + /// + public void CopyPoseToTarget() + { + if (sourceAnimator == null || targetAnimator == null) + { + Debug.LogError("소스 또는 타겟 Animator가 설정되지 않았습니다."); + return; + } + + // 모든 본에 대해 포즈 복사 + for (int i = 0; i <= 54; i++) + { + HumanBodyBones bone = (HumanBodyBones)i; + Transform sourceBone = sourceAnimator.GetBoneTransform(bone); + Transform targetBone = targetAnimator.GetBoneTransform(bone); + + if (sourceBone != null && targetBone != null) + { + // 회전은 오프셋 적용, 위치는 그대로 복사 + Quaternion targetRotation = ApplyRotationOffset(bone, sourceBone.rotation); + targetBone.rotation = targetRotation; + targetBone.position = sourceBone.position; + } + } + } + + /// + /// 특정 본의 포즈를 복사합니다. + /// + /// 복사할 본 + public void CopyBonePose(HumanBodyBones bone) + { + if (sourceAnimator == null || targetAnimator == null) + { + Debug.LogError("소스 또는 타겟 Animator가 설정되지 않았습니다."); + return; + } + + Transform sourceBone = sourceAnimator.GetBoneTransform(bone); + Transform targetBone = targetAnimator.GetBoneTransform(bone); + + if (sourceBone != null && targetBone != null) + { + Quaternion targetRotation = ApplyRotationOffset(bone, sourceBone.rotation); + targetBone.rotation = targetRotation; + } + } + + #endregion + } +} diff --git a/Assets/Scripts/KindRetargeting/OffsetTransfer.cs.meta b/Assets/Scripts/KindRetargeting/OffsetTransfer.cs.meta new file mode 100644 index 00000000..aa8010ba --- /dev/null +++ b/Assets/Scripts/KindRetargeting/OffsetTransfer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2252970a315b77e4eacbd7dcfb654842 \ No newline at end of file