VRM Avatar와 Xsens Avatar의 Bone 좌표계가 맞지 않은 문제 수정

회전변환 역산을 통해 월드 Pos → offset 계산 → vrm sensor worldpos 계산으로 진행 및

모델 Scale에 따른 Offset 변환도 추가

image.png

image.png

		//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의 센서 오프셋을 구할 수 있음
 

image.png

image.png

Inner 의상 뚫는 현상 수정 및 리깅 재설정

현재 치마랑 파우치가 Outer를 뚫음 해당 부분은 VRM Collider 및 리깅 재설정 필요

Missing Script Component 삭제 툴