226 lines
8.2 KiB
C++
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;
|
|
}
|
|
}
|
|
}
|