JS calls for head motion/rotation that allow avatar flying with head movement

This commit is contained in:
Philip Rosedale 2014-08-18 21:32:40 -07:00
parent 5ca28901bd
commit 39b370979c
5 changed files with 100 additions and 14 deletions

View file

@ -21,10 +21,10 @@ var position = { x: MyAvatar.position.x, y: MyAvatar.position.y, z: MyAvatar.pos
var joysticksCaptured = false;
var THRUST_CONTROLLER = 0;
var VIEW_CONTROLLER = 1;
var INITIAL_THRUST_MULTPLIER = 1.0;
var INITIAL_THRUST_MULTIPLIER = 1.0;
var THRUST_INCREASE_RATE = 1.05;
var MAX_THRUST_MULTIPLIER = 75.0;
var thrustMultiplier = INITIAL_THRUST_MULTPLIER;
var thrustMultiplier = INITIAL_THRUST_MULTIPLIER;
var grabDelta = { x: 0, y: 0, z: 0};
var grabStartPosition = { x: 0, y: 0, z: 0};
var grabDeltaVelocity = { x: 0, y: 0, z: 0};
@ -34,6 +34,8 @@ var grabbingWithRightHand = false;
var wasGrabbingWithRightHand = false;
var grabbingWithLeftHand = false;
var wasGrabbingWithLeftHand = false;
var movingWithHead = false;
var headStartPosition, headStartPitch, headStartYaw;
var EPSILON = 0.000001;
var velocity = { x: 0, y: 0, z: 0};
var THRUST_MAG_UP = 100.0;
@ -241,6 +243,46 @@ function handleGrabBehavior(deltaTime) {
wasGrabbingWithLeftHand = grabbingWithLeftHand;
}
var HEAD_MOVE_DEAD_ZONE = 0.0;
var HEAD_STRAFE_DEAD_ZONE = 0.025;
var HEAD_ROTATE_DEAD_ZONE = 0.0;
var HEAD_THRUST_MULTIPLIER = 10000.0;
var HEAD_YAW_RATE = 2.0;
var HEAD_PITCH_RATE = 2.0;
function moveWithHead(deltaTime) {
if (movingWithHead) {
var deltaYaw = MyAvatar.getHeadFinalYaw() - headStartYaw;
var deltaPitch = MyAvatar.getHeadDeltaPitch() - headStartPitch;
print("delta pitch = " + deltaPitch);
var bodyLocalCurrentHeadVector = Vec3.subtract(MyAvatar.getHeadPosition(), MyAvatar.position);
bodyLocalCurrentHeadVector = Vec3.multiplyQbyV(Quat.angleAxis(-deltaYaw, {x:0, y: 1, z:0}), bodyLocalCurrentHeadVector);
var headDelta = Vec3.subtract(bodyLocalCurrentHeadVector, headStartPosition);
headDelta = Vec3.multiplyQbyV(Quat.inverse(Camera.getOrientation()), headDelta);
headDelta.y = 0.0; // Don't respond to any of the vertical component of head motion
Vec3.print("head delta ", headDelta);
// Lateral thrust (strafe)
//if (Math.abs(headDelta.z) > HEAD_STRAFE_DEAD_ZONE) {
// if (headDelta.z > 0) {
MyAvatar.addThrust(Vec3.multiply(Quat.getFront(Camera.getOrientation()), -headDelta.z * HEAD_THRUST_MULTIPLIER * deltaTime));
MyAvatar.addThrust(Vec3.multiply(Quat.getRight(Camera.getOrientation()), headDelta.x * HEAD_THRUST_MULTIPLIER * deltaTime));
// }
//}
//if (Vec3.length(headDelta) > HEAD_MOVE_DEAD_ZONE) {
// MyAvatar.addThrust(Vec3.multiply(headDelta, HEAD_THRUST_MULTIPLIER * deltaTime));
//}
if (Math.abs(deltaYaw) > HEAD_ROTATE_DEAD_ZONE) {
//print("yaw = " + deltaYaw);
var orientation = Quat.multiply(Quat.angleAxis(deltaYaw * HEAD_YAW_RATE * deltaTime, {x:0, y: 1, z:0}), MyAvatar.orientation);
MyAvatar.orientation = orientation;
}
MyAvatar.headPitch += deltaPitch * HEAD_PITCH_RATE * deltaTime;
}
}
// Update for joysticks and move button
function flyWithHydra(deltaTime) {
var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER);
@ -262,7 +304,7 @@ function flyWithHydra(deltaTime) {
thrustJoystickPosition.x * thrustMultiplier * deltaTime);
MyAvatar.addThrust(thrustRight);
} else {
thrustMultiplier = INITIAL_THRUST_MULTPLIER;
thrustMultiplier = INITIAL_THRUST_MULTIPLIER;
}
// View Controller
@ -280,6 +322,7 @@ function flyWithHydra(deltaTime) {
MyAvatar.headPitch = newPitch;
}
handleGrabBehavior(deltaTime);
moveWithHead(deltaTime);
displayDebug();
}
@ -296,3 +339,20 @@ function scriptEnding() {
}
Script.scriptEnding.connect(scriptEnding);
Controller.keyPressEvent.connect(function(event) {
if (event.text == "z" && !movingWithHead) {
movingWithHead = true;
headStartPosition = Vec3.subtract(MyAvatar.getHeadPosition(), MyAvatar.position);
headStartPitch = MyAvatar.getHeadDeltaPitch();
headStartYaw = MyAvatar.getHeadFinalYaw();
Vec3.print("head start position = ", headStartPosition);
print(" yaw = " + headStartYaw + " pitch = " + headStartPitch);
}
});
Controller.keyReleaseEvent.connect(function(event) {
if (event.text == "z") {
movingWithHead = false;
print("move ended");
}
});

