This file contains changes introduced to PsychXR for each version. Breaking
changes may be incompatible with your current code or build environment.

Version 0.2.4 - 2021/07/12
--------------------------

Overview:

    This release adds experimental an OpenHMD driver, some new API features
    introduced to LibOVR, and refactors how driver modules are organized in
    PsychXR. The refactor is work was intended to facilitate current and future
    additions to the PsychXR driver library (e.g., OpenHMD and OpenXR).

    A significant addition this release is preliminary (preview) support for
    OpenHMD. OpenHMD is a FOSS project which aims to provide completely free
    drivers for HMDs, already supporting a substantial number of commercial
    devices. However, OpenHMD is not feature complete (yet) so things like
    positional tracking and a compositor are not available on all platforms.
    This requires the user to implement their own solutions for the time being.
    Ultimately, FOSS drivers provide a net benefit for researchers since the
    ethical pitfalls around using proprietary frameworks (e.g., third-party
    collection of biometric data, "finger printing", etc.) are generally avoided
    and a participant's privacy is respected. There are no substantial demos yet
    for OpenHMD, and the API is very simple. However, the OpenHMD interface will
    be expanded to be as close to `LibOVR` as possible in future releases.
    Furthermore, OpenHMD provides a means to use "homebrew" HMDs which might be
    helpful for some users. By default, the OpenHMD driver interface is built
    when building from source and is included with binary packages.
    Unfortunately, while OpenHMD is cross-platform (runs on Linux and Windows),
    PsychXR is still exclusive to Windows at this point. Cross-platform (read
    Linux) support is a priority now that there is a driver available for it.

    The LibOVR driver also got a significant update with the inclusion of color
    management to ensure content authored on one display appears "correct" on
    others. This is an important development introduced to the LibOVR API,
    giving information about the color space in use by the display with some
    limited capacity to remap it. PsychXR provides the `LibOVRHmdColorSpace`
    class and API functions to work with this new color management system.
    Documentation and recommendations are a bit thin at this point, but expect
    that to change in coming releases.

    Another change is the inclusion of a new `vrmath` library. This is intended
    to provide FOSS versions of classes included with `LibOVR` for 3D math. This
    will hopefully result in some degree of interoperability between drivers, by
    providing a common set of tools of working with VR environments. This
    library is currently in development and might contain bugs.

    Finally, refactoring work has been done to allow PsychXR to accommodate
    multiple driver extension modules. This means that driver interface have
    been moved to `psychxr.drivers` from the top-level package, so that
    `psychxr.libovr` is now at `psychxr.drivers.libovr`. So that there are not
    any surprises for users, a stub file was added in the original place of the
    `LibOVR` extension so extant scripts using the old import path
    (`psychxr.libovr`) will still work for now.

New Features:

    - Experimental OpenHMD driver `psychxr.drivers.openhmd`.
    - Version bump of the Oculus PC SDK to 23.0 (latest as of this release).
    - The Oculus SDK driver module `psychxr.libovr` has been moved to
      `psychxr.drivers.libovr`. This change is needed to organize things better
      for when other drivers and packages are added (eg. OpenXR). Eventually,
      drivers like `libovr` may be made optional and can be added to PsychXR as
      a plugin package. For now, you can still use the placeholder module
      `psychxr.libovr` to access the Oculus SDK driver interface.
    - Source code for the LibOVR driver has been split across multiple files.
      This should make it easier to navigate the code.
    - Added symbolic constants `HMD_QUEST` and `HMD_QUEST2`, they will be set
      as `LibOVRHmdInfo.hmdType` when using those devices to identify the
      hardware. Note that those HMDs need to be tethered to a PC using a link
      cable to use PsychXR with them. Remote desktop support is not yet
      tested but may work.
    - Added API features related to colorspace data and calibration recently
      added to LibOVR (beta feature, may not work as intended through PsychXR).
    - Removed constant `BUILD_NUMBER`, unused now.
    - Added the `psychxr.vrmath` library.
    - Deprecated `resetBoundaryColor` and `setBoundaryColor`. The API calls used
      by these functions have been deprecated by the Oculus PC SDK and may fail
      in future versions.
    - Added `raycastPose` method to `LibOVRPose`, this allows you to perform
      raypicking on bounding boxes belonging to other poses. The method returns
      the position in world space the intersection occurs. Bounding boxes are
      oriented by the poses they belong to.
    - Added some automated tests for `vrmath`. The `LibOVRPose` class is used
      as a reference.

