/** * @file * * @author Max Lammers * @author Mamadou Babaei * * @section LICENSE * * Copyright (c) 2020 - 2022 SenseGlove * * @section DESCRIPTION * * Data class containing all variables to draw or analyze a virtual hand in * different formats. */ #pragma once #include #include #include #include "BasicHandModel.hpp" #include "Fingers.hpp" #include "Platform.hpp" namespace SGCore { namespace Kinematics { class Quat; class Vect3D; }// namespace Kinematics /// Contains all variables required to draw or analyze a virtual hand. class SGCORE_API HandPose; }// namespace SGCore /// Contains all variables required to draw or analyze a virtual hand. class SGCORE_API SGCore::HandPose { public: /// Deserialize a HandPose back into usable values. static HandPose Deserialize(const std::string& serializedString); //--------------------------------------------------------------------------------------------------------------------- // Generating Poses /// Generate a HandPose based on articulation angles (handAngles). /// /// /// /// static HandPose FromHandAngles(const std::vector>& handAngles, bool bRightHanded, const Kinematics::BasicHandModel& handDimensions); /// Generate a HandPose based on articulation angles (handAngles), with a default HandModel. /// /// /// static HandPose FromHandAngles(const std::vector>& handAngles, bool bRightHanded); /// Create a new instance of a left or right handed Pose that is "idle"; in a neutral position. /// /// /// static HandPose DefaultIdle(bool bRightHanded, const Kinematics::BasicHandModel& handDimensions); /// Create a new instance of a left or right handed Pose that is "idle"; in a neutral position. /// /// static HandPose DefaultIdle(bool bRightHanded); /// Generates a HandPose representing an 'open hand', used in calibration to determine finger extension. /// /// /// static HandPose FlatHand(bool bRightHanded, const Kinematics::BasicHandModel& handDimensions); /// Generates a HandPose representing an 'open hand', used in calibration to determine finger extension. /// /// static HandPose FlatHand(bool bRightHanded); /// Generates a HandPose representing a 'thumbs up', used in calibration to determine finger flexion, thumb extension and adduction. /// /// /// static HandPose ThumbsUp(bool bRightHanded, const Kinematics::BasicHandModel& handDimensions); /// Generates a HandPose representing a 'thumbs up', used in calibration to determine finger flexion, thumb extension and adduction. /// /// static HandPose ThumbsUp(bool bRightHanded); /// Generates a HandPose representing a 'fist', used in calibration to determine, thumb flexion and abduction. /// /// /// static HandPose Fist(bool bRightHanded, const Kinematics::BasicHandModel& handDimensions); /// Generates a HandPose representing a 'fist', used in calibration to determine, thumb flexion and abduction. /// /// static HandPose Fist(bool bRightHanded); private: struct Impl; std::unique_ptr Pimpl; public: /// The default constructor. HandPose(); /// Create a new instance of HandPose. HandPose(bool bRightHanded, const std::vector>& jointPositions, const std::vector>& jointRotations, const std::vector>& handAngles); /** * The copy constructor. */ HandPose(const HandPose& rhs); /** * The move constructor. */ HandPose(HandPose&& rhs) noexcept; /// Default Destructor. virtual ~HandPose(); public: /** * The copy assignment operator. */ HandPose& operator=(const HandPose& rhs); /** * The move assignment operator. */ HandPose& operator=(HandPose&& rhs) noexcept; public: /// Whether this HandPose was created to be a right- or left hand. [[nodiscard]] bool IsRight() const; #if SENSEGLOVE_UNREAL_ENGINE_PLUGIN void SetIsRight(bool bRightHanded); #endif /* SENSEGLOVE_UNREAL_ENGINE_PLUGIN */ /// Positions of all hand joints relative to the Sense Glove origin. From thumb to pinky, proximal to distal. [[nodiscard]] const std::vector>& GetJointPositions() const; #if SENSEGLOVE_UNREAL_ENGINE_PLUGIN void SetJointPositions(const std::vector>& jointPositions); #endif /* SENSEGLOVE_UNREAL_ENGINE_PLUGIN */ /// Quaternion rotations of all hand joints. From thumb to pinky, proximal to distal. [[nodiscard]] const std::vector>& GetJointRotations() const; #if SENSEGLOVE_UNREAL_ENGINE_PLUGIN void SetJointRotations(const std::vector>& jointRotations); #endif /* SENSEGLOVE_UNREAL_ENGINE_PLUGIN */ /// Euler representations of all possible hand angles. From thumb to pinky, proximal to distal. [[nodiscard]] const std::vector>& GetHandAngles() const; #if SENSEGLOVE_UNREAL_ENGINE_PLUGIN void SetHandAngles(const std::vector>& handAngles); #endif /* SENSEGLOVE_UNREAL_ENGINE_PLUGIN */ public: /// Returns true of these two hand poses are roughly equal. [[nodiscard]] bool Equals(const HandPose& handPose) const; //--------------------------------------------------------------------------------------------------------------------- // Formats //GetFormat (animator), GetFormat (MoCap), etc? /// Returns the total flexion of a specific finger as a value between 0 (fully extended) and 1 (fully flexed). /// Useful for animation or for detecting gestures. [[nodiscard]] float GetNormalizedFlexion(EFinger finger, bool bClamp01 = true) const; /// Returns the total flexion the fingers as a value between 0 (fully extended) and 1 (fully flexed). /// Useful for animation or for detecting gestures. [[nodiscard]] std::vector GetNormalizedFlexion(bool bClamp01 = true) const; protected: /// Returns the total flexion of a specific finger as a value between 0 (fully extended) and 1 (fully flexed). /// Separate function because we use it multiple times, protected because we don't want indexOutOfRange exceptions. [[nodiscard]] float GetNormalizedFlexion(int32_t finger, bool bClamp01 = true) const; public: [[nodiscard]] std::string ToString(bool bShortFormat = false) const; /// Serialize this HandPose into a string representation. [[nodiscard]] std::string Serialize() const; };