From 902672f85ececbb87944a28e73efdde555d3a054 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 22 Feb 2018 17:20:36 -0800 Subject: [PATCH 1/5] add dynamic mode for scripted avatar motor --- interface/src/avatar/MyAvatar.cpp | 92 +++++++++++++++++++++++-------- interface/src/avatar/MyAvatar.h | 5 ++ libraries/gl/src/gl/Context.cpp | 2 +- 3 files changed, 75 insertions(+), 24 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c25aaeeecd..445b176c15 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -79,6 +79,8 @@ float DEFAULT_SCRIPTED_MOTOR_TIMESCALE = 1.0e6f; const int SCRIPTED_MOTOR_CAMERA_FRAME = 0; const int SCRIPTED_MOTOR_AVATAR_FRAME = 1; const int SCRIPTED_MOTOR_WORLD_FRAME = 2; +const int SCRIPTED_MOTOR_SIMPLE_MODE = 0; +const int SCRIPTED_MOTOR_DYNAMIC_MODE = 1; const QString& DEFAULT_AVATAR_COLLISION_SOUND_URL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/Body_Hits_Impact.wav"; const float MyAvatar::ZOOM_MIN = 0.5f; @@ -92,6 +94,7 @@ MyAvatar::MyAvatar(QThread* thread) : _pitchSpeed(PITCH_SPEED_DEFAULT), _scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE), _scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME), + _scriptedMotorMode(SCRIPTED_MOTOR_SIMPLE_MODE), _motionBehaviors(AVATAR_MOTION_DEFAULTS), _characterController(this), _eyeContactTarget(LEFT_EYE), @@ -1623,32 +1626,38 @@ controller::Pose MyAvatar::getControllerPoseInAvatarFrame(controller::Action act void MyAvatar::updateMotors() { _characterController.clearMotors(); glm::quat motorRotation; + glm::quat avatarOrientation = getWorldOrientation(); + + const float FLYING_MOTOR_TIMESCALE = 0.05f; + const float WALKING_MOTOR_TIMESCALE = 0.2f; + const float INVALID_MOTOR_TIMESCALE = 1.0e6f; + + float horizontalMotorTimescale; + float verticalMotorTimescale; + + if (_characterController.getState() == CharacterController::State::Hover || + _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { + horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE; + verticalMotorTimescale = FLYING_MOTOR_TIMESCALE; + } + else { + horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE; + verticalMotorTimescale = INVALID_MOTOR_TIMESCALE; + } + if (_motionBehaviors & AVATAR_MOTION_ACTION_MOTOR_ENABLED) { - - const float FLYING_MOTOR_TIMESCALE = 0.05f; - const float WALKING_MOTOR_TIMESCALE = 0.2f; - const float INVALID_MOTOR_TIMESCALE = 1.0e6f; - - float horizontalMotorTimescale; - float verticalMotorTimescale; - if (_characterController.getState() == CharacterController::State::Hover || _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { motorRotation = getMyHead()->getHeadOrientation(); - horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE; - verticalMotorTimescale = FLYING_MOTOR_TIMESCALE; } else { // non-hovering = walking: follow camera twist about vertical but not lift // we decompose camera's rotation and store the twist part in motorRotation // however, we need to perform the decomposition in the avatar-frame // using the local UP axis and then transform back into world-frame - glm::quat orientation = getWorldOrientation(); - glm::quat headOrientation = glm::inverse(orientation) * getMyHead()->getHeadOrientation(); // avatar-frame + glm::quat headOrientation = glm::inverse(avatarOrientation) * getMyHead()->getHeadOrientation(); // avatar-frame glm::quat liftRotation; swingTwistDecomposition(headOrientation, Vectors::UNIT_Y, liftRotation, motorRotation); - motorRotation = orientation * motorRotation; - horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE; - verticalMotorTimescale = INVALID_MOTOR_TIMESCALE; + motorRotation = avatarOrientation * motorRotation; } if (_isPushing || _isBraking || !_isBeingPushed) { @@ -1660,15 +1669,36 @@ void MyAvatar::updateMotors() { } } if (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) { - if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { - motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); - } else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { - motorRotation = getWorldOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); - } else { - // world-frame - motorRotation = glm::quat(); + if (_scriptedMotorMode == SCRIPTED_MOTOR_SIMPLE_MODE) { + if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { + motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); + } + else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { + motorRotation = avatarOrientation * glm::angleAxis(PI, Vectors::UNIT_Y); + } + else { + // world-frame + motorRotation = glm::quat(); + } + _characterController.addMotor(_scriptedMotorVelocity, motorRotation, _scriptedMotorTimescale); + } else { + // dynamic mode + glm::vec3 avatarFrameVelocity; + if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { + // convert camera frame velocity to avatar frame + glm::quat cameraOrientation = qApp->getCamera().getOrientation(); + avatarFrameVelocity = glm::inverse(avatarOrientation) * cameraOrientation * _scriptedMotorVelocity; + } else if (_scriptedMotorFrame == SCRIPTED_MOTOR_WORLD_FRAME) { + // convert world frame velocity to avatar frame + avatarFrameVelocity = glm::inverse(avatarOrientation) * _scriptedMotorVelocity; + } else { + // avatar frame + avatarFrameVelocity = _scriptedMotorVelocity; + } + // dynamic mode for scripted motor uses avatar frame and piggybacks off of the default action motor's timescales + motorRotation = avatarOrientation * glm::angleAxis(PI, Vectors::UNIT_Y); + _characterController.addMotor(avatarFrameVelocity, motorRotation, horizontalMotorTimescale, verticalMotorTimescale); } - _characterController.addMotor(_scriptedMotorVelocity, motorRotation, _scriptedMotorTimescale); } // legacy support for 'MyAvatar::applyThrust()', which has always been implemented as a @@ -1752,6 +1782,14 @@ QString MyAvatar::getScriptedMotorFrame() const { return frame; } +QString MyAvatar::getScriptedMotorMode() const { + QString mode = "simple"; + if (_scriptedMotorMode == SCRIPTED_MOTOR_DYNAMIC_MODE) { + mode = "dynamic"; + } + return mode; +} + void MyAvatar::setScriptedMotorVelocity(const glm::vec3& velocity) { float MAX_SCRIPTED_MOTOR_SPEED = 500.0f; _scriptedMotorVelocity = velocity; @@ -1778,6 +1816,14 @@ void MyAvatar::setScriptedMotorFrame(QString frame) { } } +void MyAvatar::setScriptedMotorMode(QString frame) { + if (frame.toLower() == "simple") { + _scriptedMotorMode = SCRIPTED_MOTOR_SIMPLE_MODE; + } else if (frame.toLower() == "dynamic") { + _scriptedMotorMode = SCRIPTED_MOTOR_DYNAMIC_MODE; + } +} + void MyAvatar::clearScriptableSettings() { _scriptedMotorVelocity = Vectors::ZERO; _scriptedMotorTimescale = DEFAULT_SCRIPTED_MOTOR_TIMESCALE; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 28af8b62fd..464d94bce7 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -69,6 +69,7 @@ class MyAvatar : public Avatar { * @property motorTimescale {float} Specifies how quickly the avatar should accelerate to meet the motorVelocity, * smaller values will result in higher acceleration. * @property motorReferenceFrame {string} Reference frame of the motorVelocity, must be one of the following: "avatar", "camera", "world" + * @property motorMode {string} Type of scripted motor behavior, "simple" = unmodified legacy behavior and "dynamic" = same as default motor * @property collisionSoundURL {string} Specifies the sound to play when the avatar experiences a collision. * You can provide a mono or stereo 16-bit WAV file running at either 24 Khz or 48 Khz. * The latter is downsampled by the audio mixer, so all audio effectively plays back at a 24 Khz sample rate. @@ -124,6 +125,7 @@ class MyAvatar : public Avatar { Q_PROPERTY(glm::vec3 motorVelocity READ getScriptedMotorVelocity WRITE setScriptedMotorVelocity) Q_PROPERTY(float motorTimescale READ getScriptedMotorTimescale WRITE setScriptedMotorTimescale) Q_PROPERTY(QString motorReferenceFrame READ getScriptedMotorFrame WRITE setScriptedMotorFrame) + Q_PROPERTY(QString motorMode READ getScriptedMotorMode WRITE setScriptedMotorMode) Q_PROPERTY(QString collisionSoundURL READ getCollisionSoundURL WRITE setCollisionSoundURL) Q_PROPERTY(AudioListenerMode audioListenerMode READ getAudioListenerMode WRITE setAudioListenerMode) Q_PROPERTY(glm::vec3 customListenPosition READ getCustomListenPosition WRITE setCustomListenPosition) @@ -662,9 +664,11 @@ private: glm::vec3 getScriptedMotorVelocity() const { return _scriptedMotorVelocity; } float getScriptedMotorTimescale() const { return _scriptedMotorTimescale; } QString getScriptedMotorFrame() const; + QString getScriptedMotorMode() const; void setScriptedMotorVelocity(const glm::vec3& velocity); void setScriptedMotorTimescale(float timescale); void setScriptedMotorFrame(QString frame); + void setScriptedMotorMode(QString frame); virtual void attach(const QString& modelURL, const QString& jointName = QString(), const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(), float scale = 1.0f, bool isSoft = false, @@ -706,6 +710,7 @@ private: glm::vec3 _scriptedMotorVelocity; // target local-frame velocity of avatar (analog script) float _scriptedMotorTimescale; // timescale for avatar to achieve its target velocity int _scriptedMotorFrame; + int _scriptedMotorMode; quint32 _motionBehaviors; QString _collisionSoundURL; diff --git a/libraries/gl/src/gl/Context.cpp b/libraries/gl/src/gl/Context.cpp index 309839808e..155849bffa 100644 --- a/libraries/gl/src/gl/Context.cpp +++ b/libraries/gl/src/gl/Context.cpp @@ -147,7 +147,7 @@ static void debugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum s } // FIXME For high severity errors, force a sync to the log, since we might crash // before the log file was flushed otherwise. Performance hit here - qCDebug(glLogging) << "OpenGL: " << message; + //qCDebug(glLogging) << "OpenGL: " << message; } static void setupPixelFormatSimple(HDC hdc) { From ba0ba96d81a096100948d11730b3ff2d7b3825a3 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 22 Feb 2018 17:54:03 -0800 Subject: [PATCH 2/5] undo --- libraries/gl/src/gl/Context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gl/src/gl/Context.cpp b/libraries/gl/src/gl/Context.cpp index 155849bffa..309839808e 100644 --- a/libraries/gl/src/gl/Context.cpp +++ b/libraries/gl/src/gl/Context.cpp @@ -147,7 +147,7 @@ static void debugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum s } // FIXME For high severity errors, force a sync to the log, since we might crash // before the log file was flushed otherwise. Performance hit here - //qCDebug(glLogging) << "OpenGL: " << message; + qCDebug(glLogging) << "OpenGL: " << message; } static void setupPixelFormatSimple(HDC hdc) { From a418129bea79b5f7cb2e0724305377d7db067258 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 23 Feb 2018 15:00:23 -0800 Subject: [PATCH 3/5] simplify to just changing timescales --- interface/src/avatar/MyAvatar.cpp | 44 +++++++++++-------------------- interface/src/avatar/MyAvatar.h | 4 +-- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index d5d85b3365..4a58af9378 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1626,7 +1626,6 @@ controller::Pose MyAvatar::getControllerPoseInAvatarFrame(controller::Action act void MyAvatar::updateMotors() { _characterController.clearMotors(); glm::quat motorRotation; - glm::quat avatarOrientation = getWorldOrientation(); const float FLYING_MOTOR_TIMESCALE = 0.05f; const float WALKING_MOTOR_TIMESCALE = 0.2f; @@ -1654,10 +1653,11 @@ void MyAvatar::updateMotors() { // we decompose camera's rotation and store the twist part in motorRotation // however, we need to perform the decomposition in the avatar-frame // using the local UP axis and then transform back into world-frame - glm::quat headOrientation = glm::inverse(avatarOrientation) * getMyHead()->getHeadOrientation(); // avatar-frame + glm::quat orientation = getWorldOrientation(); + glm::quat headOrientation = glm::inverse(orientation) * getMyHead()->getHeadOrientation(); // avatar-frame glm::quat liftRotation; swingTwistDecomposition(headOrientation, Vectors::UNIT_Y, liftRotation, motorRotation); - motorRotation = avatarOrientation * motorRotation; + motorRotation = orientation * motorRotation; } if (_isPushing || _isBraking || !_isBeingPushed) { @@ -1669,35 +1669,21 @@ void MyAvatar::updateMotors() { } } if (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) { + if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { + motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); + } + else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { + motorRotation = getWorldOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); + } + else { + // world-frame + motorRotation = glm::quat(); + } if (_scriptedMotorMode == SCRIPTED_MOTOR_SIMPLE_MODE) { - if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { - motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); - } - else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { - motorRotation = avatarOrientation * glm::angleAxis(PI, Vectors::UNIT_Y); - } - else { - // world-frame - motorRotation = glm::quat(); - } _characterController.addMotor(_scriptedMotorVelocity, motorRotation, _scriptedMotorTimescale); - } else { + } else { // dynamic mode - glm::vec3 avatarFrameVelocity; - if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { - // convert camera frame velocity to avatar frame - glm::quat cameraOrientation = qApp->getCamera().getOrientation(); - avatarFrameVelocity = glm::inverse(avatarOrientation) * cameraOrientation * _scriptedMotorVelocity; - } else if (_scriptedMotorFrame == SCRIPTED_MOTOR_WORLD_FRAME) { - // convert world frame velocity to avatar frame - avatarFrameVelocity = glm::inverse(avatarOrientation) * _scriptedMotorVelocity; - } else { - // avatar frame - avatarFrameVelocity = _scriptedMotorVelocity; - } - // dynamic mode for scripted motor uses avatar frame and piggybacks off of the default action motor's timescales - motorRotation = avatarOrientation * glm::angleAxis(PI, Vectors::UNIT_Y); - _characterController.addMotor(avatarFrameVelocity, motorRotation, horizontalMotorTimescale, verticalMotorTimescale); + _characterController.addMotor(_scriptedMotorVelocity, motorRotation, horizontalMotorTimescale, verticalMotorTimescale); } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 464d94bce7..fa5206e128 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -69,7 +69,7 @@ class MyAvatar : public Avatar { * @property motorTimescale {float} Specifies how quickly the avatar should accelerate to meet the motorVelocity, * smaller values will result in higher acceleration. * @property motorReferenceFrame {string} Reference frame of the motorVelocity, must be one of the following: "avatar", "camera", "world" - * @property motorMode {string} Type of scripted motor behavior, "simple" = unmodified legacy behavior and "dynamic" = same as default motor + * @property motorMode {string} Type of scripted motor behavior, "simple" = use motorTimescale property (default mode) and "dynamic" = use action motor's timescales * @property collisionSoundURL {string} Specifies the sound to play when the avatar experiences a collision. * You can provide a mono or stereo 16-bit WAV file running at either 24 Khz or 48 Khz. * The latter is downsampled by the audio mixer, so all audio effectively plays back at a 24 Khz sample rate. @@ -668,7 +668,7 @@ private: void setScriptedMotorVelocity(const glm::vec3& velocity); void setScriptedMotorTimescale(float timescale); void setScriptedMotorFrame(QString frame); - void setScriptedMotorMode(QString frame); + void setScriptedMotorMode(QString mode); virtual void attach(const QString& modelURL, const QString& jointName = QString(), const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(), float scale = 1.0f, bool isSoft = false, From da391564a8577676875c34335f5f31fcc742a1e9 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 23 Feb 2018 15:01:29 -0800 Subject: [PATCH 4/5] CR changes --- interface/src/avatar/MyAvatar.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4a58af9378..28cfb3e8f4 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1638,8 +1638,7 @@ void MyAvatar::updateMotors() { _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE; verticalMotorTimescale = FLYING_MOTOR_TIMESCALE; - } - else { + } else { horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE; verticalMotorTimescale = INVALID_MOTOR_TIMESCALE; } @@ -1671,11 +1670,9 @@ void MyAvatar::updateMotors() { if (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) { if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); - } - else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { + } else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { motorRotation = getWorldOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); - } - else { + } else { // world-frame motorRotation = glm::quat(); } From 283b5724ba42b69edec649ed15a0a60335c29e1d Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 23 Feb 2018 15:02:51 -0800 Subject: [PATCH 5/5] CR changes --- interface/src/avatar/MyAvatar.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 28cfb3e8f4..b6fa3fde96 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1799,10 +1799,10 @@ void MyAvatar::setScriptedMotorFrame(QString frame) { } } -void MyAvatar::setScriptedMotorMode(QString frame) { - if (frame.toLower() == "simple") { +void MyAvatar::setScriptedMotorMode(QString mode) { + if (mode.toLower() == "simple") { _scriptedMotorMode = SCRIPTED_MOTOR_SIMPLE_MODE; - } else if (frame.toLower() == "dynamic") { + } else if (mode.toLower() == "dynamic") { _scriptedMotorMode = SCRIPTED_MOTOR_DYNAMIC_MODE; } }