Fix : 장갑 모션데이터 전달 불량 수정

This commit is contained in:
DESKTOP-S4BOTN2\user 2025-06-22 22:35:35 +09:00
parent ea1f905cc0
commit 8278a6d7c8
3 changed files with 43 additions and 109 deletions

View File

@ -8,6 +8,7 @@ using UnityEngine;
namespace Rokoko.Inputs
{
[DefaultExecutionOrder(-1)]
public class Actor : MonoBehaviour
{
[System.Serializable]
@ -25,14 +26,6 @@ namespace Rokoko.Inputs
Self
}
[System.Serializable]
public enum PoseApplicationScope
{
All, // Apply to all bones
HandsAndFingers, // Apply to hands (wrists) and all fingers
FingersOnly // Apply to fingers only
}
[HideInInspector] public string profileName = "DemoProfile";
[HideInInspector] public BoneMappingEnum boneMapping;
@ -45,11 +38,6 @@ namespace Rokoko.Inputs
[Tooltip("Convert Studio data to Unity rotation space")]
public RotationSpace rotationSpace = RotationSpace.Offset;
[Space(10)]
[Header("Pose Application")]
[Tooltip("Select which bones to apply motion capture data to")]
public PoseApplicationScope poseScope = PoseApplicationScope.All;
[Space(10)]
[Tooltip("Calculate Model's height comparing to Actor's and position the Hips accordingly.\nGreat tool to align with the floor")]
public bool adjustHipHeightBasedOnStudioActor = false;
@ -285,10 +273,6 @@ namespace Rokoko.Inputs
foreach (HumanBodyBones bone in RokokoHelper.HumanBodyBonesArray)
{
if (bone == HumanBodyBones.LastBone) break;
// Skip bones that are not in the selected scope
if (!ShouldApplyToBone(bone))
continue;
ActorJointFrame? boneFrame = actorFrame.body.GetBoneFrame(bone);
if (boneFrame != null)
@ -313,52 +297,6 @@ namespace Rokoko.Inputs
}
}
/// <summary>
/// Determine if a bone should be included based on the selected pose scope.
/// </summary>
private bool ShouldApplyToBone(HumanBodyBones bone)
{
switch (poseScope)
{
case PoseApplicationScope.All:
return true;
case PoseApplicationScope.HandsAndFingers:
return IsHandOrFingerBone(bone);
case PoseApplicationScope.FingersOnly:
return IsFingerBone(bone);
default:
return true;
}
}
/// <summary>
/// Check if the bone is a hand (wrist) or finger bone.
/// </summary>
private bool IsHandOrFingerBone(HumanBodyBones bone)
{
return bone == HumanBodyBones.LeftHand || bone == HumanBodyBones.RightHand || IsFingerBone(bone);
}
/// <summary>
/// Check if the bone is a finger bone.
/// </summary>
private bool IsFingerBone(HumanBodyBones bone)
{
return bone == HumanBodyBones.LeftThumbProximal || bone == HumanBodyBones.LeftThumbIntermediate || bone == HumanBodyBones.LeftThumbDistal ||
bone == HumanBodyBones.LeftIndexProximal || bone == HumanBodyBones.LeftIndexIntermediate || bone == HumanBodyBones.LeftIndexDistal ||
bone == HumanBodyBones.LeftMiddleProximal || bone == HumanBodyBones.LeftMiddleIntermediate || bone == HumanBodyBones.LeftMiddleDistal ||
bone == HumanBodyBones.LeftRingProximal || bone == HumanBodyBones.LeftRingIntermediate || bone == HumanBodyBones.LeftRingDistal ||
bone == HumanBodyBones.LeftLittleProximal || bone == HumanBodyBones.LeftLittleIntermediate || bone == HumanBodyBones.LeftLittleDistal ||
bone == HumanBodyBones.RightThumbProximal || bone == HumanBodyBones.RightThumbIntermediate || bone == HumanBodyBones.RightThumbDistal ||
bone == HumanBodyBones.RightIndexProximal || bone == HumanBodyBones.RightIndexIntermediate || bone == HumanBodyBones.RightIndexDistal ||
bone == HumanBodyBones.RightMiddleProximal || bone == HumanBodyBones.RightMiddleIntermediate || bone == HumanBodyBones.RightMiddleDistal ||
bone == HumanBodyBones.RightRingProximal || bone == HumanBodyBones.RightRingIntermediate || bone == HumanBodyBones.RightRingDistal ||
bone == HumanBodyBones.RightLittleProximal || bone == HumanBodyBones.RightLittleIntermediate || bone == HumanBodyBones.RightLittleDistal;
}
/// <summary>
/// Apply additional rotation offsets to thumb proximal bones.
/// </summary>

