7 #include "PlusConfigure.h" 10 #include "vtkMatrix4x4.h" 11 #include "vtkObjectFactory.h" 13 #include "vtkTransform.h" 14 #include "vtkXMLDataElement.h" 15 #include "vtkXMLUtilities.h" 16 #include "vtksys/SystemTools.hxx" 21 #if ( _MSC_VER >= 1300 ) // Visual studio .NET 22 #pragma warning ( disable : 4311 ) 23 #pragma warning ( disable : 4312 ) 24 # define vtkGetWindowLong GetWindowLongPtr 25 # define vtkSetWindowLong SetWindowLongPtr 26 # define vtkGWL_USERDATA GWLP_USERDATA 27 # define GWL_USERDATA_TYPE LONG_PTR 28 #else // regular Visual studio 29 # define vtkGetWindowLong GetWindowLong 30 # define vtkSetWindowLong SetWindowLong 31 # define vtkGWL_USERDATA GWL_USERDATA 32 # define GWL_USERDATA_TYPE LONG; 40 : Mutex(vtkSmartPointer<vtkIGSIORecursiveCriticalSection>::New())
41 , SpaceNavigatorTool(NULL)
42 , LatestMouseTransform(vtkMatrix4x4::New())
43 , DeviceToTrackerTransform(vtkMatrix4x4::New())
44 , OperatingMode(JOYSTICK_MODE)
45 , CaptureWindowClassName(
"")
46 , CaptureWindowHandle(0)
47 , RegisteredRawInputDevices(NULL)
48 , NumberOfRegisteredRawInputDevices(0)
52 this->TranslationScales[0] = 0.001;
53 this->TranslationScales[1] = 0.001;
54 this->TranslationScales[2] = 0.001;
55 this->RotationScales[0] = 0.001;
56 this->RotationScales[1] = 0.001;
57 this->RotationScales[2] = 0.001;
74 if (this->DeviceToTrackerTransform != NULL)
76 this->DeviceToTrackerTransform->Delete();
77 this->DeviceToTrackerTransform = NULL;
79 if (this->LatestMouseTransform != NULL)
81 this->LatestMouseTransform->Delete();
82 this->LatestMouseTransform = NULL;
91 if (GetRawInputDeviceList(NULL, &nDevices,
sizeof(RAWINPUTDEVICELIST)) != 0)
93 LOG_ERROR(
"No RawInput devices attached");
96 PRAWINPUTDEVICELIST pRawInputDeviceList = NULL;
97 if ((pRawInputDeviceList = (PRAWINPUTDEVICELIST)malloc(
sizeof(RAWINPUTDEVICELIST) * nDevices)) == NULL)
99 LOG_ERROR(
"Error allocating memory for device list");
104 if (GetRawInputDeviceList(pRawInputDeviceList, &nDevices,
sizeof(RAWINPUTDEVICELIST)) == -1)
106 LOG_ERROR(
"Error getting raw input device list");
107 free(pRawInputDeviceList);
111 this->RegisteredRawInputDevices = (PRAWINPUTDEVICE)malloc(nDevices *
sizeof(RAWINPUTDEVICE));
112 this->NumberOfRegisteredRawInputDevices = 0;
115 for (UINT
i = 0;
i < nDevices;
i++)
117 if (pRawInputDeviceList[
i].dwType == RIM_TYPEHID)
121 if (GetRawInputDeviceInfo(pRawInputDeviceList[
i].hDevice, RIDI_DEVICENAME,
deviceName, &nchars) >= 0)
123 LOG_DEBUG(
"Device[" <<
i <<
"]: handle=" << pRawInputDeviceList[
i].hDevice <<
" name = " <<
deviceName);
126 RID_DEVICE_INFO dinfo;
127 UINT sizeofdinfo =
sizeof(dinfo);
128 dinfo.cbSize = sizeofdinfo;
129 if (GetRawInputDeviceInfo(pRawInputDeviceList[
i].hDevice, RIDI_DEVICEINFO, &dinfo, &sizeofdinfo) < 0)
133 if (dinfo.dwType != RIM_TYPEHID)
138 RID_DEVICE_INFO_HID* phidInfo = &dinfo.hid;
139 LOG_DEBUG(
"VID = " << phidInfo->dwVendorId);
140 LOG_DEBUG(
"PID = " << phidInfo->dwProductId);
141 LOG_DEBUG(
"Version = " << phidInfo->dwVersionNumber);
142 LOG_DEBUG(
"UsagePage = " << phidInfo->usUsagePage);
143 LOG_DEBUG(
"Usage = " << phidInfo->usUsage);
150 if (phidInfo->usUsagePage == 1 && phidInfo->usUsage == 8)
152 this->RegisteredRawInputDevices[this->NumberOfRegisteredRawInputDevices].usUsagePage = phidInfo->usUsagePage;
153 this->RegisteredRawInputDevices[this->NumberOfRegisteredRawInputDevices].usUsage = phidInfo->usUsage;
154 this->RegisteredRawInputDevices[this->NumberOfRegisteredRawInputDevices].dwFlags = RIDEV_INPUTSINK;
155 this->RegisteredRawInputDevices[this->NumberOfRegisteredRawInputDevices].hwndTarget = this->CaptureWindowHandle;
156 this->NumberOfRegisteredRawInputDevices++;
161 free(pRawInputDeviceList);
164 if (RegisterRawInputDevices(this->RegisteredRawInputDevices, this->NumberOfRegisteredRawInputDevices,
sizeof(RAWINPUTDEVICE)) ==
FALSE)
166 LOG_ERROR(
"Error calling RegisterRawInputDevices");
176 if (this->RegisteredRawInputDevices)
178 for (UINT
i = 0;
i < this->NumberOfRegisteredRawInputDevices;
i++)
180 this->RegisteredRawInputDevices[
i].dwFlags = RIDEV_REMOVE;
181 this->RegisteredRawInputDevices[
i].hwndTarget = NULL;
183 if (RegisterRawInputDevices(this->RegisteredRawInputDevices, this->NumberOfRegisteredRawInputDevices,
sizeof(RAWINPUTDEVICE)) ==
FALSE)
185 LOG_ERROR(
"Error unregistering input devices");
187 free(this->RegisteredRawInputDevices);
188 this->RegisteredRawInputDevices = NULL;
189 this->NumberOfRegisteredRawInputDevices = 0;
203 LOG_TRACE(
"WM_DESTROY");
204 self->OnCaptureWindowDestroy();
207 return DefWindowProc(hwnd,
message, wParam, lParam);
213 LOG_TRACE(
"WM_INPUT lParam=" << lParam);
215 RAWINPUTHEADER header;
216 UINT size =
sizeof(header);
217 if (GetRawInputData((HRAWINPUT)lParam, RID_HEADER, &header, &size,
sizeof(RAWINPUTHEADER)) == -1)
219 LOG_ERROR(
"Error from GetRawInputData(RID_HEADER)");
223 LOG_TRACE(
"rawEvent.header: hDevice = " << header.hDevice);
226 size = header.dwSize;
227 LPRAWINPUT
event = (LPRAWINPUT)malloc(size);
228 if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, event, &size,
sizeof(RAWINPUTHEADER)) == -1)
230 LOG_ERROR(
"Error from GetRawInputData(RID_INPUT)");
233 if (event->header.dwType != RIM_TYPEHID)
241 static int all6DOFs[6] = {0};
242 LPRAWHID pRawHid = &
event->data.hid;
245 LOG_TRACE(
"rawInput count: " << pRawHid->dwCount <<
" size: " << pRawHid->dwSizeHid);
246 for (UINT
i = 0;
i < pRawHid->dwSizeHid;
i++)
248 LOG_TRACE(
"value: " << pRawHid->bRawData[
i]);
253 if (pRawHid->bRawData[0] == 1)
256 all6DOFs[0] = (pRawHid->bRawData[1] & 0x000000ff) | ((
signed short)(pRawHid->bRawData[2] << 8) & 0xffffff00);
257 all6DOFs[1] = (pRawHid->bRawData[3] & 0x000000ff) | ((
signed short)(pRawHid->bRawData[4] << 8) & 0xffffff00);
258 all6DOFs[2] = (pRawHid->bRawData[5] & 0x000000ff) | ((
signed short)(pRawHid->bRawData[6] << 8) & 0xffffff00);
259 bGotTranslation =
TRUE;
261 else if (pRawHid->bRawData[0] == 2)
264 all6DOFs[3] = (pRawHid->bRawData[1] & 0x000000ff) | ((
signed short)(pRawHid->bRawData[2] << 8) & 0xffffff00);
265 all6DOFs[4] = (pRawHid->bRawData[3] & 0x000000ff) | ((
signed short)(pRawHid->bRawData[4] << 8) & 0xffffff00);
266 all6DOFs[5] = (pRawHid->bRawData[5] & 0x000000ff) | ((
signed short)(pRawHid->bRawData[6] << 8) & 0xffffff00);
269 else if (pRawHid->bRawData[0] == 3)
272 LOG_TRACE(
"Button status: " << (
unsigned char)pRawHid->bRawData[3] <<
", " << (
unsigned char)pRawHid->bRawData[2] <<
", " << (
unsigned char)pRawHid->bRawData[1]);
275 if (bGotTranslation && bGotRotation)
277 bGotTranslation = bGotRotation =
FALSE;
278 LOG_TRACE(
"all6DOFs: " << all6DOFs[0] <<
"," << all6DOFs[1] <<
"," << all6DOFs[2] <<
"," << all6DOFs[3] <<
"," << all6DOFs[4] <<
"," << all6DOFs[5]);
279 vtkSmartPointer<vtkTransform> currentTransform = vtkSmartPointer<vtkTransform>::New();
280 currentTransform->Identity();
281 currentTransform->Translate(all6DOFs[0]*this->TranslationScales[0], all6DOFs[1]*this->TranslationScales[1], all6DOFs[2]*this->TranslationScales[2]);
282 currentTransform->RotateX(all6DOFs[3]*this->RotationScales[0]);
283 currentTransform->RotateY(all6DOFs[4]*this->RotationScales[1]);
284 currentTransform->RotateZ(all6DOFs[5]*this->RotationScales[2]);
287 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->Mutex);
288 currentTransform->GetMatrix(this->LatestMouseTransform);
298 HINSTANCE hinstance = GetModuleHandle(NULL);
300 const char CAPTURE_WINDOW_CLASS_NAME_PREFIX[] =
"3dConnexionTracker capture window";
302 if (this->CaptureWindowClassName.empty())
304 this->CaptureWindowClassName = CAPTURE_WINDOW_CLASS_NAME_PREFIX;
309 wc.lpszClassName = this->CaptureWindowClassName.c_str();
310 wc.hInstance = hinstance;
312 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
314 wc.lpszMenuName = NULL;
315 wc.hbrBackground = NULL;
316 wc.style = CS_HREDRAW | CS_VREDRAW;
317 wc.cbClsExtra =
sizeof(
void*);
320 bool registrationSuccessful =
false;
321 const int MAX_WINDOW_CLASS_REGISTRATION_ATTEMPTS = 32;
322 for (
int i = 1;
i <= MAX_WINDOW_CLASS_REGISTRATION_ATTEMPTS;
i++)
324 if (RegisterClass(&wc))
326 registrationSuccessful =
true;
330 std::ostringstream windowName;
331 windowName << CAPTURE_WINDOW_CLASS_NAME_PREFIX <<
" " <<
i << std::ends;
332 this->CaptureWindowClassName = windowName.str();
333 wc.lpszClassName = this->CaptureWindowClassName.c_str();
335 if (!registrationSuccessful)
337 LOG_ERROR(
"Initialize: failed to register 3dConnexionTracker capture window class (" << GetLastError() <<
")");
341 this->CaptureWindowHandle = CreateWindow(this->CaptureWindowClassName.c_str(),
"Plus 3dConnexion capture window", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, hinstance, NULL);
342 if (!this->CaptureWindowHandle)
344 LOG_ERROR(
"Initialize: failed to create window (" << GetLastError() <<
")");
358 this->CaptureWindowHandle = NULL;
364 if (this->CaptureWindowHandle)
366 DestroyWindow(this->CaptureWindowHandle);
367 this->CaptureWindowHandle = 0;
370 if (!this->CaptureWindowClassName.empty())
373 UnregisterClass(this->CaptureWindowClassName.c_str(), GetModuleHandle(NULL));
374 this->CaptureWindowClassName.clear();
382 LOG_TRACE(
"vtkPlus3dConnexionTracker::Connect");
386 LOG_ERROR(
"Failed to create capture window");
391 LOG_ERROR(
"Failed to register the 3dConnexion device");
396 this->SpaceNavigatorTool = NULL;
405 LOG_TRACE(
"vtkPlus3dConnexionTracker::Disconnect");
411 this->SpaceNavigatorTool = NULL;
418 LOG_TRACE(
"vtkPlus3dConnexionTracker::Probe");
419 LOG_ERROR(
"vtkPlus3dConnexionTracker::Probe is not implemented");
426 LOG_TRACE(
"vtkPlus3dConnexionTracker::InternalStartRecording");
433 LOG_TRACE(
"vtkPlus3dConnexionTracker::InternalStopRecording");
440 LOG_TRACE(
"vtkPlus3dConnexionTracker::InternalUpdate");
442 const double unfilteredTimestamp = vtkIGSIOAccurateTimer::GetSystemTime();
444 if (this->SpaceNavigatorTool != NULL)
447 igsioLockGuard<vtkIGSIORecursiveCriticalSection> updateMutexGuardedLock(this->Mutex);
448 switch (this->OperatingMode)
451 this->DeviceToTrackerTransform->DeepCopy(this->LatestMouseTransform);
455 vtkSmartPointer<vtkMatrix4x4> cumulatedTransform = vtkSmartPointer<vtkMatrix4x4>::New();
456 vtkMatrix4x4::Multiply4x4(this->LatestMouseTransform, this->DeviceToTrackerTransform, cumulatedTransform);
459 cumulatedTransform->Element[0][3] = this->DeviceToTrackerTransform->Element[0][3] + this->LatestMouseTransform->Element[0][3];
460 cumulatedTransform->Element[1][3] = this->DeviceToTrackerTransform->Element[1][3] + this->LatestMouseTransform->Element[1][3];
461 cumulatedTransform->Element[2][3] = this->DeviceToTrackerTransform->Element[2][3] + this->LatestMouseTransform->Element[2][3];
463 this->DeviceToTrackerTransform->DeepCopy(cumulatedTransform);
467 LOG_ERROR(
"Operating mode is invalid: " << this->OperatingMode);
472 unsigned long frameNumber = this->SpaceNavigatorTool->GetFrameNumber() + 1 ;
473 ToolTimeStampedUpdate(this->SpaceNavigatorTool->GetId(), this->DeviceToTrackerTransform, TOOL_OK, frameNumber, unfilteredTimestamp);
484 if (deviceConfig->GetAttribute(
"Mode"))
486 if (STRCASECMP(deviceConfig->GetAttribute(
"Mode"),
"MOUSE") == 0)
490 else if (STRCASECMP(deviceConfig->GetAttribute(
"Mode"),
"JOYSTICK") == 0)
496 LOG_ERROR(
"Unknown Mode: " << deviceConfig->GetAttribute(
"Mode") <<
". Valid options: MOUSE, JOYSTICK.");
500 double translationScales[3] = {0.001, 0.001, 0.001};
501 int translationScalesComponentRead = deviceConfig->GetVectorAttribute(
"TranslationScales", 3, translationScales);
502 if (translationScalesComponentRead == 1)
504 this->TranslationScales[0] = translationScales[0];
505 this->TranslationScales[1] = translationScales[0];
506 this->TranslationScales[2] = translationScales[0];
508 else if (translationScalesComponentRead == 3)
510 this->TranslationScales[0] = translationScales[0];
511 this->TranslationScales[1] = translationScales[1];
512 this->TranslationScales[2] = translationScales[2];
514 else if (translationScalesComponentRead > 0)
516 LOG_ERROR(
"TranslationScales vector has " << translationScalesComponentRead <<
" components. Valid number of components: 1 or 3");
519 double rotationScales[3] = {0.001, 0.001, 0.001};
520 int rotationScalesComponentRead = deviceConfig->GetVectorAttribute(
"RotationScales", 3, rotationScales);
521 if (rotationScalesComponentRead == 1)
523 this->RotationScales[0] = rotationScales[0];
524 this->RotationScales[1] = rotationScales[0];
525 this->RotationScales[2] = rotationScales[0];
527 else if (rotationScalesComponentRead == 3)
529 this->RotationScales[0] = rotationScales[0];
530 this->RotationScales[1] = rotationScales[1];
531 this->RotationScales[2] = rotationScales[2];
533 else if (rotationScalesComponentRead > 0)
535 LOG_ERROR(
"RotationScales vector has " << rotationScalesComponentRead <<
" components. Valid number of components: 1 or 3");
546 switch (this->OperatingMode)
549 trackerConfig->SetAttribute(
"Mode",
"MOUSE");
552 trackerConfig->SetAttribute(
"Mode",
"JOYSTICK");
555 LOG_ERROR(
"Cannot write unknown operating mode into config file: " << this->OperatingMode);
558 trackerConfig->SetVectorAttribute(
"TranslationScales", 3, this->TranslationScales);
559 trackerConfig->SetVectorAttribute(
"RotationScales", 3, this->RotationScales);
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
virtual PlusStatus ToolTimeStampedUpdate(const std::string &aToolSourceId, vtkMatrix4x4 *matrix, ToolStatus status, unsigned long frameNumber, double unfilteredtimestamp, const igsioFieldMapType *customFields=NULL)
bool RequirePortNameInDeviceSetConfiguration
PlusStatus RegisterDevice()
void ProcessDeviceInputEvent(LPARAM lParam)
PlusStatus InternalConnect()
PlusStatus InternalStopRecording()
virtual PlusStatus Disconnect()
PlusStatus ReadConfiguration(vtkXMLDataElement *config)
void OnCaptureWindowDestroy()
Interface for 3D Connexion 3D mouse devices.
PlusStatus GetToolByPortName(const char *aPortName, vtkPlusDataSource *&aSource)
virtual PlusStatus StopRecording()
#define GWL_USERDATA_TYPE
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
PlusStatus InternalStartRecording()
virtual PlusStatus InternalDisconnect()
bool StartThreadForInternalUpdates
LONG FAR PASCAL vtkPlus3dConnexionTrackerWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
PlusStatus WriteConfiguration(vtkXMLDataElement *config)
PlusStatus InternalUpdate()
vtkStandardNewMacro(vtkPlus3dConnexionTracker)
void DestroyCaptureWindow()
~vtkPlus3dConnexionTracker()
PlusStatus CreateCaptureWindow()
vtkPlus3dConnexionTracker()