Bug Fixes:

    - Added missing `viewMatrix` attribute to `LibOVRPose`.
    - Fixed wrong order of return values for `LibOVRPose.getOriAxisAngle`.
    - Fixed `LibOVRPose.inverseViewMatrix` not being returned correctly.
    - Added unit tests to check if `LibOVRPose` and `RigidBodyPose` are
      equivalent (i.e. give the same values).

Breaking Changes:

    - Oculus PC SDK version 23.0 is needed to build this release of PsychXR.
      Compilation will likely fail if any older version of the SDK is specified.
    - Branch `master` has been renamed to `main`. Update your local git branches
      accordingly.

Known Issues:

    - Calling `psychxr.drivers.libovr.shutdown()` results in the application
      quitting with exit code -1073741819 (0xC0000005) on Windows. This seems to
      only occur after creating an OpenGL swap chain, so it might be related to
      how the library interacts with the driver. You can ignore calling
      `shutdown` to circumvent this issue for now, hopefully the `LibOVR`
      runtime will free up resources associated with your app automatically.
    - OpenHMD support is incomplete, available only for preview and not
      recommended for general use yet.

Version 0.2.3 - 2019/12/10
--------------------------

Overview:

    This release has some minor fixes and features such as improved memory use
    and performance.

New Features:

    - Added function `checkSessionStarted` to determine if there is an active VR
      session. This is helpful to determine if a session is active from another
      module or file within the same interpreter thread.
    - Added `normalMatrix` and `getNormalMatrix` which retrieves a normal matrix
      for a mesh at a given pose. This matrix is commonly used by fragment
      shaders, and would usually need to be computed separately with the model
      matrix. That's no longer the case, you can now get a normal matrix along
      with your model matrix from a `LibOVRPose` instance.
    - `LibOVRPose` matrices are now cached to improve performance and memory
      access. Returned `ndarray` matrices now reference data directly instead of
      being copied over to new arrays every time. Matrices are computed only
      after `pos` and `ori` are accessed/changed. Furthermore, they are computed
      only when any attribute or method of `LibOVRPose` which returns a matrix
      is invoked. If there are no changes to `pos` and `ori` between successive
      matrix related attribute or method calls, cached data will be returned
      immediately without additional computation. One caveat about this approach
      is that matrices are always recomputed when accessing values, even if
      attributes `pos` and `ori` were only read, since currently there is no way
      to determine if the referencing `ndarrays` modified their referenced data.
      So it's just always assumed that they did. There is also a `ctypes`
      attribute associated with the class which returns a dictionary of `ctypes`
      pointers to the underlying matrix data. This allows `pyglet`'s GL
      implementation to directly access the data contained in these matrices
      without needing to create pointers yourself from returned `ndarray`
      objects. See `Known Issues` for more information about possible problems
      associated with caching.
    - Added `turn` method to `LibOVRPose` to rotate objects about an axis by
      some angle cumulatively.

Bug Fixes:

    - Fixed `LibOVRPose.setIdentity()` method not working.
    - Fixed some errata in the documentation.
    - `getEyeProjectionMatrix` no longer needs to be called for `cullPose` to
      give valid results. The projection matrix is now computed and is persistent
      after setting the render FOV.

Breaking Changes:

    - `getEyeProjectionMatrix` no longer computes a matrix (just gets one) that
      is now done when `setEyeRenderFov` is called. Therefore, `setEyeRenderFov`
      now accepts near and far clipping planes. Those arguments have been
      removed from `getEyeProjectionMatrix` and will cause a crash if your
      program set them there.

