Add : 로코코 옵티 관련 기능 추가 패치
This commit is contained in:
parent
45bf6f8649
commit
1087a30949
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Avatar/VrmAvatar.asset
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Avatar/VrmAvatar.asset
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Meshes/newton.baked.asset
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.Meshes/newton.baked.asset
(Stored with Git LFS)
vendored
Binary file not shown.
@ -269,7 +269,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger2Metacarpal
|
||||
- boneName: LeftFinger2Proximal
|
||||
humanName: Left Index Proximal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -277,7 +277,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger2Proximal
|
||||
- boneName: LeftFinger2Medial
|
||||
humanName: Left Index Intermediate
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -285,7 +285,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger2Medial
|
||||
- boneName: LeftFinger2Distal
|
||||
humanName: Left Index Distal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -293,7 +293,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger3Metacarpal
|
||||
- boneName: LeftFinger3Proximal
|
||||
humanName: Left Middle Proximal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -301,7 +301,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger3Proximal
|
||||
- boneName: LeftFinger3Medial
|
||||
humanName: Left Middle Intermediate
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -309,7 +309,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger3Medial
|
||||
- boneName: LeftFinger3Distal
|
||||
humanName: Left Middle Distal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -317,7 +317,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger4Metacarpal
|
||||
- boneName: LeftFinger4Proximal
|
||||
humanName: Left Ring Proximal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -325,7 +325,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger4Proximal
|
||||
- boneName: LeftFinger4Medial
|
||||
humanName: Left Ring Intermediate
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -333,7 +333,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger4Medial
|
||||
- boneName: LeftFinger4Distal
|
||||
humanName: Left Ring Distal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -341,7 +341,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger5Metacarpal
|
||||
- boneName: LeftFinger5Proximal
|
||||
humanName: Left Little Proximal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -349,7 +349,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger5Proximal
|
||||
- boneName: LeftFinger5Medial
|
||||
humanName: Left Little Intermediate
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -357,7 +357,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: LeftFinger5Medial
|
||||
- boneName: LeftFinger5Distal
|
||||
humanName: Left Little Distal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -389,7 +389,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger2Metacarpal
|
||||
- boneName: RightFinger2Proximal
|
||||
humanName: Right Index Proximal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -397,7 +397,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger2Proximal
|
||||
- boneName: RightFinger2Medial
|
||||
humanName: Right Index Intermediate
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -405,7 +405,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger2Medial
|
||||
- boneName: RightFinger2Distal
|
||||
humanName: Right Index Distal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -413,7 +413,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger3Metacarpal
|
||||
- boneName: RightFinger3Proximal
|
||||
humanName: Right Middle Proximal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -421,7 +421,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger3Proximal
|
||||
- boneName: RightFinger3Medial
|
||||
humanName: Right Middle Intermediate
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -429,7 +429,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger3Medial
|
||||
- boneName: RightFinger3Distal
|
||||
humanName: Right Middle Distal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -437,7 +437,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger4Metacarpal
|
||||
- boneName: RightFinger4Proximal
|
||||
humanName: Right Ring Proximal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -445,7 +445,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger4Proximal
|
||||
- boneName: RightFinger4Medial
|
||||
humanName: Right Ring Intermediate
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -453,7 +453,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger4Medial
|
||||
- boneName: RightFinger4Distal
|
||||
humanName: Right Ring Distal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -461,7 +461,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger5Metacarpal
|
||||
- boneName: RightFinger5Proximal
|
||||
humanName: Right Little Proximal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -469,7 +469,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger5Proximal
|
||||
- boneName: RightFinger5Medial
|
||||
humanName: Right Little Intermediate
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -477,7 +477,7 @@ ModelImporter:
|
||||
value: {x: 0, y: 0, z: 0}
|
||||
length: 0
|
||||
modified: 0
|
||||
- boneName: RightFinger5Medial
|
||||
- boneName: RightFinger5Distal
|
||||
humanName: Right Little Distal
|
||||
limit:
|
||||
min: {x: 0, y: 0, z: 0}
|
||||
@ -582,7 +582,7 @@ ModelImporter:
|
||||
- name: LeftFinger1Metacarpal
|
||||
parentName: LeftHand
|
||||
position: {x: -0.027847009, y: 0.020784134, z: -0.001056083}
|
||||
rotation: {x: 0.09904506, y: -0.36964288, z: 0.23911677, w: 0.89239985}
|
||||
rotation: {x: 0.04233702, y: -0.5728508, z: 0.3376046, w: 0.74570274}
|
||||
scale: {x: 1.0000001, y: 0.99999994, z: 1.0000001}
|
||||
- name: LeftFinger1Proximal
|
||||
parentName: LeftFinger1Metacarpal
|
||||
@ -707,7 +707,7 @@ ModelImporter:
|
||||
- name: RightFinger1Metacarpal
|
||||
parentName: RightHand
|
||||
position: {x: 0.027845163, y: 0.020768387, z: -0.0010154283}
|
||||
rotation: {x: 0.09904415, y: 0.36964288, z: -0.23911713, w: 0.89239985}
|
||||
rotation: {x: 0.04219337, y: 0.5729466, z: -0.33736277, w: 0.7457468}
|
||||
scale: {x: 1, y: 0.99999994, z: 0.9999998}
|
||||
- name: RightFinger1Proximal
|
||||
parentName: RightFinger1Metacarpal
|
||||
|
||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.prefab
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.prefab
(Stored with Git LFS)
vendored
Binary file not shown.
@ -68,14 +68,14 @@ copy "$(OutDir)ExampleGloveData.csv" "C:/Program Files/OptiTrack/Motive/device
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;ANALOGSYSTEM_IMPORTS;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<GenerateXMLDocumentationFiles>false</GenerateXMLDocumentationFiles>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ShowProgress>NotSet</ShowProgress>
|
||||
<AdditionalDependencies>PeripheralImport.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<ProjectReference>
|
||||
<LinkLibraryDependencies>false</LinkLibraryDependencies>
|
||||
@ -88,7 +88,7 @@ copy "$(OutDir)ExampleGloveData.csv" "C:/Program Files/OptiTrack/Motive/device
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;ANALOGSYSTEM_IMPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -96,7 +96,7 @@ copy "$(OutDir)ExampleGloveData.csv" "C:/Program Files/OptiTrack/Motive/device
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>PeripheralImport.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -134,9 +134,13 @@ namespace OptiTrackPluginDevices
|
||||
* Example data map for storing aggregated device data.
|
||||
*/
|
||||
uint16_t mDeviceCount = 0;
|
||||
std::vector<uint64_t> mDetectedDevices;
|
||||
std::unordered_map<uint64_t, sGloveDeviceData> mLatestGloveData;
|
||||
std::unordered_map<uint64_t, sGloveDeviceBaseInfo> mLatestDeviceInfo;
|
||||
std::vector<uint64_t> mDetectedDevices;
|
||||
std::unordered_map<uint64_t, sGloveDeviceData> mLatestGloveData;
|
||||
std::unordered_map<uint64_t, sGloveDeviceBaseInfo> mLatestDeviceInfo;
|
||||
|
||||
// T-포즈 캘리브레이션 데이터 (로컬 로테이션 계산을 위해 필요)
|
||||
std::unordered_map<uint64_t, std::vector<sFingerNode>> mTPoseReferences; // 장치별 T-포즈 기준값
|
||||
std::unordered_map<uint64_t, bool> mTPoseCalibrated; // 장치별 캘리브레이션 상태
|
||||
|
||||
/**
|
||||
* Rokoko integration members
|
||||
@ -173,14 +177,9 @@ namespace OptiTrackPluginDevices
|
||||
*/
|
||||
void UpdateDeviceInfo(uint64_t deviceId);
|
||||
|
||||
/**
|
||||
* Detect and create Rokoko devices dynamically
|
||||
*/
|
||||
// Dynamic Device Detection and Management
|
||||
void DetectAndCreateRokokoDevices();
|
||||
|
||||
/**
|
||||
* Process data for multiple devices (left/right hand)
|
||||
*/
|
||||
void DetectActorsFromRokokoData(const RokokoData::LiveFrame_v4& rokokoFrame);
|
||||
void ProcessMultipleDeviceData(const RokokoData::LiveFrame_v4& rokokoFrame);
|
||||
|
||||
/**
|
||||
@ -202,6 +201,128 @@ namespace OptiTrackPluginDevices
|
||||
* Map individual joint data
|
||||
*/
|
||||
void MapJoint(const RokokoData::ActorJointFrame& rokokoJoint, sFingerNode& optiTrackNode);
|
||||
|
||||
// 로컬 로테이션 변환 함수들
|
||||
void ConvertToLocalRotations(std::vector<sFingerNode>& nodes, eGloveHandSide handSide);
|
||||
void ApplyLocalRotation(sFingerNode& childNode, const sFingerNode& parentNode);
|
||||
|
||||
// 쿼터니언 연산 헬퍼 함수들
|
||||
void MultiplyQuaternions(const sFingerNode& q1, const sFingerNode& q2, sFingerNode& result);
|
||||
void InverseQuaternion(const sFingerNode& q, sFingerNode& result);
|
||||
void NormalizeQuaternion(sFingerNode& q);
|
||||
|
||||
// T-포즈 캘리브레이션 시스템
|
||||
void CalibrateTPose(uint64_t deviceId, const std::vector<sFingerNode>& tPoseData);
|
||||
void ApplyTPoseOffset(std::vector<sFingerNode>& nodes, uint64_t deviceId);
|
||||
bool IsTPoseCalibrated(uint64_t deviceId) const;
|
||||
void ResetTPoseCalibration(uint64_t deviceId);
|
||||
|
||||
// 손목 기준 로컬 변환 시스템 (기존)
|
||||
void ConvertToWristLocalRotations(std::vector<sFingerNode>& nodes, const RokokoData::Body& body, eGloveHandSide handSide);
|
||||
bool GetWristRotation(const RokokoData::Body& body, eGloveHandSide handSide, sFingerNode& wristRotation);
|
||||
|
||||
// 진짜 로컬 로테이션 변환 시스템 (계층적)
|
||||
void ConvertToTrueLocalRotations(std::vector<sFingerNode>& nodes, const RokokoData::Body& body, eGloveHandSide handSide);
|
||||
void CalculateFingerLocalRotations(const std::vector<RokokoData::ActorJointFrame*>& fingerJoints, std::vector<sFingerNode>& outputNodes, int startIndex, const RokokoData::Body& body, eGloveHandSide handSide);
|
||||
bool GetFingerJointRotations(const RokokoData::Body& body, eGloveHandSide handSide, std::vector<std::vector<RokokoData::ActorJointFrame*>>& allFingers);
|
||||
|
||||
// 좌표계 변환 및 디버깅
|
||||
void ConvertRokokoToOptiTrackCoordinates(sFingerNode& node, eGloveHandSide handSide);
|
||||
void LogRotationData(const std::string& label, const sFingerNode& rotation);
|
||||
void DebugCoordinateSystem(const RokokoData::Body& body, eGloveHandSide handSide);
|
||||
|
||||
// 절대 로컬 로테이션 시스템 (손목에 완전히 독립적)
|
||||
void ConvertToAbsoluteLocalRotations(std::vector<sFingerNode>& nodes, const RokokoData::Body& body, eGloveHandSide handSide);
|
||||
void CalculateAbsoluteLocalForFinger(const std::vector<RokokoData::ActorJointFrame*>& fingerJoints, std::vector<sFingerNode>& outputNodes, int startIndex, eGloveHandSide handSide);
|
||||
sFingerNode CalculateRelativeRotation(const sFingerNode& parent, const sFingerNode& child);
|
||||
|
||||
// Unity 방식 Rokoko 데이터 처리 (원시 데이터 + T-포즈 오프셋)
|
||||
void ConvertToUnityRokokoMethod(std::vector<sFingerNode>& nodes, const RokokoData::Body& body, eGloveHandSide handSide);
|
||||
sFingerNode GetUnityTPoseOffset(int fingerIndex, int jointIndex, eGloveHandSide handSide);
|
||||
void ApplyUnityRokokoRotation(sFingerNode& node, const RokokoData::ActorJointFrame* jointFrame, int fingerIndex, int jointIndex, eGloveHandSide handSide);
|
||||
|
||||
// 가상 Unity 아바타 시뮬레이션 시스템
|
||||
void ConvertToVirtualUnityAvatar(std::vector<sFingerNode>& nodes, const RokokoData::Body& body, eGloveHandSide handSide);
|
||||
|
||||
// Unity Transform 시뮬레이션 구조
|
||||
struct VirtualTransform {
|
||||
sFingerNode localRotation; // Unity localRotation
|
||||
sFingerNode worldRotation; // Unity rotation (world)
|
||||
VirtualTransform* parent; // Unity parent transform
|
||||
std::vector<VirtualTransform*> children; // Unity children
|
||||
std::string name; // 디버깅용
|
||||
};
|
||||
|
||||
struct VirtualUnityAvatar {
|
||||
// 전체 스켈레톤 구조 (Unity Humanoid와 동일한 계층)
|
||||
VirtualTransform root;
|
||||
|
||||
// 몸통 구조
|
||||
VirtualTransform* hips; // 허리 (Root)
|
||||
VirtualTransform* spine; // 스파인
|
||||
VirtualTransform* chest; // 가슴
|
||||
|
||||
// 어깨 구조
|
||||
VirtualTransform* leftShoulder; // 왼쪽 어깨
|
||||
VirtualTransform* rightShoulder; // 오른쪽 어깨
|
||||
|
||||
// 팔 구조
|
||||
VirtualTransform* leftUpperArm; // 왼쪽 상완
|
||||
VirtualTransform* leftLowerArm; // 왼쪽 하완
|
||||
VirtualTransform* leftHand; // 왼쪽 손
|
||||
|
||||
VirtualTransform* rightUpperArm; // 오른쪽 상완
|
||||
VirtualTransform* rightLowerArm; // 오른쪽 하완
|
||||
VirtualTransform* rightHand; // 오른쪽 손
|
||||
|
||||
// 손가락 구조 (Unity 계층과 동일)
|
||||
VirtualTransform* leftThumb[3]; // Proximal, Intermediate, Distal
|
||||
VirtualTransform* leftIndex[3];
|
||||
VirtualTransform* leftMiddle[3];
|
||||
VirtualTransform* leftRing[3];
|
||||
VirtualTransform* leftLittle[3];
|
||||
|
||||
VirtualTransform* rightThumb[3];
|
||||
VirtualTransform* rightIndex[3];
|
||||
VirtualTransform* rightMiddle[3];
|
||||
VirtualTransform* rightRing[3];
|
||||
VirtualTransform* rightLittle[3];
|
||||
};
|
||||
|
||||
// 가상 Unity 아바타 헬퍼 함수들
|
||||
void InitializeVirtualUnityAvatar(VirtualUnityAvatar& avatar);
|
||||
void ApplyRokokoDataToVirtualAvatar(VirtualUnityAvatar& avatar, const RokokoData::Body& body);
|
||||
void CalculateLocalRotationsFromWorldRotations(VirtualUnityAvatar& avatar);
|
||||
void ExtractLocalRotationsFromVirtualAvatar(const VirtualUnityAvatar& avatar, std::vector<sFingerNode>& nodes, eGloveHandSide handSide);
|
||||
void UpdateWorldRotationFromParent(VirtualTransform* transform);
|
||||
|
||||
// 가상 손 노드 구조
|
||||
struct VirtualJoint {
|
||||
sFingerNode worldRotation;
|
||||
sFingerNode localRotation;
|
||||
VirtualJoint* parent;
|
||||
};
|
||||
|
||||
struct VirtualFinger {
|
||||
VirtualJoint mp; // Metacarpophalangeal
|
||||
VirtualJoint pip; // Proximal Interphalangeal
|
||||
VirtualJoint dip; // Distal Interphalangeal
|
||||
};
|
||||
|
||||
struct VirtualHand {
|
||||
sFingerNode wristRotation;
|
||||
VirtualFinger thumb;
|
||||
VirtualFinger index;
|
||||
VirtualFinger middle;
|
||||
VirtualFinger ring;
|
||||
VirtualFinger little;
|
||||
};
|
||||
|
||||
// 가상 손 구조 헬퍼 함수들
|
||||
void BuildVirtualHandFromRokoko(VirtualHand& virtualHand, const RokokoData::Body& body, eGloveHandSide handSide);
|
||||
void CalculateHierarchicalLocalRotations(VirtualHand& virtualHand);
|
||||
void ExtractLocalRotationsToNodes(const VirtualHand& virtualHand, std::vector<sFingerNode>& nodes);
|
||||
sFingerNode CalculateLocalRotationFromParent(const VirtualJoint& parent, const VirtualJoint& child);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@ -74,6 +74,7 @@ struct sGloveDeviceBaseInfo
|
||||
int battery = 0 ;
|
||||
int signalStrength= 0;
|
||||
eGloveHandSide handSide = eGloveHandSide::Unknown;
|
||||
std::string actorName = ""; // Actor 이름 (다중 장비 구분용)
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -3,9 +3,48 @@
|
||||
//======================================================================================================
|
||||
|
||||
#include "LZ4Wrapper.h"
|
||||
#include "lz4.h"
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <windows.h>
|
||||
|
||||
// Unity LZ4 DLL 동적 로딩
|
||||
static HMODULE lz4Module = nullptr;
|
||||
static decltype(&Unity_LZ4_uncompressSize) pUnity_LZ4_uncompressSize = nullptr;
|
||||
static decltype(&Unity_LZ4_decompress) pUnity_LZ4_decompress = nullptr;
|
||||
|
||||
static bool LoadUnityLZ4()
|
||||
{
|
||||
if (lz4Module == nullptr) {
|
||||
// 다양한 경로에서 Unity LZ4 DLL 로드 시도
|
||||
const wchar_t* dllPaths[] = {
|
||||
L"lz4.dll", // 현재 디렉토리
|
||||
L".\\lz4.dll", // 명시적 현재 디렉토리
|
||||
L"x64\\Debug\\lz4.dll", // 디버그 폴더
|
||||
L"C:\\Users\\user\\Documents\\Streamingle_URP\\Assets\\External\\Rokoko\\Scripts\\Plugins\\LZ4\\x86_64\\lz4.dll" // Unity 절대 경로
|
||||
};
|
||||
|
||||
for (const auto& path : dllPaths) {
|
||||
lz4Module = LoadLibrary(path);
|
||||
if (lz4Module != nullptr) {
|
||||
// DLL 로드 성공 - 함수 포인터 획득
|
||||
pUnity_LZ4_uncompressSize = (decltype(pUnity_LZ4_uncompressSize))GetProcAddress(lz4Module, "Unity_LZ4_uncompressSize");
|
||||
pUnity_LZ4_decompress = (decltype(pUnity_LZ4_decompress))GetProcAddress(lz4Module, "Unity_LZ4_decompress");
|
||||
|
||||
if (pUnity_LZ4_uncompressSize != nullptr && pUnity_LZ4_decompress != nullptr) {
|
||||
// 성공
|
||||
break;
|
||||
} else {
|
||||
// 함수를 찾지 못함 - DLL 언로드하고 다음 시도
|
||||
FreeLibrary(lz4Module);
|
||||
lz4Module = nullptr;
|
||||
pUnity_LZ4_uncompressSize = nullptr;
|
||||
pUnity_LZ4_decompress = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (lz4Module != nullptr && pUnity_LZ4_uncompressSize != nullptr && pUnity_LZ4_decompress != nullptr);
|
||||
}
|
||||
|
||||
namespace RokokoIntegration
|
||||
{
|
||||
@ -17,33 +56,38 @@ namespace RokokoIntegration
|
||||
return {};
|
||||
}
|
||||
|
||||
// LZ4 데이터 유효성 검사
|
||||
if (!IsValidLZ4Data(compressedData, compressedSize)) {
|
||||
// Unity LZ4 DLL 로드
|
||||
if (!LoadUnityLZ4()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// 압축 해제된 크기 추정
|
||||
int decompressedSize = GetDecompressedSize(compressedData, compressedSize);
|
||||
if (decompressedSize <= 0) {
|
||||
// Unity 방식 정확히 구현
|
||||
// 1. Unity_LZ4_uncompressSize로 압축 해제된 크기 구하기
|
||||
int uncompressedSize = pUnity_LZ4_uncompressSize(
|
||||
reinterpret_cast<const char*>(compressedData),
|
||||
compressedSize
|
||||
);
|
||||
|
||||
if (uncompressedSize <= 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// 크기 유효성 검사
|
||||
if (!ValidateDecompressedSize(compressedSize, decompressedSize)) {
|
||||
if (uncompressedSize > MAX_DECOMPRESSED_SIZE) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// 압축 해제 실행
|
||||
std::vector<uint8_t> decompressed(decompressedSize);
|
||||
int actualSize = LZ4_decompress_safe(
|
||||
// 2. Unity_LZ4_decompress로 압축 해제
|
||||
std::vector<uint8_t> decompressed(uncompressedSize);
|
||||
int result = pUnity_LZ4_decompress(
|
||||
reinterpret_cast<const char*>(compressedData),
|
||||
reinterpret_cast<char*>(decompressed.data()),
|
||||
compressedSize,
|
||||
decompressedSize
|
||||
reinterpret_cast<char*>(decompressed.data()),
|
||||
uncompressedSize
|
||||
);
|
||||
|
||||
// 압축 해제 결과 검증
|
||||
if (actualSize != decompressedSize) {
|
||||
// Unity에서는 result != 0이면 실패
|
||||
if (result != 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -61,20 +105,37 @@ namespace RokokoIntegration
|
||||
return false;
|
||||
}
|
||||
|
||||
// LZ4 매직 넘버 확인 (간단한 검증)
|
||||
// 실제로는 더 정교한 검증이 필요할 수 있음
|
||||
// Rokoko Studio의 LZ4 데이터는 일반적으로 JSON이 아니므로
|
||||
// 첫 번째 바이트가 '{'가 아닌 경우 LZ4로 간주
|
||||
if (size > 0 && data[0] == '{') {
|
||||
return false; // JSON 데이터는 LZ4가 아님
|
||||
}
|
||||
|
||||
// 기본적인 LZ4 매직 넘버 확인
|
||||
// LZ4 프레임 헤더의 일부 패턴 확인
|
||||
if (size >= 4) {
|
||||
// LZ4 프레임 헤더의 매직 넘버 (0x184D2204)
|
||||
if (data[0] == 0x04 && data[1] == 0x22 && data[2] == 0x4D && data[3] == 0x18) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 매직 넘버가 없어도 압축된 데이터로 간주 (Rokoko Studio 특성상)
|
||||
return true;
|
||||
}
|
||||
|
||||
int LZ4Wrapper::GetDecompressedSize(const uint8_t* compressedData, int compressedSize)
|
||||
{
|
||||
try {
|
||||
// LZ4에서 압축 해제된 크기 추정
|
||||
int decompressedSize = LZ4_decompress_safe(
|
||||
// Unity LZ4 DLL 로드
|
||||
if (!LoadUnityLZ4()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Unity 방식으로 압축 해제된 크기 구하기
|
||||
int decompressedSize = pUnity_LZ4_uncompressSize(
|
||||
reinterpret_cast<const char*>(compressedData),
|
||||
nullptr,
|
||||
compressedSize,
|
||||
0
|
||||
compressedSize
|
||||
);
|
||||
return decompressedSize;
|
||||
|
||||
|
||||
@ -10,6 +10,12 @@
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
// Unity LZ4 함수들 선언
|
||||
extern "C" {
|
||||
int Unity_LZ4_uncompressSize(const char* srcBuffer, int srcSize);
|
||||
int Unity_LZ4_decompress(const char* src, int srcSize, char* dst, int dstCapacity);
|
||||
}
|
||||
|
||||
namespace RokokoIntegration
|
||||
{
|
||||
class LZ4Wrapper
|
||||
|
||||
@ -37,9 +37,39 @@ namespace RokokoData
|
||||
Vector4Frame rotation;
|
||||
};
|
||||
|
||||
// Body structure containing finger joints
|
||||
// Body structure containing full skeleton (Unity BodyFrame와 동일)
|
||||
struct Body
|
||||
{
|
||||
// 전신 스켈레톤 데이터 (Unity BodyFrame과 동일)
|
||||
std::shared_ptr<ActorJointFrame> hip;
|
||||
std::shared_ptr<ActorJointFrame> spine;
|
||||
std::shared_ptr<ActorJointFrame> chest;
|
||||
std::shared_ptr<ActorJointFrame> neck;
|
||||
std::shared_ptr<ActorJointFrame> head;
|
||||
|
||||
std::shared_ptr<ActorJointFrame> leftShoulder;
|
||||
std::shared_ptr<ActorJointFrame> leftUpperArm;
|
||||
std::shared_ptr<ActorJointFrame> leftLowerArm;
|
||||
std::shared_ptr<ActorJointFrame> leftHand;
|
||||
|
||||
std::shared_ptr<ActorJointFrame> rightShoulder;
|
||||
std::shared_ptr<ActorJointFrame> rightUpperArm;
|
||||
std::shared_ptr<ActorJointFrame> rightLowerArm;
|
||||
std::shared_ptr<ActorJointFrame> rightHand;
|
||||
|
||||
// 다리 데이터 (필요시)
|
||||
std::shared_ptr<ActorJointFrame> leftUpLeg;
|
||||
std::shared_ptr<ActorJointFrame> leftLeg;
|
||||
std::shared_ptr<ActorJointFrame> leftFoot;
|
||||
std::shared_ptr<ActorJointFrame> leftToe;
|
||||
std::shared_ptr<ActorJointFrame> leftToeEnd;
|
||||
|
||||
std::shared_ptr<ActorJointFrame> rightUpLeg;
|
||||
std::shared_ptr<ActorJointFrame> rightLeg;
|
||||
std::shared_ptr<ActorJointFrame> rightFoot;
|
||||
std::shared_ptr<ActorJointFrame> rightToe;
|
||||
std::shared_ptr<ActorJointFrame> rightToeEnd;
|
||||
|
||||
// Left hand finger joints
|
||||
std::shared_ptr<ActorJointFrame> leftThumbProximal;
|
||||
std::shared_ptr<ActorJointFrame> leftThumbMedial;
|
||||
|
||||
@ -14,101 +14,173 @@ namespace RokokoIntegration
|
||||
bool RokokoDataParser::ParseLiveFrame(const std::string& jsonString, RokokoData::LiveFrame_v4& frame)
|
||||
{
|
||||
try {
|
||||
// 간단한 JSON 파싱 구현 (실제로는 nlohmann/json 라이브러리 사용 권장)
|
||||
// 현재는 기본 구조만 생성
|
||||
// nlohmann/json을 사용하여 JSON 파싱
|
||||
nlohmann::json j = nlohmann::json::parse(jsonString);
|
||||
|
||||
// 기본 프레임 데이터 초기화
|
||||
frame.scene.actors.clear();
|
||||
frame.scene.actors.push_back(RokokoData::ActorData());
|
||||
// Unity JsonLiveSerializerV3.cs와 동일한 구조로 파싱
|
||||
|
||||
// 기본 손가락 데이터 구조 생성
|
||||
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;
|
||||
// Scene 데이터 파싱
|
||||
if (j.contains("scene")) {
|
||||
auto& scene = j["scene"];
|
||||
|
||||
// 타임스탬프
|
||||
if (scene.contains("timestamp")) {
|
||||
frame.timestamp = scene["timestamp"];
|
||||
}
|
||||
|
||||
// Actors 파싱
|
||||
if (scene.contains("actors") && scene["actors"].is_array()) {
|
||||
auto& actors = scene["actors"];
|
||||
for (const auto& actorJson : actors) {
|
||||
RokokoData::ActorData actor;
|
||||
|
||||
// Actor 기본 정보
|
||||
if (actorJson.contains("name")) {
|
||||
actor.name = actorJson["name"];
|
||||
}
|
||||
|
||||
// Body 데이터 파싱
|
||||
if (actorJson.contains("body")) {
|
||||
ParseBodyFrame(actorJson["body"], actor.body);
|
||||
}
|
||||
|
||||
frame.scene.actors.push_back(actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} catch (...) {
|
||||
} catch (const nlohmann::json::exception& e) {
|
||||
// JSON 파싱 에러 처리
|
||||
std::cerr << "JSON parsing error: " << e.what() << std::endl;
|
||||
return false;
|
||||
} catch (...) {
|
||||
// 기타 예외 처리
|
||||
std::cerr << "Unknown error during JSON parsing" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RokokoDataParser::ParseBodyFrame(const nlohmann::json& bodyJson, RokokoData::Body& body)
|
||||
{
|
||||
// Unity JsonLiveSerializerV3.cs의 BodyFrame 구조와 동일하게 파싱
|
||||
|
||||
// === 전신 스켈레톤 데이터 파싱 (Unity BodyFrame과 동일) ===
|
||||
|
||||
// 몸통 파싱
|
||||
ParseFingerJoint(bodyJson, "hip", body.hip);
|
||||
ParseFingerJoint(bodyJson, "spine", body.spine);
|
||||
ParseFingerJoint(bodyJson, "chest", body.chest);
|
||||
ParseFingerJoint(bodyJson, "neck", body.neck);
|
||||
ParseFingerJoint(bodyJson, "head", body.head);
|
||||
|
||||
// 왼쪽 팔 파싱
|
||||
ParseFingerJoint(bodyJson, "leftShoulder", body.leftShoulder);
|
||||
ParseFingerJoint(bodyJson, "leftUpperArm", body.leftUpperArm);
|
||||
ParseFingerJoint(bodyJson, "leftLowerArm", body.leftLowerArm);
|
||||
ParseFingerJoint(bodyJson, "leftHand", body.leftHand);
|
||||
|
||||
// 오른쪽 팔 파싱
|
||||
ParseFingerJoint(bodyJson, "rightShoulder", body.rightShoulder);
|
||||
ParseFingerJoint(bodyJson, "rightUpperArm", body.rightUpperArm);
|
||||
ParseFingerJoint(bodyJson, "rightLowerArm", body.rightLowerArm);
|
||||
ParseFingerJoint(bodyJson, "rightHand", body.rightHand);
|
||||
|
||||
// 다리 파싱 (필요시)
|
||||
ParseFingerJoint(bodyJson, "leftUpLeg", body.leftUpLeg);
|
||||
ParseFingerJoint(bodyJson, "leftLeg", body.leftLeg);
|
||||
ParseFingerJoint(bodyJson, "leftFoot", body.leftFoot);
|
||||
ParseFingerJoint(bodyJson, "leftToe", body.leftToe);
|
||||
ParseFingerJoint(bodyJson, "leftToeEnd", body.leftToeEnd);
|
||||
|
||||
ParseFingerJoint(bodyJson, "rightUpLeg", body.rightUpLeg);
|
||||
ParseFingerJoint(bodyJson, "rightLeg", body.rightLeg);
|
||||
ParseFingerJoint(bodyJson, "rightFoot", body.rightFoot);
|
||||
ParseFingerJoint(bodyJson, "rightToe", body.rightToe);
|
||||
ParseFingerJoint(bodyJson, "rightToeEnd", body.rightToeEnd);
|
||||
|
||||
// === 손가락 데이터 파싱 ===
|
||||
|
||||
// 왼손 손가락 데이터 파싱
|
||||
ParseFingerJoint(bodyJson, "leftThumbProximal", body.leftThumbProximal);
|
||||
ParseFingerJoint(bodyJson, "leftThumbMedial", body.leftThumbMedial);
|
||||
ParseFingerJoint(bodyJson, "leftThumbDistal", body.leftThumbDistal);
|
||||
ParseFingerJoint(bodyJson, "leftThumbTip", body.leftThumbTip);
|
||||
|
||||
ParseFingerJoint(bodyJson, "leftIndexProximal", body.leftIndexProximal);
|
||||
ParseFingerJoint(bodyJson, "leftIndexMedial", body.leftIndexMedial);
|
||||
ParseFingerJoint(bodyJson, "leftIndexDistal", body.leftIndexDistal);
|
||||
ParseFingerJoint(bodyJson, "leftIndexTip", body.leftIndexTip);
|
||||
|
||||
ParseFingerJoint(bodyJson, "leftMiddleProximal", body.leftMiddleProximal);
|
||||
ParseFingerJoint(bodyJson, "leftMiddleMedial", body.leftMiddleMedial);
|
||||
ParseFingerJoint(bodyJson, "leftMiddleDistal", body.leftMiddleDistal);
|
||||
ParseFingerJoint(bodyJson, "leftMiddleTip", body.leftMiddleTip);
|
||||
|
||||
ParseFingerJoint(bodyJson, "leftRingProximal", body.leftRingProximal);
|
||||
ParseFingerJoint(bodyJson, "leftRingMedial", body.leftRingMedial);
|
||||
ParseFingerJoint(bodyJson, "leftRingDistal", body.leftRingDistal);
|
||||
ParseFingerJoint(bodyJson, "leftRingTip", body.leftRingTip);
|
||||
|
||||
ParseFingerJoint(bodyJson, "leftLittleProximal", body.leftLittleProximal);
|
||||
ParseFingerJoint(bodyJson, "leftLittleMedial", body.leftLittleMedial);
|
||||
ParseFingerJoint(bodyJson, "leftLittleDistal", body.leftLittleDistal);
|
||||
ParseFingerJoint(bodyJson, "leftLittleTip", body.leftLittleTip);
|
||||
|
||||
// 오른손 손가락 데이터 파싱
|
||||
ParseFingerJoint(bodyJson, "rightThumbProximal", body.rightThumbProximal);
|
||||
ParseFingerJoint(bodyJson, "rightThumbMedial", body.rightThumbMedial);
|
||||
ParseFingerJoint(bodyJson, "rightThumbDistal", body.rightThumbDistal);
|
||||
ParseFingerJoint(bodyJson, "rightThumbTip", body.rightThumbTip);
|
||||
|
||||
ParseFingerJoint(bodyJson, "rightIndexProximal", body.rightIndexProximal);
|
||||
ParseFingerJoint(bodyJson, "rightIndexMedial", body.rightIndexMedial);
|
||||
ParseFingerJoint(bodyJson, "rightIndexDistal", body.rightIndexDistal);
|
||||
ParseFingerJoint(bodyJson, "rightIndexTip", body.rightIndexTip);
|
||||
|
||||
ParseFingerJoint(bodyJson, "rightMiddleProximal", body.rightMiddleProximal);
|
||||
ParseFingerJoint(bodyJson, "rightMiddleMedial", body.rightMiddleMedial);
|
||||
ParseFingerJoint(bodyJson, "rightMiddleDistal", body.rightMiddleDistal);
|
||||
ParseFingerJoint(bodyJson, "rightMiddleTip", body.rightMiddleTip);
|
||||
|
||||
ParseFingerJoint(bodyJson, "rightRingProximal", body.rightRingProximal);
|
||||
ParseFingerJoint(bodyJson, "rightRingMedial", body.rightRingMedial);
|
||||
ParseFingerJoint(bodyJson, "rightRingDistal", body.rightRingDistal);
|
||||
ParseFingerJoint(bodyJson, "rightRingTip", body.rightRingTip);
|
||||
|
||||
ParseFingerJoint(bodyJson, "rightLittleProximal", body.rightLittleProximal);
|
||||
ParseFingerJoint(bodyJson, "rightLittleMedial", body.rightLittleMedial);
|
||||
ParseFingerJoint(bodyJson, "rightLittleDistal", body.rightLittleDistal);
|
||||
ParseFingerJoint(bodyJson, "rightLittleTip", body.rightLittleTip);
|
||||
}
|
||||
|
||||
void RokokoDataParser::ParseFingerJoint(const nlohmann::json& bodyJson, const std::string& jointName, std::shared_ptr<RokokoData::ActorJointFrame>& joint)
|
||||
{
|
||||
if (bodyJson.contains(jointName)) {
|
||||
auto& jointJson = bodyJson[jointName];
|
||||
|
||||
joint = std::make_shared<RokokoData::ActorJointFrame>();
|
||||
|
||||
// Position 파싱
|
||||
if (jointJson.contains("position")) {
|
||||
auto& pos = jointJson["position"];
|
||||
joint->position.x = pos.value("x", 0.0f);
|
||||
joint->position.y = pos.value("y", 0.0f);
|
||||
joint->position.z = pos.value("z", 0.0f);
|
||||
}
|
||||
|
||||
// Rotation 파싱
|
||||
if (jointJson.contains("rotation")) {
|
||||
auto& rot = jointJson["rotation"];
|
||||
joint->rotation.x = rot.value("x", 0.0f);
|
||||
joint->rotation.y = rot.value("y", 0.0f);
|
||||
joint->rotation.z = rot.value("z", 0.0f);
|
||||
joint->rotation.w = rot.value("w", 1.0f);
|
||||
|
||||
// 쿼터니언 정규화
|
||||
NormalizeQuaternion(joint->rotation.x, joint->rotation.y, joint->rotation.z, joint->rotation.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,7 +194,7 @@ namespace RokokoIntegration
|
||||
|
||||
const auto& actor = frame.scene.actors[0];
|
||||
|
||||
// 손가락 데이터 검증
|
||||
// 손가락 데이터 검증 (왼손 엄지손가락만 체크)
|
||||
if (!actor.body.leftThumbMedial || !actor.body.leftThumbDistal || !actor.body.leftThumbTip) {
|
||||
return false;
|
||||
}
|
||||
@ -148,19 +220,57 @@ namespace RokokoIntegration
|
||||
|
||||
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);
|
||||
}
|
||||
// 왼손 데이터 추출 (20개 관절)
|
||||
if (actor.body.leftThumbProximal) leftHandFingers.push_back(*actor.body.leftThumbProximal);
|
||||
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* 데이터 사용
|
||||
if (actor.body.leftIndexProximal) leftHandFingers.push_back(*actor.body.leftIndexProximal);
|
||||
if (actor.body.leftIndexMedial) leftHandFingers.push_back(*actor.body.leftIndexMedial);
|
||||
if (actor.body.leftIndexDistal) leftHandFingers.push_back(*actor.body.leftIndexDistal);
|
||||
if (actor.body.leftIndexTip) leftHandFingers.push_back(*actor.body.leftIndexTip);
|
||||
|
||||
if (actor.body.leftMiddleProximal) leftHandFingers.push_back(*actor.body.leftMiddleProximal);
|
||||
if (actor.body.leftMiddleMedial) leftHandFingers.push_back(*actor.body.leftMiddleMedial);
|
||||
if (actor.body.leftMiddleDistal) leftHandFingers.push_back(*actor.body.leftMiddleDistal);
|
||||
if (actor.body.leftMiddleTip) leftHandFingers.push_back(*actor.body.leftMiddleTip);
|
||||
|
||||
if (actor.body.leftRingProximal) leftHandFingers.push_back(*actor.body.leftRingProximal);
|
||||
if (actor.body.leftRingMedial) leftHandFingers.push_back(*actor.body.leftRingMedial);
|
||||
if (actor.body.leftRingDistal) leftHandFingers.push_back(*actor.body.leftRingDistal);
|
||||
if (actor.body.leftRingTip) leftHandFingers.push_back(*actor.body.leftRingTip);
|
||||
|
||||
if (actor.body.leftLittleProximal) leftHandFingers.push_back(*actor.body.leftLittleProximal);
|
||||
if (actor.body.leftLittleMedial) leftHandFingers.push_back(*actor.body.leftLittleMedial);
|
||||
if (actor.body.leftLittleDistal) leftHandFingers.push_back(*actor.body.leftLittleDistal);
|
||||
if (actor.body.leftLittleTip) leftHandFingers.push_back(*actor.body.leftLittleTip);
|
||||
|
||||
// 오른손 데이터 추출 (20개 관절)
|
||||
if (actor.body.rightThumbProximal) rightHandFingers.push_back(*actor.body.rightThumbProximal);
|
||||
if (actor.body.rightThumbMedial) rightHandFingers.push_back(*actor.body.rightThumbMedial);
|
||||
if (actor.body.rightThumbDistal) rightHandFingers.push_back(*actor.body.rightThumbDistal);
|
||||
if (actor.body.rightThumbTip) rightHandFingers.push_back(*actor.body.rightThumbTip);
|
||||
|
||||
if (actor.body.rightIndexProximal) rightHandFingers.push_back(*actor.body.rightIndexProximal);
|
||||
if (actor.body.rightIndexMedial) rightHandFingers.push_back(*actor.body.rightIndexMedial);
|
||||
if (actor.body.rightIndexDistal) rightHandFingers.push_back(*actor.body.rightIndexDistal);
|
||||
if (actor.body.rightIndexTip) rightHandFingers.push_back(*actor.body.rightIndexTip);
|
||||
|
||||
if (actor.body.rightMiddleProximal) rightHandFingers.push_back(*actor.body.rightMiddleProximal);
|
||||
if (actor.body.rightMiddleMedial) rightHandFingers.push_back(*actor.body.rightMiddleMedial);
|
||||
if (actor.body.rightMiddleDistal) rightHandFingers.push_back(*actor.body.rightMiddleDistal);
|
||||
if (actor.body.rightMiddleTip) rightHandFingers.push_back(*actor.body.rightMiddleTip);
|
||||
|
||||
if (actor.body.rightRingProximal) rightHandFingers.push_back(*actor.body.rightRingProximal);
|
||||
if (actor.body.rightRingMedial) rightHandFingers.push_back(*actor.body.rightRingMedial);
|
||||
if (actor.body.rightRingDistal) rightHandFingers.push_back(*actor.body.rightRingDistal);
|
||||
if (actor.body.rightRingTip) rightHandFingers.push_back(*actor.body.rightRingTip);
|
||||
|
||||
if (actor.body.rightLittleProximal) rightHandFingers.push_back(*actor.body.rightLittleProximal);
|
||||
if (actor.body.rightLittleMedial) rightHandFingers.push_back(*actor.body.rightLittleMedial);
|
||||
if (actor.body.rightLittleDistal) rightHandFingers.push_back(*actor.body.rightLittleDistal);
|
||||
if (actor.body.rightLittleTip) rightHandFingers.push_back(*actor.body.rightLittleTip);
|
||||
|
||||
return true;
|
||||
|
||||
@ -197,7 +307,7 @@ namespace RokokoIntegration
|
||||
|
||||
// 쿼터니언 길이 체크 (정규화된 경우 1.0에 가까워야 함)
|
||||
float length = std::sqrt(x * x + y * y + z * z + w * w);
|
||||
if (std::abs(length - 1.0f) > 0.1f) {
|
||||
if (length < 0.1f || length > 10.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -207,15 +317,13 @@ namespace RokokoIntegration
|
||||
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;
|
||||
if (length > 0.0001f) {
|
||||
x /= length;
|
||||
y /= length;
|
||||
z /= length;
|
||||
w /= length;
|
||||
} else {
|
||||
// 유효하지 않은 쿼터니언인 경우 기본값 설정
|
||||
// 기본값 설정
|
||||
x = 0.0f;
|
||||
y = 0.0f;
|
||||
z = 0.0f;
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// Forward declarations for JSON data structures
|
||||
namespace RokokoData
|
||||
@ -19,6 +20,7 @@ namespace RokokoData
|
||||
struct ActorJointFrame;
|
||||
struct ActorData;
|
||||
struct LiveFrame_v4;
|
||||
struct Body;
|
||||
}
|
||||
|
||||
namespace RokokoIntegration
|
||||
@ -53,6 +55,22 @@ namespace RokokoIntegration
|
||||
std::vector<RokokoData::ActorJointFrame>& rightHandFingers);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Parses body frame data from JSON
|
||||
* @param bodyJson JSON object containing body data
|
||||
* @param body Output body data structure
|
||||
*/
|
||||
static void ParseBodyFrame(const nlohmann::json& bodyJson, RokokoData::Body& body);
|
||||
|
||||
/**
|
||||
* Parses individual finger joint data from JSON
|
||||
* @param bodyJson JSON object containing body data
|
||||
* @param jointName Name of the joint to parse
|
||||
* @param joint Output joint data structure
|
||||
*/
|
||||
static void ParseFingerJoint(const nlohmann::json& bodyJson, const std::string& jointName,
|
||||
std::shared_ptr<RokokoData::ActorJointFrame>& joint);
|
||||
|
||||
/**
|
||||
* Parses actor data from JSON
|
||||
* @param actorJson JSON object containing actor data
|
||||
|
||||
@ -72,14 +72,15 @@ if exist "$(OutDir)ExampleGloveData.csv" copy "$(OutDir)ExampleGloveData.csv" "C
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;ANALOGSYSTEM_IMPORTS;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<GenerateXMLDocumentationFiles>false</GenerateXMLDocumentationFiles>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;..\external;..\external\nlohmann;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ShowProgress>NotSet</ShowProgress>
|
||||
<AdditionalDependencies>PeripheralImport.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<ProjectReference>
|
||||
<LinkLibraryDependencies>false</LinkLibraryDependencies>
|
||||
@ -93,7 +94,8 @@ if exist "$(OutDir)ExampleGloveData.csv" copy "$(OutDir)ExampleGloveData.csv" "C
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;ANALOGSYSTEM_IMPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;..\external;..\external\nlohmann;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -101,7 +103,7 @@ if exist "$(OutDir)ExampleGloveData.csv" copy "$(OutDir)ExampleGloveData.csv" "C
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>PeripheralImport.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
@ -111,7 +113,7 @@ if exist "$(OutDir)ExampleGloveData.csv" copy "$(OutDir)ExampleGloveData.csv" "C
|
||||
<ClInclude Include="GloveDeviceBase.h" />
|
||||
<ClInclude Include="GloveDataFormat.h" />
|
||||
<ClInclude Include="LZ4Wrapper.h" />
|
||||
<ClInclude Include="lz4.h" />
|
||||
|
||||
<ClInclude Include="RokokoData.h" />
|
||||
<ClInclude Include="RokokoDataParser.h" />
|
||||
<ClInclude Include="RokokoUDPReceiver.h" />
|
||||
@ -130,7 +132,7 @@ if exist "$(OutDir)ExampleGloveData.csv" copy "$(OutDir)ExampleGloveData.csv" "C
|
||||
<ClCompile Include="ExampleGloveDevice.cpp" />
|
||||
<ClCompile Include="GloveDeviceBase.cpp" />
|
||||
<ClCompile Include="LZ4Wrapper.cpp" />
|
||||
<ClCompile Include="lz4.c" />
|
||||
|
||||
<ClCompile Include="RokokoUDPReceiver.cpp" />
|
||||
<ClCompile Include="RokokoDataParser.cpp" />
|
||||
<ClCompile Include="RokokoDataConverter.cpp" />
|
||||
|
||||
@ -195,8 +195,7 @@ namespace RokokoIntegration
|
||||
}
|
||||
}
|
||||
|
||||
// CPU 사용률 조절
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
// 🚀 실시간성 최우선 - sleep 제거 (CPU 사용률보다 반응성 우선)
|
||||
|
||||
} catch (...) {
|
||||
SetError("Exception in receive thread");
|
||||
|
||||
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveAdapterSingleton.obj
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveAdapterSingleton.obj
(Stored with Git LFS)
Binary file not shown.
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveDevice.obj
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/ExampleGloveDevice.obj
(Stored with Git LFS)
Binary file not shown.
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/GloveDeviceBase.obj
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/GloveDeviceBase.obj
(Stored with Git LFS)
Binary file not shown.
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/LZ4Wrapper.obj
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/LZ4Wrapper.obj
(Stored with Git LFS)
Binary file not shown.
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataConverter.obj
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataConverter.obj
(Stored with Git LFS)
Binary file not shown.
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataParser.obj
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoDataParser.obj
(Stored with Git LFS)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,2 +1,2 @@
|
||||
^C:\USERS\QSCFT\ONEDRIVE\문서\OPTITRACK\MOTIVE\PERIPHERALAPI\EXAMPLE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV
|
||||
C:\Users\qscft\OneDrive\문서\OptiTrack\Motive\PeripheralAPI\example\x64\Debug\ExampleGloveData.csv
|
||||
^C:\USERS\USER\DOCUMENTS\STREAMINGLE_URP\OPTITRACK ROKOKO GLOVE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV
|
||||
C:\Users\user\Documents\Streamingle_URP\Optitrack Rokoko Glove\x64\Debug\ExampleGloveData.csv
|
||||
|
||||
@ -1 +1 @@
|
||||
^C:\USERS\QSCFT\ONEDRIVE\문서\OPTITRACK\MOTIVE\PERIPHERALAPI\EXAMPLE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV
|
||||
^C:\USERS\USER\DOCUMENTS\STREAMINGLE_URP\OPTITRACK ROKOKO GLOVE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
^C:\USERS\QSCFT\ONEDRIVE\문서\OPTITRACK\MOTIVE\PERIPHERALAPI\EXAMPLE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV
|
||||
C:\USERS\QSCFT\ONEDRIVE\문서\OPTITRACK\MOTIVE\PERIPHERALAPI\EXAMPLE\X64\DEBUG\EXAMPLEGLOVEDATA.CSV
|
||||
^C:\USERS\USER\DOCUMENTS\STREAMINGLE_URP\OPTITRACK ROKOKO GLOVE\ROKOKOGLOVEDEVICE\EXAMPLEGLOVEDATA.CSV
|
||||
C:\USERS\USER\DOCUMENTS\STREAMINGLE_URP\OPTITRACK ROKOKO GLOVE\X64\DEBUG\EXAMPLEGLOVEDATA.CSV
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
PlatformToolSet=v142:VCToolArchitecture=Native64Bit:VCToolsVersion=14.29.30133:TargetPlatformVersion=8.1:VcpkgTriplet=x64-windows:
|
||||
Debug|x64|C:\Users\qscft\OneDrive\문서\OptiTrack\Motive\PeripheralAPI\example\|
|
||||
PlatformToolSet=v142:VCToolArchitecture=Native64Bit:VCToolsVersion=14.29.30133:TargetPlatformVersion=8.1:
|
||||
Debug|x64|C:\Users\user\Documents\Streamingle_URP\Optitrack Rokoko Glove\|
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,7 +2,7 @@
|
||||
<Project>
|
||||
<ProjectOutputs>
|
||||
<ProjectOutput>
|
||||
<FullPath>C:\Users\qscft\OneDrive\문서\OptiTrack\Motive\PeripheralAPI\example\x64\Debug\RokokoGloveDevice.dll</FullPath>
|
||||
<FullPath>C:\Users\user\Documents\Streamingle_URP\Optitrack Rokoko Glove\x64\Debug\RokokoGloveDevice.dll</FullPath>
|
||||
</ProjectOutput>
|
||||
</ProjectOutputs>
|
||||
<ContentFiles />
|
||||
|
||||
Binary file not shown.
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoUDPReceiver.obj
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/RokokoUDPReceiver.obj
(Stored with Git LFS)
Binary file not shown.
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/dllmain.obj
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/dllmain.obj
(Stored with Git LFS)
Binary file not shown.
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/lz4.obj
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/RokokoGloveDevice/x64/Debug/lz4.obj
(Stored with Git LFS)
Binary file not shown.
Binary file not shown.
@ -67,14 +67,14 @@ copy "$(OutDir)SimpleDeviceExample.dll" "C:/Program Files/OptiTrack/Motive/dev
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;ANALOGSYSTEM_IMPORTS;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<GenerateXMLDocumentationFiles>false</GenerateXMLDocumentationFiles>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ShowProgress>NotSet</ShowProgress>
|
||||
<AdditionalDependencies>PeripheralImport.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
@ -84,7 +84,7 @@ copy "$(OutDir)SimpleDeviceExample.dll" "C:/Program Files/OptiTrack/Motive/dev
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ANALOGSYSTEM_IMPORTS;OPTITRACKPERIPHERALEXAMPLE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -92,7 +92,7 @@ copy "$(OutDir)SimpleDeviceExample.dll" "C:/Program Files/OptiTrack/Motive/dev
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>PeripheralImport.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
PlatformToolSet=v142:VCToolArchitecture=Native64Bit:VCToolsVersion=14.29.30133:TargetPlatformVersion=8.1:VcpkgTriplet=x64-windows:
|
||||
Debug|x64|C:\Users\qscft\OneDrive\문서\OptiTrack\Motive\PeripheralAPI\example\|
|
||||
PlatformToolSet=v142:VCToolArchitecture=Native64Bit:VCToolsVersion=14.29.30133:TargetPlatformVersion=8.1:
|
||||
Debug|x64|C:\Users\user\Documents\Streamingle_URP\Optitrack Rokoko Glove\|
|
||||
|
||||
BIN
Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/dllmain.obj
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/SimpleDeviceExample/x64/Debug/dllmain.obj
(Stored with Git LFS)
Binary file not shown.
Binary file not shown.
24765
Optitrack Rokoko Glove/external/nlohmann/json.hpp
vendored
Normal file
24765
Optitrack Rokoko Glove/external/nlohmann/json.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
93
Optitrack Rokoko Glove/include/AnalogChannelDescriptor.h
Normal file
93
Optitrack Rokoko Glove/include/AnalogChannelDescriptor.h
Normal file
@ -0,0 +1,93 @@
|
||||
//======================================================================================================
|
||||
// Copyright 2016, NaturalPoint Inc.
|
||||
//======================================================================================================
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "AnalogSystemBuildConfig.h"
|
||||
#include "PropertySet.h"
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable: 4251 )
|
||||
|
||||
namespace tinyxml2wc
|
||||
{
|
||||
class XMLElement;
|
||||
}
|
||||
|
||||
namespace AnalogSystem
|
||||
{
|
||||
class AnalogChannelDescriptor;
|
||||
class IDeviceManager;
|
||||
|
||||
// Channel properties
|
||||
static const char* ChannelProp_Enabled = "AnalogChannel_Enabled";
|
||||
static const char* ChannelProp_EnabledLabel = "Enabled";
|
||||
static const char* ChannelProp_Name = "AnalogChannel_Name";
|
||||
static const char* ChannelProp_NameLabel = "Channel Name";
|
||||
static const char* ChannelProp_TerminalName = "AnalogChannel_TerminalName";
|
||||
static const char* ChannelProp_TerminalNameLabel = "Terminal Name";
|
||||
static const char* ChannelProp_DataType = "AnalogChannel_DataType";
|
||||
static const char* ChannelProp_MinVoltage = "AnalogChannel_MinVoltage";
|
||||
static const char* ChannelProp_MinVoltageLabel = "Min. Voltage";
|
||||
static const char* ChannelProp_MaxVoltage = "AnalogChannel_MaxVoltage";
|
||||
static const char* ChannelProp_MaxVoltageLabel = "Max. Voltage";
|
||||
static const char* ChannelProp_TerminalType = "AnalogChannel_TerminalType";
|
||||
static const char* ChannelProp_TerminalTypeLabel = "Terminal Type";
|
||||
static const char* ChannelProp_Units = "AnalogChannel_Units";
|
||||
static const char* ChannelProp_Selected = "AnalogChannel_Selected";
|
||||
static const char* ChannelProp_OwnerSerial = "AnalogChannel_OwnerSerial";
|
||||
|
||||
/// <summary>
|
||||
/// Channel physical signal type (Analog capture devices)
|
||||
/// </summary>
|
||||
enum TerminalConfigurationType
|
||||
{
|
||||
Terminal_RSE = 0, // Referenced single ended. Measurement with respect to ground (e.g. AI_GND) (Default)
|
||||
Terminal_NRSE, // NonReferenced single ended. Measurement with respect to single analog input (e.g. AISENSE)
|
||||
Terminal_Diff, // Differential. Measurement between two inputs (e.g. AI0+, AI0-)
|
||||
Terminal_PseudoDiff // Differential. Measurement between two inputs and impeded common ground.
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Channel data type
|
||||
/// </summary>
|
||||
enum ChannelDataType
|
||||
{
|
||||
ChannelType_Int = 0,
|
||||
ChannelType_Float,
|
||||
ChannelType_Double,
|
||||
ChannelType_Unknown
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// AnalogChannelDescriptor describes a device's physical channel for exposing in the UI,
|
||||
/// including channel name (user-definable), channel signal type, measurement range.
|
||||
/// </summary>
|
||||
class ANALOGSYSTEM_API AnalogChannelDescriptor : public cPropertySet
|
||||
{
|
||||
public:
|
||||
AnalogChannelDescriptor();
|
||||
~AnalogChannelDescriptor();
|
||||
|
||||
// IProfileSubscriber Interface
|
||||
virtual std::wstring ProfileTypeName() const;
|
||||
virtual std::wstring ProfileLabel() const;
|
||||
virtual std::wstring ProfileDescription() const;
|
||||
virtual void SaveToProfile( tinyxml2wc::XMLElement& saveTo ) const;
|
||||
virtual bool LoadFromProfile( const tinyxml2wc::XMLElement& source );
|
||||
|
||||
private:
|
||||
// Create the channel property definitions
|
||||
void CreatePropertyDefinitions();
|
||||
|
||||
std::wstring mProfileName;
|
||||
static Core::cUID sPropertyDefinitionsID;
|
||||
|
||||
AnalogChannelDescriptor( const AnalogChannelDescriptor& other ) = delete;
|
||||
AnalogChannelDescriptor& operator=( const AnalogChannelDescriptor& other ) = delete;
|
||||
};
|
||||
}
|
||||
|
||||
#pragma warning( pop )
|
||||
144
Optitrack Rokoko Glove/include/AnalogFrame.h
Normal file
144
Optitrack Rokoko Glove/include/AnalogFrame.h
Normal file
@ -0,0 +1,144 @@
|
||||
//======================================================================================================
|
||||
// Copyright 2016, NaturalPoint Inc.
|
||||
//======================================================================================================
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "AnalogSystemBuildConfig.h"
|
||||
|
||||
namespace AnalogSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// AnalogFrameBase is the abstract base implementation for a device's 'frame' of data.
|
||||
/// A device 'frame' is a single sample of data from an analog device, one sample per
|
||||
/// active channel, of the same data type, along with any header information for that sampling.
|
||||
///
|
||||
/// Analog frames contain a templated value for each physical signal (channel) the device reports.
|
||||
/// A force plate device typically contains 6 channels (Fx,Fy,Fz,Mx,My,Mz), so the analog frame
|
||||
/// would contain 6 float values, 1 for each active channel. A NIDAQ device has a user-configurable
|
||||
/// active number of analog and digital channels, so the number of channels and frame types may
|
||||
/// be variable.
|
||||
/// </summary>
|
||||
class ANALOGSYSTEM_API AnalogFrameBase
|
||||
{
|
||||
public:
|
||||
AnalogFrameBase( int channelCount = 1 );
|
||||
AnalogFrameBase( const AnalogFrameBase& src );
|
||||
AnalogFrameBase& operator=( const AnalogFrameBase& src );
|
||||
|
||||
virtual ~AnalogFrameBase() = default;
|
||||
|
||||
/// <summary>template specific copy with alloc (implemented by derived class)</summary>
|
||||
virtual std::unique_ptr<AnalogFrameBase> Copy() const = 0;
|
||||
|
||||
/// <summary>Return the number of channels in the frame</summary>
|
||||
virtual const int ChannelCount() const;
|
||||
|
||||
/// <summary>Returns a pointer to the channel data array</summary>
|
||||
void* ChannelData() const;
|
||||
|
||||
/// <summary>Returns a pointer to the channel data array</summary>
|
||||
void* ChannelData( int channel ) { return ( (char*) mChannelData + ( channel * mChannelSize ) ); }
|
||||
const void* ChannelData( int channel ) const { return ( (char*) mChannelData + ( channel * mChannelSize ) ); }
|
||||
|
||||
/// <summary>Gets the memory size of the channel type(in bytes)</summary>
|
||||
int ChannelSize() const { return mChannelSize; }
|
||||
|
||||
/// <summary>Sets the frame ID</summary>
|
||||
/// <param name="id">frame ID</param>
|
||||
virtual void SetID( long id );
|
||||
|
||||
/// <summary>Gets the frame ID</summary>
|
||||
virtual const long ID() const;
|
||||
|
||||
/// <summary>Sets the ID of the device that generated this frame</summary>
|
||||
/// <param name="id">device identifier</param>
|
||||
virtual void SetDeviceID( int id );
|
||||
|
||||
/// <summary>Gets the ID of the device that generated this frame</summary>
|
||||
virtual const int DeviceID() const;
|
||||
|
||||
/// <summary>Sets the timestamp of the frame</summary>
|
||||
/// <param name="id">device identifier</param>
|
||||
virtual void SetTimestamp( double timestamp );
|
||||
|
||||
/// <summary>Gets the timestamp of the frame</summary>
|
||||
virtual const double Timestamp() const;
|
||||
|
||||
/// <summary>Sets flags for this frame (frame specific bit information (e.g. trigger bit set on this frame).</summary>
|
||||
/// <param name="flag">flag word</param>
|
||||
virtual void SetFlag( int flag );
|
||||
|
||||
/// <summary>Gets device-specific flag bits for this frame</summary>
|
||||
virtual const int Flag() const;
|
||||
|
||||
protected:
|
||||
/// <summary>The number of channels</summary>
|
||||
int mChannelCount;
|
||||
|
||||
/// <summary>Channel size (bytes)</summary>
|
||||
int mChannelSize;
|
||||
|
||||
/// <summary>Flat array of channel data </summary>
|
||||
void* mChannelData;
|
||||
|
||||
private:
|
||||
long mID; // frame ID, usually a counter from the device source
|
||||
int mDeviceID; // ID for the device associated with this data
|
||||
double mTimestamp; // NTP compatible timestamp (64 bit fixed point)
|
||||
int mFlag; // user defined data
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// AnalogFrame is a type-specific implementation of a device frame.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
class AnalogFrame : public AnalogFrameBase
|
||||
{
|
||||
public:
|
||||
/// <summary>Initializes a new instance of the <see cref="AnalogFrame"/> class/// </summary>
|
||||
/// <param name="channelCount">Number of typed data channels to allocate.</param>
|
||||
AnalogFrame( int channelCount = 1 ) : AnalogFrameBase( channelCount )
|
||||
{
|
||||
mChannelData = new T[channelCount];
|
||||
mChannelSize = sizeof( T );
|
||||
::memset( mChannelData, 0, channelCount * sizeof( T ) );
|
||||
}
|
||||
|
||||
AnalogFrame( const AnalogFrame& src ) : AnalogFrameBase( src )
|
||||
{
|
||||
mChannelData = new T[mChannelCount];
|
||||
mChannelSize = sizeof( T );
|
||||
::memcpy( this->mChannelData, src.mChannelData, (size_t) ( mChannelCount * sizeof( T ) ) );
|
||||
}
|
||||
|
||||
AnalogFrame& operator=( const AnalogFrame& src )
|
||||
{
|
||||
if( this != &src )
|
||||
{
|
||||
__super::operator=( src );
|
||||
if( mChannelData )
|
||||
delete[] mChannelData;
|
||||
mChannelData = new T[mChannelCount];
|
||||
mChannelSize = sizeof( T );
|
||||
::memcpy( this->mChannelData, src.mChannelData, mChannelCount * sizeof( T ) );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>Finalizes an instance of the <see cref="AnalogFrame"/> class</summary>
|
||||
virtual ~AnalogFrame() { delete[] mChannelData; }
|
||||
|
||||
/// <summary>Allocates a new typed frame from an existing frame in the thread's memory context</summary>
|
||||
std::unique_ptr<AnalogFrameBase> Copy() const override { return std::make_unique<AnalogFrame<T>>( *this ); }
|
||||
|
||||
/// <summary>Returns a typed pointer to the channel data array</summary>
|
||||
const T* ChannelData() const { return reinterpret_cast<T*>( mChannelData ); }
|
||||
T* ChannelData() { return reinterpret_cast<T*>( mChannelData ); }
|
||||
|
||||
/// <summary>Returns a typed pointer to the channel value</summary>
|
||||
T* ChannelData( int channel ) { return &( reinterpret_cast<T*>( mChannelData )[channel] ); }
|
||||
};
|
||||
}
|
||||
|
||||
12
Optitrack Rokoko Glove/include/AnalogSystemBuildConfig.h
Normal file
12
Optitrack Rokoko Glove/include/AnalogSystemBuildConfig.h
Normal file
@ -0,0 +1,12 @@
|
||||
//======================================================================================================
|
||||
// Copyright 2017, NaturalPoint Inc.
|
||||
//======================================================================================================
|
||||
#pragma once
|
||||
|
||||
#ifdef ANALOGSYSTEM_EXPORTS
|
||||
#define ANALOGSYSTEM_API __declspec(dllexport)
|
||||
#elif defined ANALOGSYSTEM_IMPORTS
|
||||
#define ANALOGSYSTEM_API __declspec(dllimport)
|
||||
#else
|
||||
#define ANALOGSYSTEM_API
|
||||
#endif
|
||||
81
Optitrack Rokoko Glove/include/IDevice.h
Normal file
81
Optitrack Rokoko Glove/include/IDevice.h
Normal file
@ -0,0 +1,81 @@
|
||||
//======================================================================================================
|
||||
// Copyright 2016, NaturalPoint Inc.
|
||||
//======================================================================================================
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "AnalogSystemBuildConfig.h"
|
||||
|
||||
namespace tinyxml2wc
|
||||
{
|
||||
class XMLElement;
|
||||
}
|
||||
|
||||
namespace AnalogSystem
|
||||
{
|
||||
class AnalogChannelDescriptor;
|
||||
class AnalogFrameBase;
|
||||
class IDeviceManager;
|
||||
class IPropVal;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for a Motive Device. Refer to PluginDeviceBase for details.
|
||||
/// </summary>
|
||||
class ANALOGSYSTEM_API IDevice
|
||||
{
|
||||
public:
|
||||
IDevice() = default;
|
||||
virtual ~IDevice() = default;
|
||||
|
||||
// operations
|
||||
virtual bool Configure() = 0;
|
||||
virtual bool Deconfigure() = 0;
|
||||
virtual void Zero() = 0;
|
||||
virtual bool PrepareForSync() = 0;
|
||||
virtual bool PreCapture() = 0;
|
||||
virtual bool StartCapture() = 0;
|
||||
virtual bool StopCapture() = 0;
|
||||
virtual bool PostCapture() = 0;
|
||||
virtual bool IsCapturing() const = 0;
|
||||
|
||||
// channels
|
||||
virtual int ChannelDescriptorCount() const = 0;
|
||||
virtual AnalogChannelDescriptor* ChannelDescriptor( int index ) = 0;
|
||||
virtual AnalogChannelDescriptor* ChannelDescriptor( const char* channelName ) = 0;
|
||||
virtual int ActiveChannelCount() const = 0;
|
||||
virtual int ChannelID( int index ) const = 0;
|
||||
virtual AnalogChannelDescriptor* ActiveChannelDescriptor( int index ) = 0;
|
||||
|
||||
// data
|
||||
virtual AnalogFrameBase* BeginFrameUpdate( long DeviceFrameID, bool wait = true ) = 0;
|
||||
virtual void EndFrameUpdate() = 0;
|
||||
virtual void UpdateDriftCorrection( long mocapFrameID ) = 0;
|
||||
virtual const AnalogFrameBase* GetFrameByDeviceFrameID( long frameID ) const = 0;
|
||||
virtual const AnalogFrameBase* GetFrameByBufferIndex( int index ) const = 0;
|
||||
virtual int GetMostRecentFrameIndex() const = 0;
|
||||
virtual long GetMostRecentFrameID() const = 0;
|
||||
virtual bool MocapFrameIDToDeviceFrameIDs( long requestedMocapFrameID, long& deviceStart, long& deviceStop ) const = 0;
|
||||
|
||||
// events
|
||||
virtual void OnPropertyChanged( const char* ) = 0;
|
||||
virtual void OnChannelPropertyChanged( const char* channelName, const char* propertyName ) = 0;
|
||||
virtual bool ValidatePropertyChange( const char* propertyName, const IPropVal& val ) = 0;
|
||||
|
||||
// IProfileSubscriber Interface
|
||||
virtual std::wstring ProfileTypeName() const = 0;
|
||||
virtual std::wstring ProfileLabel() const = 0;
|
||||
virtual std::wstring ProfileDescription() const = 0;
|
||||
virtual void SaveToProfile( tinyxml2wc::XMLElement& saveTo ) const = 0;
|
||||
virtual bool LoadFromProfile( const tinyxml2wc::XMLElement& source ) = 0;
|
||||
|
||||
// helpers
|
||||
virtual void SetDeviceManager( IDeviceManager* pDevManager ) = 0;
|
||||
virtual IDeviceManager* DeviceManager() = 0;
|
||||
virtual const char* LastError() const = 0;
|
||||
virtual int MessageFromHost( const char* ) const = 0;
|
||||
|
||||
IDevice( const IDevice& other ) = delete;
|
||||
IDevice& operator=( const IDevice& other ) = delete;
|
||||
};
|
||||
}
|
||||
58
Optitrack Rokoko Glove/include/IDeviceFactory.h
Normal file
58
Optitrack Rokoko Glove/include/IDeviceFactory.h
Normal file
@ -0,0 +1,58 @@
|
||||
//======================================================================================================
|
||||
// Copyright 2016, NaturalPoint Inc.
|
||||
//======================================================================================================
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "AnalogSystemBuildConfig.h"
|
||||
|
||||
namespace AnalogSystem
|
||||
{
|
||||
class IDevice;
|
||||
|
||||
/// <summary>
|
||||
/// IDeviceFactory creates a specific instance of a device.
|
||||
/// </summary>
|
||||
class ANALOGSYSTEM_API IDeviceFactory
|
||||
{
|
||||
public:
|
||||
virtual ~IDeviceFactory() = default;
|
||||
|
||||
///<summary>Returns factory name</summary>
|
||||
virtual const char* Name() const = 0;
|
||||
|
||||
///<summary>Returns device instance name</summary>
|
||||
virtual const char* DeviceName() const = 0;
|
||||
|
||||
///<summary>Creates a new instance of the device.</summary>
|
||||
virtual std::unique_ptr<IDevice> Create() const = 0;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Base implementation for a Plugin Device factory.
|
||||
/// See Plugin Device SDK for example implementation
|
||||
/// </summary>
|
||||
/// <seealso cref="IDeviceFactory" />
|
||||
class ANALOGSYSTEM_API PluginDeviceFactory : public IDeviceFactory
|
||||
{
|
||||
public:
|
||||
PluginDeviceFactory( const char* deviceName )
|
||||
{
|
||||
strcpy_s( mDeviceName, deviceName );
|
||||
}
|
||||
|
||||
PluginDeviceFactory( const PluginDeviceFactory& ) = delete;
|
||||
PluginDeviceFactory& operator=( const PluginDeviceFactory& ) = delete;
|
||||
|
||||
virtual ~PluginDeviceFactory() = default;
|
||||
|
||||
const char* DeviceName() const override
|
||||
{
|
||||
return mDeviceName;
|
||||
}
|
||||
|
||||
private:
|
||||
char mDeviceName[255];
|
||||
};
|
||||
}
|
||||
92
Optitrack Rokoko Glove/include/IDeviceManager.h
Normal file
92
Optitrack Rokoko Glove/include/IDeviceManager.h
Normal file
@ -0,0 +1,92 @@
|
||||
//======================================================================================================
|
||||
// Copyright 2016, NaturalPoint Inc.
|
||||
//======================================================================================================
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "AnalogSystemBuildConfig.h"
|
||||
|
||||
namespace AnalogSystem
|
||||
{
|
||||
class IDeviceFactory;
|
||||
class IDevice;
|
||||
|
||||
/// <summary>Error message type </summary>
|
||||
enum MessageType
|
||||
{
|
||||
MessageType_StatusInfo = 0, // To be displayed as info item in StatusLog Panel
|
||||
MessageType_StatusError, // To be displayed as error item in StatusLog Panel
|
||||
MessageType_StatusErrorAggregate, // To be displayed as error item in StatusLog Panel (aggregate)
|
||||
MessageType_DialogError, // To be displayed as error MessageBox (critical stop)
|
||||
MessageType_Internal, // Do not display
|
||||
MessageType_RequestRestart, // Device requests restart
|
||||
MessageType_PrepareForSync, // Prepare device for live sync startup
|
||||
MessageType_RequestResync, // request resync
|
||||
MessageType_UpdateFromProfile, // apply profile settings to device
|
||||
MessageType_Hotplug_Add, // add device after startup (hotplugged)
|
||||
MessageType_Hotplug_Remove // remove device after startup (hotplugged)
|
||||
};
|
||||
|
||||
/// <summary>App run mode state </summary>
|
||||
enum AppRunMode
|
||||
{
|
||||
RunMode_Undefined = -1,
|
||||
RunMode_Live = 0,
|
||||
RunMode_Recording = 1,
|
||||
RunMode_Playback = 2
|
||||
};
|
||||
|
||||
/// <summary>Plugin to Motive communication interface</summary>
|
||||
class ANALOGSYSTEM_API IDeviceManager
|
||||
{
|
||||
public:
|
||||
IDeviceManager() = default;
|
||||
virtual ~IDeviceManager() = default;
|
||||
|
||||
/// <summary>Registers the device factory with Motive. 1 Factory per device instance.</summary>
|
||||
/// <param name="df">The plugin device factory</param>
|
||||
virtual void RegisterDeviceFactory( std::unique_ptr<IDeviceFactory> df ) = 0;
|
||||
|
||||
/// <summary>Dynamically add device (hotplug) from Motive's list of devices.</summary>
|
||||
/// <param name="df">The device factorye</param>
|
||||
virtual bool AddDevice( std::unique_ptr<IDeviceFactory> df ) = 0;
|
||||
|
||||
/// <summary>Dynamically remove a device (hotplug) from Motive's list of devices.</summary>
|
||||
/// <param name="deviceName">The plugin device</param>
|
||||
virtual bool RemoveDevice( const char* deviceName ) = 0;
|
||||
|
||||
/// <summary>Notifies Motive when device configuration requires an application configuration update.</summary>
|
||||
/// <param name="pDevice">The plugin device</param>
|
||||
virtual bool UpdateDeviceConfiguration( IDevice* pDevice ) = 0;
|
||||
|
||||
/// <summary>Notifies Motive with a message.</summary>
|
||||
virtual void MessageToHost( const char* message, int messageType = 0 ) = 0;
|
||||
|
||||
/// <summary>Notifies Motive with a message.</summary>
|
||||
/// <param name="pDevice">The plugin device</param>
|
||||
virtual void MessageToHost( IDevice* pDevice, const char* message, int messageType = 0 ) = 0;
|
||||
|
||||
/// <summary>Gets the number of slaves associated with a master device.</summary>
|
||||
/// <param name="pMasterDevice">The master device.</param>
|
||||
virtual int SlaveDeviceCount( IDevice* pMasterDevice ) = 0;
|
||||
|
||||
/// <summary>Get a slave deive by index</summary>
|
||||
/// <param name="pMasterDevice">The master device.</param>
|
||||
/// <param name="slaveIndex">Slave index.</param>
|
||||
virtual IDevice* SlaveDevice( IDevice* pMasterDevice, int slaveIndex ) = 0;
|
||||
|
||||
/// <summary>Get a device by serial number</summary>
|
||||
/// <param name="serial">Deviceserial number</param>
|
||||
virtual IDevice* GetDevice( const char* serial ) = 0;
|
||||
|
||||
/// <summary>Gets current app playback state</summary>
|
||||
virtual AppRunMode HostRunMode() = 0;
|
||||
|
||||
/// <summary>Gets an Motive application-wide setting</summary>
|
||||
virtual bool GetProperty(const char* propertyName, char** propertyValue) = 0;
|
||||
|
||||
IDeviceManager( const IDeviceManager& other ) = delete;
|
||||
IDeviceManager& operator=( const IDeviceManager& other ) = delete;
|
||||
};
|
||||
}
|
||||
49
Optitrack Rokoko Glove/include/PluginDevice.h
Normal file
49
Optitrack Rokoko Glove/include/PluginDevice.h
Normal file
@ -0,0 +1,49 @@
|
||||
//======================================================================================================
|
||||
// Copyright 2016, NaturalPoint Inc.
|
||||
//======================================================================================================
|
||||
#pragma once
|
||||
|
||||
#include "AnalogSystemBuildConfig.h"
|
||||
#include "PluginDeviceBase.h"
|
||||
|
||||
namespace AnalogSystem
|
||||
{
|
||||
template <class T> class AnalogFrame;
|
||||
|
||||
/// <summary>
|
||||
/// cPluginDevice is a type-specific implementation of a Plugin Device.
|
||||
/// It provides type specific frame allocation and frame buffer access.
|
||||
/// See Plugin Device SDK for example implementation
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
class cPluginDevice : public cPluginDeviceBase
|
||||
{
|
||||
public:
|
||||
cPluginDevice() : cPluginDeviceBase()
|
||||
{
|
||||
mDataSize = sizeof( T );
|
||||
}
|
||||
|
||||
/// <summary>Gets a pointer to next slot in the device's data buffer to write data into</summary>
|
||||
/// <param name="frameID">The device frame ID the device will associate with this slot</param>
|
||||
AnalogFrame<T>* BeginFrameUpdate( long frameID, bool wait = true ) override
|
||||
{
|
||||
return dynamic_cast<AnalogFrame<T>*>( __super::BeginFrameUpdate( frameID, wait ) );
|
||||
}
|
||||
|
||||
/// <summary>Gets the frame by device frame identifier.</summary>
|
||||
/// <param name="frameID">The device frame ID</param>
|
||||
const AnalogFrame<T>* GetFrameByDeviceFrameID( long frameID ) const override
|
||||
{
|
||||
return dynamic_cast<const AnalogFrame<T>*>( __super::GetFrameByDeviceFrameID( frameID ) );
|
||||
}
|
||||
|
||||
protected:
|
||||
/// <summary>Allocates a frame in the plugin's memory context</summary>
|
||||
/// <param name="channelCount">The channel count</param>
|
||||
virtual AnalogFrame<T>* AllocateFrame( int channelCount ) override
|
||||
{
|
||||
return new AnalogFrame<T>( channelCount );
|
||||
}
|
||||
};
|
||||
}
|
||||
398
Optitrack Rokoko Glove/include/PluginDeviceBase.h
Normal file
398
Optitrack Rokoko Glove/include/PluginDeviceBase.h
Normal file
@ -0,0 +1,398 @@
|
||||
//======================================================================================================
|
||||
// Copyright 2016, NaturalPoint Inc.
|
||||
//======================================================================================================
|
||||
#pragma once
|
||||
|
||||
// STL
|
||||
// Private STL members are OK in exported class since they do not cross the DLL boundary
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4251 )
|
||||
#pragma warning( disable : 4275 )
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
||||
// OptiTrack PluginDevice API
|
||||
#include "AnalogSystemBuildConfig.h"
|
||||
#include "IDevice.h"
|
||||
#include "AnalogFrame.h"
|
||||
#include "AnalogChannelDescriptor.h"
|
||||
#include "PropertySet.h"
|
||||
|
||||
#define ANALOG_DEVICEBUFFERSIZE 1000
|
||||
#define ANALOG_ERRORMESSAGESIZE 4096
|
||||
#define ANALOG_MAXSAMPLESPERMOCAPFRAME 16
|
||||
|
||||
namespace MoCapCore
|
||||
{
|
||||
class cPropertyCollectionDefinition;
|
||||
}
|
||||
|
||||
namespace AnalogSystem
|
||||
{
|
||||
class AnalogChannelDescriptor;
|
||||
class IDeviceManager;
|
||||
class AnalogFrameGroup;
|
||||
|
||||
/// <summary>
|
||||
/// Device sync mode
|
||||
/// </summary>
|
||||
enum DeviceSyncMode
|
||||
{
|
||||
DeviceSync_FreeRun = 0, // Free running
|
||||
DeviceSync_Triggered // Waits for a trigger signal in data packet before starting
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Device Type (Devices can register themselves as a known type (e.g. Force Plate)
|
||||
/// which can help Motive in interpreting the device in the UI, used derived node classes, etc.
|
||||
/// </summary>
|
||||
enum DeviceType
|
||||
{
|
||||
DeviceType_None = 0, // No particular type
|
||||
DeviceType_NIDAQ, // NIDAQ card
|
||||
DeviceType_ForcePlate, // Force plate
|
||||
DeviceType_EyeTracker, // Eye Tracker
|
||||
DeviceType_Pointer, // Pointer
|
||||
DeviceType_Glove // Glove
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Frame Flags
|
||||
/// </summary>
|
||||
enum FrameFlag
|
||||
{
|
||||
FrameFlag_SyncBit = 0x01, // this frame contained a sync bit from the device
|
||||
FrameFlag_DropFrame = 0x02, // this frame was dropped by the device and is padded with 0's
|
||||
FrameFlag_Synthetic = 0x04 // this frame contains synthetic (padded or device filled) data
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Device frame buffer state
|
||||
/// </summary>
|
||||
enum DeviceBufferState
|
||||
{
|
||||
Buffer_Ready = 0,
|
||||
Buffer_NeedSync = -1,
|
||||
Buffer_Behind = -2,
|
||||
Buffer_Ahead = -3,
|
||||
Buffer_Empty = -4,
|
||||
Buffer_MocapFrameOutOfRange = -5
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Device data state (not ready, ready, data flowing)
|
||||
/// </summary>
|
||||
enum DeviceDataState
|
||||
{
|
||||
DeviceState_NotReady = 0, // Device not ready (channels not configured, not calibrated, etc)
|
||||
DeviceState_Ready, // Device ready for capture (channels enabled and correctly configured, calibrated, etc)
|
||||
DeviceState_ReceivingData // Device actually actively receiving data
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Device sync state
|
||||
/// </summary>
|
||||
enum DeviceSyncStatus
|
||||
{
|
||||
DeviceSyncStatus_NeedSync = 0,
|
||||
DeviceSyncStatus_Resyncing,
|
||||
DeviceSyncStatus_ReadyForSync,
|
||||
DeviceSyncStatus_Synced
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// cPluginDeviceBase is the base implementation class for a Motive Plugin Device/
|
||||
///
|
||||
/// Implementors should derive from the template PluginDevice subclass
|
||||
//
|
||||
/// A PluginDevice provides
|
||||
/// - Device operation callbacks, to be overridden by device implementor
|
||||
/// - Device channel and property management, for exposing device channel information
|
||||
/// and custom properties to the Motive UI. Also provides property change event
|
||||
/// communication between Motive and Device
|
||||
/// - Data management, providing a thread-safe user-typed data buffer for the device to
|
||||
/// quickly write to, and for Motive to read from.
|
||||
/// </summary>
|
||||
/// <seealso cref="IDevice" />
|
||||
class ANALOGSYSTEM_API cPluginDeviceBase : public IDevice, public cPropertySet
|
||||
{
|
||||
public:
|
||||
cPluginDeviceBase();
|
||||
virtual ~cPluginDeviceBase();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Plugin Device Interface (override in derived plugin device)
|
||||
//
|
||||
|
||||
///<summary>Perform device specific configuration, allocates channel buffer. (Call base when implementing)</summary>
|
||||
bool Configure() override;
|
||||
|
||||
/// <summary>Deconfigure this instance</summary>
|
||||
bool Deconfigure() override;
|
||||
|
||||
/// <summary>Zero the device</summary>
|
||||
void Zero() override;
|
||||
|
||||
/// <summary>Prepare live clocked devices for sync</summary>
|
||||
bool PrepareForSync() override;
|
||||
|
||||
/// <summary>Perform any device-specific pre-capture operations</summary>
|
||||
bool PreCapture() override;
|
||||
|
||||
/// <summary>Start device sampling (Call base when implementing)</summary>
|
||||
bool StartCapture() override;
|
||||
|
||||
/// <summary>Stop device sampling (Call base when implementing)</summary>
|
||||
bool StopCapture() override;
|
||||
|
||||
/// <summary>Perform any device-specific post-capture operations</summary>
|
||||
bool PostCapture() override;
|
||||
|
||||
/// <summary>Return whether device is actively capturing data</summary>
|
||||
bool IsCapturing() const override;
|
||||
|
||||
/// <summary>Return whether device is actively capturing data</summary>
|
||||
bool IsReady() const;
|
||||
|
||||
/// <summary>Gives device a chance to validate a property value before applying it</summary>
|
||||
bool ValidatePropertyChange( const char* propertyName, const IPropVal& val ) override;
|
||||
|
||||
/// <summary>Handle device specific property change events</summary>
|
||||
void OnPropertyChanged( const char* propertyName ) override;
|
||||
|
||||
/// <summary>Handle device channel property change events</summary>
|
||||
void OnChannelPropertyChanged( const char* channelName, const char* propertyName ) override;
|
||||
|
||||
/// <summary>Generic device-defined message passed from host (e.g. Motive) to device</summary>
|
||||
int MessageFromHost( const char* ) const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Plugin Device Base Implementation (do not override)
|
||||
//
|
||||
|
||||
// channels
|
||||
|
||||
/// <summary>Retrieves the ChannelDescriptor at the specified index</summary>
|
||||
AnalogChannelDescriptor* ChannelDescriptor( int index ) override;
|
||||
|
||||
/// <summary>Retrieves the ChannelDescriptor at the specified channel name</summary>
|
||||
AnalogChannelDescriptor* ChannelDescriptor( const char* channelName ) override;
|
||||
|
||||
/// <summary>Retrieves the number of Channels</summary>
|
||||
int ChannelDescriptorCount() const override;
|
||||
|
||||
/// <summary>Retrieves the number of enabled channels</summary>
|
||||
int ActiveChannelCount() const override;
|
||||
|
||||
/// <summary>Retrieves the ChannelDescriptor at the specified active channel index</summary>
|
||||
AnalogChannelDescriptor* ActiveChannelDescriptor( int index ) override;
|
||||
|
||||
/// <summary>Retrieves the ChannelID at the specified index</summary>
|
||||
int ChannelID( int index ) const override;
|
||||
|
||||
/// <summary>Retrieves the ChannelID associated with the specified channel name</summary>
|
||||
int ChannelID( const char* channelName ) const;
|
||||
|
||||
// data
|
||||
|
||||
/// <summary>Called by Device before updating the frame buffer to lock the buffer and provide a slot</summary>
|
||||
/// <param name="DeviceFrameID">The device frame ID.</param>
|
||||
/// <returns>Slot to write data to</returns>
|
||||
AnalogFrameBase* BeginFrameUpdate( long DeviceFrameID, bool wait = true ) override;
|
||||
|
||||
/// <summary>Called by device when frame update is done, unlocking the buffer and updating the indexer</summary>
|
||||
void EndFrameUpdate() override;
|
||||
|
||||
/// <summary>Gets a frame of data from the device buffer at the specified buffer index</summary>
|
||||
const AnalogFrameBase* GetFrameByBufferIndex( int index ) const override;
|
||||
|
||||
/// <summary>Gets a frame of data from the device buffer at the specified frame ID</summary>
|
||||
const AnalogFrameBase* GetFrameByDeviceFrameID( long frameID ) const override;
|
||||
|
||||
/// <summary>Gets a newly allocated mocap aligned group of device frames. Caller is responsible for relasing framegroup</summary>
|
||||
/// <param name="mocapFrameID">The mocap frame ID</param>
|
||||
/// <param name="resultCode">0 if successful, error code otherwise</param>
|
||||
/// <returns>Collection of analog frames</returns>
|
||||
AnalogFrameGroup* GetFrameGroupByMocapFrameID( long mocapFrameID, DeviceBufferState& resultCode, bool recording = false );
|
||||
|
||||
/// <summary>Gets a mocap aligned frame group</summary>
|
||||
/// <param name="frameGroup">caller provided frame group</param>
|
||||
/// <param name="mocapFrameID">The mocap frame ID</param>
|
||||
/// <returns>0 if successful, error code otherwise</returns>
|
||||
DeviceBufferState GetFrameGroupByMocapFrameID( AnalogFrameGroup& frameGroup, long mocapFrameID, bool recording = false );
|
||||
|
||||
/// <summary>Gets the buffer index of the most recently added frame</summary>
|
||||
int GetMostRecentFrameIndex() const override;
|
||||
|
||||
/// <summary>Gets the frame ID of the most recently added frame</summary>
|
||||
long GetMostRecentFrameID() const override;
|
||||
|
||||
/// <summary>Gets the frame ID of the oldest frame in the buffer</summary>
|
||||
long GetOldestFrameID();
|
||||
|
||||
/// <summary>Updates the software drift correction based on the most recent mocap and device frames</summary>
|
||||
/// <param name="mocapFrameID">Most recent mocap frame ID</param>
|
||||
void UpdateDriftCorrection( long mocapFrameID ) override;
|
||||
|
||||
/// <summary>Resets the drift correction</summary>
|
||||
void ResetDriftCorrection();
|
||||
|
||||
/// <summary>Resets all sync counters (frame id, timestamp)</summary>
|
||||
void ResetSyncCounters();
|
||||
|
||||
/// <summary>Gets the most recent Frame ID</summary>
|
||||
long FrameCounter() const;
|
||||
|
||||
/// <summary>Sets the most recent Frame ID</summary>
|
||||
void SetFrameCounter( long val );
|
||||
|
||||
/// <summary>Sets the DeviceManager (Device to Motive communication interface)</summary>
|
||||
void SetDeviceManager( IDeviceManager* pDeviceManager ) override;
|
||||
|
||||
/// <summary>Gets the DeviceManager</summary>
|
||||
IDeviceManager* DeviceManager() override;
|
||||
|
||||
/// <summary>Logs an error message</summary>
|
||||
void LogError( int errorType, const char* fmt, ... );
|
||||
|
||||
/// <summary>Gets the last logged error message</summary>
|
||||
const char* LastError() const override;
|
||||
|
||||
/// <summary>Gets the size (in bytes) of a channel</summary>
|
||||
int DataSize() const;
|
||||
|
||||
/// <summary>Returns the number of device frame sampled per mocap frame</summary>
|
||||
int DeviceFramesPerMocapFrame() const;
|
||||
|
||||
/// <summary>Return the sync aligned device frame IDs for the specified mocap frame ID</summary>
|
||||
/// <param name="requestedMocapFrameID">Mocap frame</param>
|
||||
/// <param name="deviceStart">Device frame start</param>
|
||||
/// <param name="deviceStop">Device frame stop</param>
|
||||
/// <returns>true if successful, false otherwise</returns>
|
||||
bool MocapFrameIDToDeviceFrameIDs( long requestedMocapFrameID, long& deviceStart, long& deviceStop ) const override;
|
||||
|
||||
bool HaveSyncFrames() const;
|
||||
|
||||
void UpdateDeviceSyncStatus();
|
||||
|
||||
uint64_t LastArrivedSampleTimestamp() const;
|
||||
|
||||
// IProfileSubscriber Interface
|
||||
std::wstring ProfileTypeName() const override;
|
||||
std::wstring ProfileLabel() const override;
|
||||
std::wstring ProfileDescription() const override;
|
||||
void SaveToProfile( tinyxml2wc::XMLElement& saveTo ) const override;
|
||||
bool LoadFromProfile( const tinyxml2wc::XMLElement& source ) override;
|
||||
|
||||
// deprecated
|
||||
void AddFrameToBuffer( AnalogFrameBase* pFrame );
|
||||
virtual void RegisterFactory( int channelCount ) { };
|
||||
|
||||
// PluginDevice Standard Properties. Plugins can add UI exposed custom properties via AddProperty()
|
||||
static const char* kEnabledPropName;
|
||||
static const char* kNamePropName;
|
||||
static const char* kDisplayNamePropName;
|
||||
static const char* kModelPropName;
|
||||
static const char* kSerialPropName;
|
||||
static const char* kChannelCountPropName;
|
||||
static const char* kRatePropName;
|
||||
static const char* kMocapRateMultiplePropName;
|
||||
static const char* kUseExternalClockPropName;
|
||||
static const char* kDeviceTypePropName;
|
||||
static const char* kExternalClockTerminalPropName;
|
||||
static const char* kExternalTriggerTerminalPropName;
|
||||
static const char* kOrderPropName;
|
||||
|
||||
static const char* kMocapRatePropName;
|
||||
static const char* kSyncStatusPropName;
|
||||
static const char* kSyncModePropName;
|
||||
static const char* kMocapSyncFramePropName;
|
||||
static const char* kSyncFramePropName;
|
||||
static const char* kNeedDeviceSyncFramePropName;
|
||||
static const char* kNeedMocapSyncFramePropName;
|
||||
static const char* kDriftCorrectionPropName;
|
||||
static const char* kUseDriftCorrectionPropName;
|
||||
static const char* kExternalClockChannelPropName;
|
||||
static const char* kMasterSerialPropName;
|
||||
static const char* kSlaveIndexPropName;
|
||||
static const char* kNoiseAveragePropName;
|
||||
static const char* kZeroPropName;
|
||||
static const char* kDataStatePropName;
|
||||
static const char* kAppRunModePropName;
|
||||
static const char* kGroupNamePropName;
|
||||
static const char* kAssetPropName;
|
||||
static const char* kConnectedPropName;
|
||||
static const char* kDummySerialPropName;
|
||||
static const char* kUserDataPropName;
|
||||
|
||||
static const char* kCorner0PropName;
|
||||
static const char* kCorner1PropName;
|
||||
static const char* kCorner2PropName;
|
||||
static const char* kCorner3PropName;
|
||||
static const char* kScalePropName;
|
||||
static const char* kCalOffsetPropName;
|
||||
static const char* kCalSquareRotationPropName;
|
||||
|
||||
protected:
|
||||
/// <summary>Adds a channel definition to the device</summary>
|
||||
/// <param name="channelName">Name of the channel.</param>
|
||||
/// <param name="dataType">Type of the data.</param>
|
||||
/// <returns>ID of the new channel</returns>
|
||||
int AddChannelDescriptor( char* channelName, int dataType = (int) ChannelType_Float );
|
||||
|
||||
// allocate a new frame (implemented in derived template class)
|
||||
virtual AnalogFrameBase* AllocateFrame( int channelCount ) = 0;
|
||||
|
||||
/// <summary>Size (in bytes) of a data channel</summary>
|
||||
int mDataSize;
|
||||
bool mIsReady;
|
||||
bool mIsCapturing;
|
||||
|
||||
long mRecordingDeviceSyncFrame = -1;
|
||||
long mLiveDeviceSyncFrame = -1;
|
||||
|
||||
private:
|
||||
// properties
|
||||
std::shared_ptr<MoCapCore::cPropertyCollectionDefinition> CreatePropertyDefinitions();
|
||||
|
||||
// channels
|
||||
std::vector<AnalogChannelDescriptor*> mChannelDescriptors;
|
||||
std::vector<int> mActiveChannelMap;
|
||||
|
||||
// data
|
||||
AnalogFrameBase* GetNextSlot( long DeviceFrameID );
|
||||
bool LockBuffer( bool wait = true ) const;
|
||||
void UnlockBuffer() const;
|
||||
void ReleaseBuffer();
|
||||
std::vector<AnalogFrameBase*> mFrameBuffer;
|
||||
mutable void* mFrameBufferLock;
|
||||
int mFrameBufferSize;
|
||||
int mLastAddedIndex;
|
||||
std::map<long, int> mAnalogFrameIDToBufferIndex;
|
||||
|
||||
long mFrameCounter;
|
||||
long mDriftCorrection;
|
||||
|
||||
// helpers
|
||||
IDeviceManager* mDeviceManager;
|
||||
char mLastErrorMsg[ANALOG_ERRORMESSAGESIZE];
|
||||
void* mMessageLock;
|
||||
|
||||
std::wstring mDeviceName;
|
||||
static const std::wstring kPropertyDefinitionName;
|
||||
static Core::cUID sPropertyDefinitionsID;
|
||||
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> mLastTimestamp;
|
||||
bool mCached_NeedDeviceSyncFrame = true;
|
||||
};
|
||||
}
|
||||
|
||||
#pragma warning( pop )
|
||||
6
Optitrack Rokoko Glove/include/PluginDeviceFactory.h
Normal file
6
Optitrack Rokoko Glove/include/PluginDeviceFactory.h
Normal file
@ -0,0 +1,6 @@
|
||||
//======================================================================================================
|
||||
// Copyright 2016, NaturalPoint Inc.
|
||||
//======================================================================================================
|
||||
#pragma once
|
||||
|
||||
#include "IDeviceFactory.h"
|
||||
125
Optitrack Rokoko Glove/include/PropertySet.h
Normal file
125
Optitrack Rokoko Glove/include/PropertySet.h
Normal file
@ -0,0 +1,125 @@
|
||||
//======================================================================================================
|
||||
// Copyright 2016, NaturalPoint Inc.
|
||||
//======================================================================================================
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "AnalogSystemBuildConfig.h"
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4251 )
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class cUID;
|
||||
}
|
||||
|
||||
namespace MoCapCore
|
||||
{
|
||||
class cPropertyCollection;
|
||||
}
|
||||
|
||||
namespace AnalogSystem
|
||||
{
|
||||
class IPropVal
|
||||
{
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// cPropertyValue is a property value wrapper
|
||||
/// </summary>
|
||||
template<typename T>
|
||||
class cPropVal : public IPropVal
|
||||
{
|
||||
public:
|
||||
cPropVal( const T value ) { mValue = value; }
|
||||
|
||||
void SetValue( const T value ) { mValue = value; }
|
||||
const T GetValue() { return mValue; }
|
||||
|
||||
private:
|
||||
T mValue;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// cPropertySet is a wrapper for a Motive property collection, providing:
|
||||
/// - Access to Motive PluginDevice base properties
|
||||
/// - Ability to add custom properties, which will be settable in the UI
|
||||
/// - Ability to respond to and generate property change events
|
||||
///
|
||||
/// See Plugin Device SDK for example.
|
||||
///
|
||||
/// Devices and DeviceChannels derive from this.
|
||||
/// </summary>
|
||||
class ANALOGSYSTEM_API cPropertySet
|
||||
{
|
||||
public:
|
||||
cPropertySet() = default;
|
||||
virtual ~cPropertySet() = default;
|
||||
|
||||
/// <summary>Sets the property.</summary>
|
||||
/// <param name="propertyName">Name of the property.</param>
|
||||
/// <param name="newValue">The new value.</param>
|
||||
/// <returns></returns>
|
||||
bool SetProperty( const char* propertyName, const char* newValue );
|
||||
bool SetProperty( const char* propertyName, bool newValue );
|
||||
bool SetProperty( const char* propertyName, int newValue );
|
||||
bool SetProperty( const char* propertyName, double newValue );
|
||||
bool SetProperty( const char* propertyName, double x, double y, double z );
|
||||
|
||||
/// <summary>Gets the property.</summary>
|
||||
/// <param name="propertyName">Name of the property.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns></returns>
|
||||
bool GetProperty( const char* propertyName, char* value, size_t bufferSize ) const;
|
||||
bool GetProperty( const char* propertyName, bool& value ) const;
|
||||
bool GetProperty( const char* propertyName, int& value ) const;
|
||||
bool GetProperty( const char* propertyName, double& value ) const;
|
||||
bool GetProperty( const char* propertyName, double& x, double& y, double& z ) const;
|
||||
|
||||
/// <summary>(Internal) Gets the shared pointer to the Motive cPropertyCollection</summary>
|
||||
/// <returns>Motive cPropertyCollection</returns>
|
||||
std::shared_ptr<MoCapCore::cPropertyCollection> PropertyCollection();
|
||||
std::shared_ptr<const MoCapCore::cPropertyCollection> PropertyCollection() const;
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a property's attributes.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of the property.</param>
|
||||
/// <param name="readOnly">if set to <c>true</c> [read only].</param>
|
||||
/// <param name="hidden">if set to <c>true</c> [hidden].</param>
|
||||
/// <param name="group">The group.</param>
|
||||
/// <returns>true if successful, false otherwise</returns>
|
||||
bool ModifyProperty( const char* propertyName, bool readOnly, bool hidden, bool advanced = false, bool serializable = true );
|
||||
|
||||
protected:
|
||||
/// <summary>Create and initializes the cPropertyCollection.</summary>
|
||||
/// <param name="propertySetName">Name of the property set.</param>
|
||||
/// <returns>true if successful, false otherwise</returns>
|
||||
bool Initialize( const char* propertySetName );
|
||||
|
||||
/// <summary>
|
||||
/// Adds the property with the default value, which determines the property type.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of the property.</param>
|
||||
/// <param name="defaultValue">The default value.</param>
|
||||
/// <returns>true if successful, false otherwise</returns>
|
||||
bool AddProperty( const char* propertyName, const char* defaultValue, const char* group = "", bool serializable = true );
|
||||
bool AddProperty( const char* propertyName, bool defaultValue, const char* group = "", bool serializable = true );
|
||||
bool AddProperty( const char* propertyName, int defaultValue, const char* group = "", bool serializable = true );
|
||||
bool AddProperty( const char* propertyName, double defaultValue, const char* group = "", bool serializable = true );
|
||||
bool AddProperty( const char* propertyName, const char* constraintNames[], int constraintCount, int defaultValue, const char* group = "", bool serializable = true );
|
||||
|
||||
// Internal use only
|
||||
bool Initialize( const Core::cUID& definitionID );
|
||||
|
||||
private:
|
||||
template<typename T2> bool GetPropertyInternal( const char* propertyName, T2& value ) const;
|
||||
template<typename T2> bool SetPropertyInternal( const char* propertyName, T2 value );
|
||||
|
||||
std::shared_ptr<MoCapCore::cPropertyCollection> mPropertyCollection;
|
||||
};
|
||||
}
|
||||
|
||||
#pragma warning( pop )
|
||||
BIN
Optitrack Rokoko Glove/lib/PeripheralImport.lib
Normal file
BIN
Optitrack Rokoko Glove/lib/PeripheralImport.lib
Normal file
Binary file not shown.
BIN
Optitrack Rokoko Glove/x64/Debug/RokokoGloveDevice.dll
(Stored with Git LFS)
BIN
Optitrack Rokoko Glove/x64/Debug/RokokoGloveDevice.dll
(Stored with Git LFS)
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Optitrack Rokoko Glove/x64/Debug/lz4.dll
(Stored with Git LFS)
Normal file
BIN
Optitrack Rokoko Glove/x64/Debug/lz4.dll
(Stored with Git LFS)
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user