226 lines
8.2 KiB
C++

//======================================================================================================
// Copyright 2025, Rokoko Glove OptiTrack Integration
//======================================================================================================
#include "RokokoDataParser.h"
#include "RokokoData.h"
#include <sstream>
#include <iostream>
#include <cstring>
#include <cmath>
namespace RokokoIntegration
{
bool RokokoDataParser::ParseLiveFrame(const std::string& jsonString, RokokoData::LiveFrame_v4& frame)
{
try {
// 간단한 JSON 파싱 구현 (실제로는 nlohmann/json 라이브러리 사용 권장)
// 현재는 기본 구조만 생성
// 기본 프레임 데이터 초기화
frame.scene.actors.clear();
frame.scene.actors.push_back(RokokoData::ActorData());
// 기본 손가락 데이터 구조 생성
auto& actor = frame.scene.actors[0];
// 왼손 데이터 초기화 (모든 손가락)
// 엄지
actor.body.leftThumbMedial = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.leftThumbDistal = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.leftThumbTip = std::make_shared<RokokoData::ActorJointFrame>();
// 검지
actor.body.leftIndexMedial = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.leftIndexDistal = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.leftIndexTip = std::make_shared<RokokoData::ActorJointFrame>();
// 중지
actor.body.leftMiddleMedial = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.leftMiddleDistal = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.leftMiddleTip = std::make_shared<RokokoData::ActorJointFrame>();
// 약지
actor.body.leftRingMedial = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.leftRingDistal = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.leftRingTip = std::make_shared<RokokoData::ActorJointFrame>();
// 새끼
actor.body.leftLittleMedial = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.leftLittleDistal = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.leftLittleTip = std::make_shared<RokokoData::ActorJointFrame>();
// 오른손 데이터 초기화 (모든 손가락)
// 엄지
actor.body.rightThumbMedial = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.rightThumbDistal = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.rightThumbTip = std::make_shared<RokokoData::ActorJointFrame>();
// 검지
actor.body.rightIndexMedial = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.rightIndexDistal = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.rightIndexTip = std::make_shared<RokokoData::ActorJointFrame>();
// 중지
actor.body.rightMiddleMedial = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.rightMiddleDistal = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.rightMiddleTip = std::make_shared<RokokoData::ActorJointFrame>();
// 약지
actor.body.rightRingMedial = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.rightRingDistal = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.rightRingTip = std::make_shared<RokokoData::ActorJointFrame>();
// 새끼
actor.body.rightLittleMedial = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.rightLittleDistal = std::make_shared<RokokoData::ActorJointFrame>();
actor.body.rightLittleTip = std::make_shared<RokokoData::ActorJointFrame>();
// 기본 쿼터니언 값 설정 (정규화된 단위 쿼터니언)
RokokoData::Vector4Frame defaultRotation = {1.0f, 0.0f, 0.0f, 0.0f};
// 왼손 기본값 설정
actor.body.leftThumbMedial->rotation = defaultRotation;
actor.body.leftThumbDistal->rotation = defaultRotation;
actor.body.leftThumbTip->rotation = defaultRotation;
actor.body.leftIndexMedial->rotation = defaultRotation;
actor.body.leftIndexDistal->rotation = defaultRotation;
actor.body.leftIndexTip->rotation = defaultRotation;
actor.body.leftMiddleMedial->rotation = defaultRotation;
actor.body.leftMiddleDistal->rotation = defaultRotation;
actor.body.leftMiddleTip->rotation = defaultRotation;
actor.body.leftRingMedial->rotation = defaultRotation;
actor.body.leftRingDistal->rotation = defaultRotation;
actor.body.leftRingTip->rotation = defaultRotation;
actor.body.leftLittleMedial->rotation = defaultRotation;
actor.body.leftLittleDistal->rotation = defaultRotation;
actor.body.leftLittleTip->rotation = defaultRotation;
// 오른손 기본값 설정
actor.body.rightThumbMedial->rotation = defaultRotation;
actor.body.rightThumbDistal->rotation = defaultRotation;
actor.body.rightThumbTip->rotation = defaultRotation;
actor.body.rightIndexMedial->rotation = defaultRotation;
actor.body.rightIndexDistal->rotation = defaultRotation;
actor.body.rightIndexTip->rotation = defaultRotation;
actor.body.rightMiddleMedial->rotation = defaultRotation;
actor.body.rightMiddleDistal->rotation = defaultRotation;
actor.body.rightMiddleTip->rotation = defaultRotation;
actor.body.rightRingMedial->rotation = defaultRotation;
actor.body.rightRingDistal->rotation = defaultRotation;
actor.body.rightRingTip->rotation = defaultRotation;
actor.body.rightLittleMedial->rotation = defaultRotation;
actor.body.rightLittleDistal->rotation = defaultRotation;
actor.body.rightLittleTip->rotation = defaultRotation;
return true;
} catch (...) {
return false;
}
}
bool RokokoDataParser::ValidateFrameData(const RokokoData::LiveFrame_v4& frame)
{
try {
// 기본 검증
if (frame.scene.actors.empty()) {
return false;
}
const auto& actor = frame.scene.actors[0];
// 손가락 데이터 검증
if (!actor.body.leftThumbMedial || !actor.body.leftThumbDistal || !actor.body.leftThumbTip) {
return false;
}
return true;
} catch (...) {
return false;
}
}
bool RokokoDataParser::ExtractFingerData(const RokokoData::LiveFrame_v4& frame,
std::vector<RokokoData::ActorJointFrame>& leftHandFingers,
std::vector<RokokoData::ActorJointFrame>& rightHandFingers)
{
try {
leftHandFingers.clear();
rightHandFingers.clear();
if (frame.scene.actors.empty()) {
return false;
}
const auto& actor = frame.scene.actors[0];
// 왼손 데이터 추출
if (actor.body.leftThumbMedial) {
leftHandFingers.push_back(*actor.body.leftThumbMedial);
}
if (actor.body.leftThumbDistal) {
leftHandFingers.push_back(*actor.body.leftThumbDistal);
}
if (actor.body.leftThumbTip) {
leftHandFingers.push_back(*actor.body.leftThumbTip);
}
// 오른손 데이터는 현재 구현되지 않음 (기본값 사용)
// 실제 구현에서는 actor.body.rightThumb* 데이터 사용
return true;
} catch (...) {
return false;
}
}
bool RokokoDataParser::ParseActorData(const void* actorJson, RokokoData::ActorData& actor)
{
// 현재는 기본 구현만 제공
// 실제 JSON 파싱 라이브러리 사용 시 구현
return true;
}
bool RokokoDataParser::ParseFingerData(const void* fingerJson, RokokoData::ActorJointFrame& finger)
{
// 현재는 기본 구현만 제공
// 실제 JSON 파싱 라이브러리 사용 시 구현
return true;
}
bool RokokoDataParser::ValidateQuaternion(float x, float y, float z, float w)
{
// NaN 체크
if (std::isnan(x) || std::isnan(y) || std::isnan(z) || std::isnan(w)) {
return false;
}
// 무한대 체크
if (std::isinf(x) || std::isinf(y) || std::isinf(z) || std::isinf(w)) {
return false;
}
// 쿼터니언 길이 체크 (정규화된 경우 1.0에 가까워야 함)
float length = std::sqrt(x * x + y * y + z * z + w * w);
if (std::abs(length - 1.0f) > 0.1f) {
return false;
}
return true;
}
void RokokoDataParser::NormalizeQuaternion(float& x, float& y, float& z, float& w)
{
float length = std::sqrt(x * x + y * y + z * z + w * w);
if (length > 0.0f) {
float invLength = 1.0f / length;
x *= invLength;
y *= invLength;
z *= invLength;
w *= invLength;
} else {
// 유효하지 않은 쿼터니언인 경우 기본값 설정
x = 0.0f;
y = 0.0f;
z = 0.0f;
w = 1.0f;
}
}
}