Known Issues:

    - Users need to be aware of idiosyncrasies related to the memory
      improvements listed above. One must be careful not to modify returned
      arrays since they will also modify their caches stored by the `LibOVRPose`
      instance. Furthermore, if the `LibOVRPose` instance is garbage collected
      because it is no longer referenced or manually deleted (by using `del`),
      any `ndarrays` or pointers still alive will access invalid data since
      the caches had their memory freed! This problem can be caused by doing the
      following::

            # don't do this
            myPose = LibOVRPose((0., 0., -2.))
            myMatrix = myPose.modelMatrix

      It's best to keep pose objects alive by not creating references to their
      data and using them directly::

            # don't do this ...
            myPose = LibOVRPose((0., 0., -2.))
            modelMatrix = myPose.modelMatrix
            viewMatrix = myPose.viewMatrix
            modelViewMatrix = numpy.matmul(viewMatrix, modelMatrix)

            # instead do this ...
            modelViewMatrix = numpy.matmul(myPose.viewMatrix, myPose.modelMatrix)

      Keep in mind there is near zero-overhead to doing this since `ndarray`
      objects are not created when accessing an attribute. If you wish not to
      keep the `LibOVRPose` object alive for some reason (or can't), you can
      copy the data like so::

            myPose = LibOVRPose((0., 0., -2.))
            modelMatrix = planePose.modelMatrix.copy()
            del myPose  # you can do this and myMatrix will have valid data

      Note that "getter" methods `get*` (eg. `getModelMatrix`) will always
      return copies of cached matrix data. So use those instead of attributes
      to avoid the problems above. In future versions of PsychXR, the caching
      system will be improved, expanded, and made more robust to get around
      these issues. Further reducing overhead and leaving more headroom
      per-frame for the user.


Version 0.2.2 - 2019/10/16
--------------------------

Overview:

    Bugfix release.

New Features:

    - None

Bug Fixes:

    - Fixed `LibOVRPerfStats` setting up incorrect pointers to
      `LibOVRPerfStatsPerCompositorFrame` objects.
    - Fixed TOUCH_* module level constants not being exposed by __all__.

Breaking Changes:

    - None


Version 0.2.1 - 2019/09/25
--------------------------

Overview:

    This release adds improved haptics support, bounding boxes, visibility
    culling, and more features to `LibOVRPose`. There are a few minor API
    breaking changes, however in the future API changes will raise deprecation
    warnings and be phased out gradually over several releases.

New Features:

    - Support for haptic buffers for use with Touch controllers. A haptics
      buffer contains an array of samples which specify Touch controller
      vibration amplitudes. Buffers can be passed to the haptics engine for
      playback, permitting custom vibration profiles.
    - Added `mirrorOptions` to `createMirrorTexture` to customize how mirrors
      are presented (eg. pre-distortion, rectilinear, one eye only, etc.)
    - Added `getViewMatrix` to `LibOVRPose` which creates view matrices, which
      transforms points into the space of the pose. This allows you to use rigid
      body poses to define eye locations for rendering. You can do crazy things
      like calculating eye poses using touch controller poses (make sure
      head-locking is enabled!)
    - Added `getAzimuthElevation` and `getAngleTo` methods to `LibOVRPose`, for
      computing Euler angles of targets within the reference frame of a poses.
    - Nearly all `LibOVRPose` transformation methods can write values to
      pre-allocated output arrays.
    - Added an optional `originPose` to `calcEyePoses`.
    - Added a bounding box attribute to poses. You can create an axis-aligned
      bounding box object (`LibOVRBounds`) and assign them to poses.
      `LibOVRBounds` has a `fit` method to compute boundaries for a 3D model if
      supplied a list of vertices.
    - New `cullPose` function allows you to cull meshes associated with poses if
      they are not visible during rendering by testing if their bounding boxes
      fall outside of the view frustum. This reduces CPU/GPU workload when
      complex drawing scenes.
    - Added logging callbacks. You can register a Python function as a callback
      for when LibOVR returns a message. Spits out lots of information, maybe
      you'll find some of it useful?
    - `endFrame` returns the absolute system time it was called.
    - ASW stats are also returned with `LibOVRPerfStatsPerCompositorFrame`.

Bug Fixes:

    - Fixed head-locking. Head-locking prevents compositor ASW from acting upon
      the layer. This fix restores the behaviour seen in the alpha releases
      of PsychXR.

Breaking Changes:

    - `getTrackingState` now returns a `LibOVRTrackingState` instance. This was
      changed given the previous system returned a data structure that was
      not intuitive to work with. This returns to the behaviour of the 0.1
      series of PsychXR and will stay this way.
    - `endFrame` now returns two values.
    - `resetFrameStats` is now `resetPerfStats` for naming consistency.

Known Issues:

    - None


Version 0.1.5 - 2019-09-25
~~~~~~~~~~~~~~~~~~~~~~~~~~

Hotfix release for version 0.1.4 which fixes an input bug where the range of
thumbstick values is improperly clipped.

Bug Fixes:

    - Fixed thumbstick values being clipped to 1.0 regardless of the input.


Version 0.2.0 - 2019/07/06
--------------------------

Overview:

    This release bring considerable changes to PsychXR to address issues and
    feedback from the initial public release (0.1.4). This version will break
    compatibility with software running any previous version, see the reference
    code in the demo directory for a minimal example using the new API.

    One of the biggest changes is NumPy integration, which exposes vector and
    matrix types as arrays instead of custom extension types. This allows you
    to take advantage of the scientific software ecosystem built around NumPy
    when working with data from HMDs. As a result, NumPy is now a requirement
    to build PsychXR.

    Several new extension types have been added, notably the LibOVRPose and
    LibOVRPoseState classes which store and manipulate rigid body pose data.
    There are plenty of class methods available to transform (e.g. invert) and
    convert (to a 4x4 matrix) poses, apply transformations, and do things like
    raypicking, interpolation, and time integration.

    Lastly, documentation has been greatly improved, providing lots of examples
    and details associated with each function and class.

New Features:

    - Added LibOVRPose, LibOVRPoseState, LibOVRSessionStatus, LibOVRHmdInfo,
      etc.
    - Library now exposes vectors, quaternions, and matrices as Numpy arrays.
    - LibOVR version bump to 1.37.
    - Functions which call the LibOVR API return error/success codes, making it
      easier to write custom error handlers.
    - More arguments for 'initialize()', such as 'focusAware'.
    - LibOVRPose handles rigid body pose data like 'ovr.math.Posef' did.
    - Added swap chain names 'LIBOVR_TEXTURE_SWAP_CHAIN*' so you don't need to
      define them yourself.
    - Added 'setControllerVibration' for haptic feedback.
    - Added 'getDevicePose' to get the absolute poses of tracked objects.
    - Functions can copy data into existing arrays rather than creating new
      ones.
    - Added functions to compute viewing parameters, such as horizontal FOV and
      aspect ratio.
    - LibOVRPoseState objects can be time integrated.
    - Controller states functions return time stamps and states in a single
      call.
    - Tracker/sensor information is now available.
    - Many more ...

Bug Fixes:

    - Cleaned up old and unused code from 'psychxr.libovr'.
    - Fixed crash when shutdown is called after a texture swap chain is created.

Breaking Changes:

    - Many API functions have been removed or renamed, some functions take
      different arguments all together.
    - Removed 'ovr.math' module, use LibOVRPose for rigid body transforms.
    - Removed 'ovr.capi', import 'psychxr.libovr' instead.
    - Reduced number of possible swap chains to 8 for now.
    - You must now manage getting the next available swap chain index.

Known Issues:

    - None so far ...

Version 0.1.5 - 2019/09/25
--------------------------

Hotfix release to fix an issue where thumbstick values are improperly clipped.

New Features:

    - None

Bug Fixes:

    - Updated licensing information.

Breaking:

    - None


Version 0.1.4 - 2019/02/11
--------------------------

New Features:

    - None

Bug Fixes:

    - Updated licensing information.

Breaking:

    - None


Version 0.1.3 - 2018/07/04
--------------------------

New Features:

    - Added "getPitchYawRoll" method to ovrQuatf object.
    - Changed "ovrSessionStatus" getter functions to properties.

Bug Fixes:

    - No bug fixes this release.

Breaking:

    - "ovrSessionStatus" getter functions are now properties.