View file

@ -106,7 +106,14 @@ public:
virtual int parseDataAtOffset(const QByteArray& packet, int offset);
static void sendKillAvatar();
Q_INVOKABLE glm::vec3 getHeadPosition() const { return getHead()->getPosition(); }
Q_INVOKABLE float getHeadFinalYaw() const { return getHead()->getFinalYaw(); }
Q_INVOKABLE float getHeadFinalPitch() const { return getHead()->getFinalPitch(); }
Q_INVOKABLE float getHeadDeltaPitch() const { return getHead()->getDeltaPitch(); }
Q_INVOKABLE glm::vec3 getEyePosition() const { return getHead()->getEyePosition(); }
Q_INVOKABLE glm::vec3 getTargetAvatarPosition() const { return _targetAvatarPosition; }
AvatarData* getLookAtTargetAvatar() const { return _lookAtTargetAvatar.data(); }
void updateLookAtTargetAvatar();

View file

@ -242,13 +242,11 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
// Set blendshapes
float EYE_MAGNIFIER = 4.0f;
float rightEye = (updateAndGetCoefficient(_rightEye, packet.expressions[0])) * EYE_MAGNIFIER;
float rightEye = glm::clamp((updateAndGetCoefficient(_rightEye, packet.expressions[0])) * EYE_MAGNIFIER, 0.0f, 1.0f);
_blendshapeCoefficients[_rightBlinkIndex] = rightEye;
float leftEye = (updateAndGetCoefficient(_leftEye, packet.expressions[1])) * EYE_MAGNIFIER;
float leftEye = glm::clamp((updateAndGetCoefficient(_leftEye, packet.expressions[1])) * EYE_MAGNIFIER, 0.0f, 1.0f);
_blendshapeCoefficients[_leftBlinkIndex] = leftEye;
// Right eye = packet.expressions[0];
float leftBrow = 1.0f - rescaleCoef(packet.expressions[14]);
if (leftBrow < 0.5f) {
@ -270,9 +268,9 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
float JAW_OPEN_MAGNIFIER = 1.4f;
_blendshapeCoefficients[_jawOpenIndex] = rescaleCoef(packet.expressions[21]) * JAW_OPEN_MAGNIFIER;
_blendshapeCoefficients[_mouthSmileLeftIndex] = rescaleCoef(packet.expressions[24]);
_blendshapeCoefficients[_mouthSmileRightIndex] = rescaleCoef(packet.expressions[23]);
float SMILE_MULTIPLIER = 2.0f;
_blendshapeCoefficients[_mouthSmileLeftIndex] = glm::clamp(packet.expressions[24] * SMILE_MULTIPLIER, 0.f, 1.f);
_blendshapeCoefficients[_mouthSmileRightIndex] = glm::clamp(packet.expressions[23] * SMILE_MULTIPLIER, 0.f, 1.f);
} else {

View file

@ -31,6 +31,10 @@ Faceshift::Faceshift() :
_tcpEnabled(true),
_tcpRetryCount(0),
_lastTrackingStateReceived(0),
_headAngularVelocity(0),
_headLinearVelocity(0),
_lastHeadTranslation(0),
_filteredHeadTranslation(0),
_eyeGazeLeftPitch(0.0f),
_eyeGazeLeftYaw(0.0f),
_eyeGazeRightPitch(0.0f),
@ -195,6 +199,7 @@ void Faceshift::send(const std::string& message) {
void Faceshift::receive(const QByteArray& buffer) {
#ifdef HAVE_FACESHIFT
float AVERAGE_FACESHIFT_FRAME_TIME = 0.033f;
_stream.received(buffer.size(), buffer.constData());
fsMsgPtr msg;
for (fsMsgPtr msg; (msg = _stream.get_message()); ) {
@ -209,7 +214,6 @@ void Faceshift::receive(const QByteArray& buffer) {
float theta = 2 * acos(r.w);
if (theta > EPSILON) {
float rMag = glm::length(glm::vec3(r.x, r.y, r.z));
float AVERAGE_FACESHIFT_FRAME_TIME = 0.033f;
_headAngularVelocity = theta / AVERAGE_FACESHIFT_FRAME_TIME * glm::vec3(r.x, r.y, r.z) / rMag;
} else {
_headAngularVelocity = glm::vec3(0,0,0);
@ -217,8 +221,22 @@ void Faceshift::receive(const QByteArray& buffer) {
_headRotation = newRotation;
const float TRANSLATION_SCALE = 0.02f;
_headTranslation = glm::vec3(data.m_headTranslation.x, data.m_headTranslation.y,
-data.m_headTranslation.z) * TRANSLATION_SCALE;
glm::vec3 newHeadTranslation = glm::vec3(data.m_headTranslation.x, data.m_headTranslation.y,
-data.m_headTranslation.z) * TRANSLATION_SCALE;
_headLinearVelocity = (newHeadTranslation - _lastHeadTranslation) / AVERAGE_FACESHIFT_FRAME_TIME;
//qDebug() << "Head vel: " << glm::length(_headLinearVelocity);
// Velocity filter the faceshift head translation because it's noisy
float velocityFilter = glm::clamp(1.0f - glm::length(_headLinearVelocity), 0.0f, 1.0f);
_filteredHeadTranslation = velocityFilter * _filteredHeadTranslation + (1.0f - velocityFilter) * newHeadTranslation;
_lastHeadTranslation = newHeadTranslation;
_headTranslation = _filteredHeadTranslation;
//_headTranslation = newHeadTranslation;
_eyeGazeLeftPitch = -data.m_eyeGazeLeftPitch;
_eyeGazeLeftYaw = data.m_eyeGazeLeftYaw;
_eyeGazeRightPitch = -data.m_eyeGazeRightPitch;

View file

@ -100,6 +100,9 @@ private:
quint64 _lastTrackingStateReceived;
glm::vec3 _headAngularVelocity;
glm::vec3 _headLinearVelocity;
glm::vec3 _lastHeadTranslation;
glm::vec3 _filteredHeadTranslation;
// degrees
float _eyeGazeLeftPitch;