472 lines
16 KiB
C++
472 lines
16 KiB
C++
// -*-c++-*-
|
|
// SPDX-License-Identifier: LGPL-2.1-only
|
|
// Copyright (C) 2021 James Hogan <james@albanarts.com>
|
|
|
|
#ifndef OSGXR_Action
|
|
#define OSGXR_Action 1
|
|
|
|
#include <osgXR/Export>
|
|
|
|
#include <osg/Quat>
|
|
#include <osg/Referenced>
|
|
#include <osg/Vec2f>
|
|
#include <osg/Vec3f>
|
|
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace osgXR {
|
|
|
|
class ActionSet;
|
|
class Subaction;
|
|
|
|
/**
|
|
* Represents an OpenXR action.
|
|
* OpenXR actions are inputs & outputs which are abstracted from the physical
|
|
* input sources. The OpenXR runtime is responsible for binding them to sources,
|
|
* using suggested bindings in interaction profiles.
|
|
*
|
|
* These Action objects can persist across multiple VR sessions, and changes can
|
|
* be made at any time, however some changes won't take effect while a session
|
|
* is running.
|
|
*/
|
|
class OSGXR_EXPORT Action : public osg::Referenced
|
|
{
|
|
public:
|
|
|
|
class Private;
|
|
|
|
protected:
|
|
|
|
/// Constructor (internal).
|
|
Action(Private *priv);
|
|
|
|
public:
|
|
|
|
/// Destructor.
|
|
~Action();
|
|
|
|
/**
|
|
* Add a subaction that may be later queried.
|
|
* Any subaction that is intended to be queried must be added to the
|
|
* action first.
|
|
* @param subaction Subaction that may be later queried.
|
|
*/
|
|
void addSubaction(Subaction *subaction);
|
|
|
|
// Accessors
|
|
|
|
/**
|
|
* Set the action's name and localized name.
|
|
* @param name New name for OpenXR action.
|
|
* @param localizedName A localized version of @p name.
|
|
*/
|
|
void setName(const std::string &name,
|
|
const std::string &localizedName);
|
|
|
|
/**
|
|
* Set the action's name.
|
|
* @param name New name for OpenXR action.
|
|
*/
|
|
void setName(const std::string &name);
|
|
/// Get the action's name.
|
|
const std::string &getName() const;
|
|
|
|
/**
|
|
* Set the action's localized name.
|
|
* @param localizedName The localized name for the action.
|
|
*/
|
|
void setLocalizedName(const std::string &localizedName);
|
|
/// Get the action's localized name.
|
|
const std::string &getLocalizedName() const;
|
|
|
|
/**
|
|
* Get a list of currently bound source paths for this action.
|
|
* @param sourcePaths[out] Vector of source paths to write into.
|
|
*/
|
|
void getBoundSources(std::vector<std::string> &sourcePaths) const;
|
|
|
|
typedef enum {
|
|
// Must match XR_INPUT_SOURCE_LOCALIZED_NAME_*
|
|
/// Include user path (e.g. "Left Hand").
|
|
USER_PATH_BIT = 1,
|
|
/// Include interaction profile (e.g. "Vive Controller").
|
|
INTERACTION_PROFILE_BIT = 2,
|
|
/// Include input component (e.g. "Trigger").
|
|
COMPONENT_BIT = 4,
|
|
} LocalizedNameFlags;
|
|
|
|
/**
|
|
* Get a list of currently bound source localized names for this action.
|
|
* @param whichComponents Which components to include.
|
|
* @param names[out] Vector of names to write into.
|
|
*/
|
|
void getBoundSourcesLocalizedNames(uint32_t whichComponents,
|
|
std::vector<std::string> &names) const;
|
|
|
|
private:
|
|
|
|
std::unique_ptr<Private> _private;
|
|
|
|
// Copying not permitted
|
|
Action(const Action ©);
|
|
};
|
|
|
|
/// An action that can only have boolean values.
|
|
class OSGXR_EXPORT ActionBoolean : public Action
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct a boolean action.
|
|
* @param actionSet The action set the action should belong to.
|
|
*/
|
|
ActionBoolean(ActionSet *actionSet);
|
|
|
|
/**
|
|
* Construct a boolean action.
|
|
* @param actionSet The action set the action should belong to.
|
|
* @param name The name of the OpenXR action, also used as the
|
|
* localized name.
|
|
*/
|
|
ActionBoolean(ActionSet *actionSet,
|
|
const std::string &name);
|
|
|
|
/**
|
|
* Construct a boolean action.
|
|
* @param actionSet The action set the action should belong to.
|
|
* @param name The name of the OpenXR action.
|
|
* @param localizedName The localized name for the action.
|
|
*/
|
|
ActionBoolean(ActionSet *actionSet,
|
|
const std::string &name,
|
|
const std::string &localizedName);
|
|
|
|
/**
|
|
* Get the current value of the action as a bool.
|
|
* @param subaction The subaction to filter sources from, which must
|
|
* have been specified to Action::addSubaction().
|
|
* @return The current value of the action.
|
|
*/
|
|
bool getValue(Subaction *subaction = nullptr);
|
|
};
|
|
|
|
/// An action that can have floating point values.
|
|
class OSGXR_EXPORT ActionFloat : public Action
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct a floating-point action.
|
|
* @param actionSet The action set the action should belong to.
|
|
*/
|
|
ActionFloat(ActionSet *actionSet);
|
|
|
|
/**
|
|
* Construct a floating-point action.
|
|
* @param actionSet The action set the action should belong to.
|
|
* @param name The name of the OpenXR action, also used as the
|
|
* localized name.
|
|
*/
|
|
ActionFloat(ActionSet *actionSet,
|
|
const std::string &name);
|
|
|
|
/**
|
|
* Construct a floating-point action.
|
|
* @param actionSet The action set the action should belong to.
|
|
* @param name The name of the OpenXR action.
|
|
* @param localizedName The localized name for the action.
|
|
*/
|
|
ActionFloat(ActionSet *actionSet,
|
|
const std::string &name,
|
|
const std::string &localizedName);
|
|
|
|
/**
|
|
* Get the current value of the action as a float.
|
|
* @param subaction The subaction to filter sources from, which must
|
|
* have been specified to Action::addSubaction().
|
|
* @return The current value of the action.
|
|
*/
|
|
float getValue(Subaction *subaction = nullptr);
|
|
};
|
|
|
|
/// An action that can have 2 dimentional floating point vector values.
|
|
class OSGXR_EXPORT ActionVector2f : public Action
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct a 2d floating-point vector action.
|
|
* @param actionSet The action set the action should belong to.
|
|
*/
|
|
ActionVector2f(ActionSet *actionSet);
|
|
|
|
/**
|
|
* Construct a 2d floating-point vector action.
|
|
* @param actionSet The action set the action should belong to.
|
|
* @param name The name of the OpenXR action, also used as the
|
|
* localized name.
|
|
*/
|
|
ActionVector2f(ActionSet *actionSet,
|
|
const std::string &name);
|
|
|
|
/**
|
|
* Construct a 2d floating-point vector action.
|
|
* @param actionSet The action set the action should belong to.
|
|
* @param name The name of the OpenXR action.
|
|
* @param localizedName The localized name for the action.
|
|
*/
|
|
ActionVector2f(ActionSet *actionSet,
|
|
const std::string &name,
|
|
const std::string &localizedName);
|
|
|
|
/**
|
|
* Get the current value of the action as an OSG vector.
|
|
* @param subaction The subaction to filter sources from, which must
|
|
* have been specified to Action::addSubaction().
|
|
* @return The current value of the action.
|
|
*/
|
|
osg::Vec2f getValue(Subaction *subaction = nullptr);
|
|
};
|
|
|
|
/// An action that can have pose (position and orientation) values.
|
|
class OSGXR_EXPORT ActionPose : public Action
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct a pose action.
|
|
* @param actionSet The action set the action should belong to.
|
|
*/
|
|
ActionPose(ActionSet *actionSet);
|
|
|
|
/**
|
|
* Construct a pose action.
|
|
* @param actionSet The action set the action should belong to.
|
|
* @param name The name of the OpenXR action, also used as the
|
|
* localized name.
|
|
*/
|
|
ActionPose(ActionSet *actionSet,
|
|
const std::string &name);
|
|
|
|
/**
|
|
* Construct a pose action.
|
|
* @param actionSet The action set the action should belong to.
|
|
* @param name The name of the OpenXR action.
|
|
* @param localizedName The localized name for the action.
|
|
*/
|
|
ActionPose(ActionSet *actionSet,
|
|
const std::string &name,
|
|
const std::string &localizedName);
|
|
|
|
/**
|
|
* Represents a pose action's position and orientation.
|
|
* This represents a pose action's position and orientation, along with
|
|
* flags to indicate whether each of these are valid and whether they're
|
|
* currently tracked (as opposed to estimated based on recent tracking).
|
|
*/
|
|
class OSGXR_EXPORT Location
|
|
{
|
|
public:
|
|
|
|
typedef enum {
|
|
// Must match XR_SPACE_LOCATION_* */
|
|
ORIENTATION_VALID_BIT = 0x1,
|
|
POSITION_VALID_BIT = 0x2,
|
|
ORIENTATION_TRACKED_BIT = 0x4,
|
|
POSITION_TRACKED_BIT = 0x8,
|
|
} Flags;
|
|
|
|
// Constructors
|
|
|
|
/// Construct a pose action location.
|
|
Location();
|
|
/// Construct a pose action location.
|
|
Location(Flags flags,
|
|
const osg::Quat &orientation,
|
|
const osg::Vec3f &position);
|
|
|
|
// Accessors
|
|
|
|
/**
|
|
* Find whether the orientation is valid.
|
|
* If not, the orientation is undefined.
|
|
* @return Whether the orientation is valid.
|
|
*/
|
|
bool isOrientationValid() const
|
|
{
|
|
return _flags & ORIENTATION_VALID_BIT;
|
|
}
|
|
|
|
/**
|
|
* Find whether the position is valid.
|
|
* If not, the position is undefined.
|
|
* @return Whether the position is valid.
|
|
*/
|
|
bool isPositionValid() const
|
|
{
|
|
return _flags & POSITION_VALID_BIT;
|
|
}
|
|
|
|
/**
|
|
* Find whether the orientation is being tracked.
|
|
* If not, the orientation may only be an estimate.
|
|
* @return Whether the orientation is being tracked.
|
|
*/
|
|
bool isOrientationTracked() const
|
|
{
|
|
return _flags & ORIENTATION_TRACKED_BIT;
|
|
}
|
|
|
|
/**
|
|
* Find whether the position is being tracked.
|
|
* If not, the position may only be an estimate.
|
|
* @return Whether the position is being tracked.
|
|
*/
|
|
bool isPositionTracked() const
|
|
{
|
|
return _flags & POSITION_TRACKED_BIT;
|
|
}
|
|
|
|
/// Get the flags which indicate validity and tracking.
|
|
Flags getFlags() const
|
|
{
|
|
return _flags;
|
|
}
|
|
|
|
/**
|
|
* Get the pose action's orientation as a quaternion.
|
|
* Get the pose action's orientation relative to the default
|
|
* reference space as an OSG quaternion.
|
|
*
|
|
* The orientation is undefined if isOrientationValid() returns
|
|
* false.
|
|
*
|
|
* The orientation may only be an estimate if
|
|
* isOrientationTracked() returns false.
|
|
*/
|
|
const osg::Quat &getOrientation() const
|
|
{
|
|
return _orientation;
|
|
}
|
|
|
|
/**
|
|
* Get the pose action's position as a 3D vector.
|
|
* Get the pose action's position relative to the default
|
|
* reference space as an OSG 3D vector.
|
|
*
|
|
* The position is undefined if isPositionValid() returns false.
|
|
*
|
|
* The position may only be an estimate if isPositionTracked()
|
|
* returns false.
|
|
*/
|
|
const osg::Vec3f &getPosition() const
|
|
{
|
|
return _position;
|
|
}
|
|
|
|
// Comparison operators
|
|
|
|
bool operator != (const Location &other) const
|
|
{
|
|
return _flags != other._flags ||
|
|
(isOrientationValid() && _orientation != other._orientation) ||
|
|
(isPositionValid() && _position != other._position);
|
|
}
|
|
|
|
bool operator == (const Location &other) const
|
|
{
|
|
return !operator != (other);
|
|
}
|
|
|
|
protected:
|
|
|
|
Flags _flags;
|
|
osg::Quat _orientation;
|
|
osg::Vec3f _position;
|
|
};
|
|
|
|
/**
|
|
* Get the current pose of the action as a Location object.
|
|
* @param subaction The subaction to filter sources from, which must
|
|
* have been specified to Action::addSubaction().
|
|
* @return The current pose of the action.
|
|
*/
|
|
Location getValue(Subaction *subaction = nullptr);
|
|
};
|
|
|
|
/// An output action for vibration.
|
|
class OSGXR_EXPORT ActionVibration : public Action
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct a vibration output action.
|
|
* @param actionSet The action set the action should belong to.
|
|
*/
|
|
ActionVibration(ActionSet *actionSet);
|
|
|
|
/**
|
|
* Construct a vibration output action.
|
|
* @param actionSet The action set the action should belong to.
|
|
* @param name The name of the OpenXR action, also used as the
|
|
* localized name.
|
|
*/
|
|
ActionVibration(ActionSet *actionSet,
|
|
const std::string &name);
|
|
|
|
/**
|
|
* Construct a vibration output action.
|
|
* @param actionSet The action set the action should belong to.
|
|
* @param name The name of the OpenXR action.
|
|
* @param localizedName The localized name for the action.
|
|
*/
|
|
ActionVibration(ActionSet *actionSet,
|
|
const std::string &name,
|
|
const std::string &localizedName);
|
|
|
|
enum {
|
|
/// Indicates a minimum supported durection for a haptic device.
|
|
DURATION_MIN = -1,
|
|
/// Indicates an optimal frequency for a haptic pulse.
|
|
FREQUENCY_UNSPECIFIED = 0,
|
|
};
|
|
|
|
/**
|
|
* Apply haptic feedback.
|
|
* @param duration_ns Duration of vibration in nanoseconds.
|
|
* @param frequency Frequency of vibration in Hz.
|
|
* @param amplitude Amplitude of vibration between 0.0 and 1.0.
|
|
* @return true on success, false otherwise.
|
|
*/
|
|
bool applyHapticFeedback(int64_t duration_ns, float frequency,
|
|
float amplitude);
|
|
|
|
/**
|
|
* Apply haptic feedback.
|
|
* @param subaction The subaction to apply haptics to, which must
|
|
* have been specified to Action::addSubaction().
|
|
* @param duration_ns Duration of vibration in nanoseconds.
|
|
* @param frequency Frequency of vibration in Hz.
|
|
* @param amplitude Amplitude of vibration between 0.0 and 1.0.
|
|
* @return true on success, false otherwise.
|
|
*/
|
|
bool applyHapticFeedback(Subaction *subaction,
|
|
int64_t duration_ns, float frequency,
|
|
float amplitude);
|
|
|
|
/**
|
|
* Stop any in-progress haptic feedback.
|
|
* @param subaction The subaction to apply haptics to, which must
|
|
* have been specified to Action::addSubaction().
|
|
* @return true on success, false otherwise.
|
|
*/
|
|
bool stopHapticFeedback(Subaction *subaction = nullptr);
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|