Fix : 리타겟팅 버그 업데이트 프랍 데이터베이스 추가
This commit is contained in:
parent
4b59344a3e
commit
4aa22756e5
@ -109,8 +109,9 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
// OptiTrack 본 이름 → Transform 빠른 캐시 (GetMappedTransform O(n) → O(1))
|
// OptiTrack 본 이름 → Transform 빠른 캐시 (GetMappedTransform O(n) → O(1))
|
||||||
private Dictionary<string, Transform> m_optiNameTransformCache = new Dictionary<string, Transform>();
|
private Dictionary<string, Transform> m_optiNameTransformCache = new Dictionary<string, Transform>();
|
||||||
|
|
||||||
// 필터 적용 전 raw 월드 위치 (IK 타겟용 — 접지력 보존)
|
// 필터 적용 전 raw 월드 위치/회전 (IK 타겟용 — 접지력 보존)
|
||||||
private Dictionary<HumanBodyBones, Vector3> m_rawWorldPositions = new Dictionary<HumanBodyBones, Vector3>();
|
private Dictionary<HumanBodyBones, Vector3> m_rawWorldPositions = new Dictionary<HumanBodyBones, Vector3>();
|
||||||
|
private Dictionary<HumanBodyBones, Quaternion> m_rawWorldRotations = new Dictionary<HumanBodyBones, Quaternion>();
|
||||||
|
|
||||||
// raw 위치를 캡처할 IK 포인트 본 목록
|
// raw 위치를 캡처할 IK 포인트 본 목록
|
||||||
private static readonly HumanBodyBones[] k_IKPointBones = new HumanBodyBones[]
|
private static readonly HumanBodyBones[] k_IKPointBones = new HumanBodyBones[]
|
||||||
@ -373,12 +374,15 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
mapping.cachedTransform.localPosition = rawPos;
|
mapping.cachedTransform.localPosition = rawPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raw 상태에서 IK 포인트 월드 위치 캡처
|
// Raw 상태에서 IK 포인트 월드 위치/회전 캡처
|
||||||
foreach (var ikBone in k_IKPointBones)
|
foreach (var ikBone in k_IKPointBones)
|
||||||
{
|
{
|
||||||
Transform t = GetBoneTransform(ikBone);
|
Transform t = GetBoneTransform(ikBone);
|
||||||
if (t != null)
|
if (t != null)
|
||||||
|
{
|
||||||
m_rawWorldPositions[ikBone] = t.position;
|
m_rawWorldPositions[ikBone] = t.position;
|
||||||
|
m_rawWorldRotations[ikBone] = t.rotation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass 2: 필터 적용된 데이터로 덮어쓰기
|
// Pass 2: 필터 적용된 데이터로 덮어쓰기
|
||||||
@ -419,20 +423,23 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
mapping.cachedTransform.localPosition = finalPos;
|
mapping.cachedTransform.localPosition = finalPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 필터 없으면 현재 Transform 위치가 곧 raw
|
// 필터 없으면 현재 Transform 위치/회전이 곧 raw
|
||||||
foreach (var ikBone in k_IKPointBones)
|
foreach (var ikBone in k_IKPointBones)
|
||||||
{
|
{
|
||||||
Transform t = GetBoneTransform(ikBone);
|
Transform t = GetBoneTransform(ikBone);
|
||||||
if (t != null)
|
if (t != null)
|
||||||
|
{
|
||||||
m_rawWorldPositions[ikBone] = t.position;
|
m_rawWorldPositions[ikBone] = t.position;
|
||||||
|
m_rawWorldRotations[ikBone] = t.rotation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 어깨 증폭 + 상완 역보정 (1.0이면 스킵) ──
|
// ── 어깨 증폭 + 상완 역보정 (1.0이면 스킵) ──
|
||||||
if (Mathf.Abs(shoulderAmplify - 1f) > 0.001f)
|
if (Mathf.Abs(shoulderAmplify - 1f) > 0.001f)
|
||||||
{
|
{
|
||||||
AmplifyShoulderWithCompensation("LShoulder", "LUArm");
|
AmplifyShoulderWithCompensation("LShoulder", "LUArm", true);
|
||||||
AmplifyShoulderWithCompensation("RShoulder", "RUArm");
|
AmplifyShoulderWithCompensation("RShoulder", "RUArm", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -440,17 +447,35 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 어깨 회전을 rest pose 대비 증폭하고, 상완에서 추가 회전분을 상쇄하여 손 위치를 보존합니다.
|
/// 어깨 회전을 rest pose 대비 증폭하고, 상완에서 추가 회전분을 상쇄하여 손 위치를 보존합니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void AmplifyShoulderWithCompensation(string shoulderName, string upperArmName)
|
private float m_leftShoulderBlend = 0f;
|
||||||
|
private float m_rightShoulderBlend = 0f;
|
||||||
|
|
||||||
|
/// <param name="isLeft">true = 왼쪽(Z < 0일 때 증폭), false = 오른쪽(Z > 0일 때 증폭)</param>
|
||||||
|
private void AmplifyShoulderWithCompensation(string shoulderName, string upperArmName, bool isLeft)
|
||||||
{
|
{
|
||||||
Transform shoulder = GetMappedTransform(shoulderName);
|
Transform shoulder = GetMappedTransform(shoulderName);
|
||||||
Transform upperArm = GetMappedTransform(upperArmName);
|
Transform upperArm = GetMappedTransform(upperArmName);
|
||||||
if (shoulder == null || upperArm == null) return;
|
if (shoulder == null || upperArm == null) return;
|
||||||
|
|
||||||
// rest pose 대비 델타 추출 → 증폭
|
// rest pose 대비 델타 추출
|
||||||
Quaternion restRot = GetRestLocalRotation(shoulderName);
|
Quaternion restRot = GetRestLocalRotation(shoulderName);
|
||||||
Quaternion currentRot = shoulder.localRotation;
|
Quaternion currentRot = shoulder.localRotation;
|
||||||
Quaternion delta = Quaternion.Inverse(restRot) * currentRot;
|
Quaternion delta = Quaternion.Inverse(restRot) * currentRot;
|
||||||
Quaternion amplifiedDelta = Quaternion.SlerpUnclamped(Quaternion.identity, delta, shoulderAmplify);
|
|
||||||
|
// 어깨가 올라가는 방향일 때만 증폭 (왼쪽: Z < 0, 오른쪽: Z > 0)
|
||||||
|
Vector3 deltaEuler = delta.eulerAngles;
|
||||||
|
float z = deltaEuler.z > 180f ? deltaEuler.z - 360f : deltaEuler.z;
|
||||||
|
float targetBlend = isLeft ? Mathf.Clamp01(-z / 5f) : Mathf.Clamp01(z / 5f);
|
||||||
|
|
||||||
|
// 부드러운 블렌딩 (급격한 on/off 방지)
|
||||||
|
ref float blend = ref (isLeft ? ref m_leftShoulderBlend : ref m_rightShoulderBlend);
|
||||||
|
blend = Mathf.Lerp(blend, targetBlend, 10f * Time.deltaTime);
|
||||||
|
|
||||||
|
if (blend < 0.001f) return;
|
||||||
|
|
||||||
|
// 증폭량: 1(원본) ~ shoulderAmplify 사이를 blend로 보간
|
||||||
|
float effectiveAmplify = Mathf.Lerp(1f, shoulderAmplify, blend);
|
||||||
|
Quaternion amplifiedDelta = Quaternion.SlerpUnclamped(Quaternion.identity, delta, effectiveAmplify);
|
||||||
Quaternion amplifiedRot = restRot * amplifiedDelta;
|
Quaternion amplifiedRot = restRot * amplifiedDelta;
|
||||||
|
|
||||||
// 추가된 회전량
|
// 추가된 회전량
|
||||||
@ -748,6 +773,14 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
return m_rawWorldPositions.TryGetValue(bone, out position);
|
return m_rawWorldPositions.TryGetValue(bone, out position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1€ 필터 적용 전의 raw 월드 회전을 반환합니다.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryGetRawWorldRotation(HumanBodyBones bone, out Quaternion rotation)
|
||||||
|
{
|
||||||
|
return m_rawWorldRotations.TryGetValue(bone, out rotation);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// HumanBodyBones enum으로 OptiTrack 매핑된 Transform 반환
|
/// HumanBodyBones enum으로 OptiTrack 매핑된 Transform 반환
|
||||||
/// (Humanoid 호환 레이어 — sourceAnimator.GetBoneTransform() 대체)
|
/// (Humanoid 호환 레이어 — sourceAnimator.GetBoneTransform() 대체)
|
||||||
|
|||||||
BIN
Assets/Resources/Settings/PropDatabase.asset
(Stored with Git LFS)
BIN
Assets/Resources/Settings/PropDatabase.asset
(Stored with Git LFS)
Binary file not shown.
@ -1257,12 +1257,25 @@ namespace KindRetargeting
|
|||||||
{
|
{
|
||||||
// 1€ 필터 적용 전 raw 위치 사용 (접지력 보존)
|
// 1€ 필터 적용 전 raw 위치 사용 (접지력 보존)
|
||||||
// raw가 없으면 필터된 Transform.position fallback
|
// raw가 없으면 필터된 Transform.position fallback
|
||||||
|
// 1€ 필터 적용 전 raw 위치/회전 사용 (접지력 보존)
|
||||||
Vector3 targetPosition;
|
Vector3 targetPosition;
|
||||||
if (optitrackSource != null && optitrackSource.TryGetRawWorldPosition(endBone, out Vector3 rawPos))
|
if (optitrackSource != null && optitrackSource.TryGetRawWorldPosition(endBone, out Vector3 rawPos))
|
||||||
targetPosition = rawPos;
|
targetPosition = rawPos;
|
||||||
else
|
else
|
||||||
targetPosition = sourceBone.position;
|
targetPosition = sourceBone.position;
|
||||||
Quaternion targetRotation = targetBone.rotation;
|
|
||||||
|
// raw 회전 + 리타게팅 오프셋 적용 (필터 스무딩 없는 회전)
|
||||||
|
Quaternion targetRotation;
|
||||||
|
if (optitrackSource != null
|
||||||
|
&& optitrackSource.TryGetRawWorldRotation(endBone, out Quaternion rawRot)
|
||||||
|
&& rotationOffsets.TryGetValue(endBone, out Quaternion endOffset))
|
||||||
|
{
|
||||||
|
targetRotation = rawRot * endOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetRotation = targetBone.rotation;
|
||||||
|
}
|
||||||
|
|
||||||
// 발 본인 경우 오프셋 적용
|
// 발 본인 경우 오프셋 적용
|
||||||
if (endBone == HumanBodyBones.LeftFoot || endBone == HumanBodyBones.RightFoot)
|
if (endBone == HumanBodyBones.LeftFoot || endBone == HumanBodyBones.RightFoot)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user