Merge pull request #14678 from hyperlogic/feature/hmd-avatar-alignment-type

Added HMD Avatar Alignment Type
This commit is contained in:
Shannon Romano 2019-01-25 17:32:41 -08:00 committed by GitHub
commit f084021fdf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 156 additions and 21 deletions

View file

@ -254,6 +254,7 @@ Rectangle {
onSaveClicked: function() {
var avatarSettings = {
dominantHand : settings.dominantHandIsLeft ? 'left' : 'right',
hmdAvatarAlignmentType : settings.hmdAvatarAlignmentTypeIsEyes ? 'eyes' : 'head',
collisionsEnabled : settings.environmentCollisionsOn,
otherAvatarsCollisionsEnabled : settings.otherAvatarsCollisionsOn,
animGraphOverrideUrl : settings.avatarAnimationOverrideJSON,

View file

@ -37,6 +37,7 @@ Rectangle {
property alias dominantHandIsLeft: leftHandRadioButton.checked
property alias otherAvatarsCollisionsOn: otherAvatarsCollisionsEnabledRadiobutton.checked
property alias environmentCollisionsOn: environmentCollisionsEnabledRadiobutton.checked
property alias hmdAvatarAlignmentTypeIsEyes: eyesRadioButton.checked
property alias avatarAnimationOverrideJSON: avatarAnimationUrlInputText.text
property alias avatarAnimationJSON: avatarAnimationUrlInputText.placeholderText
property alias avatarCollisionSoundUrl: avatarCollisionSoundUrlInputText.text
@ -65,6 +66,11 @@ Rectangle {
} else {
environmentCollisionsDisabledRadiobutton.checked = true;
}
if (settings.hmdAvatarAlignmentType === 'eyes') {
eyesRadioButton.checked = true;
} else {
headRadioButton.checked = true;
}
avatarAnimationJSON = settings.animGraphUrl;
avatarAnimationOverrideJSON = settings.animGraphOverrideUrl;
@ -210,7 +216,7 @@ Rectangle {
anchors.left: parent.left
anchors.right: parent.right
rows: 2
rows: 4
rowSpacing: 25
columns: 3
@ -233,7 +239,7 @@ Rectangle {
Layout.row: 0
Layout.column: 1
Layout.leftMargin: -20
Layout.leftMargin: -15
ButtonGroup.group: leftRight
checked: true
@ -249,7 +255,7 @@ Rectangle {
id: rightHandRadioButton
Layout.row: 0
Layout.column: 3
Layout.column: 2
Layout.rightMargin: -15
ButtonGroup.group: leftRight
@ -260,7 +266,7 @@ Rectangle {
text: "Right"
boxSize: 20
}
HifiConstants {
id: hifi
}
@ -272,17 +278,17 @@ Rectangle {
Layout.column: 0
text: "Avatar to avatar collision"
}
ButtonGroup {
id: otherAvatarsOnOff
}
HifiControlsUit.RadioButton {
id: otherAvatarsCollisionsEnabledRadiobutton
Layout.row: 1
Layout.column: 1
Layout.leftMargin: -20
Layout.leftMargin: -15
ButtonGroup.group: otherAvatarsOnOff
@ -297,7 +303,7 @@ Rectangle {
id: otherAvatarsCollisionsDisabledRadiobutton
Layout.row: 1
Layout.column: 3
Layout.column: 2
Layout.rightMargin: -15
ButtonGroup.group: otherAvatarsOnOff
@ -320,13 +326,13 @@ Rectangle {
ButtonGroup {
id: worldOnOff
}
HifiControlsUit.RadioButton {
id: environmentCollisionsEnabledRadiobutton
Layout.row: 2
Layout.column: 1
Layout.leftMargin: -20
Layout.leftMargin: -15
ButtonGroup.group: worldOnOff
@ -341,7 +347,7 @@ Rectangle {
id: environmentCollisionsDisabledRadiobutton
Layout.row: 2
Layout.column: 3
Layout.column: 2
Layout.rightMargin: -15
ButtonGroup.group: worldOnOff
@ -352,6 +358,52 @@ Rectangle {
text: "Off"
boxSize: 20
}
// TextStyle9
RalewaySemiBold {
size: 17;
Layout.row: 3
Layout.column: 0
text: "HMD Alignment"
}
ButtonGroup {
id: headEyes
}
HifiControlsUit.RadioButton {
id: headRadioButton
Layout.row: 3
Layout.column: 1
Layout.leftMargin: -15
ButtonGroup.group: headEyes
checked: true
colorScheme: hifi.colorSchemes.light
fontSize: 17
letterSpacing: 1.4
text: "Head"
boxSize: 20
}
HifiControlsUit.RadioButton {
id: eyesRadioButton
Layout.row: 3
Layout.column: 2
Layout.rightMargin: -15
ButtonGroup.group: headEyes
colorScheme: hifi.colorSchemes.light
fontSize: 17
letterSpacing: 1.4
text: "Eyes"
boxSize: 20
}
}
ColumnLayout {

View file

@ -6062,6 +6062,13 @@ void Application::update(float deltaTime) {
auto userInputMapper = DependencyManager::get<UserInputMapper>();
controller::HmdAvatarAlignmentType hmdAvatarAlignmentType;
if (myAvatar->getHmdAvatarAlignmentType() == "eyes") {
hmdAvatarAlignmentType = controller::HmdAvatarAlignmentType::Eyes;
} else {
hmdAvatarAlignmentType = controller::HmdAvatarAlignmentType::Head;
}
controller::InputCalibrationData calibrationData = {
myAvatar->getSensorToWorldMatrix(),
createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition()),
@ -6075,7 +6082,8 @@ void Application::update(float deltaTime) {
myAvatar->getRightArmCalibrationMat(),
myAvatar->getLeftArmCalibrationMat(),
myAvatar->getRightHandCalibrationMat(),
myAvatar->getLeftHandCalibrationMat()
myAvatar->getLeftHandCalibrationMat(),
hmdAvatarAlignmentType
};
InputPluginPointer keyboardMousePlugin;

View file

@ -125,6 +125,7 @@ MyAvatar::MyAvatar(QThread* thread) :
_prevShouldDrawHead(true),
_audioListenerMode(FROM_HEAD),
_dominantHandSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "dominantHand", DOMINANT_RIGHT_HAND),
_hmdAvatarAlignmentTypeSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "hmdAvatarAlignmentType", DEFAULT_HMD_AVATAR_ALIGNMENT_TYPE),
_headPitchSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "", 0.0f),
_scaleSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "scale", _targetScale),
_yawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "yawSpeed", _yawSpeed),
@ -286,10 +287,25 @@ MyAvatar::~MyAvatar() {
_myScriptEngine = nullptr;
}
QString MyAvatar::getDominantHand() const {
return _dominantHand.get();
}
void MyAvatar::setDominantHand(const QString& hand) {
if (hand == DOMINANT_LEFT_HAND || hand == DOMINANT_RIGHT_HAND) {
_dominantHand = hand;
emit dominantHandChanged(_dominantHand);
_dominantHand.set(hand);
emit dominantHandChanged(hand);
}
}
QString MyAvatar::getHmdAvatarAlignmentType() const {
return _hmdAvatarAlignmentType.get();
}
void MyAvatar::setHmdAvatarAlignmentType(const QString& type) {
if (type != _hmdAvatarAlignmentType.get()) {
_hmdAvatarAlignmentType.set(type);
emit hmdAvatarAlignmentTypeChanged(type);
}
}
@ -377,6 +393,7 @@ void MyAvatar::resetSensorsAndBody() {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "resetSensorsAndBody");
return;
}
qApp->getActiveDisplayPlugin()->resetSensors();
@ -1277,7 +1294,8 @@ void MyAvatar::resizeAvatarEntitySettingHandles(uint32_t maxIndex) {
}
void MyAvatar::saveData() {
_dominantHandSetting.set(_dominantHand);
_dominantHandSetting.set(getDominantHand());
_hmdAvatarAlignmentTypeSetting.set(getHmdAvatarAlignmentType());
_headPitchSetting.set(getHead()->getBasePitch());
_scaleSetting.set(_targetScale);
_yawSpeedSetting.set(_yawSpeed);
@ -1882,6 +1900,7 @@ void MyAvatar::loadData() {
setCollisionSoundURL(_collisionSoundURLSetting.get(QUrl(DEFAULT_AVATAR_COLLISION_SOUND_URL)).toString());
setSnapTurn(_useSnapTurnSetting.get());
setDominantHand(_dominantHandSetting.get(DOMINANT_RIGHT_HAND).toLower());
setHmdAvatarAlignmentType(_hmdAvatarAlignmentTypeSetting.get(DEFAULT_HMD_AVATAR_ALIGNMENT_TYPE).toLower());
setUserHeight(_userHeightSetting.get(DEFAULT_AVATAR_HEIGHT));
setTargetScale(_scaleSetting.get());

View file

@ -252,6 +252,7 @@ class MyAvatar : public Avatar {
const QString DOMINANT_LEFT_HAND = "left";
const QString DOMINANT_RIGHT_HAND = "right";
const QString DEFAULT_HMD_AVATAR_ALIGNMENT_TYPE = "head";
using Clock = std::chrono::system_clock;
using TimePoint = Clock::time_point;
@ -519,7 +520,18 @@ public:
* @function MyAvatar.getDominantHand
* @returns {string}
*/
Q_INVOKABLE QString getDominantHand() const { return _dominantHand; }
Q_INVOKABLE QString getDominantHand() const;
/**jsdoc
* @function MyAvatar.setHmdAvatarAlignmentType
* @param {string} hand
*/
Q_INVOKABLE void setHmdAvatarAlignmentType(const QString& hand);
/**jsdoc
* @function MyAvatar.setHmdAvatarAlignmentType
* @returns {string}
*/
Q_INVOKABLE QString getHmdAvatarAlignmentType() const;
/**jsdoc
* @function MyAvatar.setCenterOfGravityModelEnabled
@ -1585,6 +1597,13 @@ signals:
*/
void dominantHandChanged(const QString& hand);
/**jsdoc
* @function MyAvatar.hmdAvatarAlignmentTypeChanged
* @param {string} type
* @returns {Signal}
*/
void hmdAvatarAlignmentTypeChanged(const QString& type);
/**jsdoc
* @function MyAvatar.sensorToWorldScaleChanged
* @param {number} scale
@ -1773,7 +1792,8 @@ private:
ThreadSafeValueCache<QUrl> _prefOverrideAnimGraphUrl;
QUrl _fstAnimGraphOverrideUrl;
bool _useSnapTurn { true };
QString _dominantHand { DOMINANT_RIGHT_HAND };
ThreadSafeValueCache<QString> _dominantHand { DOMINANT_RIGHT_HAND };
ThreadSafeValueCache<QString> _hmdAvatarAlignmentType { DEFAULT_HMD_AVATAR_ALIGNMENT_TYPE };
const float ROLL_CONTROL_DEAD_ZONE_DEFAULT = 8.0f; // degrees
const float ROLL_CONTROL_RATE_DEFAULT = 114.0f; // degrees / sec
@ -1946,6 +1966,7 @@ private:
TimePoint _nextTraitsSendWindow;
Setting::Handle<QString> _dominantHandSetting;
Setting::Handle<QString> _hmdAvatarAlignmentTypeSetting;
Setting::Handle<float> _headPitchSetting;
Setting::Handle<float> _scaleSetting;
Setting::Handle<float> _yawSpeedSetting;

View file

@ -15,6 +15,11 @@
namespace controller {
enum class HmdAvatarAlignmentType {
Eyes = 0, // align the user's eyes with the avatars eyes
Head // align the user's head with the avatars head
};
struct InputCalibrationData {
glm::mat4 sensorToWorldMat; // sensor to world
glm::mat4 avatarMat; // avatar to world
@ -29,6 +34,7 @@ struct InputCalibrationData {
glm::mat4 defaultLeftArm; // default pose for leftArm joint in sensor space
glm::mat4 defaultRightHand; // default pose for rightHand joint in sensor space
glm::mat4 defaultLeftHand; // default pose for leftHand joint in sensor space
HmdAvatarAlignmentType hmdAvatarAlignmentType;
};
enum class ChannelType {

View file

@ -44,7 +44,7 @@ const float DEFAULT_AVATAR_RIGHTHAND_MASS = 2.0f;
// Used when avatar is missing joints... (avatar space)
const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 };
const glm::vec3 DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET = { 0.0f, 0.06f, -0.09f };
const glm::vec3 DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET = { 0.0f, 0.064f, 0.084f };
const glm::vec3 DEFAULT_AVATAR_HEAD_POS { 0.0f, 0.53f, 0.0f };
const glm::quat DEFAULT_AVATAR_HEAD_ROT { Quaternions::Y_180 };
const glm::vec3 DEFAULT_AVATAR_RIGHTARM_POS { -0.134824f, 0.396348f, -0.0515777f };

View file

@ -17,6 +17,7 @@
#include <controllers/UserInputMapper.h>
#include <controllers/StandardControls.h>
#include <AvatarConstants.h>
#include <PerfStat.h>
#include <PathUtils.h>
#include <NumericalConstants.h>
@ -327,8 +328,14 @@ void OculusControllerManager::TouchDevice::handleHeadPose(float deltaTime,
ovr::toGlm(headPose.AngularVelocity));
glm::mat4 sensorToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
glm::mat4 defaultHeadOffset = glm::inverse(inputCalibrationData.defaultCenterEyeMat) *
inputCalibrationData.defaultHeadMat;
glm::mat4 defaultHeadOffset;
if (inputCalibrationData.hmdAvatarAlignmentType == controller::HmdAvatarAlignmentType::Eyes) {
// align the eyes of the user with the eyes of the avatar
defaultHeadOffset = glm::inverse(inputCalibrationData.defaultCenterEyeMat) * inputCalibrationData.defaultHeadMat;
} else {
// align the head of the user with the head of the avatar
defaultHeadOffset = createMatFromQuatAndPos(Quaternions::IDENTITY, -DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET);
}
pose.valid = true;
_poseStateMap[controller::HEAD] = pose.postTransform(defaultHeadOffset).transform(sensorToAvatar);

View file

@ -27,6 +27,7 @@
#include <SettingHandle.h>
#include <OffscreenUi.h>
#include <GLMHelpers.h>
#include <AvatarConstants.h>
#include <glm/ext.hpp>
#include <glm/gtc/quaternion.hpp>
#include <ui-plugins/PluginContainer.h>
@ -1024,7 +1025,16 @@ void ViveControllerManager::InputDevice::handleHeadPoseEvent(const controller::I
//perform a 180 flip to make the HMD face the +z instead of -z, beacuse the head faces +z
glm::mat4 matYFlip = mat * Matrices::Y_180;
controller::Pose pose(extractTranslation(matYFlip), glmExtractRotation(matYFlip), linearVelocity, angularVelocity);
glm::mat4 defaultHeadOffset = glm::inverse(inputCalibrationData.defaultCenterEyeMat) * inputCalibrationData.defaultHeadMat;
glm::mat4 defaultHeadOffset;
if (inputCalibrationData.hmdAvatarAlignmentType == controller::HmdAvatarAlignmentType::Eyes) {
// align the eyes of the user with the eyes of the avatar
defaultHeadOffset = glm::inverse(inputCalibrationData.defaultCenterEyeMat) * inputCalibrationData.defaultHeadMat;
} else {
// align the head of the user with the head of the avatar
defaultHeadOffset = createMatFromQuatAndPos(Quaternions::IDENTITY, -DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET);
}
glm::mat4 sensorToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
_poseStateMap[controller::HEAD] = pose.postTransform(defaultHeadOffset).transform(sensorToAvatar);
}

View file

@ -62,6 +62,7 @@ function getMyAvatar() {
function getMyAvatarSettings() {
return {
dominantHand: MyAvatar.getDominantHand(),
hmdAvatarAlignmentType: MyAvatar.getHmdAvatarAlignmentType(),
collisionsEnabled: MyAvatar.getCollisionsEnabled(),
otherAvatarsCollisionsEnabled: MyAvatar.getOtherAvatarsCollisionsEnabled(),
collisionSoundUrl : MyAvatar.collisionSoundURL,
@ -129,6 +130,13 @@ function onDominantHandChanged(dominantHand) {
}
}
function onHmdAvatarAlignmentTypeChanged(type) {
if (currentAvatarSettings.hmdAvatarAlignmentType !== type) {
currentAvatarSettings.hmdAvatarAlignmentType = type;
sendToQml({'method' : 'settingChanged', 'name' : 'hmdAvatarAlignmentType', 'value' : type});
}
}
function onCollisionsEnabledChanged(enabled) {
if(currentAvatarSettings.collisionsEnabled !== enabled) {
currentAvatarSettings.collisionsEnabled = enabled;
@ -331,6 +339,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
currentAvatar.avatarScale = message.avatarScale;
MyAvatar.setDominantHand(message.settings.dominantHand);
MyAvatar.setHmdAvatarAlignmentType(message.settings.hmdAvatarAlignmentType);
MyAvatar.setOtherAvatarsCollisionsEnabled(message.settings.otherAvatarsCollisionsEnabled);
MyAvatar.setCollisionsEnabled(message.settings.collisionsEnabled);
MyAvatar.collisionSoundURL = message.settings.collisionSoundUrl;
@ -521,6 +530,7 @@ function off() {
Entities.deletingWearable.disconnect(onDeletingWearable);
MyAvatar.skeletonModelURLChanged.disconnect(onSkeletonModelURLChanged);
MyAvatar.dominantHandChanged.disconnect(onDominantHandChanged);
MyAvatar.hmdAvatarAlignmentTypeChanged.disconnect(onHmdAvatarAlignmentTypeChanged);
MyAvatar.collisionsEnabledChanged.disconnect(onCollisionsEnabledChanged);
MyAvatar.otherAvatarsCollisionsEnabledChanged.disconnect(onOtherAvatarsCollisionsEnabledChanged);
MyAvatar.newCollisionSoundURL.disconnect(onNewCollisionSoundUrl);
@ -542,6 +552,7 @@ function on() {
Entities.deletingWearable.connect(onDeletingWearable);
MyAvatar.skeletonModelURLChanged.connect(onSkeletonModelURLChanged);
MyAvatar.dominantHandChanged.connect(onDominantHandChanged);
MyAvatar.hmdAvatarAlignmentTypeChanged.connect(onHmdAvatarAlignmentTypeChanged);
MyAvatar.collisionsEnabledChanged.connect(onCollisionsEnabledChanged);
MyAvatar.otherAvatarsCollisionsEnabledChanged.connect(onOtherAvatarsCollisionsEnabledChanged);
MyAvatar.newCollisionSoundURL.connect(onNewCollisionSoundUrl);