117 lines
4.7 KiB
C++
117 lines
4.7 KiB
C++
//======================================================================================================
|
|
// Copyright 2025, Rokoko Glove OptiTrack Integration
|
|
//======================================================================================================
|
|
/**
|
|
* RokokoDataConverter class provides data conversion functionality from Rokoko format to OptiTrack format.
|
|
* This converter handles the mapping of 20 Rokoko finger joints to 15 OptiTrack finger joints.
|
|
*/
|
|
|
|
#pragma once
|
|
#include <vector>
|
|
#include <memory>
|
|
#include "GloveDataFormat.h"
|
|
|
|
// Forward declarations
|
|
namespace RokokoData
|
|
{
|
|
struct Vector3Frame;
|
|
struct Vector4Frame;
|
|
struct ActorJointFrame;
|
|
struct ActorData;
|
|
struct LiveFrame_v4;
|
|
}
|
|
|
|
namespace RokokoIntegration
|
|
{
|
|
class RokokoDataConverter
|
|
{
|
|
public:
|
|
/**
|
|
* Converts Rokoko LiveFrame_v4 data to OptiTrack glove data format
|
|
* @param rokokoFrame Input Rokoko frame data
|
|
* @return Converted OptiTrack glove data
|
|
*/
|
|
static sGloveDeviceData ConvertRokokoToOptiTrack(const RokokoData::LiveFrame_v4& rokokoFrame);
|
|
|
|
/**
|
|
* Converts Rokoko finger joint data to OptiTrack finger node format
|
|
* @param rokokoJoint Input Rokoko joint data
|
|
* @param optiTrackNode Output OptiTrack node data
|
|
* @return true if conversion successful
|
|
*/
|
|
static bool ConvertJoint(const RokokoData::ActorJointFrame& rokokoJoint, sFingerNode& optiTrackNode);
|
|
|
|
/**
|
|
* Validates converted OptiTrack data
|
|
* @param gloveData Data to validate
|
|
* @return true if data is valid
|
|
*/
|
|
static bool ValidateOptiTrackData(const sGloveDeviceData& gloveData);
|
|
|
|
/**
|
|
* Gets the mapping information for debugging
|
|
* @return String containing mapping details
|
|
*/
|
|
static std::string GetMappingInfo();
|
|
|
|
private:
|
|
/**
|
|
* Maps Rokoko finger joints to OptiTrack format
|
|
* Maps 20 Rokoko joints (4 per finger) to 15 OptiTrack joints (3 per finger)
|
|
* Removes proximal joints and keeps medial, distal, tip
|
|
*/
|
|
static void MapFingerJoints(const std::vector<RokokoData::ActorJointFrame>& rokokoFingers,
|
|
std::vector<sFingerNode>& optiTrackNodes);
|
|
|
|
/**
|
|
* Converts quaternion from Rokoko format to OptiTrack format
|
|
* @param rokokoQuat Input Rokoko quaternion
|
|
* @param optiTrackQuat Output OptiTrack quaternion
|
|
*/
|
|
static void ConvertQuaternion(const RokokoData::Vector4Frame& rokokoQuat,
|
|
float& quat_w, float& quat_x, float& quat_y, float& quat_z);
|
|
|
|
/**
|
|
* Normalizes quaternion values
|
|
* @param w, x, y, z Quaternion components (modified in place)
|
|
*/
|
|
static void NormalizeQuaternion(float& w, float& x, float& y, float& z);
|
|
|
|
/**
|
|
* Validates quaternion values
|
|
* @param w, x, y, z Quaternion components
|
|
* @return true if quaternion is valid
|
|
*/
|
|
static bool ValidateQuaternion(float w, float x, float y, float z);
|
|
|
|
/**
|
|
* Applies coordinate system conversion for left/right hands
|
|
* @param isLeftHand true if left hand, false if right hand
|
|
* @param x, y, z Position coordinates (modified in place)
|
|
*/
|
|
static void ApplyHandCoordinateSystem(bool isLeftHand, float& x, float& y, float& z);
|
|
|
|
// Finger mapping constants
|
|
static inline const int ROKOKO_JOINTS_PER_FINGER = 4; // Proximal, Medial, Distal, Tip
|
|
static inline const int OPTITRACK_JOINTS_PER_FINGER = 3; // MP, PIP, DIP
|
|
static inline const int TOTAL_FINGERS = 5; // Thumb, Index, Middle, Ring, Little
|
|
static inline const int TOTAL_ROKOKO_JOINTS = TOTAL_FINGERS * ROKOKO_JOINTS_PER_FINGER; // 20
|
|
static inline const int TOTAL_OPTITRACK_JOINTS = TOTAL_FINGERS * OPTITRACK_JOINTS_PER_FINGER; // 15
|
|
|
|
// Joint mapping table: Rokoko index -> OptiTrack index
|
|
// Removes proximal joints (index 0, 4, 8, 12, 16)
|
|
static inline const int JOINT_MAPPING[15] = {
|
|
// Thumb: Medial(1), Distal(2), Tip(3) -> MP(0), PIP(1), DIP(2)
|
|
1, 2, 3,
|
|
// Index: Medial(5), Distal(6), Tip(7) -> MP(3), PIP(4), DIP(5)
|
|
5, 6, 7,
|
|
// Middle: Medial(9), Distal(10), Tip(11) -> MP(6), PIP(7), DIP(8)
|
|
9, 10, 11,
|
|
// Ring: Medial(13), Distal(14), Tip(15) -> MP(9), PIP(10), DIP(11)
|
|
13, 14, 15,
|
|
// Little: Medial(17), Distal(18), Tip(19) -> MP(12), PIP(13), DIP(14)
|
|
17, 18, 19
|
|
};
|
|
};
|
|
}
|