2#include <cgv/math/ftransform.h>
5#include <cgv/gui/key_event.h>
6#include <cgv/gui/trigger.h>
7#include <cgv_reflect_types/math/fvec.h>
8#include <cgv_reflect_types/math/quaternion.h>
9#include <cg_vr/vr_server.h>
11#include <cg_gamepad/gamepad_server.h>
13const float Body_height = 1740.0f;
14const float Eye_height = 1630.0f;
15const float Chin_height = 1530.0f;
16const float Shoulder_height = 1425.0f;
17const float Shoulder_breadth = 485.0f;
18const float Arm_span = 1790.0f;
19const float Arm_length = 790.0f;
20const float Hip_width = 360.0f;
21const float Hip_height = 935.0f;
22const float Elbow_height = 1090.0f;
23const float Hand_height = 755.0f;
24const float Reach_Upwards = 2060.0f;
25const float Pupillary_distance = 63.0f;
39cgv::mat4 vr_emulated_kit::construct_homogeneous_matrix(
const quat& orientation,
const cgv::vec3& position)
42 orientation.put_matrix(R);
51cgv::vec3 vr_emulated_kit::get_body_direction()
const
57 z_dir = cross(x_dir, up_dir);
58 return -sin(body_direction)*x_dir + cos(body_direction)*z_dir;
61void vr_emulated_kit::compute_state_poses()
63 float scale = body_height / Body_height;
68 z_dir = cross(x_dir, up_dir);
70 T_body.
set_col(0,
cgv::vec4(cos(body_direction)*x_dir + sin(body_direction)*z_dir, 0));
72 T_body.
set_col(2,
cgv::vec4(-sin(body_direction)*x_dir + cos(body_direction)*z_dir,0));
75 cgv::math::translate4<float>(
cgv::vec3(0,scale*Hip_height,0))*
76 cgv::math::rotate4<float>(-60*hip_parameter,
cgv::vec3(1, 0, 0));
78 cgv::math::translate4<float>(
cgv::vec3(0, scale*(Chin_height - Hip_height), 0))*
79 cgv::math::rotate4<float>(-90*yaw_parameter,
cgv::vec3(0, 1, 0));
83 cgv::math::translate4<float>(
84 scale*
cgv::vec3((-Shoulder_breadth + Arm_length * hand_position[0](0)),
85 Shoulder_height - Hip_height + Arm_length * hand_position[0](1),
86 Arm_length*hand_position[0](2)))*R;
89 cgv::math::translate4<float>(
90 scale*
cgv::vec3(+(Shoulder_breadth + Arm_length * hand_position[1](0)),
91 Shoulder_height - Hip_height + Arm_length * hand_position[1](1),
92 Arm_length*hand_position[1](2)))*R;
94 set_pose_matrix(T_body*T_hip*T_head, state.
hmd.
pose);
97 static unsigned ts = 1;
101 for (
int i = 0; i < 4; ++i) {
102 if (!tracker_enabled[i]) {
106 cgv::mat4 T = construct_homogeneous_matrix(tracker_orientations[i], tracker_positions[i]);
107 switch (tracker_attachments[i]) {
108 case TA_HEAD: T = T_body * T_hip*T_head*T;
break;
109 case TA_LEFT_HAND: T = T_body * T_hip*T_left*T;
break;
110 case TA_RIGHT_HAND: T = T_body * T_hip*T_right*T;
break;
118vr_emulated_kit::vr_emulated_kit(
float _body_direction,
const cgv::vec3& _body_position,
float _body_height,
unsigned _width,
unsigned _height,
vr::vr_driver* _driver,
void* _handle,
const std::string& _name,
int _nr_trackers)
119 : vr_kit(_driver, _handle, _name, _width, _height)
121 body_position = _body_position;
122 body_direction=_body_direction;
123 body_height = _body_height;
127 hand_position[0] =
cgv::vec3(0, -0.5f, -0.2f);
128 hand_position[1] =
cgv::vec3(0, -0.5f, -0.2f);
129 hand_orientation[0] = quat(1, 0, 0, 0);
130 hand_orientation[1] = quat(1, 0, 0, 0);
135 for (
int i=0; i<4; ++i)
136 tracker_enabled[i] = i < _nr_trackers;
138 tracker_positions[0] =
cgv::vec3(0.2f, 1.2f, 0.0f);
139 tracker_positions[1] =
cgv::vec3(-0.2f, 1.2f, 0.0f);
140 tracker_positions[2] =
cgv::vec3(-0.6f, 1.2f, 0.0f);
141 tracker_positions[3] =
cgv::vec3(0.6f, 1.2f, 0.0f);
142 tracker_orientations[0] = tracker_orientations[1] = tracker_orientations[2] = tracker_orientations[3] = quat(0.71f,-0.71f,0,0);
143 tracker_attachments[0] = tracker_attachments[1] = tracker_attachments[2] = tracker_attachments[3] = TA_WORLD;
154 for (
int ci = 0; ci < 6; ++ci) {
176 compute_state_poses();
179const std::vector<std::pair<int, int> >& vr_emulated_kit::get_controller_throttles_and_sticks(
int controller_index)
const
181 static std::vector<std::pair<int, int> > throttles_and_sticks;
182 if (throttles_and_sticks.empty()) {
184 throttles_and_sticks.push_back(std::pair<int, int>(0, 1));
186 throttles_and_sticks.push_back(std::pair<int, int>(2, -1));
188 return throttles_and_sticks;
191const std::vector<std::pair<float, float> >& vr_emulated_kit::get_controller_throttles_and_sticks_deadzone_and_precision(
int controller_index)
const
193 static std::vector<std::pair<float, float> > deadzone_and_precision;
194 if (deadzone_and_precision.empty()) {
195 deadzone_and_precision.push_back(std::pair<float, float>(0.1f, 0.01f));
196 deadzone_and_precision.push_back(std::pair<float, float>(0.0f, 0.2f));
198 return deadzone_and_precision;
202void vr_emulated_kit::set_pose_matrix(
const cgv::mat4& H,
float* pose)
const
220 compute_state_poses();
226 vr_em_ptr->coordinate_rotation.
put_matrix(
reinterpret_cast<cgv::mat3&
>(coordinate_transform));
227 reinterpret_cast<cgv::vec3&
>(coordinate_transform(0, 3)) = vr_em_ptr->coordinate_displacement;
228 cgv::math::pose_transform(coordinate_transform,
reinterpret_cast<cgv::mat3x4&
>(state.
hmd.
pose[0]));
229 for (
int ci = 0; ci < 6; ++ci)
244 float scale = body_height / Body_height;
246 cgv::math::translate4<float>(
247 scale*
cgv::vec3(
float(eye - 0.5f)*Pupillary_distance, Eye_height - Chin_height, -Pupillary_distance)
254 reinterpret_cast<cgv::mat4&
>(*projection_matrix) =
255 cgv::math::perspective4<float>(fovy,
float(
width)/height, z_near, z_far);
264vr_emulator::vr_emulator() :
cgv::base::node(
"vr_emulator")
266 current_kit_index = -1;
267 interaction_mode = IM_BODY;
269 left_ctrl = right_ctrl = up_ctrl = down_ctrl =
false;
270 home_ctrl = end_ctrl = pgup_ctrl = pgdn_ctrl =
false;
280 coordinate_rotation =
cgv::quat(1,0,0,0);
281 coordinate_displacement =
cgv::vec3(0.0f);
286 base_orientations.push_back(
cgv::quat(cgv::math::rotate3<float>(
cgv::vec3(-20.0f, 45.0f, 0))));
287 base_positions.push_back(
cgv::vec3(1.0f, 2.0f, 1.0f));
288 base_serials.push_back(
"vr_emulator_base_01");
290 base_orientations.push_back(
cgv::quat(cgv::math::rotate3<float>(
cgv::vec3(-20.0f, -45.0f, 0))));
291 base_positions.push_back(
cgv::vec3(-1.0f, 2.0f, 1.0f));
292 base_serials.push_back(
"vr_emulator_base_02");
294 update_reference_states();
302 int ib = i, ie = i + 1;
305 ie = (int)base_serials.size();
307 cgv::mat3x4 coordinate_transform = pose_construct(coordinate_rotation, coordinate_displacement);
308 for (
int k = ib; k < ie; ++k) {
311 base_orientations[k].put_matrix(pose_orientation(pose));
312 pose_position(pose) = base_positions[k];
313 pose_transform(coordinate_transform, pose);
317void vr_emulator::timer_event(
double t,
double dt)
319 if (current_kit_index >= 0 && current_kit_index < (
int)kits.size()) {
320 switch (interaction_mode)
323 if (left_ctrl || right_ctrl) {
325 kits[current_kit_index]->body_position -= (float)(left_ctrl ? -dt : dt) * cross(kits[current_kit_index]->get_body_direction(),
cgv::vec3(0, 1, 0));
327 kits[current_kit_index]->body_direction += 3 * (float)(left_ctrl ? -dt : dt);
331 if (up_ctrl || down_ctrl) {
332 kits[current_kit_index]->body_position -= (float)(down_ctrl ? -dt : dt) * kits[current_kit_index]->get_body_direction();
336 if (home_ctrl || end_ctrl) {
337 kits[current_kit_index]->yaw_parameter += (float)(home_ctrl ? -dt : dt);
338 if (kits[current_kit_index]->yaw_parameter < -1)
339 kits[current_kit_index]->yaw_parameter = -1;
340 else if (kits[current_kit_index]->yaw_parameter > 1)
341 kits[current_kit_index]->yaw_parameter = 1;
345 if (pgup_ctrl || pgdn_ctrl) {
346 kits[current_kit_index]->hip_parameter += (float)(pgup_ctrl ? -dt : dt);
347 if (kits[current_kit_index]->hip_parameter < -1)
348 kits[current_kit_index]->hip_parameter = -1;
349 else if (kits[current_kit_index]->hip_parameter > 1)
350 kits[current_kit_index]->hip_parameter = 1;
357 if (home_ctrl || end_ctrl) {
358 float& value = kits[current_kit_index]->state.controller[interaction_mode - IM_LEFT_HAND].axes[2];
359 value += 1.0f * float(home_ctrl ? -dt : dt);
360 value = std::max(std::min(1.0f, value), 0.0f);
376 if (interaction_mode < IM_TRACKER_1) {
377 orientation_ptr = &kits[current_kit_index]->hand_orientation[interaction_mode - IM_LEFT_HAND];
378 position_ptr = &kits[current_kit_index]->hand_position[interaction_mode - IM_LEFT_HAND];
380 else if (interaction_mode < IM_BASE_1) {
381 orientation_ptr = &kits[current_kit_index]->tracker_orientations[interaction_mode - IM_TRACKER_1];
382 position_ptr = &kits[current_kit_index]->tracker_positions[interaction_mode - IM_TRACKER_1];
385 orientation_ptr = &base_orientations[interaction_mode - IM_BASE_1];
386 position_ptr = &base_positions[interaction_mode - IM_BASE_1];
388 if (left_ctrl || right_ctrl) {
390 (*position_ptr)[0] += 0.3f * (float)(left_ctrl ? -dt : dt);
392 *orientation_ptr =
cgv::quat(
cgv::vec3(0, 1, 0), (
float)(right_ctrl ? -dt : dt))*(*orientation_ptr);
396 if (up_ctrl || down_ctrl) {
398 (*position_ptr)[1] += 0.3f * (float)(down_ctrl ? -dt : dt);
400 *orientation_ptr =
cgv::quat(
cgv::vec3(1, 0, 0), (
float)(up_ctrl ? -dt : dt))*(*orientation_ptr);
404 if (pgup_ctrl || pgdn_ctrl) {
406 (*position_ptr)[2] += 0.3f * (float)(pgup_ctrl ? -dt : dt);
408 *orientation_ptr =
cgv::quat(
cgv::vec3(0, 0, 1), (
float)(pgup_ctrl ? -dt : dt))*(*orientation_ptr);
412 if (interaction_mode >= IM_BASE_1) {
427 if (member_ptr == ¤t_kit_index) {
428 while (current_kit_index >= (
int)kits.size())
431 if (!base_serials.empty()) {
432 for (
int i = 0; i < (int)base_serials.size(); ++i)
433 if (member_ptr >= &base_orientations[i] && member_ptr < &base_orientations[i]+1 ||
434 member_ptr >= &base_positions[i] && member_ptr < &base_positions[i]+1)
453bool vr_emulator::gamepad_connected =
false;
455void vr_emulator::add_new_kit()
457 if (!gamepad_connected) {
458 gamepad_connected =
true;
463 (
unsigned&)
handle = counter;
465 screen_width, screen_height,
this,
handle,
467 kits.push_back(new_kit);
469 if (current_kit_index == -1) {
470 current_kit_index = int(kits.size()) - 1;
480 std::vector<void*> result;
482 for (
auto kit_ptr : kits)
483 result.push_back(kit_ptr->get_handle());
493 for (
auto kit_ptr : kits) {
509 for (
auto kit_ptr : kits) {
510 if (kit_ptr == old_kit_ptr ||
vr::get_vr_kit(kit_ptr->get_handle()) == old_kit_ptr) {
540 for (
unsigned i = 0; i < 6; ++i) {
541 float angle = float(2 * M_PI*i / 6);
542 cgv::vec3 pi(1.5f*cos(angle), 0, 2.5f*sin(angle));
543 reinterpret_cast<cgv::vec3&
>(boundary[3 * i]) = pi;
548 if (current_kit_index == -1)
550 if (current_kit_index >= (
int)kits.size())
555 kits[current_kit_index]->state.controller[controller_index].axes[0] = touch_x;
556 kits[current_kit_index]->state.controller[controller_index].axes[1] = touch_y;
559 kits[current_kit_index]->state.controller[controller_index].button_flags ^= button;
566bool vr_emulator::handle_ctrl_key(
cgv::gui::key_event& ke,
bool& fst_ctrl,
bool* snd_ctrl_ptr)
568 if (current_kit_index == -1)
604 current_kit_index = ke.
get_key() -
'0';
605 if (current_kit_index >= (
int)kits.size())
606 current_kit_index = -1;
617 interaction_mode = InteractionMode(IM_BODY + ke.
get_key() -
'0');
620 case 'Q':
return check_for_button_toggle(ke, 0,
vr::VRF_SYSTEM, -1, 1);
621 case 'W':
return check_for_button_toggle(ke, 0,
vr::VRF_MENU, 0, 1);
622 case 'E':
return check_for_button_toggle(ke, 0,
vr::VRF_A, 1, 1);
625 case 'S':
return check_for_button_toggle(ke, 0,
vr::VRF_INPUT0, 0, 0);
628 case 'Y':
return check_for_button_toggle(ke, 0,
vr::VRF_GRIP, -1, -1);
629 case 'X':
return check_for_button_toggle(ke, 0,
vr::VRF_GRIP, 0, -1);
630 case 'C':
return check_for_button_toggle(ke, 0,
vr::VRF_INPUT1, 1, -1);
633 case 'U':
return check_for_button_toggle(ke, 1,
vr::VRF_SYSTEM, -1, 1);
634 case 'I':
return check_for_button_toggle(ke, 1,
vr::VRF_MENU, 0, 1);
635 case 'O':
return check_for_button_toggle(ke, 1,
vr::VRF_A, 1, 1);
638 case 'K':
return check_for_button_toggle(ke, 1,
vr::VRF_INPUT0, 0, 0);
641 case 'M':
return check_for_button_toggle(ke, 1,
vr::VRF_GRIP, -1, -1);
642 case ',':
return check_for_button_toggle(ke, 1,
vr::VRF_GRIP, 0, -1);
643 case '.':
return check_for_button_toggle(ke, 1,
vr::VRF_INPUT1, 1, -1);
647 return handle_ctrl_key(ke, left_ctrl, &home_ctrl);
650 return handle_ctrl_key(ke, right_ctrl, &end_ctrl);
653 return handle_ctrl_key(ke, up_ctrl, &pgup_ctrl);
656 return handle_ctrl_key(ke, down_ctrl, &pgdn_ctrl);
659 return handle_ctrl_key(ke, home_ctrl);
662 return handle_ctrl_key(ke, end_ctrl);
665 return handle_ctrl_key(ke, pgup_ctrl);
668 return handle_ctrl_key(ke, pgdn_ctrl);
675 os <<
"vr_emulator:\n"
676 <<
" Ctrl-Alt-N to create vr kit indexed from 0\n"
677 <<
" Shift-<0-3> to select to be controlled vr kit (unselect if key's kit not exits)\n"
678 <<
" <0-9> select <body|left hand|right hand|tracker 1|tracker 2|tracker 3|tracker 4|base 1|base 2|base 3> for control\n"
679 <<
" body: <up|down> .. move, <left|right> .. turn, <pgup|pgdn> .. bend, \n"
680 <<
" <home|end> .. gear, <alt>+<left|right> .. side step\n"
681 <<
" hand: <home|end> .. trigger\n"
682 <<
" hand&tracker: <left|right|up|down|pgdn|pgup> .. rotate or with <alt> translate\n"
683 <<
" <Q|W|E|A|S|D|Y|X|C:U|I|O|J|K|L|M|,|.> toggle left:right controller buttons\n"
684 <<
" <System|Menu|A|Touch0|Press0|Touch1|Grip|Grip|Press1>; adjust TP position with Shift\n"
685 <<
" <Shift>-<QWE:ASD:YXC>|<UIO:HJK:BNM> to set left:right controller touch xy to -1|0|+1\n"
691 return "vr_emulator";
696 static std::string i_modes(
"body,left hand,right hand,tracker 1,tracker 2,tracker 3,tracker 4,base 1, base 2,base 3, base 4");
709 for (
auto kit_ptr : kits) {
726 if (res && current_kit_index != -1 && current_kit_index < (
int)kits.size()) {
735 srh.
reflect_member(
"left_hand_position", kit_ptr->hand_position[0]) &&
736 srh.
reflect_member(
"right_hand_position", kit_ptr->hand_position[1]) &&
737 srh.
reflect_member(
"tracker_1_position", kit_ptr->tracker_positions[0]) &&
738 srh.
reflect_member(
"tracker_2_position", kit_ptr->tracker_positions[1]) &&
739 srh.
reflect_member(
"tracker_3_position", kit_ptr->tracker_positions[2]) &&
740 srh.
reflect_member(
"tracker_4_position", kit_ptr->tracker_positions[3]) &&
741 srh.
reflect_member(
"tracker_1_enabled", kit_ptr->tracker_enabled[0]) &&
742 srh.
reflect_member(
"tracker_2_enabled", kit_ptr->tracker_enabled[1]) &&
743 srh.
reflect_member(
"tracker_3_enabled", kit_ptr->tracker_enabled[2]) &&
744 srh.
reflect_member(
"tracker_4_enabled", kit_ptr->tracker_enabled[3]) &&
745 srh.
reflect_member(
"tracker_1_orientation", kit_ptr->tracker_orientations[0]) &&
746 srh.
reflect_member(
"tracker_2_orientation", kit_ptr->tracker_orientations[1]) &&
747 srh.
reflect_member(
"tracker_3_orientation", kit_ptr->tracker_orientations[2]) &&
748 srh.
reflect_member(
"tracker_4_orientation", kit_ptr->tracker_orientations[3]) &&
749 srh.
reflect_member(
"left_hand_orientation", kit_ptr->hand_orientation[0]) &&
750 srh.
reflect_member(
"right_hand_orientation", kit_ptr->hand_orientation[1]) &&
751 srh.
reflect_member(
"tracker_1_attachment", (
int&)kit_ptr->tracker_attachments[0]) &&
752 srh.
reflect_member(
"tracker_2_attachment", (
int&)kit_ptr->tracker_attachments[1]) &&
753 srh.
reflect_member(
"tracker_3_attachment", (
int&)kit_ptr->tracker_attachments[2]) &&
754 srh.
reflect_member(
"tracker_4_attachment", (
int&)kit_ptr->tracker_attachments[3]);
764 add_view(
"x.x", ts.
pose[0],
"value",
"w=50;step=0.0001",
" ");
765 add_view(
"x.y", ts.
pose[1],
"value",
"w=50;step=0.0001",
" ");
766 add_view(
"x.z", ts.
pose[2],
"value",
"w=50;step=0.0001");
767 add_view(
"y.x", ts.
pose[3],
"value",
"w=50;step=0.0001",
" ");
768 add_view(
"y.y", ts.
pose[4],
"value",
"w=50;step=0.0001",
" ");
769 add_view(
"y.z", ts.
pose[5],
"value",
"w=50;step=0.0001");
770 add_view(
"z.x", ts.
pose[6],
"value",
"w=50;step=0.0001",
" ");
771 add_view(
"z.y", ts.
pose[7],
"value",
"w=50;step=0.0001",
" ");
772 add_view(
"z.z", ts.
pose[8],
"value",
"w=50;step=0.0001");
773 add_view(
"0.x", ts.
pose[9],
"value",
"w=50;step=0.0001",
" ");
774 add_view(
"0.y", ts.
pose[10],
"value",
"w=50;step=0.0001",
" ");
775 add_view(
"0.z", ts.
pose[11],
"value",
"w=50;step=0.0001");
800 add_member_control(
this,
"attachment", kit->tracker_attachments[i],
"dropdown",
"enums='world,head,left hand,right hand'");
802 add_gui(
"position", kit->tracker_positions[i],
"vector",
"gui_type='value_slider';options='min=-3;max=3;step=0.0001;ticks=true'");
804 add_gui(
"orientation",
reinterpret_cast<cgv::vec4&
>(kit->tracker_orientations[i]),
"direction",
"gui_type='value_slider';options='min=-1;max=1;step=0.0001;ticks=true'");
812 if (
begin_tree_node(
"base and calib", coordinate_rotation,
false,
"level=2")) {
815 add_gui(
"coordinate_rotation",
reinterpret_cast<cgv::vec4&
>(coordinate_rotation),
"direction",
"options='min=-1;max=1;step=0.0001;ticks=true'");
816 add_gui(
"coordinate_displacement", coordinate_displacement,
"",
"options='min=-2;max=2;step=0.0001;ticks=true'");
818 for (uint32_t i = 0; i < base_serials.size(); ++i) {
820 add_gui(
"orientation",
reinterpret_cast<cgv::vec4&
>(base_orientations[i]),
"direction",
"options='min=-1;max=1;step=0.0001;ticks=true'");
821 add_gui(
"position", base_positions[i],
"",
"options='min=-2;max=2;step=0.0001;ticks=true'");
828 add_member_control(
this,
"screen_width", screen_width,
"value_slider",
"min=320;max=1920;ticks=true");
829 add_member_control(
this,
"screen_height", screen_height,
"value_slider",
"min=240;max=1920;ticks=true");
830 add_gui(
"body_position", body_position,
"",
"options='min=-1;max=1;step=0.0001;ticks=true'");
831 add_member_control(
this,
"body_direction", body_direction,
"min=0;max=6.3;ticks=true");
832 add_member_control(
this,
"body_height", body_height,
"min=1.2;max=2.0;step=0.001;ticks=true");
834 connect_copy(
add_button(
"create new kit")->click, cgv::signal::rebind(
this, &vr_emulator::add_new_kit));
838 add_view(
"current_kit", current_kit_index,
"",
"w=50",
" ");
839 add_member_control(
this,
"mode", interaction_mode,
"dropdown",
"w=100;enums='body,left hand,right hand,tracker 1,tracker 2,tracker 3,tracker 4,base 1, base 2,base 3, base 4'");
850 for (
unsigned i = 0; i < kits.size(); ++i) {
853 add_view(
"buttons left", kits[i]->fovy,
"",
"w=0",
"");
854 add_gui(
"button_flags", kits[i]->state.controller[0].button_flags,
"bit_field_control",
855 "enums='SY=1,ME=2,GR=4,A=128,PT=256,PP=512,TT=1024,TP=2048';options='w=16;tooltip=\""
856 "SYstem button<Q> \nMEnu button <W>\nA button <E>\n"
857 "Pad Touch <A>\nPad Press <S>\nTrigger Touch\n<D>"
858 "GRip button <Y|X>\nTrigger Press <C>\"';"
859 "align='';gui_type='toggle'");
861 add_view(
"Pxy", kits[i]->state.controller[0].axes[0],
"",
"w=16",
"");
862 add_view(
"", kits[i]->state.controller[0].axes[1],
"",
"w=16");
863 add_view(
"buttons right", kits[i]->fovy,
"",
"w=0",
"");
864 add_gui(
"button_flags", kits[i]->state.controller[1].button_flags,
"bit_field_control",
865 "enums='SY=1,ME=2,GR=4,A=128,PT=256,PP=512,TT=1024,TP=2048';options='w=16;tooltip=\""
866 "SYstem button<U>\nMEnu button <I>\nA button <O>\n"
867 "Pad Touch <J>\nPad Press <K>\nTrigger Touch\n"
868 "GRip button <M|,>\nTrigger Press\"';"
869 "align='';gui_type='toggle'");
871 add_view(
"Pxy", kits[i]->state.controller[1].axes[0],
"",
"w=16",
"");
872 add_view(
"", kits[i]->state.controller[1].axes[1],
"",
"w=16");
874 add_member_control(
this,
"fovy", kits[i]->fovy,
"value_slider",
"min=30;max=180;ticks=true;log=true");
875 if (
begin_tree_node(
"body pose", kits[i]->body_position,
false,
"level=3")) {
878 add_gui(
"body_position", kits[i]->body_position,
"",
"options='min=-5;max=5;ticks=true'");
879 add_member_control(
this,
"body_direction", kits[i]->body_direction,
"value_slider",
"min=0;max=6.3;ticks=true");
880 add_member_control(
this,
"body_height", kits[i]->body_height,
"value_slider",
"min=1.2;max=2.0;ticks=true");
881 add_member_control(
this,
"hip_parameter", kits[i]->hip_parameter,
"value_slider",
"min=-1;max=1;step=0.0001;ticks=true");
882 add_member_control(
this,
"yaw_parameter", kits[i]->yaw_parameter,
"value_slider",
"min=-1;max=1;step=0.0001;ticks=true");
883 for (
int j = 0; j < 2; ++j) {
884 if (
begin_tree_node(j == 0 ?
"left hand" :
"right hand", kits[i]->hand_position[j],
false,
"level=3")) {
887 add_gui(
"position", kits[i]->hand_position[j],
"vector",
"gui_type='value_slider';options='min=-3;max=3;step=0.0001;ticks=true'");
889 add_gui(
"orientation",
reinterpret_cast<cgv::vec4&
>(kits[i]->hand_orientation[j]),
"direction",
"gui_type='value_slider';options='min=-1;max=1;step=0.0001;ticks=true'");
897 create_tracker_gui(kits[i], 0);
898 create_tracker_gui(kits[i], 1);
899 create_tracker_gui(kits[i], 2);
900 create_tracker_gui(kits[i], 3);
901 if (
begin_tree_node(
"state", kits[i]->state.controller[0].pose[1],
false,
"level=3")) {
903 if (
begin_tree_node(
"hmd", kits[i]->state.hmd.pose[0],
false,
"level=3")) {
905 create_trackable_gui(
"hmd", kits[i]->state.hmd);
909 for (
unsigned ci = 0; ci < 2; ++ci) {
910 if (
begin_tree_node((ci==0?
"left controller":
"right controller"), kits[i]->state.controller[ci],
false,
"level=3")) {
const std::string & get_name() const
return the parent node
std::string name
store the name as a string
unsigned get_kind() const
return, what kind of event this is, typically a value from the EventId enum
unsigned char get_modifiers() const
return the active modifiers as values from EventModifier combined with a logical or-operation
class to represent all possible keyboard events with the EID_KEY
unsigned short get_key() const
return the key being a capital letter, digit or a value from the Keys enum
KeyAction get_action() const
return the key event action
bool add_gui(const std::string &label, T &value, const std::string &gui_type="", const std::string &options="")
Add a composed gui of the given gui_type for the given value.
cgv::base::base_ptr add_decorator(const std::string &label, const std::string &decorator_type, const std::string &options="", const std::string &align="\n")
add a newly created decorator to the group
void align(const std::string &_align)
send pure alignment information
virtual void update_all_members()
call this to update all views and controls of all member
bool begin_tree_node(const std::string &label, const T &value, bool initial_visibility=false, const std::string &options="", gui_group_ptr ggp=gui_group_ptr())
Begin a sub tree of a tree structured gui.
virtual void update_member(void *member_ptr)
call this to update all views and controls of a member
data::ref_ptr< control< T > > add_member_control(cgv::base::base *base_ptr, const std::string &label, T &value, const std::string &gui_type="", const std::string &options="", const std::string &align="\n")
add control with callback to cgv::base::on_set method on cgv::gui::control::value_change
void end_tree_node(const T &value)
template specialization that allows to specify value reference plus node_instance by using the result...
virtual void post_recreate_gui()
delayed recreation of gui
data::ref_ptr< view< T > > add_view(const std::string &label, const T &value, const std::string &gui_type="", const std::string &options="", const std::string &align="\n")
use this to add a new view to the gui with a given value type, gui type and init options
button_ptr add_button(const std::string &label, const std::string &options="", const std::string &align="\n")
use the current gui driver to append a new button with the given label
static double get_current_time()
return the current time
void check_device_changes(double time)
check which vr_kits are present and emit on_device_change events
fvec< T, N > & col(unsigned j)
reference a column of the matrix as a vector
void set_col(unsigned j, const fvec< T, N > &v)
set column j of the matrix to vector v
void put_homogeneous_matrix(hmat_type &M) const
compute equivalent homogeneous 4x4 rotation matrix
void put_matrix(mat_type &M) const
compute equivalent 3x3 rotation matrix
the self reflection handler is passed to the virtual self_reflect() method of cgv::base::base.
bool reflect_member(const std::string &member_name, T &member_ref, bool hard_cast=false)
call this to reflect a member by member name and reference to the member.
base class for all drawables, which is independent of the used rendering API.
void post_redraw()
posts a redraw event to the current context if one is available
unsigned width
pixel dimensions of render targets
interface class for vr drivers.
void replace_vr_kit(void *handle, vr_kit *kit)
call this method during replacement of vr kits. In case vr kit handle had been registered before it i...
void register_vr_kit(void *handle, vr_kit *kit)
call this method during scanning of vr kits. In case vr kit handle had been registered before,...
vr_trackable_state & ref_tracking_reference_state(const std::string &serial_nummer)
provide reference to tracking reference states
void put_x_direction(float *x_dir) const
put a 3d x direction into passed array
virtual void put_up_direction(float *up_dir) const =0
put a 3d up direction into passed array
a vr kit is composed of headset, two controllers, and two trackers, where all devices can be attached...
vr_trackable_state & ref_tracking_reference_state(const std::string &serial_nummer)
write access to the state of the tracking reference with given serial number
vr_kit_info info
store vr kit info to be filled and updated by driver implementations
const vr_driver * get_driver() const
return driver
vr_driver * driver
pointer to driver that created the vr kit
bool set_vibration(unsigned controller_index, float low_frequency_strength, float high_frequency_strength)
set the vibration strength between 0 and 1 of low and high frequency motors, return false if device i...
void submit_frame()
submit the rendered stereo frame to the hmd
cgv::mat3x4 construct_pos_matrix(const quat &orientation, const cgv::vec3 &position)
helper functions to construct matrices
void put_projection_matrix(int eye, float z_near, float z_far, float *projection_matrix, const float *hmd_pose) const
access to 4x4 matrix in column major format for perspective transformation from eye (0....
bool query_state_impl(vr::vr_kit_state &state, int pose_query=2)
derived kits implement this without caring about calibration; vr_kit::query_state() will apply driver...
void put_eye_to_head_matrix(int eye, float *pose_matrix) const
access to 3x4 matrix in column major format for transformation from eye (0..left, 1....
bool handle(cgv::gui::event &e)
overload and implement this method to handle events
void put_up_direction(float *up_dir) const
put a 3d up direction into passed array
void update_reference_states(int i=-1)
update a single renference state or all from base_orientations, base_positions and base_serials
vr::vr_kit * replace_by_index(int &index, vr::vr_kit *new_kit_ptr)
scan all connected vr kits and return a vector with their ids
bool self_reflect(cgv::reflect::reflection_handler &srh)
used for simple self reflection
bool replace_by_pointer(vr::vr_kit *old_kit_ptr, vr::vr_kit *new_kit_ptr)
scan all connected vr kits and return a vector with their ids
void finish_frame(cgv::render::context &)
this method is called in one pass over all drawables after drawing
std::string get_type_name() const
return the type name
bool init(cgv::render::context &ctx)
this method is called after creation or recreation of the context, return whether all necessary funct...
void init_frame(cgv::render::context &)
this method is called in one pass over all drawables before the draw method
bool is_installed() const
return whether driver is installed
std::string get_driver_name() const
return name of driver
float get_action_zone_height() const
return height of action zone in meters
std::vector< void * > scan_vr_kits()
scan all connected vr kits and return a vector with their ids
void stream_stats(std::ostream &)
overload to show the content of this object
void create_controller_gui(int i, vr::vr_controller_state &cs)
void draw(cgv::render::context &)
overload to draw the content of this drawable
void stream_help(std::ostream &os)
overload to stream help information to the given output stream
void on_set(void *member_ptr)
this callback is called when the set_void method has changed a member and can be overloaded in derive...
float get_floor_level() const
return the floor level relativ to the world origin
void put_action_zone_bounary(std::vector< float > &boundary) const
return a vector of floor points defining the action zone boundary as a closed polygon
void create_gui()
you must overload this for gui creation
Helper functions to convert numeric types into strings using std streams.
vr_server & ref_vr_server()
return a reference to gamepad server singleton
@ KA_PRESS
key press action
@ KA_RELEASE
key release action
@ KEY_Page_Down
page down key
@ KEY_Right
right arrow key
@ EID_KEY
id for key event
trigger & get_animation_trigger()
return the global trigger used for animation, which runs by default with 60 Hz
void connect_gamepad_server(cgv::gui::window_ptr w)
connect the gamepad server to the given window or the first window of the application,...
std::string get_element(const std::string &s, int element_index, char sep)
interpret s as a list separated by sep and return the element with the given element index.
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
cgv::math::quaternion< float > quat
declare type of quaternion
cgv::math::fvec< float, 3 > vec3
declare type of 3d single precision floating point vectors
VRButtonStateFlags
one flag for each vr controller button
@ VRF_INPUT0
button of input 0
@ VRF_MENU
application menu button
@ VRF_INPUT1_TOUCH
touch sensor for input 1 which often is touchpad or stick
@ VRF_INPUT1
button of input 1
@ VRF_SYSTEM
system button
@ VRF_INPUT0_TOUCH
touch sensor for input 0 which often is touchpad or stick
vr_kit * get_vr_kit(void *handle)
query a pointer to a vr kit by its device handle, function can return null pointer in case that no vr...
void register_driver(vr_driver *vrd)
register a new driver
@ VRS_TRACKED
trackable is connected and tracked
@ VRS_DETACHED
trackable is not reachable via wireless
helper functions to work with poses that can be represented with 3x4 matrix or quaternion plus vector
Helper functions to process strings.
int32_t nr_axes
total number of axes provided by all inputs
VRControllerType type
controller type
VRButtonStateFlags supported_buttons
one flag per button telling whether it is supported
VRControllerRole role
controller role
VRInputType input_type[max_nr_controller_inputs]
type of up to 5vr::max_nr_controller_inputs inputs built into the controller
VRAxisType axis_type[max_nr_controller_axes]
axis type for each of the vr::max_nr_controller_axes axes in the state
int32_t nr_inputs
number of used inputs
Extends the trackable state by information on the buttons, input axes and vibration strengths.
float axes[max_nr_controller_axes]
up to vr::max_nr_controller_axes axis values in the range [-1,1] or [0,1] (VIVE: 0|1....
unsigned time_stamp
a unique time stamp for fast test whether state changed
float vibration[2]
strength of the vibration motors
std::string serial_number
unique identifier of device
std::string model_number
number describing the device type
float ipd
interpupilar distance measured in meters
float head_to_eye_distance
distance from head origin to eye centers in meters
int32_t number_cameras
number of cameras
vr_hmd_info hmd
information for head mounted display
vr_controller_info controller[max_nr_controllers]
information for attached controllers and trackers
bool force_feedback_support
whether force feedback is supported
structure that stores all information describing the state of a VR kit
vr_controller_state controller[max_nr_controllers]
status, pose, button, axes, and vibration information of up to vr::max_nr_controllers controller and ...
vr_trackable_state hmd
status and pose of hmd
bool has_proximity_sensor
whether device has proximity sensor
std::string device_type
type name of device
int32_t device_class
index of device class
bool is_wireless
whether device is wireless
a trackable knows whether it is tracked and its 6d pose stored as 3x4 matrix in column major format
VRStatus status
whether trackable is currently tracked, only in case of true, the pose member contains useful informa...
float pose[12]
pose as 3x4 matrix in column major format, where each column is a vector in world coordinates
provides vr_emulator and vr_emulated_kit classes.