123 lines
4.1 KiB
C#

using UnityEngine;
using System.Collections.Generic;
using System;
public class OptitrackVisualizer : MonoBehaviour
{
[Header("OptiTrack 설정")]
public OptitrackRawDataReceiver dataReceiver;
[Header("시각화 설정")]
public bool showGizmos = true;
public float gizmoSize = 0.05f;
public float handGizmoScale = 0.1f; // 손 기즈모 크기 비율 (1 = 100%)
public Color boneColor = Color.red;
public bool drawBoneConnections = true;
public Color connectionColor = Color.yellow;
private OptitrackSkeletonDefinition skeletonDef;
private Dictionary<int, Transform> boneTransforms = new Dictionary<int, Transform>();
private List<(Transform, Transform)> boneConnections = new List<(Transform, Transform)>();
void Start()
{
if (dataReceiver == null)
{
dataReceiver = FindFirstObjectByType<OptitrackRawDataReceiver>();
if (dataReceiver == null)
{
Debug.LogError("OptitrackRawDataReceiver를 찾을 수 없습니다.");
return;
}
}
// 스켈레톤 정의 가져오기
skeletonDef = dataReceiver.StreamingClient.GetSkeletonDefinitionByName(dataReceiver.SkeletonAssetName);
if (skeletonDef == null) return;
// 본 Transform 생성
foreach (var bone in skeletonDef.Bones)
{
GameObject boneObj = new GameObject(bone.Name);
boneTransforms[bone.Id] = boneObj.transform;
}
// 본 계층 구조 설정
foreach (var bone in skeletonDef.Bones)
{
Transform boneTransform = boneTransforms[bone.Id];
if (bone.ParentId == 0)
{
boneTransform.SetParent(transform, false);
}
else if (boneTransforms.TryGetValue(bone.ParentId, out Transform parentTransform))
{
boneTransform.SetParent(parentTransform, false);
boneConnections.Add((parentTransform, boneTransform));
}
}
}
void Update()
{
if (dataReceiver == null || skeletonDef == null) return;
// 최신 스켈레톤 상태 가져오기
OptitrackSkeletonState skelState = dataReceiver.StreamingClient.GetLatestSkeletonState(skeletonDef.Id);
if (skelState == null) return;
// 각 본의 위치와 회전 업데이트
foreach (var bone in skeletonDef.Bones)
{
if (boneTransforms.TryGetValue(bone.Id, out Transform boneTransform))
{
if (skelState.BonePoses.TryGetValue(bone.Id, out OptitrackPose pose))
{
boneTransform.localPosition = pose.Position;
boneTransform.localRotation = pose.Orientation;
}
}
}
}
void OnDrawGizmos()
{
if (!showGizmos || !Application.isPlaying || skeletonDef == null) return;
// 본 기즈모 그리기
Gizmos.color = boneColor;
foreach (var bone in skeletonDef.Bones)
{
if (boneTransforms.TryGetValue(bone.Id, out Transform transform))
{
float size = gizmoSize;
string boneName = bone.Name.ToLower();
// 손과 손가락 기즈모 크기 조절
if (boneName.Contains("hand") ||
boneName.Contains("thumb") ||
boneName.Contains("index") ||
boneName.Contains("middle") ||
boneName.Contains("ring") ||
boneName.Contains("pinky"))
{
size *= handGizmoScale;
}
Gizmos.DrawWireSphere(transform.position, size);
}
}
// 본 연결선 그리기
if (drawBoneConnections)
{
Gizmos.color = connectionColor;
foreach (var (parent, child) in boneConnections)
{
Gizmos.DrawLine(parent.position, child.position);
}
}
}
}