View File

@ -42,7 +42,7 @@ namespace KindRetargeting
List<float> leftLegEndWeights = new List<float>();
List<float> rightLegEndWeights = new List<float>();
List<float> leftLegBendWeights = new List<float>();
List<float> leftLegBendWeights = new List<float>();
List<float> rightLegBendWeights = new List<float>();
private float MasterleftArmEndWeights = 0f;
@ -99,7 +99,7 @@ namespace KindRetargeting
props = FindObjectsByType<PropTypeController>(FindObjectsSortMode.None).Select(controller => controller.transform).ToList();
// 프랍 오브젝트 찾기
Gethnad();
GetHand();
//HandDistances();에서 사용을 위한 리스트 추가
//손 거리에 따른 웨이트 업데이트 인덱스 0번
@ -137,24 +137,24 @@ namespace KindRetargeting
rightLegEndWeights.Add(1f);
}
private void Gethnad()
private void GetHand()
{
// 모든 LimbWeightController 찾기
LimbWeightController[] allControllers = FindObjectsOfType<LimbWeightController>();
foreach (LimbWeightController controller in allControllers)
{
// 자기 자신은 제외
if (controller == this) continue;
// CustomRetargetingScript 가져오기
CustomRetargetingScript otherCrs = controller.GetComponent<CustomRetargetingScript>();
if (otherCrs == null) continue;
// 왼손과 오른손 Transform 가져오기
Transform leftHand = otherCrs.sourceAnimator.GetBoneTransform(HumanBodyBones.LeftHand);
Transform rightHand = otherCrs.sourceAnimator.GetBoneTransform(HumanBodyBones.RightHand);
Transform leftHand = otherCrs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.LeftHand);
Transform rightHand = otherCrs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.RightHand);
// 손이 존재하면 props 리스트에 추가
if (leftHand != null)
{
@ -182,59 +182,53 @@ namespace KindRetargeting
/// </summary>
private void HandDistances()
{
if (fbik == null || fbik == null) return;
if (fbik == null || crs == null) return;
// 왼쪽 팔 가중치 업데이트
if (fbik.solver.leftArm.target != null && fbik.solver.rightArm.target != null)
{
Transform leftHandTransform = crs.sourceAnimator.GetBoneTransform(HumanBodyBones.LeftHand);
Transform rightHandTransform = crs.sourceAnimator.GetBoneTransform(HumanBodyBones.RightHand);
if (leftHandTransform != null && rightHandTransform != null)
Transform leftHandTransform = crs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.LeftHand);
Transform rightHandTransform = crs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.RightHand);
if (leftHandTransform != null && rightHandTransform != null &&
props != null && props.Count > 0)
{
float Distance = Vector3.Distance(leftHandTransform.position, rightHandTransform.position);
float Weight = 1f - Mathf.Clamp01((Distance - minDistance) / (maxDistance - minDistance));
leftArmEndWeights[0] = Weight;
rightArmEndWeights[0] = Weight;
}
else
{
// props가 없을 때 기본 가중치 설정
leftArmEndWeights[0] = 0f;
rightArmEndWeights[0] = 0f;
}
}
}
void SitLegDistances()
{
if (fbik == null || fbik == null) return;
if (fbik == null || crs == null || characterRoot == null) return;
Transform hips = crs.sourceAnimator.GetBoneTransform(HumanBodyBones.Hips);
Transform hips = crs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.Hips);
if (hips == null) return;
// 캐릭터 루트 기준으로 히프의 로컬 높이 계산
float hipHeight = characterRoot.InverseTransformPoint(hips.position).y;
float normalStandingHeight = 0.9f;
float sitThreshold = 0.6f;
// 기본적으로 다리 가중치를 1로 설정
while (leftLegEndWeights.Count <= 0) leftLegEndWeights.Add(1f);
while (rightLegEndWeights.Count <= 0) rightLegEndWeights.Add(1f);
leftLegEndWeights[0] = 1f;
rightLegEndWeights[0] = 1f;
// 히프가 충분히 낮을 때만 가중치 감소 처리
if (hipHeight < sitThreshold * normalStandingHeight)
// 바닥 기준 히프 보정 변수들을 활용한 앉아있는 판단
// groundHipsMaxHeight 이하일 때 앉아있다고 판단
if (hipHeight <= groundHipsMaxHeight)
{
// 왼쪽 다리 처리
ProcessSitLegWeight(
hips,
fbik.solver.leftLeg.target,
leftLegEndWeights,
0 // 레이어 인덱스
);
ProcessSitLegWeight(hips, fbik.solver.leftLeg.target, leftLegEndWeights, 0);
// 오른쪽 다리 처리
ProcessSitLegWeight(
hips,
fbik.solver.rightLeg.target,
rightLegEndWeights,
0 // 레이어 인덱스
);
ProcessSitLegWeight(hips, fbik.solver.rightLeg.target, rightLegEndWeights, 0);
}
}
@ -242,29 +236,31 @@ namespace KindRetargeting
{
if (footTarget == null) return;
// 히프와 발 타겟 사이의 수평 거리 계산 (Y축 제외)
// Y축을 제외한 실제 수평 거리 계산
Vector3 hipPos = hips.position;
Vector3 footPos = footTarget.position;
float horizontalDistance = Vector3.Distance(hipPos, footPos);
Vector3 hipPosFlat = new Vector3(hipPos.x, 0, hipPos.z);
Vector3 footPosFlat = new Vector3(footPos.x, 0, footPos.z);
float horizontalDistance = Vector3.Distance(hipPosFlat, footPosFlat);
// 다리 길이를 기준으로 최대/최소 허용 거리 설정
float maxLegDistance = 0.8f; // 다리 길이의 80%를 최대 거리로 설정
float minLegDistance = 0.5f; // 다리 길이의 30%를 최소 거리로 설정
const float MAX_LEG_DISTANCE_RATIO = 0.8f; // 다리 길이의 80%
const float MIN_LEG_DISTANCE_RATIO = 0.3f; // 다리 길이의 30%
// 거리가 멀수록 가중치 감소
float weight = 1f - Mathf.Clamp01((horizontalDistance - minLegDistance) / (maxLegDistance - minLegDistance));
float weight = 1f - Mathf.Clamp01((horizontalDistance - MIN_LEG_DISTANCE_RATIO) /
(MAX_LEG_DISTANCE_RATIO - MIN_LEG_DISTANCE_RATIO));
// 계산된 가중치 설정
weightList[weightIndex] = weight;
}
void PropDistances()
{
if (fbik == null || fbik == null) return;
if (fbik == null || crs == null) return;
// 프랍과의 거리에 따른 웨이트 업데이트
Transform leftHandTransform = crs.sourceAnimator.GetBoneTransform(HumanBodyBones.LeftHand);
Transform rightHandTransform = crs.sourceAnimator.GetBoneTransform(HumanBodyBones.RightHand);
Transform leftHandTransform = crs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.LeftHand);
Transform rightHandTransform = crs?.sourceAnimator?.GetBoneTransform(HumanBodyBones.RightHand);
if (leftHandTransform != null && rightHandTransform != null && props != null)
{
@ -495,7 +491,7 @@ namespace KindRetargeting
/// </summary>
private void UpdateFootHeightBasedWeight()
{
if (fbik == null || fbik == null || characterRoot == null) return;
if (fbik == null || crs == null || characterRoot == null) return;
// 왼발 처리
ProcessFootHeightWeight(