VRM Avatar와 Xsens Avatar의 Bone 좌표계가 맞지 않은 문제 수정
회전변환 역산을 통해 월드 Pos → offset 계산 → vrm sensor worldpos 계산으로 진행 및
모델 Scale에 따른 Offset 변환도 추가


//Base Avatar(Xsens)를 기준으로 적용된 센서의 월드 포지션을 구한 뒤
//타겟 본에서 얼마나 떨어져있는지를 구한 뒤 다시 타겟에 적용하는 과정
private Vector3 ConvertSensorPosToBase(SensorOffsetData.SensorEntry sensorEntry)
{
var baseBone = baseAvatar.GetBoneTransform(sensorEntry.bone);
var targetBone = animator.GetBoneTransform(sensorEntry.bone);
float avatarScale = GetScaleRatio();
Vector3 newSensorOffset = sensorEntry.localPositionOffset * avatarScale;
Vector3 baseSensorWorldPos =
baseBone.position + baseBone.rotation * newSensorOffset;
Vector3 targetLocalOffset =
Quaternion.Inverse(targetBone.rotation) * (baseSensorWorldPos - baseBone.position);
Vector3 targetSensorWorldPos =
targetBone.position + targetBone.rotation * targetLocalOffset;
return targetSensorWorldPos;
}
//두 모델의 크기 차이로 인하여 오프셋이 틀어지기 때문에
//비율을 계산하여 offset에 적용
private float GetScaleRatio()
{
Transform baseBoneStart =
baseAvatar.GetBoneTransform(HumanBodyBones.LeftUpperArm);
Transform baseBoneEnd =
baseAvatar.GetBoneTransform(HumanBodyBones.LeftLowerArm);
Transform targetBoneStart =
animator.GetBoneTransform(HumanBodyBones.LeftUpperArm);
Transform targetBoneEnd =
animator.GetBoneTransform(HumanBodyBones.LeftLowerArm);
float baseLength =
Vector3.Distance(baseBoneStart.position, baseBoneEnd.position);
float targetLength =
Vector3.Distance(targetBoneStart.position, targetBoneEnd.position);
return targetLength / baseLength;
}
Vector3 targetLocalOffset =
Quaternion.Inverse(targetBone.rotation) * (baseSensorWorldPos - baseBone.position);
(baseSensorWorldPos - baseBone.position);
-> 두 벡터 사이의 오프셋(baseBone에서 센서가 얼마나 떨어져있는지)
Quaternion.Inverse(targetBone.rotation)
-> 월드 좌표계의 회전값을 되돌리기 위해 역회전값을 사용
물체가 회전할 때 로컬 회전값도 변화하기에
물체가 회전하여 위치했다면, 위치한 곳에서 역회전하여 원래 위치로 변환
두 값을 곱해주면 target Bone의 센서 오프셋을 구할 수 있음


Inner 의상 뚫는 현상 수정 및 리깅 재설정
현재 치마랑 파우치가 Outer를 뚫음 해당 부분은 VRM Collider 및 리깅 재설정 필요
‣
Missing Script Component 삭제 툴