//====================================================================================================== // Copyright 2025, Rokoko Glove OptiTrack Integration //====================================================================================================== #include "RokokoDataParser.h" #include "RokokoData.h" #include #include #include #include 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(); actor.body.leftThumbDistal = std::make_shared(); actor.body.leftThumbTip = std::make_shared(); // 검지 actor.body.leftIndexMedial = std::make_shared(); actor.body.leftIndexDistal = std::make_shared(); actor.body.leftIndexTip = std::make_shared(); // 중지 actor.body.leftMiddleMedial = std::make_shared(); actor.body.leftMiddleDistal = std::make_shared(); actor.body.leftMiddleTip = std::make_shared(); // 약지 actor.body.leftRingMedial = std::make_shared(); actor.body.leftRingDistal = std::make_shared(); actor.body.leftRingTip = std::make_shared(); // 새끼 actor.body.leftLittleMedial = std::make_shared(); actor.body.leftLittleDistal = std::make_shared(); actor.body.leftLittleTip = std::make_shared(); // 오른손 데이터 초기화 (모든 손가락) // 엄지 actor.body.rightThumbMedial = std::make_shared(); actor.body.rightThumbDistal = std::make_shared(); actor.body.rightThumbTip = std::make_shared(); // 검지 actor.body.rightIndexMedial = std::make_shared(); actor.body.rightIndexDistal = std::make_shared(); actor.body.rightIndexTip = std::make_shared(); // 중지 actor.body.rightMiddleMedial = std::make_shared(); actor.body.rightMiddleDistal = std::make_shared(); actor.body.rightMiddleTip = std::make_shared(); // 약지 actor.body.rightRingMedial = std::make_shared(); actor.body.rightRingDistal = std::make_shared(); actor.body.rightRingTip = std::make_shared(); // 새끼 actor.body.rightLittleMedial = std::make_shared(); actor.body.rightLittleDistal = std::make_shared(); actor.body.rightLittleTip = std::make_shared(); // 기본 쿼터니언 값 설정 (정규화된 단위 쿼터니언) 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& leftHandFingers, std::vector& 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; } } }