mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 21:33:09 +02:00
add dynamic mode for scripted avatar motor
This commit is contained in:
parent
10f99602bb
commit
902672f85e
3 changed files with 75 additions and 24 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue