mirror of
https://github.com/overte-org/overte.git
synced 2025-08-14 11:09:38 +02:00
JS calls for head motion/rotation that allow avatar flying with head movement
This commit is contained in:
parent
5ca28901bd
commit
39b370979c
5 changed files with 100 additions and 14 deletions
|
@ -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");
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -100,6 +100,9 @@ private:
|
|||
quint64 _lastTrackingStateReceived;
|
||||
|
||||
glm::vec3 _headAngularVelocity;
|
||||
glm::vec3 _headLinearVelocity;
|
||||
glm::vec3 _lastHeadTranslation;
|
||||
glm::vec3 _filteredHeadTranslation;
|
||||
|
||||
// degrees
|
||||
float _eyeGazeLeftPitch;
|
||||
|
|
Loading…
Reference in a new issue