OPENVR Scol plugin
sOpenvr.cpp
1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OpenSpace3D
4 For the latest info, see http://www.openspace3d.com
5 
6 Copyright (c) 2013 I-maginer
7 
8 This program is free software; you can redistribute it and/or modify it under
9 the terms of the GNU Lesser General Public License as published by the Free Software
10 Foundation; either version 2 of the License, or (at your option) any later
11 version.
12 
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License along with
18 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20 http://www.gnu.org/copyleft/lesser.txt
21 
22 -----------------------------------------------------------------------------
23 */
24 
25 #include "sOpenvr.h"
26 
27 //TODO get player area vr::HmdQuad_t TempPlayArea; vr::VRChaperone()->GetPlayAreaRect(&TempPlayArea); // https://bitbucket.org/mkultra333/openvrtest
28 
29 extern int Openvr_QUIT_CB;
30 extern int Openvr_IPD_CB;
31 
32 //generic tickcount function
33 int64 getTickCount(void)
34 {
35 #if defined WIN32 || defined _WIN32 || defined WINCE
36  LARGE_INTEGER counter;
37  QueryPerformanceCounter(&counter);
38  return (int64)counter.QuadPart;
39 #elif defined __linux || defined __linux__
40  struct timespec tp;
41  clock_gettime(CLOCK_MONOTONIC, &tp);
42  return (int64)tp.tv_sec * 1000000000 + tp.tv_nsec;
43 #elif defined __MACH__ && defined __APPLE__
44  return (int64)mach_absolute_time();
45 #else
46  struct timeval tv;
47  struct timezone tz;
48  gettimeofday(&tv, &tz);
49  return (int64)tv.tv_sec * 1000000 + tv.tv_usec;
50 #endif
51 }
52 
53 sOpenvr::sOpenvr(const char* inpuPath)
54 {
55  mConnected = false;
56  mHMDSystem = NULL;
57  mVisible = false;
58  mCamera = NULL;
59  mCameraWidth = 0;
60  mCameraHeight = 0;
61  mCameraFrameBufferSize = 0;
62  mCameraFrameBuffer = NULL;
63  mCameraLastFrameId = 0;
64  mCameraEnable = false;
65 
66 #if USE_VR_INPUT
67  mInputPath = inpuPath;
68  mActionSet = vr::k_ulInvalidActionSetHandle;
69 #endif
70 
71  mTrackedCameraHandle = INVALID_TRACKED_CAMERA_HANDLE;
72 
73  mTexturesBounds[0].uMin = 0;
74  mTexturesBounds[0].uMax = 1;
75  mTexturesBounds[0].vMin = 1;
76  mTexturesBounds[0].vMax = 0;
77 
78  mTexturesBounds[1].uMin = 0;
79  mTexturesBounds[1].uMax = 1;
80  mTexturesBounds[1].vMin = 1;
81  mTexturesBounds[1].vMax = 0;
82 
83  for (unsigned int i = 0; i < MAX_VR_CONTROLLERS; i++)
84  mControllers[i] = 0;
85 
86 #ifdef USE_VIVE_GESTURE
87  mGestureInterface = true;
88  UseExternalTransform(false);
89  mLastGestureFrameIndex = -1;
90 #endif
91 }
92 
94 {
95  Disconnect();
96 }
97 
98 bool sOpenvr::IsConnected()
99 {
100  return mConnected;
101 }
102 
103 bool sOpenvr::Connect()
104 {
105  if (mConnected)
106  return false;
107 
108 #ifdef USE_VIVE_GESTURE
109 
110  // Add your code here to modify option by changing backend or mode
111  mGestureOption.mode = GestureModeSkeleton;
112 
113  // Start detection and check result
114  GestureFailure result = StartGestureDetection(&mGestureOption);
115  if (result != GestureFailureNone)
116  mGestureInterface = false;
117  else
118  mGestureInterface = true;
119 #endif
120 
121  mHMDSystem = VR_Init(&mHMDError, vr::EVRApplicationType::VRApplication_Scene);
122  if (mHMDError != vr::VRInitError_None) //Check for errors
123  {
124  switch (mHMDError)
125  {
126  default:
127  MMechostr(MSKRUNTIME, "OpenVR Error: failed OpenVR VR_Init, Non described error when initializing the OpenVR Render object.\n");
128  break;
129 
130  case vr::VRInitError_Init_HmdNotFound:
131  case vr::VRInitError_Init_HmdNotFoundPresenceFailed:
132  MMechostr(MSKRUNTIME, "OpenVR Error: cannot find HMD, Please install SteamVR and launch it, and verify HMD USB and HDMI connection\n");
133  break;
134  }
135  return false;
136  }
137 
138  if (!mHMDSystem)
139  {
140  MMechostr(MSKRUNTIME, "OpenVR Error: failed to init VRsystem, Non described error when initializing the OpenVR Render object.\n");
141  return false;
142  }
143 
144  //Check if VRCompositor is present
145  if (!vr::VRCompositor())
146  {
147  MMechostr(MSKRUNTIME, "OpenVR Error: failed to init OpenVR VRCompositor\n");
148  return false;
149  }
150 
151  //Get Driver and Display information
152  std::string sdevice;
153  int bufflen = mHMDSystem->GetStringTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String, 0, 0, 0);
154  if (bufflen != 0)
155  {
156  char* buff = new char[bufflen];
157  mHMDSystem->GetStringTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String, buff, bufflen, 0);
158  sdevice = buff;
159  delete[] buff;
160  }
161 
162  MMechostr(MSKRUNTIME, "OpenVR HMD name: %s\n", sdevice.c_str());
163 
164  std::string sserial;
165  bufflen = mHMDSystem->GetStringTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String, 0, 0, 0);
166  if (bufflen != 0)
167  {
168  char* buff = new char[bufflen];
169  mHMDSystem->GetStringTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String, buff, bufflen, 0);
170  sserial = buff;
171  delete[] buff;
172  }
173 
174  MMechostr(MSKRUNTIME, "OpenVR HMD serial: %s\n", sserial.c_str());
175 
176  // init controllers
177  //mControllers[VrControllerSide::Left] = new sOpenvrController(mHMDSystem, VrControllerSide::Left);
178  //mControllers[VrControllerSide::Right] = new sOpenvrController(mHMDSystem, VrControllerSide::Right);
179  for (unsigned int i = 0; i < MAX_VR_CONTROLLERS; i++)
180  {
181  mControllers[i] = new sOpenvrController(mHMDSystem, i);
182  }
183 
184  //check camera
185  mCamera = vr::VRTrackedCamera();
186  if (!mCamera)
187  {
188  MMechostr(MSKRUNTIME, "OpenVR No camera found\n");
189  }
190 
191  bool bHasCamera = false;
192  vr::EVRTrackedCameraError nCameraError = mCamera->HasCamera(vr::k_unTrackedDeviceIndex_Hmd, &bHasCamera);
193  if (nCameraError != vr::VRTrackedCameraError_None || !bHasCamera)
194  {
195  MMechostr(MSKRUNTIME, "OpenVR No tracked camera available: %s\n", mCamera->GetCameraErrorNameFromEnum(nCameraError));
196  mCamera = NULL;
197  }
198 
199 #if USE_VR_INPUT
200  //TODO check file exist or create it / them + check errors
201  vr::VRInput()->SetActionManifestPath(mInputPath.c_str());
202  vr::VRInput()->GetActionSetHandle("/actions/scol", &mActionSet);
203 #endif
204 
205  mConnected = true;
206  return true;
207 }
208 
209 std::string sOpenvr::GetHmdName()
210 {
211  if (!mConnected)
212  return "";
213 
214  std::string sdevice;
215  int bufflen = mHMDSystem->GetStringTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String, 0, 0, 0);
216  if (bufflen != 0)
217  {
218  char* buff = new char[bufflen];
219  mHMDSystem->GetStringTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String, buff, bufflen, 0);
220  sdevice = buff;
221  delete[] buff;
222  }
223  return sdevice;
224 }
225 
226 void sOpenvr::Disconnect()
227 {
228  // Free controllers
229  for (unsigned int i = 0; i < MAX_VR_CONTROLLERS; i++)
230  SAFE_DELETE(mControllers[i]);
231 
232  if (mCamera)
233  {
234  mCamera->ReleaseVideoStreamingService(mTrackedCameraHandle);
235  mCamera = NULL;
236  mCameraEnable = false;
237  }
238 
239  if (mCameraFrameBuffer)
240  {
241  delete[] mCameraFrameBuffer;
242  mCameraFrameBuffer = NULL;
243  }
244 
245  if (mConnected)
246  {
247  //Shutdown SteamVR
248  if (mHMDSystem)
249  vr::VR_Shutdown();
250 
251  mHMDSystem = NULL;
252  mConnected = false;
253  }
254 
255 #ifdef USE_VIVE_GESTURE
256  if (mGestureInterface)
257  StopGestureDetection();
258 #endif
259 }
260 
261 void sOpenvr::ResetHmd()
262 {
263  if (mHMDSystem)
264  mHMDSystem->ResetSeatedZeroPose();
265 }
266 
267 bool sOpenvr::IsVisible()
268 {
269  return mVisible;
270 }
271 
272 inline Matrix4 sOpenvr::getMatrix4FromSteamVRMatrix34(const vr::HmdMatrix34_t& mat)
273 {
274  return Matrix4
275  {
276  mat.m[0][0], mat.m[0][1], mat.m[0][2], mat.m[0][3],
277  mat.m[1][0], mat.m[1][1], mat.m[1][2], mat.m[1][3],
278  mat.m[2][0], mat.m[2][1], mat.m[2][2], mat.m[2][3],
279  0.0f, 0.0f, 0.0f, 1.0f
280  };
281 }
282 
283 bool sOpenvr::GetHmdOrientation(Quaternion &quat)
284 {
285  if (!mConnected)
286  return false;
287 
288  vr::TrackedDevicePose_t hmdPose;
289  if ((hmdPose = mTrackedPoses[vr::k_unTrackedDeviceIndex_Hmd]).bPoseIsValid)
290  {
291  const vr::HmdMatrix34_t mat = hmdPose.mDeviceToAbsoluteTracking;
292  Matrix4 cmat(mat.m[0][0], mat.m[0][1], mat.m[0][2], mat.m[0][3],
293  mat.m[1][0], mat.m[1][1], mat.m[1][2], mat.m[1][3],
294  mat.m[2][0], mat.m[2][1], mat.m[2][2], mat.m[2][3],
295  0.0f, 0.0f, 0.0f, 1.0f);
296 
297  quat = cmat.extractQuaternion();
298  mPreviousHmdQuat = quat;
299  }
300  else
301  {
302  quat = mPreviousHmdQuat;
303  //return false;
304  }
305  return true;
306 }
307 
308 bool sOpenvr::GetHmdPosition(Vector3 &vec)
309 {
310  if (!mConnected)// || !(mTrackingState.StatusFlags & ovrStatus_PositionTracked))
311  return false;
312 
313  vr::TrackedDevicePose_t hmdPose;
314  if ((hmdPose = mTrackedPoses[vr::k_unTrackedDeviceIndex_Hmd]).bPoseIsValid)
315  {
316  const vr::HmdMatrix34_t mat = hmdPose.mDeviceToAbsoluteTracking;
317  Matrix4 cmat(mat.m[0][0], mat.m[0][1], mat.m[0][2], mat.m[0][3],
318  mat.m[1][0], mat.m[1][1], mat.m[1][2], mat.m[1][3],
319  mat.m[2][0], mat.m[2][1], mat.m[2][2], mat.m[2][3],
320  0.0f, 0.0f, 0.0f, 1.0f);
321 
322  vec = cmat.getTrans();
323  mPreviousHmdPos = vec;
324  }
325  else
326  {
327  vec = mPreviousHmdPos;
328  //return false;
329  }
330  return true;
331 }
332 
333 bool sOpenvr::GetProjectionMatrix(vr::EVREye eye, float nearclip, float farclip, Matrix4 &mat)
334 {
335  if (!mHMDSystem)
336  return false;
337 
338  vr::HmdMatrix44_t vrmat = mHMDSystem->GetProjectionMatrix(eye, nearclip, farclip);
339  for (unsigned int x : { 0, 1, 2, 3 })
340  for (unsigned int y : { 0, 1, 2, 3 })
341  mat[x][y] = vrmat.m[x][y];
342 
343  return true;
344 }
345 
346 bool sOpenvr::GetStereoTextureSize(unsigned int &w, unsigned int &h)
347 {
348  if (!mHMDSystem)
349  return false;
350 
351  mHMDSystem->GetRecommendedRenderTargetSize(&w, &h);
352 
353  // scale a bit for better quality
354  w = (unsigned int)((float)w * 1.25f);
355  h = (unsigned int)((float)h * 1.25f);
356  /*
357  if (UseSSAA)
358  {
359  if (AALevel / 2 > 0)
360  {
361  w *= AALevel / 2;
362  h *= AALevel / 2;
363  }
364  }*/
365 
366  return true;
367 }
368 
369 float sOpenvr::GetStereoConfigAspect()
370 {
371  return 0.0f;
372 }
373 
374 float sOpenvr::GetStereoConfigFovY()
375 {
376  return 1.919862f;
377 }
378 
379 float sOpenvr::GetStereoIPD()
380 {
381  if (mHMDSystem)
382  {
383  return mHMDSystem->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_UserIpdMeters_Float);
384  }
385  else
386  return 0.064f;
387 }
388 
389 bool sOpenvr::Update()
390 {
391  if (mHMDSystem)
392  {
393  vr::VRCompositor()->WaitGetPoses(mTrackedPoses, vr::k_unMaxTrackedDeviceCount, 0, 0);
394 
395  //Here the controllers are handled
396  ProcessEvents();
397 
398  //mHMDSystem can be closed in ProcessEvents
399  if (mHMDSystem)
400  ProcessTrackedDevices();
401 
402  return true;
403  }
404 
405  return false;
406 }
407 
408 void sOpenvr::UpdateTextures(void* leftTexture, void* rightTexture, vr::ETextureType type)
409 {
410  if (mHMDSystem)
411  {
412  mTextures[0] = { leftTexture, type, vr::ColorSpace_Gamma };
413  mTextures[1] = { rightTexture, type, vr::ColorSpace_Gamma };
414 
415  if (type == vr::TextureType_DirectX)
416  {
417  mTexturesBounds[0].uMin = 0;
418  mTexturesBounds[0].uMax = 1;
419  mTexturesBounds[0].vMin = 0;
420  mTexturesBounds[0].vMax = 1;
421 
422  mTexturesBounds[1].uMin = 0;
423  mTexturesBounds[1].uMax = 1;
424  mTexturesBounds[1].vMin = 0;
425  mTexturesBounds[1].vMax = 1;
426  }
427  else
428  {
429  mTexturesBounds[0].uMin = 0;
430  mTexturesBounds[0].uMax = 1;
431  mTexturesBounds[0].vMin = 1;
432  mTexturesBounds[0].vMax = 0;
433 
434  mTexturesBounds[1].uMin = 0;
435  mTexturesBounds[1].uMax = 1;
436  mTexturesBounds[1].vMin = 1;
437  mTexturesBounds[1].vMax = 0;
438  }
439  vr::VRCompositor()->Submit(vr::Eye_Left, &mTextures[0], &mTexturesBounds[0]);
440  vr::VRCompositor()->Submit(vr::Eye_Right, &mTextures[1], &mTexturesBounds[1]);
441  }
442 }
443 
444 void sOpenvr::ProcessEvents()
445 {
446  vr::VREvent_t event;
447  //Pump the events, and for each event, switch on it type
448  while (mHMDSystem && mHMDSystem->PollNextEvent(&event, sizeof event)) switch (event.eventType)
449  {
450  //Handle quiting the app from Steam
451  case vr::VREvent_DriverRequestedQuit:
452  case vr::VREvent_Quit:
453  vr::VRSystem()->AcknowledgeQuit_Exiting();
454  Disconnect();
455  OBJpostEvent(Openvr_QUIT_CB, SCOL_PTR this, 0);
456  break;
457 
458  //Handle user IPD adjustment
459  case vr::VREvent_IpdChanged:
460  OBJpostEvent(Openvr_IPD_CB, SCOL_PTR this, 0);
461  break;
462  default: break;
463  }
464 }
465 
466 void sOpenvr::ProcessTrackedDevices()
467 {
468  if (mTrackedPoses[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid)
469  mVisible = true;
470  else
471  mVisible = false;
472 
473 #if USE_VR_INPUT
474  vr::VRActiveActionSet_t actionSet = { 0 };
475  actionSet.ulActionSet = mActionSet;
476  vr::VRInput()->UpdateActionState(&actionSet, sizeof(actionSet), 1);
477 #endif
478 
479  unsigned int id = 0;
480  for (unsigned int trackedDevice = vr::k_unTrackedDeviceIndex_Hmd + 1; trackedDevice < vr::k_unMaxTrackedDeviceCount; trackedDevice++)
481  {
482  //If the device is not connected, pass.
483  //If the device is not recognized as a controller, pass
484  //If we don't have a valid pose of the controller, pass
485  if (!mHMDSystem || (mHMDSystem->GetTrackedDeviceClass(trackedDevice) != vr::TrackedDeviceClass_Controller && mHMDSystem->GetTrackedDeviceClass(trackedDevice) != vr::TrackedDeviceClass_GenericTracker))
486  continue;
487 
488  //From here we know that "trackedDevice" is the device index of a valid controller that has been tracked by the system
489  //Extract basic information of the device, detect if they are left/right hands
490  VrControllerSide side = VrControllerSide::Undefined;
491  switch (mHMDSystem->GetControllerRoleForTrackedDeviceIndex(trackedDevice))
492  {
493  case vr::ETrackedControllerRole::TrackedControllerRole_LeftHand:
494  side = VrControllerSide::Left;
495  break;
496 
497  case vr::ETrackedControllerRole::TrackedControllerRole_RightHand:
498  side = VrControllerSide::Right;
499  break;
500 
501  case vr::ETrackedControllerRole::TrackedControllerRole_Invalid:
502  default:
503  break;
504  }
505 
506  if (side != VrControllerSide::Undefined)
507  mControllers[side]->Update(mTrackedPoses, trackedDevice);
508  else if (((id + 2) < MAX_VR_CONTROLLERS) && (mControllers[id + 2] != 0))
509  {
510  mControllers[id + 2]->Update(mTrackedPoses, trackedDevice);
511  id++;
512  }
513  }
514 
515 #ifdef USE_VIVE_GESTURE
516  if (mGestureInterface)
517  {
518  const GestureResult* points = NULL;
519 
520  int frameIndex = -1;
521  int size = GetGestureResult(&points, &frameIndex);
522 
523  if ((frameIndex >= 0) && (frameIndex != mLastGestureFrameIndex))
524  {
525  if (size <= 0)
526  {
527  mControllers[8]->SetState(false);
528  mControllers[9]->SetState(false);
529  return;
530  }
531 
532  mLastGestureFrameIndex = frameIndex;
533  for (int i = 0; i < size; i++)
534  {
535  unsigned int id = (points[i].isLeft) ? 8 : 9;
536  mControllers[id]->UpdateGesture(points[i], id);
537  }
538  //std::cout << "Hand " << i << " is " << points[i].isLeft ? "left" : "right" << " hand" << std::endl;
539  }
540  }
541 #endif
542 }
543 
545 {
546  return (mCamera) ? true : false;
547 }
548 
549 bool sOpenvr::IsCameraEnable()
550 {
551  return mCameraEnable;
552 }
553 
554 bool sOpenvr::StartCamera()
555 {
556  uint32_t nCameraFrameBufferSize = 0;
557  if (mCamera->GetCameraFrameSize(vr::k_unTrackedDeviceIndex_Hmd, vr::VRTrackedCameraFrameType_Undistorted, &mCameraWidth, &mCameraHeight, &nCameraFrameBufferSize) != vr::VRTrackedCameraError_None)
558  {
559  MMechostr(MSKRUNTIME, "OpenVR Start camera failed\n");
560  return false;
561  }
562 
563  if (nCameraFrameBufferSize && nCameraFrameBufferSize != mCameraFrameBufferSize)
564  {
565  if (mCameraFrameBufferSize)
566  delete[] mCameraFrameBuffer;
567 
568  mCameraFrameBufferSize = nCameraFrameBufferSize;
569  mCameraFrameBuffer = new uint8_t[mCameraFrameBufferSize];
570  memset(mCameraFrameBuffer, 0, mCameraFrameBufferSize);
571  }
572 
573  mCameraLastFrameId = 0;
574 
575  mCamera->AcquireVideoStreamingService(vr::k_unTrackedDeviceIndex_Hmd, &mTrackedCameraHandle);
576  if (mTrackedCameraHandle == INVALID_TRACKED_CAMERA_HANDLE)
577  {
578  MMechostr(MSKRUNTIME, "OpenVR Acquire camera failed\n");
579  return false;
580  }
581 
582  mCameraEnable = true;
583  return true;
584 }
585 
586 void sOpenvr::StopCamera()
587 {
588  if (mCamera)
589  mCamera->ReleaseVideoStreamingService(mTrackedCameraHandle);
590  mTrackedCameraHandle = INVALID_TRACKED_CAMERA_HANDLE;
591  mCameraEnable = false;
592 }
593 
594 void sOpenvr::GetCameraSize(uint32_t &w, uint32_t &h)
595 {
596  w = mCameraWidth;
597  h = mCameraHeight;
598 }
599 
600 bool sOpenvr::GetCameraFrame(PtrObjBitmap scolBitmap)
601 {
602  if (!mCameraEnable)
603  return false;
604 
605  // get the frame header only
606  vr::CameraVideoStreamFrameHeader_t frameHeader;
607  vr::EVRTrackedCameraError nCameraError = mCamera->GetVideoStreamFrameBuffer(mTrackedCameraHandle, vr::VRTrackedCameraFrameType_Undistorted, nullptr, 0, &frameHeader, sizeof(frameHeader));
608  if (nCameraError != vr::VRTrackedCameraError_None)
609  return false;
610 
611  if (frameHeader.nFrameSequence == mCameraLastFrameId)
612  {
613  // frame hasn't changed yet, nothing to do
614  return false;
615  }
616 
617  // Frame has changed, do the more expensive frame buffer copy
618  nCameraError = mCamera->GetVideoStreamFrameBuffer(mTrackedCameraHandle, vr::VRTrackedCameraFrameType_Undistorted, mCameraFrameBuffer, mCameraFrameBufferSize, &frameHeader, sizeof(frameHeader));
619  if (nCameraError != vr::VRTrackedCameraError_None)
620  return false;
621 
622  mCameraLastFrameId = frameHeader.nFrameSequence;
623 
624  if (scolBitmap == 0)
625  return false;
626 
627  if (scolBitmap->TailleW != mCameraWidth || scolBitmap->TailleH != mCameraHeight)
628  return false;
629 
630  //Scol bitmap are 32bits aligned
631  int sbpl = mCameraWidth * 4;
632  int dbpl = scolBitmap->BPL;
633 
634  if (sbpl == dbpl)
635  memcpy(scolBitmap->bits, mCameraFrameBuffer, scolBitmap->TailleW * scolBitmap->TailleH * scolBitmap->BytesPP);
636  else
637  {
638  int numthreads = (scolBitmap->TailleH <= 8) ? 1 : boost::thread::hardware_concurrency();
639  int rows = scolBitmap->TailleH / numthreads;
640  int extra = scolBitmap->TailleH % numthreads;
641  int start = 0;
642  int end = rows;
643 
644  ConversionTools::SConvertBuffer conv(mCameraFrameBuffer, 0, scolBitmap->bits, scolBitmap->TailleW, scolBitmap->TailleH, sbpl, 1, dbpl, scolBitmap->BytesPP);
645 
646  boost::thread_group thgroup;
647  for (int t = 1; t <= numthreads; t++)
648  {
649  if (t == numthreads) // last thread does extra rows:
650  end += extra;
651 
652  thgroup.create_thread(boost::bind(ConversionTools::BuffToBitmap, start, end, conv));
653 
654  start = end;
655  end = start + rows;
656  }
657 
658  thgroup.join_all();
659  }
660 
661  return true;
662 }
663 
664 sOpenvrController* sOpenvr::GetController(unsigned int id)
665 {
666  if (id >= MAX_VR_CONTROLLERS)
667  return 0;
668 
669  return mControllers[id];
670 }
671 
672 sOpenvrController::sOpenvrController(vr::IVRSystem* hmdSystem, unsigned int id)
673 {
674  mHmdSystem = hmdSystem;
675  mDeviceId = 0;
676  mVisible = false;
677  mSide = (id > 1) ? VrControllerSide::Undefined : (VrControllerSide)id;
678  mType = (id > 7) ? HANDS_CONTROLLER : (id > 1) ? TRACKER_CONTROLLER : CLASSIC_CONTROLLER;
679  mLastRumble = 0;
680  mMatrix = Matrix4::IDENTITY;
681  mAxisValues = Vector3::ZERO;
682  mVelocity = Vector3::ZERO;
683  mAngularVelocity = Vector3::ZERO;
684 
685 #if USE_VR_INPUT
686  mSource = vr::k_ulInvalidInputValueHandle;
687  mActionPose = vr::k_ulInvalidActionHandle;
688  mActionHaptic = vr::k_ulInvalidActionHandle;
689  mPadAxis = vr::k_ulInvalidActionHandle;
690  mTriggerAxis = vr::k_ulInvalidActionHandle;
691 
692  std::string sSide = "left";
693  if (id == 1)
694  sSide = "right";
695  else if (id > 1)
696  sSide = "tracker" + std::to_string(id - 1);
697 
698  vr::VRInput()->GetInputSourceHandle((std::string("/user/hand/") + sSide).c_str(), &mSource);
699  vr::VRInput()->GetActionHandle((std::string("/actions/scol/out/") + sSide + "_haptic").c_str(), &mActionHaptic);
700  vr::VRInput()->GetActionHandle((std::string("/actions/scol/in/") + sSide + "_pose").c_str(), &mActionPose);
701 
702  vr::VRInput()->GetActionHandle((std::string("/actions/scol/in/") + sSide + "_axis0_value").c_str(), &mPadAxis);
703  vr::VRInput()->GetActionHandle((std::string("/actions/scol/in/") + sSide + "_axis1_value").c_str(), &mTriggerAxis);
704 
705  vr::VRActionHandle_t act = vr::k_ulInvalidActionHandle;
706  vr::VRInput()->GetActionHandle((std::string("/actions/scol/in/") + sSide + "_applicationmenu_press").c_str(), &act);
707  mActionsToHandle.push_back(act);
708 
709  act = vr::k_ulInvalidActionHandle;
710  vr::VRInput()->GetActionHandle((std::string("/actions/scol/in/") + sSide + "_grip_press").c_str(), &act);
711  mActionsToHandle.push_back(act);
712 
713  act = vr::k_ulInvalidActionHandle;
714  vr::VRInput()->GetActionHandle((std::string("/actions/scol/in/") + sSide + "_system_press").c_str(), &act);
715  mActionsToHandle.push_back(act);
716 
717  act = vr::k_ulInvalidActionHandle;
718  vr::VRInput()->GetActionHandle((std::string("/actions/scol/in/") + sSide + "_axis0_press").c_str(), &act);
719  mActionsToHandle.push_back(act);
720 
721  act = vr::k_ulInvalidActionHandle;
722  vr::VRInput()->GetActionHandle((std::string("/actions/scol/in/") + sSide + "_axis1_press").c_str(), &act);
723  mActionsToHandle.push_back(act);
724 #endif
725 
726  mButtonsToHandle.push_back(vr::k_EButton_ApplicationMenu);
727  mButtonsToHandle.push_back(vr::k_EButton_Grip);
728  mButtonsToHandle.push_back(vr::k_EButton_A);
729  mButtonsToHandle.push_back(vr::k_EButton_Axis0);
730  mButtonsToHandle.push_back(vr::k_EButton_Axis1);
731 
732  mButtonsStates.resize(mButtonsToHandle.size(), false);
733 }
734 
736 {
737 }
738 
739 void sOpenvrController::Update(vr::TrackedDevicePose_t* trackedPoses, unsigned int deviceId)
740 {
741  mDeviceId = deviceId;
742 
743  if (!trackedPoses[mDeviceId].bDeviceIsConnected || !trackedPoses[mDeviceId].bPoseIsValid)
744  {
745  mVisible = false;
746  return;
747  }
748  else
749  {
750  mVisible = true;
751  }
752 
753  //Extract tracking information from the device
754  mMatrix = sOpenvr::getMatrix4FromSteamVRMatrix34(trackedPoses[mDeviceId].mDeviceToAbsoluteTracking);
755 
756 #if USE_VR_INPUT
757  vr::InputDigitalActionData_t actionData;
758  for (uint8_t i = 0; i < mButtonsToHandle.size(); i++)
759  {
760  vr::VRInput()->GetDigitalActionData(mActionsToHandle[i], &actionData, sizeof(actionData), vr::k_ulInvalidInputValueHandle);
761  mButtonsStates[i] = (actionData.bActive && actionData.bState) ? true : false;
762  }
763 #else
764  //This will fill the buttons array
765  //Get the state of the controller. The state contains the buttons and triggers data at the last sample
766  mHmdSystem->GetControllerState(mDeviceId, &mControllerState, sizeof mControllerState);
767 
768  for (uint8_t i = 0; i < mButtonsToHandle.size(); i++)
769  {
770  mButtonsStates[i] = ((mControllerState.ulButtonPressed & vr::ButtonMaskFromId(mButtonsToHandle[i])) != 0) ? true : false;
771  }
772 #endif
773 
774 #if USE_VR_INPUT
775  vr::InputAnalogActionData_t analogData;
776  if (vr::VRInput()->GetAnalogActionData(mPadAxis, &analogData, sizeof(analogData), vr::k_ulInvalidInputValueHandle) == vr::VRInputError_None && analogData.bActive)
777  {
778  mAxisValues.x = analogData.x;
779  mAxisValues.y = analogData.y;
780  }
781 
782  if (vr::VRInput()->GetAnalogActionData(mTriggerAxis, &analogData, sizeof(analogData), vr::k_ulInvalidInputValueHandle) == vr::VRInputError_None && analogData.bActive)
783  {
784  mAxisValues.z = analogData.x;
785  }
786 #else
787  //Extract axis values
788  mAxisValues.x = mControllerState.rAxis[vr::k_EButton_Axis0 - vr::k_EButton_Axis0].x;
789  mAxisValues.y = mControllerState.rAxis[vr::k_EButton_Axis0 - vr::k_EButton_Axis0].y;
790  mAxisValues.z = mControllerState.rAxis[vr::k_EButton_Axis1 - vr::k_EButton_Axis0].x;
791 #endif
792 
793  float* vel = trackedPoses[mDeviceId].vVelocity.v;
794  mVelocity = Vector3(vel[0], vel[1], vel[2]);
795 
796  vel = trackedPoses[mDeviceId].vAngularVelocity.v;
797  mAngularVelocity = Vector3(vel[0], vel[1], vel[2]);
798 }
799 
800 #ifdef USE_VIVE_GESTURE
801 GestureType sOpenvrController::GetLastGesture()
802 {
803  return mLastGesture;
804 }
805 
806 void sOpenvrController::UpdateGesture(GestureResult result, unsigned int deviceId)
807 {
808  mDeviceId = deviceId;
809  mVisible = true;
810 
811  mLastGesture = result.gesture;
812 
813  //Extract tracking information from the device
814  mMatrix = Matrix4();
815  mMatrix[0][3] = result.points[0];
816  mMatrix[1][3] = result.points[1];
817  mMatrix[2][3] = result.points[2];
818 }
819 #endif // USE_VIVE_GESTURE
820 
821 bool sOpenvrController::IsVisible()
822 {
823  return mVisible;
824 }
825 
826 void sOpenvrController::SetState(bool state)
827 {
828  mVisible = false;
829 }
830 
831 void sOpenvrController::SetSide(VrControllerSide side)
832 {
833  mSide = side;
834 }
835 
836 VrControllerSide sOpenvrController::GetSide()
837 {
838  return mSide;
839 }
840 
841 void sOpenvrController::SetType(ControllerType type)
842 {
843  mType = type;
844 }
845 
846 sOpenvrController::ControllerType sOpenvrController::GetType()
847 {
848  return mType;
849 }
850 
851 Vector3 sOpenvrController::GetPosition()
852 {
853  return mMatrix.getTrans();
854 }
855 
856 Vector3 sOpenvrController::GetVelocity()
857 {
858  return mVelocity;
859 }
860 
861 Vector3 sOpenvrController::GetAngularVelocity()
862 {
863  return mAngularVelocity;
864 }
865 
866 Quaternion sOpenvrController::GetOrientation()
867 {
868  return mMatrix.extractQuaternion();
869 }
870 
871 void sOpenvrController::Rumble(float value)
872 {
873  int64 current = getTickCount();
874 
875  //Limit frequency to 1/50 hz
876  if (current - mLastRumble > 50)
877  {
878  mLastRumble = current;
879  //Max value of one pulse will be 3500µs
880  mHmdSystem->TriggerHapticPulse(mDeviceId, 0, static_cast<unsigned short>(value * 3500));
881  }
882 }
883 
884 std::vector<bool> sOpenvrController::GetButtonsState()
885 {
886  return mButtonsStates;
887 }
888 
889 Vector3 sOpenvrController::GetAxisValues()
890 {
891  return mAxisValues;
892 }
893 
894 
897 void ConversionTools::BuffToBitmap(const int start, const int end, const SConvertBuffer &conv)
898 {
899  unsigned int srcByte;
900  unsigned int destByte;
901  int x, y;
902 
903  for (y = start; y < end; y++)
904  {
905  for (x = 0; x < conv.width; x++)
906  {
907  srcByte = (x * 4) + (conv.sbpl * y);
908  destByte = (x * conv.bpp) + (conv.dbpl * y);
909 
910  ((uint8_t*)conv.dstBuff)[destByte] = conv.srcBuff[srcByte + 2];
911  ((uint8_t*)conv.dstBuff)[destByte + 1] = conv.srcBuff[srcByte + 1];
912  ((uint8_t*)conv.dstBuff)[destByte + 2] = conv.srcBuff[srcByte];
913  }
914  }
915 }
sOpenvrController(vr::IVRSystem *hmdSystem, unsigned int id)
Definition: sOpenvr.cpp:672
static void BuffToBitmap(const int start, const int end, const SConvertBuffer &conv)
Definition: sOpenvr.cpp:897
sOpenvr(const char *inpuPath)
Definition: sOpenvr.cpp:53
bool HaveCamera()
Definition: sOpenvr.cpp:544
~sOpenvr()
Definition: sOpenvr.cpp:93