oculus1

annotate libovr/Src/OVR_Device.h @ 21:ef4c9d8eeca7

added shaderless distortion method
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 02 Oct 2013 04:09:37 +0300
parents
children
rev   line source
nuclear@1 1 /************************************************************************************
nuclear@1 2
nuclear@1 3 PublicHeader: OVR.h
nuclear@1 4 Filename : OVR_Device.h
nuclear@1 5 Content : Definition of HMD-related Device interfaces
nuclear@1 6 Created : September 21, 2012
nuclear@1 7 Authors : Michael Antonov
nuclear@1 8
nuclear@1 9 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
nuclear@1 10
nuclear@1 11 Use of this software is subject to the terms of the Oculus license
nuclear@1 12 agreement provided at the time of installation or download, or which
nuclear@1 13 otherwise accompanies this software in either electronic or hard copy form.
nuclear@1 14
nuclear@1 15 *************************************************************************************/
nuclear@1 16
nuclear@1 17 #ifndef OVR_Device_h
nuclear@1 18 #define OVR_Device_h
nuclear@1 19
nuclear@1 20 #include "OVR_DeviceConstants.h"
nuclear@1 21 #include "OVR_DeviceHandle.h"
nuclear@1 22 #include "OVR_DeviceMessages.h"
nuclear@1 23 #include "OVR_HIDDeviceBase.h"
nuclear@1 24
nuclear@1 25 #include "Kernel/OVR_Atomic.h"
nuclear@1 26 #include "Kernel/OVR_RefCount.h"
nuclear@1 27 #include "Kernel/OVR_String.h"
nuclear@1 28
nuclear@1 29 namespace OVR {
nuclear@1 30
nuclear@1 31 // Declared externally
nuclear@1 32 class Profile;
nuclear@1 33 class ProfileManager; // << Should be renamed for consistency
nuclear@1 34
nuclear@1 35 // Forward declarations
nuclear@1 36 class SensorDevice;
nuclear@1 37 class DeviceCommon;
nuclear@1 38 class DeviceManager;
nuclear@1 39
nuclear@1 40 // MessageHandler is a base class from which users derive to receive messages,
nuclear@1 41 // its OnMessage handler will be called for messages once it is installed on
nuclear@1 42 // a device. Same message handler can be installed on multiple devices.
nuclear@1 43 class MessageHandler
nuclear@1 44 {
nuclear@1 45 friend class MessageHandlerImpl;
nuclear@1 46 public:
nuclear@1 47 MessageHandler();
nuclear@1 48 virtual ~MessageHandler();
nuclear@1 49
nuclear@1 50 // Returns 'true' if handler is currently installed on any devices.
nuclear@1 51 bool IsHandlerInstalled() const;
nuclear@1 52
nuclear@1 53 // Should be called from derived class destructor to avoid handler
nuclear@1 54 // being called after it exits.
nuclear@1 55 void RemoveHandlerFromDevices();
nuclear@1 56
nuclear@1 57 // Returns a pointer to the internal lock object that is locked by a
nuclear@1 58 // background thread while OnMessage() is called.
nuclear@1 59 // This lock guaranteed to survive until ~MessageHandler.
nuclear@1 60 Lock* GetHandlerLock() const;
nuclear@1 61
nuclear@1 62
nuclear@1 63 virtual void OnMessage(const Message&) { }
nuclear@1 64
nuclear@1 65 // Determines if handler supports a specific message type. Can
nuclear@1 66 // be used to filter out entire message groups. The result
nuclear@1 67 // returned by this function shouldn't change after handler creation.
nuclear@1 68 virtual bool SupportsMessageType(MessageType) const { return true; }
nuclear@1 69
nuclear@1 70 private:
nuclear@1 71 UPInt Internal[4];
nuclear@1 72 };
nuclear@1 73
nuclear@1 74
nuclear@1 75 //-------------------------------------------------------------------------------------
nuclear@1 76 // ***** DeviceBase
nuclear@1 77
nuclear@1 78 // DeviceBase is the base class for all OVR Devices. It provides the following basic
nuclear@1 79 // functionality:
nuclear@1 80 // - Reports device type, manager, and associated parent (if any).
nuclear@1 81 // - Supports installable message handlers, which are notified of device events.
nuclear@1 82 // - Device objects are created through DeviceHandle::CreateDevice or more commonly
nuclear@1 83 // through DeviceEnumerator<>::CreateDevice.
nuclear@1 84 // - Created devices are reference counted, starting with RefCount of 1.
nuclear@1 85 // - Device is resources are cleaned up when it is Released, although its handles
nuclear@1 86 // may survive longer if referenced.
nuclear@1 87
nuclear@1 88 class DeviceBase : public NewOverrideBase
nuclear@1 89 {
nuclear@1 90 friend class DeviceHandle;
nuclear@1 91 friend class DeviceManagerImpl;
nuclear@1 92 public:
nuclear@1 93
nuclear@1 94 // Enumerating DeviceBase enumerates all devices.
nuclear@1 95 enum { EnumDeviceType = Device_All };
nuclear@1 96
nuclear@1 97 virtual ~DeviceBase() { }
nuclear@1 98 virtual void AddRef();
nuclear@1 99 virtual void Release();
nuclear@1 100
nuclear@1 101 virtual DeviceBase* GetParent() const;
nuclear@1 102 virtual DeviceManager* GetManager() const;
nuclear@1 103
nuclear@1 104 virtual void SetMessageHandler(MessageHandler* handler);
nuclear@1 105 virtual MessageHandler* GetMessageHandler() const;
nuclear@1 106
nuclear@1 107 virtual DeviceType GetType() const;
nuclear@1 108 virtual bool GetDeviceInfo(DeviceInfo* info) const;
nuclear@1 109
nuclear@1 110 // returns the MessageHandler's lock
nuclear@1 111 Lock* GetHandlerLock() const;
nuclear@1 112 protected:
nuclear@1 113 // Internal
nuclear@1 114 virtual DeviceCommon* getDeviceCommon() const = 0;
nuclear@1 115 };
nuclear@1 116
nuclear@1 117
nuclear@1 118 //-------------------------------------------------------------------------------------
nuclear@1 119 // ***** DeviceInfo
nuclear@1 120
nuclear@1 121 // DeviceInfo describes a device and its capabilities, obtained by calling
nuclear@1 122 // GetDeviceInfo. This base class only contains device-independent functionality;
nuclear@1 123 // users will normally use a derived HMDInfo or SensorInfo classes for more
nuclear@1 124 // extensive device info.
nuclear@1 125
nuclear@1 126 class DeviceInfo
nuclear@1 127 {
nuclear@1 128 public:
nuclear@1 129 DeviceInfo() : InfoClassType(Device_None), Type(Device_None), Version(0)
nuclear@1 130 { ProductName[0] = Manufacturer[0] = 0; }
nuclear@1 131
nuclear@1 132 enum { MaxNameLength = 32 };
nuclear@1 133
nuclear@1 134 // Type of device for which DeviceInfo is intended.
nuclear@1 135 // This will be set to Device_HMD for HMDInfo structure, note that this may be
nuclear@1 136 // different form the actual device type since (Device_None) is valid.
nuclear@1 137 const DeviceType InfoClassType;
nuclear@1 138 // Type of device this describes. This must be the same as InfoClassType when
nuclear@1 139 // InfoClassType != Device_None.
nuclear@1 140 DeviceType Type;
nuclear@1 141 // Name string describing the product: "Oculus Rift DK1", etc.
nuclear@1 142 char ProductName[MaxNameLength];
nuclear@1 143 char Manufacturer[MaxNameLength];
nuclear@1 144 unsigned Version;
nuclear@1 145
nuclear@1 146 protected:
nuclear@1 147 DeviceInfo(DeviceType type) : InfoClassType(type), Type(type), Version(0)
nuclear@1 148 { ProductName[0] = Manufacturer[0] = 0; }
nuclear@1 149 void operator = (const DeviceInfo&) { OVR_ASSERT(0); } // Assignment not allowed.
nuclear@1 150 };
nuclear@1 151
nuclear@1 152
nuclear@1 153 //-------------------------------------------------------------------------------------
nuclear@1 154 // DeviceEnumerationArgs provides device enumeration argumenrs for DeviceManager::EnumerateDevicesEx.
nuclear@1 155 class DeviceEnumerationArgs
nuclear@1 156 {
nuclear@1 157 public:
nuclear@1 158 DeviceEnumerationArgs(DeviceType enumType, bool availableOnly)
nuclear@1 159 : EnumType(enumType), AvailableOnly(availableOnly)
nuclear@1 160 { }
nuclear@1 161
nuclear@1 162 // Helper; returns true if args match our enumeration criteria.
nuclear@1 163 bool MatchRule(DeviceType type, bool available) const
nuclear@1 164 {
nuclear@1 165 return ((EnumType == type) || (EnumType == Device_All)) &&
nuclear@1 166 (available || !AvailableOnly);
nuclear@1 167 }
nuclear@1 168
nuclear@1 169 protected:
nuclear@1 170 DeviceType EnumType;
nuclear@1 171 bool AvailableOnly;
nuclear@1 172 };
nuclear@1 173
nuclear@1 174
nuclear@1 175 // DeviceEnumerator<> is used to enumerate and create devices of specified class,
nuclear@1 176 // it is returned by calling MeviceManager::EnumerateDevices. Initially, the enumerator will
nuclear@1 177 // refer to the first device of specified type. Additional devices can be accessed by
nuclear@1 178 // calling Next().
nuclear@1 179
nuclear@1 180 template<class T = DeviceBase>
nuclear@1 181 class DeviceEnumerator : public DeviceHandle
nuclear@1 182 {
nuclear@1 183 friend class DeviceManager;
nuclear@1 184 friend class DeviceManagerImpl;
nuclear@1 185 public:
nuclear@1 186 DeviceEnumerator()
nuclear@1 187 : DeviceHandle(), EnumArgs(Device_None, true) { }
nuclear@1 188
nuclear@1 189 // Next advances enumeration to the next device that first criteria.
nuclear@1 190 // Returns false if no more devices exist that match enumeration criteria.
nuclear@1 191 bool Next() { return enumerateNext(EnumArgs); }
nuclear@1 192
nuclear@1 193 // Creates an instance of the device referenced by enumerator; returns null
nuclear@1 194 // if enumerator does not refer to a valid device or device is unavailable.
nuclear@1 195 // If device was already created, the same object with incremented ref-count is returned.
nuclear@1 196 T* CreateDevice() { return static_cast<T*>(DeviceHandle::CreateDevice()); }
nuclear@1 197
nuclear@1 198 protected:
nuclear@1 199 DeviceEnumerator(const DeviceHandle &dev, const DeviceEnumerationArgs& args)
nuclear@1 200 : DeviceHandle(dev), EnumArgs(args)
nuclear@1 201 { }
nuclear@1 202
nuclear@1 203 DeviceEnumerationArgs EnumArgs;
nuclear@1 204 };
nuclear@1 205
nuclear@1 206 //-------------------------------------------------------------------------------------
nuclear@1 207 // ***** DeviceManager
nuclear@1 208
nuclear@1 209 // DeviceManager maintains and provides access to devices supported by OVR, such as
nuclear@1 210 // HMDs and sensors. A single instance of DeviceManager is normally created at
nuclear@1 211 // program startup, allowing devices to be enumerated and created. DeviceManager is
nuclear@1 212 // reference counted and is AddRefed by its created child devices, causing it to
nuclear@1 213 // always be the last object that is released.
nuclear@1 214 //
nuclear@1 215 // Install MessageHandler on DeviceManager to detect when devices are inserted or removed.
nuclear@1 216 //
nuclear@1 217 // The following code will create the manager and its first available HMDDevice,
nuclear@1 218 // and then release it when not needed:
nuclear@1 219 //
nuclear@1 220 // DeviceManager* manager = DeviceManager::Create();
nuclear@1 221 // HMDDevice* hmd = manager->EnumerateDevices<HMDDevice>().CreateDevice();
nuclear@1 222 //
nuclear@1 223 // if (hmd) hmd->Release();
nuclear@1 224 // if (manager) manager->Release();
nuclear@1 225
nuclear@1 226
nuclear@1 227 class DeviceManager : public DeviceBase
nuclear@1 228 {
nuclear@1 229 public:
nuclear@1 230
nuclear@1 231 DeviceManager()
nuclear@1 232 { }
nuclear@1 233
nuclear@1 234 // DeviceBase implementation.
nuclear@1 235 virtual DeviceType GetType() const { return Device_Manager; }
nuclear@1 236 virtual DeviceManager* GetManager() const { return const_cast<DeviceManager*>(this); }
nuclear@1 237
nuclear@1 238 // Every DeviceManager has an associated profile manager, which us used to store
nuclear@1 239 // user settings that may affect device behavior.
nuclear@1 240 virtual ProfileManager* GetProfileManager() const = 0;
nuclear@1 241
nuclear@1 242
nuclear@1 243 // EnumerateDevices enumerates all of the available devices of the specified class,
nuclear@1 244 // returning an enumerator that references the first device. An empty enumerator is
nuclear@1 245 // returned if no devices are available. The following APIs are exposed through
nuclear@1 246 // DeviceEnumerator:
nuclear@1 247 // DeviceEnumerator::GetType() - Check device type. Returns Device_None
nuclear@1 248 // if no device was found/pointed to.
nuclear@1 249 // DeviceEnumerator::GetDeviceInfo() - Get more information on device.
nuclear@1 250 // DeviceEnumerator::CreateDevice() - Create an instance of device.
nuclear@1 251 // DeviceEnumerator::Next() - Move onto next device.
nuclear@1 252 template<class D>
nuclear@1 253 DeviceEnumerator<D> EnumerateDevices(bool availableOnly = true)
nuclear@1 254 {
nuclear@1 255 // TBD: A cleaner (but less efficient) alternative is though enumeratorFromHandle.
nuclear@1 256 DeviceEnumerator<> e = EnumerateDevicesEx(DeviceEnumerationArgs((DeviceType)D::EnumDeviceType, availableOnly));
nuclear@1 257 return *reinterpret_cast<DeviceEnumerator<D>*>(&e);
nuclear@1 258 }
nuclear@1 259
nuclear@1 260 // EnumerateDevicesEx provides internal implementation for device enumeration, enumerating
nuclear@1 261 // devices based on dynamically specified DeviceType in DeviceEnumerationArgs.
nuclear@1 262 // End users should call DeumerateDevices<>() instead.
nuclear@1 263 virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args) = 0;
nuclear@1 264
nuclear@1 265 // Creates a new DeviceManager. Only one instance of DeviceManager should be created at a time.
nuclear@1 266 static DeviceManager* Create();
nuclear@1 267
nuclear@1 268 // Static constant for this device type, used in template cast type checks.
nuclear@1 269 enum { EnumDeviceType = Device_Manager };
nuclear@1 270
nuclear@1 271
nuclear@1 272
nuclear@1 273 // Adds a device (DeviceCreateDesc*) into Devices. Returns NULL,
nuclear@1 274 // if unsuccessful or device is already in the list.
nuclear@1 275 virtual Ptr<DeviceCreateDesc> AddDevice_NeedsLock(const DeviceCreateDesc& createDesc) = 0;
nuclear@1 276
nuclear@1 277 protected:
nuclear@1 278 DeviceEnumerator<> enumeratorFromHandle(const DeviceHandle& h, const DeviceEnumerationArgs& args)
nuclear@1 279 { return DeviceEnumerator<>(h, args); }
nuclear@1 280
nuclear@1 281 DeviceManager* getThis() { return this; }
nuclear@1 282 };
nuclear@1 283
nuclear@1 284
nuclear@1 285
nuclear@1 286 //-------------------------------------------------------------------------------------
nuclear@1 287 // ***** HMDInfo
nuclear@1 288
nuclear@1 289 // This structure describes various aspects of the HMD allowing us to configure rendering.
nuclear@1 290 //
nuclear@1 291 // Currently included data:
nuclear@1 292 // - Physical screen dimensions, resolution, and eye distances.
nuclear@1 293 // (some of these will be configurable with a tool in the future).
nuclear@1 294 // These arguments allow us to properly setup projection across HMDs.
nuclear@1 295 // - DisplayDeviceName for identifying HMD screen; system-specific interpretation.
nuclear@1 296 //
nuclear@1 297 // TBD:
nuclear@1 298 // - Power on/ off?
nuclear@1 299 // - Sensor rates and capabilities
nuclear@1 300 // - Distortion radius/variables
nuclear@1 301 // - Screen update frequency
nuclear@1 302 // - Distortion needed flag
nuclear@1 303 // - Update modes:
nuclear@1 304 // Set update mode: Stereo (both sides together), mono (same in both eyes),
nuclear@1 305 // Alternating, Alternating scan-lines.
nuclear@1 306
nuclear@1 307 class HMDInfo : public DeviceInfo
nuclear@1 308 {
nuclear@1 309 public:
nuclear@1 310 // Size of the entire screen, in pixels.
nuclear@1 311 unsigned HResolution, VResolution;
nuclear@1 312 // Physical dimensions of the active screen in meters. Can be used to calculate
nuclear@1 313 // projection center while considering IPD.
nuclear@1 314 float HScreenSize, VScreenSize;
nuclear@1 315 // Physical offset from the top of the screen to the eye center, in meters.
nuclear@1 316 // This will usually, but not necessarily be half of VScreenSize.
nuclear@1 317 float VScreenCenter;
nuclear@1 318 // Distance from the eye to screen surface, in meters.
nuclear@1 319 // Useful for calculating FOV and projection.
nuclear@1 320 float EyeToScreenDistance;
nuclear@1 321 // Distance between physical lens centers useful for calculating distortion center.
nuclear@1 322 float LensSeparationDistance;
nuclear@1 323 // Configured distance between the user's eye centers, in meters. Defaults to 0.064.
nuclear@1 324 float InterpupillaryDistance;
nuclear@1 325
nuclear@1 326 // Radial distortion correction coefficients.
nuclear@1 327 // The distortion assumes that the input texture coordinates will be scaled
nuclear@1 328 // by the following equation:
nuclear@1 329 // uvResult = uvInput * (K0 + K1 * uvLength^2 + K2 * uvLength^4)
nuclear@1 330 // Where uvInput is the UV vector from the center of distortion in direction
nuclear@1 331 // of the mapped pixel, uvLength is the magnitude of that vector, and uvResult
nuclear@1 332 // the corresponding location after distortion.
nuclear@1 333 float DistortionK[4];
nuclear@1 334
nuclear@1 335 float ChromaAbCorrection[4];
nuclear@1 336
nuclear@1 337 // Desktop coordinate position of the screen (can be negative; may not be present on all platforms)
nuclear@1 338 int DesktopX, DesktopY;
nuclear@1 339
nuclear@1 340 // Windows:
nuclear@1 341 // "\\\\.\\DISPLAY3", etc. Can be used in EnumDisplaySettings/CreateDC.
nuclear@1 342 char DisplayDeviceName[32];
nuclear@1 343
nuclear@1 344 // MacOS:
nuclear@1 345 long DisplayId;
nuclear@1 346
nuclear@1 347
nuclear@1 348 HMDInfo()
nuclear@1 349 : DeviceInfo(Device_HMD),
nuclear@1 350 HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0),
nuclear@1 351 VScreenCenter(0), EyeToScreenDistance(0),
nuclear@1 352 LensSeparationDistance(0), InterpupillaryDistance(0),
nuclear@1 353 DesktopX(0), DesktopY(0), DisplayId(0)
nuclear@1 354 {
nuclear@1 355 DisplayDeviceName[0] = 0;
nuclear@1 356 memset(DistortionK, 0, sizeof(DistortionK));
nuclear@1 357 DistortionK[0] = 1;
nuclear@1 358 ChromaAbCorrection[0] = ChromaAbCorrection[2] = 1;
nuclear@1 359 ChromaAbCorrection[1] = ChromaAbCorrection[3] = 0;
nuclear@1 360 }
nuclear@1 361
nuclear@1 362 // Operator = copies local fields only (base class must be correct already)
nuclear@1 363 void operator = (const HMDInfo& src)
nuclear@1 364 {
nuclear@1 365 HResolution = src.HResolution;
nuclear@1 366 VResolution = src.VResolution;
nuclear@1 367 HScreenSize = src.HScreenSize;
nuclear@1 368 VScreenSize = src.VScreenSize;
nuclear@1 369 VScreenCenter = src.VScreenCenter;
nuclear@1 370 EyeToScreenDistance = src.EyeToScreenDistance;
nuclear@1 371 LensSeparationDistance = src.LensSeparationDistance;
nuclear@1 372 InterpupillaryDistance = src.InterpupillaryDistance;
nuclear@1 373 DistortionK[0] = src.DistortionK[0];
nuclear@1 374 DistortionK[1] = src.DistortionK[1];
nuclear@1 375 DistortionK[2] = src.DistortionK[2];
nuclear@1 376 DistortionK[3] = src.DistortionK[3];
nuclear@1 377 ChromaAbCorrection[0] = src.ChromaAbCorrection[0];
nuclear@1 378 ChromaAbCorrection[1] = src.ChromaAbCorrection[1];
nuclear@1 379 ChromaAbCorrection[2] = src.ChromaAbCorrection[2];
nuclear@1 380 ChromaAbCorrection[3] = src.ChromaAbCorrection[3];
nuclear@1 381 DesktopX = src.DesktopX;
nuclear@1 382 DesktopY = src.DesktopY;
nuclear@1 383 memcpy(DisplayDeviceName, src.DisplayDeviceName, sizeof(DisplayDeviceName));
nuclear@1 384 DisplayId = src.DisplayId;
nuclear@1 385 }
nuclear@1 386
nuclear@1 387 bool IsSameDisplay(const HMDInfo& o) const
nuclear@1 388 {
nuclear@1 389 return DisplayId == o.DisplayId &&
nuclear@1 390 String::CompareNoCase(DisplayDeviceName,
nuclear@1 391 o.DisplayDeviceName) == 0;
nuclear@1 392 }
nuclear@1 393
nuclear@1 394 };
nuclear@1 395
nuclear@1 396
nuclear@1 397 // HMDDevice represents an Oculus HMD device unit. An instance of this class
nuclear@1 398 // is typically created from the DeviceManager.
nuclear@1 399 // After HMD device is created, we its sensor data can be obtained by
nuclear@1 400 // first creating a Sensor object and then.
nuclear@1 401
nuclear@1 402 // TBD:
nuclear@1 403 // - Configure Sensor
nuclear@1 404 // - APIs to set On-Screen message, other states?
nuclear@1 405
nuclear@1 406 class HMDDevice : public DeviceBase
nuclear@1 407 {
nuclear@1 408 public:
nuclear@1 409 HMDDevice()
nuclear@1 410 { }
nuclear@1 411
nuclear@1 412 // Static constant for this device type, used in template cast type checks.
nuclear@1 413 enum { EnumDeviceType = Device_HMD };
nuclear@1 414
nuclear@1 415 virtual DeviceType GetType() const { return Device_HMD; }
nuclear@1 416
nuclear@1 417 // Creates a sensor associated with this HMD.
nuclear@1 418 virtual SensorDevice* GetSensor() = 0;
nuclear@1 419
nuclear@1 420
nuclear@1 421 // Requests the currently used profile. This profile affects the
nuclear@1 422 // settings reported by HMDInfo.
nuclear@1 423 virtual Profile* GetProfile() const = 0;
nuclear@1 424 // Obtains the currently used profile name. This is initialized to the default
nuclear@1 425 // profile name, if any; it can then be changed per-device by SetProfileName.
nuclear@1 426 virtual const char* GetProfileName() const = 0;
nuclear@1 427 // Sets the profile user name, changing the data returned by GetProfileInfo.
nuclear@1 428 virtual bool SetProfileName(const char* name) = 0;
nuclear@1 429
nuclear@1 430
nuclear@1 431 // Disconnects from real HMD device. This HMDDevice remains as 'fake' HMD.
nuclear@1 432 // SensorDevice ptr is used to restore the 'fake' HMD (can be NULL).
nuclear@1 433 HMDDevice* Disconnect(SensorDevice*);
nuclear@1 434
nuclear@1 435 // Returns 'true' if HMD device is a 'fake' HMD (was created this way or
nuclear@1 436 // 'Disconnect' method was called).
nuclear@1 437 bool IsDisconnected() const;
nuclear@1 438 };
nuclear@1 439
nuclear@1 440
nuclear@1 441 //-------------------------------------------------------------------------------------
nuclear@1 442 // ***** SensorRange & SensorInfo
nuclear@1 443
nuclear@1 444 // SensorRange specifies maximum value ranges that SensorDevice hardware is configured
nuclear@1 445 // to detect. Although this range doesn't affect the scale of MessageBodyFrame values,
nuclear@1 446 // physical motions whose positive or negative magnitude is outside the specified range
nuclear@1 447 // may get clamped or misreported. Setting lower values may result in higher precision
nuclear@1 448 // tracking.
nuclear@1 449 struct SensorRange
nuclear@1 450 {
nuclear@1 451 SensorRange(float maxAcceleration = 0.0f, float maxRotationRate = 0.0f,
nuclear@1 452 float maxMagneticField = 0.0f)
nuclear@1 453 : MaxAcceleration(maxAcceleration), MaxRotationRate(maxRotationRate),
nuclear@1 454 MaxMagneticField(maxMagneticField)
nuclear@1 455 { }
nuclear@1 456
nuclear@1 457 // Maximum detected acceleration in m/s^2. Up to 8*G equivalent support guaranteed,
nuclear@1 458 // where G is ~9.81 m/s^2.
nuclear@1 459 // Oculus DK1 HW has thresholds near: 2, 4 (default), 8, 16 G.
nuclear@1 460 float MaxAcceleration;
nuclear@1 461 // Maximum detected angular velocity in rad/s. Up to 8*Pi support guaranteed.
nuclear@1 462 // Oculus DK1 HW thresholds near: 1, 2, 4, 8 Pi (default).
nuclear@1 463 float MaxRotationRate;
nuclear@1 464 // Maximum detectable Magnetic field strength in Gauss. Up to 2.5 Gauss support guaranteed.
nuclear@1 465 // Oculus DK1 HW thresholds near: 0.88, 1.3, 1.9, 2.5 gauss.
nuclear@1 466 float MaxMagneticField;
nuclear@1 467 };
nuclear@1 468
nuclear@1 469 // SensorInfo describes capabilities of the sensor device.
nuclear@1 470 class SensorInfo : public DeviceInfo
nuclear@1 471 {
nuclear@1 472 public:
nuclear@1 473 SensorInfo() : DeviceInfo(Device_Sensor), VendorId(0), ProductId(0)
nuclear@1 474 {
nuclear@1 475 SerialNumber[0] = 0;
nuclear@1 476 }
nuclear@1 477
nuclear@1 478 // HID Vendor and ProductId of the device.
nuclear@1 479 UInt16 VendorId;
nuclear@1 480 UInt16 ProductId;
nuclear@1 481 // MaxRanges report maximum sensor range values supported by HW.
nuclear@1 482 SensorRange MaxRanges;
nuclear@1 483 // Sensor (and display) serial number.
nuclear@1 484 char SerialNumber[20];
nuclear@1 485
nuclear@1 486 private:
nuclear@1 487 void operator = (const SensorInfo&) { OVR_ASSERT(0); } // Assignment not allowed.
nuclear@1 488 };
nuclear@1 489
nuclear@1 490
nuclear@1 491 //-------------------------------------------------------------------------------------
nuclear@1 492 // ***** SensorDevice
nuclear@1 493
nuclear@1 494 // SensorDevice is an interface to sensor data.
nuclear@1 495 // Install a MessageHandler of SensorDevice instance to receive MessageBodyFrame
nuclear@1 496 // notifications.
nuclear@1 497 //
nuclear@1 498 // TBD: Add Polling API? More HID interfaces?
nuclear@1 499
nuclear@1 500 class SensorDevice : public HIDDeviceBase, public DeviceBase
nuclear@1 501 {
nuclear@1 502 public:
nuclear@1 503 SensorDevice()
nuclear@1 504 { }
nuclear@1 505
nuclear@1 506 // Static constant for this device type, used in template cast type checks.
nuclear@1 507 enum { EnumDeviceType = Device_Sensor };
nuclear@1 508
nuclear@1 509 virtual DeviceType GetType() const { return Device_Sensor; }
nuclear@1 510
nuclear@1 511
nuclear@1 512 // CoordinateFrame defines whether messages come in the coordinate frame
nuclear@1 513 // of the sensor device or HMD, which has a different internal sensor.
nuclear@1 514 // Sensors obtained form the HMD will automatically use HMD coordinates.
nuclear@1 515 enum CoordinateFrame
nuclear@1 516 {
nuclear@1 517 Coord_Sensor = 0,
nuclear@1 518 Coord_HMD = 1
nuclear@1 519 };
nuclear@1 520
nuclear@1 521 virtual void SetCoordinateFrame(CoordinateFrame coordframe) = 0;
nuclear@1 522 virtual CoordinateFrame GetCoordinateFrame() const = 0;
nuclear@1 523
nuclear@1 524 // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call).
nuclear@1 525 // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be
nuclear@1 526 // called twice or thrice at the same 'tick'.
nuclear@1 527 // If the rate is < 333 then the OnMessage / MessageBodyFrame will be called three
nuclear@1 528 // times for each 'tick': the first call will contain averaged values, the second
nuclear@1 529 // and third calls will provide with most recent two recorded samples.
nuclear@1 530 virtual void SetReportRate(unsigned rateHz) = 0;
nuclear@1 531 // Returns currently set report rate, in Hz. If 0 - error occurred.
nuclear@1 532 // Note, this value may be different from the one provided for SetReportRate. The return
nuclear@1 533 // value will contain the actual rate.
nuclear@1 534 virtual unsigned GetReportRate() const = 0;
nuclear@1 535
nuclear@1 536 // Sets maximum range settings for the sensor described by SensorRange.
nuclear@1 537 // The function will fail if you try to pass values outside Maximum supported
nuclear@1 538 // by the HW, as described by SensorInfo.
nuclear@1 539 // Pass waitFlag == true to wait for command completion. For waitFlag == true,
nuclear@1 540 // returns true if the range was applied successfully (no HW error).
nuclear@1 541 // For waitFlag = false, return 'true' means that command was enqueued successfully.
nuclear@1 542 virtual bool SetRange(const SensorRange& range, bool waitFlag = false) = 0;
nuclear@1 543
nuclear@1 544 // Return the current sensor range settings for the device. These may not exactly
nuclear@1 545 // match the values applied through SetRange.
nuclear@1 546 virtual void GetRange(SensorRange* range) const = 0;
nuclear@1 547 };
nuclear@1 548
nuclear@1 549 //-------------------------------------------------------------------------------------
nuclear@1 550 // ***** LatencyTestConfiguration
nuclear@1 551 // LatencyTestConfiguration specifies configuration information for the Oculus Latency Tester device.
nuclear@1 552 struct LatencyTestConfiguration
nuclear@1 553 {
nuclear@1 554 LatencyTestConfiguration(const Color& threshold, bool sendSamples = false)
nuclear@1 555 : Threshold(threshold), SendSamples(sendSamples)
nuclear@1 556 {
nuclear@1 557 }
nuclear@1 558
nuclear@1 559 // The color threshold for triggering a detected display change.
nuclear@1 560 Color Threshold;
nuclear@1 561 // Flag specifying whether we wish to receive a stream of color values from the sensor.
nuclear@1 562 bool SendSamples;
nuclear@1 563 };
nuclear@1 564
nuclear@1 565 //-------------------------------------------------------------------------------------
nuclear@1 566 // ***** LatencyTestDisplay
nuclear@1 567 // LatencyTestDisplay sets the mode and contents of the Latency Tester LED display.
nuclear@1 568 // See the 'Latency Tester Specification' document for more details.
nuclear@1 569 struct LatencyTestDisplay
nuclear@1 570 {
nuclear@1 571 LatencyTestDisplay(UByte mode, UInt32 value)
nuclear@1 572 : Mode(mode), Value(value)
nuclear@1 573 {
nuclear@1 574 }
nuclear@1 575
nuclear@1 576 UByte Mode; // The display mode that we wish to select.
nuclear@1 577 UInt32 Value; // The value to display.
nuclear@1 578 };
nuclear@1 579
nuclear@1 580 //-------------------------------------------------------------------------------------
nuclear@1 581 // ***** LatencyTestDevice
nuclear@1 582
nuclear@1 583 // LatencyTestDevice provides an interface to the Oculus Latency Tester which is used to test 'motion to photon' latency.
nuclear@1 584 class LatencyTestDevice : public HIDDeviceBase, public DeviceBase
nuclear@1 585 {
nuclear@1 586 public:
nuclear@1 587 LatencyTestDevice()
nuclear@1 588 { }
nuclear@1 589
nuclear@1 590 // Static constant for this device type, used in template cast type checks.
nuclear@1 591 enum { EnumDeviceType = Device_LatencyTester };
nuclear@1 592
nuclear@1 593 virtual DeviceType GetType() const { return Device_LatencyTester; }
nuclear@1 594
nuclear@1 595 // Specifies configuration information including the threshold for triggering a detected color change,
nuclear@1 596 // and a flag to enable a stream of sensor values (typically used for debugging).
nuclear@1 597 virtual bool SetConfiguration(const LatencyTestConfiguration& configuration, bool waitFlag = false) = 0;
nuclear@1 598
nuclear@1 599 // Get configuration information from device.
nuclear@1 600 virtual bool GetConfiguration(LatencyTestConfiguration* configuration) = 0;
nuclear@1 601
nuclear@1 602 // Used to calibrate the latency tester at the start of a test. Display the specified color on the screen
nuclear@1 603 // beneath the latency tester and then call this method. Calibration information is lost
nuclear@1 604 // when power is removed from the device.
nuclear@1 605 virtual bool SetCalibrate(const Color& calibrationColor, bool waitFlag = false) = 0;
nuclear@1 606
nuclear@1 607 // Triggers the start of a measurement. This starts the millisecond timer on the device and
nuclear@1 608 // causes it to respond with the 'MessageLatencyTestStarted' message.
nuclear@1 609 virtual bool SetStartTest(const Color& targetColor, bool waitFlag = false) = 0;
nuclear@1 610
nuclear@1 611 // Used to set the value displayed on the LED display panel.
nuclear@1 612 virtual bool SetDisplay(const LatencyTestDisplay& display, bool waitFlag = false) = 0;
nuclear@1 613
nuclear@1 614 virtual DeviceBase* GetDevice() { return this; }
nuclear@1 615 };
nuclear@1 616
nuclear@1 617 } // namespace OVR
nuclear@1 618
nuclear@1 619 #endif