evan 2026.1.4
Evan
Loading...
Searching...
No Matches
XrHandsMotionActions.cpp
1/*
2** ETIB PROJECT, 2026
3** evan
4** File description:
5** XrHandsMotionActions
6*/
7
8#include "evan/openxr/actions/XrHandsMotionActions.hpp"
9
10#include "evan/openxr/XrDeviceBackend.hpp"
11
14{
15 createHandsMotionActions(actionSet, deviceBackend);
16}
17
19{
20 this->getLogger().info() << "Destroying hand motion actions and spaces...";
21
22 if (_handAimAction != XR_NULL_HANDLE)
23 xrDestroyAction(_handAimAction);
24
25 xrDestroySpace(_handAimSpace[0]);
26 xrDestroySpace(_handAimSpace[1]);
27 this->getLogger().info() << "Hand motion actions and spaces destroyed.";
28
29 if (_handGripAction != XR_NULL_HANDLE)
30 xrDestroyAction(_handGripAction);
31
32 xrDestroySpace(_handGripSpace[0]);
33 xrDestroySpace(_handGripSpace[1]);
34 this->getLogger().info() << "Hand grip actions and spaces destroyed.";
35}
36
38// Public Methods //
40
41std::vector<std::shared_ptr<utility::event::Event>>
43{
44 std::vector<std::shared_ptr<utility::event::Event>> events;
45
46 _leftHandEvent = createHandMotionEvent(deviceBackend, 0);
47 if (_leftHandEvent) {
48 events.push_back(_leftHandEvent);
49 }
50 _rightHandEvent = createHandMotionEvent(deviceBackend, 1);
51 if (_rightHandEvent) {
52 events.push_back(_rightHandEvent);
53 }
54 return events;
55}
56
59{
60 this->getLogger().info() << "Creating hand motion spaces...";
61
62 for (int i = 0; i < 2; i++) {
63 this->getLogger().info()
64 << "Creating spaces for " << std::string(i == 0 ? "LEFT" : "RIGHT")
65 << " hand...";
68 };
69 spaceCreateInfo.action = _handAimAction;
70 spaceCreateInfo.subactionPath =
71 deviceBackend._handActionSubactionPath[i];
72 spaceCreateInfo.poseInActionSpace.orientation.w = 1.0f;
73
75 deviceBackend._session, &spaceCreateInfo, &_handAimSpace[i]);
76 if (result != XR_SUCCESS) {
77 this->getLogger().error()
78 << "Failed to create hand aim space: " << result;
79 return;
80 }
81 this->getLogger().info() << "Hand aim space created successfully.";
82
83 spaceCreateInfo.action = _handGripAction;
85 &_handGripSpace[i]);
86 if (result != XR_SUCCESS) {
87 this->getLogger().error()
88 << "Failed to create hand grip space: " << result;
89 return;
90 }
91 this->getLogger().info() << "Hand grip space created successfully.";
92 }
93 this->getLogger().info() << "Hand motion spaces created successfully.";
94}
95
97// Private Methods //
99
100void evan::XrHandsMotionActions::createHandsMotionActions(
102{
103 this->getLogger().info() << "Creating hand motion actions...";
104
105 // Create pose action
107 actionInfo.actionType = XR_ACTION_TYPE_POSE_INPUT;
108 actionInfo.countSubactionPaths = 2;
109 actionInfo.subactionPaths = deviceBackend._handActionSubactionPath.data();
110
111 strcpy(actionInfo.actionName, "hand_pose");
112 strcpy(actionInfo.localizedActionName, "Hand Pose");
113
114 XrResult result = xrCreateAction(actionSet, &actionInfo, &_handAimAction);
115 if (result != XR_SUCCESS) {
116 this->getLogger().error()
117 << "Failed to create hand pose action: " << result;
118 return;
119 }
120
121 this->getLogger().info() << "Hand pose action created successfully.";
122
123 // Create grip action
124 actionInfo.actionType = XR_ACTION_TYPE_POSE_INPUT;
125 actionInfo.countSubactionPaths = 2;
126 actionInfo.subactionPaths = deviceBackend._handActionSubactionPath.data();
127
128 strcpy(actionInfo.actionName, "hand_grip");
129 strcpy(actionInfo.localizedActionName, "Hand Grip");
130
131 result = xrCreateAction(actionSet, &actionInfo, &_handGripAction);
132 if (result != XR_SUCCESS) {
133 this->getLogger().error()
134 << "Failed to create hand grip action: " << result;
135 return;
136 }
137 this->getLogger().info() << "Hand grip action created successfully.";
138}
139
140std::shared_ptr<utility::event::HandMotionEvent>
141 evan::XrHandsMotionActions::createHandMotionEvent(
142 XrDeviceBackend &deviceBackend, int handIndex)
143{
144 auto handEvent = std::make_shared<utility::event::HandMotionEvent>();
145 handEvent->setHandType(handIndex == 0
146 ? utility::event::HandEvent::HandType::Left
147 : utility::event::HandEvent::HandType::Right);
148 XrActionStateGetInfo getInfo { XR_TYPE_ACTION_STATE_GET_INFO };
149 getInfo.action = _handAimAction;
150 getInfo.subactionPath = deviceBackend._handActionSubactionPath[handIndex];
151
152 XrActionStatePose poseState { XR_TYPE_ACTION_STATE_POSE };
153 xrGetActionStatePose(deviceBackend._session, &getInfo, &poseState);
154
155 if (!poseState.isActive) {
156 this->getLogger().info()
157 << (handIndex == 0 ? std::string("LEFT") : std::string("RIGHT"))
158 << std::string(" hand pose action is not active.");
159 return nullptr;
160 }
161
162 XrSpaceLocation aimLocation { XR_TYPE_SPACE_LOCATION };
163
164 XrResult res =
165 xrLocateSpace(_handAimSpace[handIndex], deviceBackend._space,
166 deviceBackend._predictedDisplayTime, &aimLocation);
167
168 if (XR_FAILED(res)) {
169 this->getLogger().error() << "Failed to locate hand space: " << res;
170 return nullptr;
171 }
172
173 if ((aimLocation.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT)
174 && (aimLocation.locationFlags
175 & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT)) {
176 utility::graphic::PoseF pose;
177 pose.setPosition(utility::graphic::Position<float>(
178 aimLocation.pose.position.x, aimLocation.pose.position.y,
179 aimLocation.pose.position.z));
180 pose.setOrientation(utility::graphic::Orientation<float>(
181 aimLocation.pose.orientation.x, aimLocation.pose.orientation.y,
182 aimLocation.pose.orientation.z, aimLocation.pose.orientation.w));
183
184 handEvent->setAim(pose);
185
186 this->getLogger().info()
187 << (handIndex == 0 ? std::string("LEFT") : std::string("RIGHT"))
188 << std::string(" HAND AIM");
189 this->getLogger().info() << "Position: " << aimLocation.pose.position.x
190 << ", " << aimLocation.pose.position.y << ", "
191 << aimLocation.pose.position.z;
192 this->getLogger().info()
193 << "Orientation: " << aimLocation.pose.orientation.x << ", "
194 << aimLocation.pose.orientation.y << ", "
195 << aimLocation.pose.orientation.z << ", "
196 << aimLocation.pose.orientation.w;
197 }
198
199 XrSpaceLocation gripLocation { XR_TYPE_SPACE_LOCATION };
200
201 res = xrLocateSpace(_handGripSpace[handIndex], deviceBackend._space,
202 deviceBackend._predictedDisplayTime, &gripLocation);
203
204 if (XR_FAILED(res)) {
205 this->getLogger().error()
206 << "Failed to locate hand grip space: " << res;
207 return nullptr;
208 }
209
210 if ((gripLocation.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT)
211 && (gripLocation.locationFlags
212 & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT)) {
213 utility::graphic::PoseF grip;
214 grip.setPosition(utility::graphic::Position<float>(
215 gripLocation.pose.position.x, gripLocation.pose.position.y,
216 gripLocation.pose.position.z));
217 grip.setOrientation(utility::graphic::Orientation<float>(
218 gripLocation.pose.orientation.x, gripLocation.pose.orientation.y,
219 gripLocation.pose.orientation.z, gripLocation.pose.orientation.w));
220
221 handEvent->setGrip(grip);
222
223 this->getLogger().info()
224 << (handIndex == 0 ? std::string("LEFT") : std::string("RIGHT"))
225 << std::string(" HAND GRIP");
226 this->getLogger().info() << "Position: " << gripLocation.pose.position.x
227 << ", " << gripLocation.pose.position.y << ", "
228 << gripLocation.pose.position.z;
229 this->getLogger().info()
230 << "Orientation: " << gripLocation.pose.orientation.x << ", "
231 << gripLocation.pose.orientation.y << ", "
232 << gripLocation.pose.orientation.z << ", "
233 << gripLocation.pose.orientation.w;
234 return handEvent;
235 }
236 return nullptr;
237}
The XrDeviceBackend class is responsible for managing the OpenXR device backend, including instance c...
std::array< XrPath, _handCount > _handActionSubactionPath
void createHandsMotionSpaces(XrDeviceBackend &deviceBackend)
Creates the hand motion actions and their corresponding spaces.
~XrHandsMotionActions()
Destructor for the XrHandsMotionActions class.
std::vector< std::shared_ptr< utility::event::Event > > getEvents(XrDeviceBackend &deviceBackend)
Retrieves the current state of the hand motion actions and generates corresponding events.
XrHandsMotionActions(XrActionSet actionSet, XrDeviceBackend &deviceBackend)
Constructs an XrHandsMotionActions instance with the specified action set and device backend.
Small result wrapper used by helpers that must return both a status and a value (e....
Definition Error.hpp:89