This commit is contained in:
amerhifi 2019-11-12 09:35:47 -08:00
commit 89d494cf81
44 changed files with 450 additions and 260 deletions

View file

@ -15,6 +15,7 @@
<uses-feature android:name="android.hardware.sensor.gyroscope" android:required="true"/>
<uses-feature android:name="android.software.vr.mode" android:required="true"/>
<uses-feature android:name="android.hardware.vr.high_performance" android:required="true"/>
<uses-feature android:name="android.hardware.vr.headtracking" android:version="1" android:required="true" />
<application
android:name="org.qtproject.qt5.android.bindings.QtApplication"

View file

@ -399,6 +399,7 @@ void Agent::executeScript() {
}
// these procedural movements are included in the recordings
scriptedAvatar->setHasScriptedBlendshapes(true);
scriptedAvatar->setHasProceduralEyeFaceMovement(false);
scriptedAvatar->setHasProceduralBlinkFaceMovement(false);
scriptedAvatar->setHasAudioEnabledFaceMovement(false);
@ -406,6 +407,7 @@ void Agent::executeScript() {
scriptedAvatar->clearRecordingBasis();
// restore procedural blendshape movement
scriptedAvatar->setHasScriptedBlendshapes(false);
scriptedAvatar->setHasProceduralEyeFaceMovement(true);
scriptedAvatar->setHasProceduralBlinkFaceMovement(true);
scriptedAvatar->setHasAudioEnabledFaceMovement(true);

View file

@ -782,7 +782,7 @@ float computeGain(float masterAvatarGain,
gain *= std::max(1.0f - d / (distanceLimit - ATTN_DISTANCE_REF), 0.0f);
gain = std::min(gain, ATTN_GAIN_MAX);
} else {
} else if (attenuationPerDoublingInDistance < 1.0f) {
// translate a positive zone setting to gain per log2(distance)
const float MIN_ATTENUATION_COEFFICIENT = 0.001f; // -60dB per log2(distance)
float g = glm::clamp(1.0f - attenuationPerDoublingInDistance, MIN_ATTENUATION_COEFFICIENT, 1.0f);
@ -792,6 +792,10 @@ float computeGain(float masterAvatarGain,
float d = (1.0f / ATTN_DISTANCE_REF) * std::max(distance, HRTF_NEARFIELD_MIN);
gain *= fastExp2f(fastLog2f(g) * fastLog2f(d));
gain = std::min(gain, ATTN_GAIN_MAX);
} else {
// translate a zone setting of 1.0 be silent at any distance
gain = 0.0f;
}
return gain;

View file

@ -58,3 +58,7 @@ if (ANDROID)
list(APPEND EXTERNAL_ARGS -DANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN})
list(APPEND EXTERNAL_ARGS -DANDROID_STL=${ANDROID_STL})
endif ()
if (APPLE)
set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep")
endif()

View file

@ -4804,16 +4804,117 @@
},
{
"children": [
{
"children": [
],
"data": {
"endFrame": 59,
"loopFlag": false,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/settle_to_idle.fbx"
},
"id": "idleSettle01",
"type": "clip"
},
{
"children": [
],
"data": {
"blendType": "",
"endFrame": 40,
"loopFlag": false,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/settle_to_idle02.fbx"
},
"id": "idleSettle02",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 60,
"loopFlag": false,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/settle_to_idle03.fbx"
},
"id": "idleSettle03",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 82,
"loopFlag": false,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/settle_to_idle04.fbx"
},
"id": "idleSettle04",
"type": "clip"
}
],
"data": {
"currentState": "idleSettle01",
"endFrame": 59,
"loopFlag": false,
"randomSwitchTimeMin": 1,
"startFrame": 1,
"states": [
{
"easingType": "easeInOutQuad",
"id": "idleSettle01",
"interpDuration": 1,
"interpTarget": 1,
"interpType": "evaluateBoth",
"priority": 1,
"resume": false,
"transitions": [
]
},
{
"easingType": "easeInOutQuad",
"id": "idleSettle02",
"interpDuration": 1,
"interpTarget": 1,
"interpType": "evaluateBoth",
"priority": 1,
"resume": false,
"transitions": [
]
},
{
"easingType": "easeInOutQuad",
"id": "idleSettle03",
"interpDuration": 1,
"interpTarget": 1,
"interpType": "evaluateBoth",
"priority": 1,
"resume": false,
"transitions": [
]
},
{
"easingType": "easeInOutQuad",
"id": "idleSettle04",
"interpDuration": 1,
"interpTarget": 1,
"interpType": "evaluateBoth",
"priority": 1,
"resume": false,
"transitions": [
]
}
],
"timeScale": 1,
"url": "qrc:///avatar/animations/settle_to_idle_small.fbx"
"url": "qrc:///avatar/animations/settle_to_idle.fbx"
},
"id": "idleSettle",
"type": "clip"
"type": "randomSwitchStateMachine"
},
{
"children": [
@ -5346,6 +5447,19 @@
},
"id": "LANDRUN",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 40,
"loopFlag": false,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/settle_to_idle_small.fbx"
},
"id": "idleSettleSmall",
"type": "clip"
}
],
"data": {
@ -5371,7 +5485,7 @@
{
"easingType": "easeInOutQuad",
"id": "idle",
"interpDuration": 15,
"interpDuration": 20,
"interpTarget": 20,
"interpType": "evaluateBoth",
"transitions": [
@ -5503,13 +5617,114 @@
{
"easingType": "easeInOutQuad",
"id": "idleSettle",
"interpDuration": 13,
"interpTarget": 14,
"interpDuration": 15,
"interpTarget": 15,
"interpType": "snapshotPrev",
"transitions": [
{
"state": "idle",
"var": "idleSettleOnDone"
"var": "idleSettle01OnDone"
},
{
"state": "idle",
"var": "idleSettle02OnDone"
},
{
"state": "idle",
"var": "idleSettle03OnDone"
},
{
"state": "idle",
"var": "idleSettle04OnDone"
},
{
"state": "idle",
"var": "reactionPositiveTrigger"
},
{
"state": "idle",
"var": "reactionNegativeTrigger"
},
{
"state": "idle",
"var": "reactionRaiseHandEnabled"
},
{
"state": "idle",
"var": "reactionApplaudEnabled"
},
{
"state": "idle",
"var": "reactionPointEnabled"
},
{
"state": "WALKFWD",
"var": "isInputForward"
},
{
"state": "WALKBWD",
"var": "isInputBackward"
},
{
"state": "STRAFERIGHT",
"var": "isInputRight"
},
{
"state": "STRAFELEFT",
"var": "isInputLeft"
},
{
"state": "strafeRightHmd",
"var": "isMovingRightHmd"
},
{
"state": "strafeLeftHmd",
"var": "isMovingLeftHmd"
},
{
"state": "turnRight",
"var": "isTurningRight"
},
{
"state": "turnLeft",
"var": "isTurningLeft"
},
{
"state": "fly",
"var": "isFlying"
},
{
"state": "takeoffStand",
"var": "isTakeoffStand"
},
{
"state": "TAKEOFFRUN",
"var": "isTakeoffRun"
},
{
"state": "inAirStand",
"var": "isInAirStand"
},
{
"state": "INAIRRUN",
"var": "isInAirRun"
},
{
"state": "seated",
"var": "isSeated"
}
]
},
{
"easingType": "easeInOutQuad",
"id": "idleSettleSmall",
"interpDuration": 10,
"interpTarget": 10,
"interpType": "snapshotPrev",
"transitions": [
{
"state": "idle",
"var": "idleSettleSmallOnDone"
},
{
"state": "idle",
@ -5595,6 +5810,10 @@
"interpTarget": 35,
"interpType": "snapshotPrev",
"transitions": [
{
"state": "idleSettleSmall",
"var": "isNotInputNoMomentum"
},
{
"state": "idleSettle",
"var": "isNotInputSlow"
@ -5659,6 +5878,10 @@
"interpTarget": 35,
"interpType": "snapshotPrev",
"transitions": [
{
"state": "idleSettleSmall",
"var": "isNotInputNoMomentum"
},
{
"state": "idleSettle",
"var": "isNotInputSlow"
@ -5723,6 +5946,10 @@
"interpTarget": 25,
"interpType": "snapshotPrev",
"transitions": [
{
"state": "idleSettleSmall",
"var": "isNotInputNoMomentum"
},
{
"state": "idleSettle",
"var": "isNotInputSlow"
@ -5787,6 +6014,10 @@
"interpTarget": 25,
"interpType": "snapshotPrev",
"transitions": [
{
"state": "idleSettleSmall",
"var": "isNotInputNoMomentum"
},
{
"state": "idleSettle",
"var": "isNotInputSlow"

View file

@ -201,8 +201,6 @@
{ "from": "Standard.LipsStretch_R", "to": "Actions.LipsStretch_R" },
{ "from": "Standard.LipsUpperClose", "to": "Actions.LipsUpperClose" },
{ "from": "Standard.LipsLowerClose", "to": "Actions.LipsLowerClose" },
{ "from": "Standard.LipsUpperOpen", "to": "Actions.LipsUpperOpen" },
{ "from": "Standard.LipsLowerOpen", "to": "Actions.LipsLowerOpen" },
{ "from": "Standard.LipsFunnel", "to": "Actions.LipsFunnel" },
{ "from": "Standard.LipsPucker", "to": "Actions.LipsPucker" },
{ "from": "Standard.Puff", "to": "Actions.Puff" },

View file

@ -96,8 +96,6 @@
{ "from": "Standard.LipsStretch_R", "to": "Actions.LipsStretch_R" },
{ "from": "Standard.LipsUpperClose", "to": "Actions.LipsUpperClose" },
{ "from": "Standard.LipsLowerClose", "to": "Actions.LipsLowerClose" },
{ "from": "Standard.LipsUpperOpen", "to": "Actions.LipsUpperOpen" },
{ "from": "Standard.LipsLowerOpen", "to": "Actions.LipsLowerOpen" },
{ "from": "Standard.LipsFunnel", "to": "Actions.LipsFunnel" },
{ "from": "Standard.LipsPucker", "to": "Actions.LipsPucker" },
{ "from": "Standard.Puff", "to": "Actions.Puff" },

View file

@ -106,33 +106,6 @@ Rectangle {
}
}
Image {
id: homeButton
source: "images/homeIcon.svg"
opacity: homeButtonMouseArea.containsMouse ? 1.0 : 0.7
anchors.top: parent.top
anchors.topMargin: 15
anchors.right: parent.right
anchors.rightMargin: 24
width: 14
height: 13
MouseArea {
id: homeButtonMouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: {
Tablet.playSound(TabletEnums.ButtonHover);
}
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
// Can't use `Window.location` in QML, so just use what setting `Window.location` actually calls under the hood:
// AddressManager.handleLookupString().
AddressManager.handleLookupString(LocationBookmarks.getAddress("hqhome"));
}
}
}
AvatarAppComponents.DisplayNameHeader {
id: displayNameHeader
previewUrl: root.avatarPreviewUrl

View file

@ -232,12 +232,6 @@ void AvatarBookmarks::loadBookmark(const QString& bookmarkName) {
emit bookmarkLoaded(bookmarkName);
});
std::shared_ptr<QMetaObject::Connection> connection2 = std::make_shared<QMetaObject::Connection>();
*connection2 = connect(myAvatar.get(), &MyAvatar::onLoadFailed, [this, bookmarkName, connection2]() {
qCDebug(interfaceapp) << "Failed to load avatar bookmark" << bookmarkName;
QObject::disconnect(*connection2);
});
qCDebug(interfaceapp) << "Start loading avatar bookmark" << bookmarkName;
const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString();

View file

@ -3452,7 +3452,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
bool isCameraYawing = getDriveKey(DELTA_YAW) + getDriveKey(STEP_YAW) + getDriveKey(YAW) != 0.0f;
bool isRotatingWhileSeated = !isCameraYawing && isMovingSideways && _characterController.getSeated();
glm::quat previousOrientation = getWorldOrientation();
glm::quat previousYaw = _lookAtYaw;
if (!computeLookAt) {
setWorldOrientation(getWorldOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f))));
_lookAtCameraTarget = eyesPosition + getWorldOrientation() * Vectors::FRONT;
@ -3462,6 +3462,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
// Compute new look at vectors
if (totalBodyYaw != 0.0f) {
_lookAtYaw = _lookAtYaw * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f)));
_lookAtYawSpeed = glm::degrees(glm::angle(_lookAtYaw * glm::inverse(previousYaw))) / deltaTime;
}
float pitchIncrement = getDriveKey(PITCH) * _pitchSpeed * deltaTime
+ getDriveKey(DELTA_PITCH) * _pitchSpeed / PITCH_SPEED_DEFAULT;
@ -3482,7 +3483,19 @@ void MyAvatar::updateOrientation(float deltaTime) {
const float REORIENT_FORWARD_BLEND = 0.25f;
const float REORIENT_TURN_BLEND = 0.03f;
const float DIAGONAL_TURN_BLEND = 0.1f;
const float AVATAR_TURNS_TO_CAM_IN_SPEED = 130.0f; // Degrees per second
const float AVATAR_TURNS_TO_CAM_OUT_SPEED = 720.0f; // Degrees per second
float blend = (_shouldTurnToFaceCamera ? REORIENT_TURN_BLEND : REORIENT_FORWARD_BLEND) * timeScale;
if (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT && _lookAtYawSpeed > AVATAR_TURNS_TO_CAM_IN_SPEED) {
// When the camera is rotating fast we should accelerate the avatar's face forward speed
// to avoid showing the cauterized head;
float cameraYawSpeed = glm::min(_lookAtYawSpeed, AVATAR_TURNS_TO_CAM_OUT_SPEED);
float blendFactor = REORIENT_TURN_BLEND + REORIENT_FORWARD_BLEND * ((cameraYawSpeed - AVATAR_TURNS_TO_CAM_IN_SPEED) /
(AVATAR_TURNS_TO_CAM_OUT_SPEED - AVATAR_TURNS_TO_CAM_IN_SPEED));
blend = glm::min(1.0f, blendFactor * timeScale);
}
if (blend > 1.0f) {
blend = 1.0f;
}
@ -3573,7 +3586,6 @@ void MyAvatar::updateOrientation(float deltaTime) {
if (frontBackDot < limitAngle) {
if (frontBackDot < 0.0f) {
ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight);
cameraVector = (ajustedYawVector * _lookAtPitch) * Vectors::FRONT;
}
if (!isRotatingWhileSeated) {
if (frontBackDot < triggerAngle) {
@ -6762,19 +6774,18 @@ glm::vec3 MyAvatar::getLookAtPivotPoint() {
glm::vec3 MyAvatar::getCameraEyesPosition(float deltaTime) {
glm::vec3 defaultEyesPosition = getLookAtPivotPoint();
if (isFlying()) {
return defaultEyesPosition;
}
glm::vec3 avatarFrontVector = getWorldOrientation() * Vectors::FRONT;
glm::vec3 avatarUpVector = getWorldOrientation() * Vectors::UP;
// Compute the offset between the default and real eye positions.
glm::vec3 defaultEyesToEyesVector = getHead()->getEyePosition() - defaultEyesPosition;
float FRONT_OFFSET_IDLE_MULTIPLIER = 2.5f;
float FRONT_OFFSET_JUMP_MULTIPLIER = 1.5f;
const float FRONT_OFFSET_IDLE_MULTIPLIER = 3.5f;
const float FRONT_OFFSET_JUMP_MULTIPLIER = 1.5f;
float frontOffset = FRONT_OFFSET_IDLE_MULTIPLIER * glm::length(defaultEyesPosition - getDefaultEyePosition());
// Looking down will aproximate move the camera forward to meet the real eye position
// Looking down will move the camera forward to meet the real eye position
float mixAlpha = glm::dot(_lookAtPitch * Vectors::FRONT, -avatarUpVector);
bool isLanding = false;
// When jumping the camera should follow the real eye on the Y coordenate
float upOffset = 0.0f;

View file

@ -2693,6 +2693,7 @@ private:
const float MAX_LOOK_AT_TIME_SCRIPT_CONTROL = 2.0f;
glm::quat _lookAtPitch;
glm::quat _lookAtYaw;
float _lookAtYawSpeed { 0.0f };
glm::vec3 _lookAtCameraTarget;
glm::vec3 _lookAtScriptTarget;
bool _headLookAtActive { false };

View file

@ -57,8 +57,6 @@ static controller::Action blendshapeActions[] = {
controller::Action::LIPSSTRETCH_R,
controller::Action::LIPSUPPERCLOSE,
controller::Action::LIPSLOWERCLOSE,
controller::Action::LIPSUPPEROPEN,
controller::Action::LIPSLOWEROPEN,
controller::Action::LIPSFUNNEL,
controller::Action::LIPSPUCKER,
controller::Action::PUFF,

View file

@ -206,7 +206,7 @@ public slots:
void browseAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
/**jsdoc
* Prompts the user to specify the path and name of a file to save to. Displays a model dialog that navigates the directory
* Prompts the user to specify the path and name of a file to save to. Displays a modal dialog that navigates the directory
* tree and allows the user to type in a file name.
* @function Window.save
* @param {string} [title=""] - The title to display at the top of the dialog.
@ -222,7 +222,7 @@ public slots:
QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
/**jsdoc
* Prompts the user to specify the path and name of a file to save to. Displays a non-model dialog that navigates the
* Prompts the user to specify the path and name of a file to save to. Displays a non-modal dialog that navigates the
* directory tree and allows the user to type in a file name. A {@link Window.saveFileChanged|saveFileChanged} signal is
* emitted when a file is specified; no signal is emitted if the user cancels the dialog.
* @function Window.saveAsync

View file

@ -96,7 +96,9 @@ const AnimPoseVec& AnimBlendDirectional::evaluate(const AnimVariantMap& animVars
}
}
_poses.resize(minSize);
blend4(minSize, &poseVecs[0][0], &poseVecs[1][0], &poseVecs[2][0], &poseVecs[3][0], &alphas[0], &_poses[0]);
if (minSize > 0) {
blend4(minSize, &poseVecs[0][0], &poseVecs[1][0], &poseVecs[2][0], &poseVecs[3][0], &alphas[0], &_poses[0]);
}
// animation stack debug stats
for (int i = 0; i < 9; i++) {

View file

@ -1171,6 +1171,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_desiredStateAge += deltaTime;
if (_state == RigRole::Move) {
glm::vec3 horizontalVel = localVel - glm::vec3(0.0f, localVel.y, 0.0f);
if (glm::length(horizontalVel) > MOVE_ENTER_SPEED_THRESHOLD) {
@ -1437,17 +1438,37 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
//stategraph vars based on input
const float INPUT_DEADZONE_THRESHOLD = 0.05f;
const float SLOW_SPEED_THRESHOLD = 1.5f;
const float HAS_MOMENTUM_THRESHOLD = 2.2f;
const float RESET_MOMENTUM_THRESHOLD = 0.05f;
if (fabsf(_previousControllerParameters.inputX) <= INPUT_DEADZONE_THRESHOLD &&
fabsf(_previousControllerParameters.inputZ) <= INPUT_DEADZONE_THRESHOLD) {
// no WASD input
if (fabsf(forwardSpeed) <= SLOW_SPEED_THRESHOLD && fabsf(lateralSpeed) <= SLOW_SPEED_THRESHOLD) {
//reset this when stopped
if (fabsf(forwardSpeed) <= RESET_MOMENTUM_THRESHOLD &&
fabsf(lateralSpeed) <= RESET_MOMENTUM_THRESHOLD) {
_isMovingWithMomentum = false;
}
_animVars.set("isInputForward", false);
_animVars.set("isInputBackward", false);
_animVars.set("isInputRight", false);
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", true);
_animVars.set("isNotInputSlow", true);
// directly reflects input
_animVars.set("isNotInput", true);
// no input + speed drops to SLOW_SPEED_THRESHOLD
// (don't transition run->idle - slow to walk first)
_animVars.set("isNotInputSlow", _isMovingWithMomentum);
// no input + speed didn't get above HAS_MOMENTUM_THRESHOLD since last idle
// (brief inputs and movement adjustments)
_animVars.set("isNotInputNoMomentum", !_isMovingWithMomentum);
} else {
_animVars.set("isInputForward", false);
@ -1456,8 +1477,13 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", true);
_animVars.set("isNotInputSlow", false);
_animVars.set("isNotInputNoMomentum", false);
}
} else if (fabsf(_previousControllerParameters.inputZ) >= fabsf(_previousControllerParameters.inputX)) {
if (fabsf(forwardSpeed) > HAS_MOMENTUM_THRESHOLD) {
_isMovingWithMomentum = true;
}
if (_previousControllerParameters.inputZ > 0.0f) {
// forward
_animVars.set("isInputForward", true);
@ -1466,6 +1492,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", false);
_animVars.set("isNotInputSlow", false);
_animVars.set("isNotInputNoMomentum", false);
} else {
// backward
_animVars.set("isInputForward", false);
@ -1474,8 +1501,13 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", false);
_animVars.set("isNotInputSlow", false);
_animVars.set("isNotInputNoMomentum", false);
}
} else {
if (fabsf(lateralSpeed) > HAS_MOMENTUM_THRESHOLD) {
_isMovingWithMomentum = true;
}
if (_previousControllerParameters.inputX > 0.0f) {
// right
_animVars.set("isInputForward", false);
@ -1484,6 +1516,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", false);
_animVars.set("isNotInputSlow", false);
_animVars.set("isNotInputNoMomentum", false);
} else {
// left
_animVars.set("isInputForward", false);
@ -1492,6 +1525,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
_animVars.set("isInputLeft", true);
_animVars.set("isNotInput", false);
_animVars.set("isNotInputSlow", false);
_animVars.set("isNotInputNoMomentum", false);
}
}

View file

@ -330,6 +330,7 @@ protected:
glm::vec3 _lastForward;
glm::vec3 _lastPosition;
glm::vec3 _lastVelocity;
bool _isMovingWithMomentum{ false };
QUrl _animGraphURL;
std::shared_ptr<AnimNode> _animNode;

View file

@ -111,11 +111,17 @@ QList<HifiAudioDeviceInfo> getAvailableDevices(QAudio::Mode mode, const QString&
}
if (defaultDesktopDevice.getDevice().isNull()) {
qCDebug(audioclient) << __FUNCTION__ << "Default device not found in list:" << defDeviceName
<< "Setting Default to: " << devices.first().deviceName();
defaultDesktopDevice = HifiAudioDeviceInfo(devices.first(), true, mode, HifiAudioDeviceInfo::desktop);
if (devices.size() > 0) {
qCDebug(audioclient) << __FUNCTION__ << "Default device not found in list:" << defDeviceName
<< "Setting Default to: " << devices.first().deviceName();
newDevices.push_front(HifiAudioDeviceInfo(devices.first(), true, mode, HifiAudioDeviceInfo::desktop));
} else {
//current audio list is empty for some reason.
qCDebug(audioclient) << __FUNCTION__ << "Default device not found in list no alternative selection available";
}
} else {
newDevices.push_front(defaultDesktopDevice);
}
newDevices.push_front(defaultDesktopDevice);
if (!hmdName.isNull()) {
HifiAudioDeviceInfo hmdDevice;

View file

@ -25,13 +25,6 @@
#define ALIGN32
#endif
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
//
// Equal-gain crossfade
//
@ -114,106 +107,49 @@ static const float nearFieldTable[NNEARFIELD][3] = { // { b0, b1, a1 }
};
//
// Model the frequency-dependent attenuation of sound propogation in air.
// Parametric lowpass filter to model sound propogation or occlusion.
//
// Fit using linear regression to a log-log model of lowpass cutoff frequency vs distance,
// loosely based on data from Handbook of Acoustics. Only the onset of significant
// attenuation is modelled, not the filter slope.
// lpf = 0.0 -> -3dB @ 50kHz
// lpf = 0.5 -> -3dB @ 1kHz
// lpf = 1.0 -> -3dB @ 20Hz
//
// 1m -> -3dB @ 55kHz
// 10m -> -3dB @ 12kHz
// 100m -> -3dB @ 2.5kHz
// 1km -> -3dB @ 0.6kHz
// 10km -> -3dB @ 0.1kHz
//
static const int NLOWPASS = 64;
static const float lowpassTable[NLOWPASS][5] = { // { b0, b1, b2, a1, a2 }
// distance = 1
{ 0.999772371f, 1.399489756f, 0.454495527f, 1.399458985f, 0.454298669f },
{ 0.999631480f, 1.357609808f, 0.425210203f, 1.357549905f, 0.424901586f },
{ 0.999405154f, 1.311503050f, 0.394349994f, 1.311386830f, 0.393871368f },
{ 0.999042876f, 1.260674595f, 0.361869089f, 1.260450057f, 0.361136504f },
// distance = 2
{ 0.998465222f, 1.204646525f, 0.327757118f, 1.204214978f, 0.326653886f },
{ 0.997548106f, 1.143019308f, 0.292064663f, 1.142195387f, 0.290436690f },
{ 0.996099269f, 1.075569152f, 0.254941286f, 1.074009405f, 0.252600301f },
{ 0.993824292f, 1.002389610f, 0.216688640f, 0.999469185f, 0.213433357f },
// distance = 4
{ 0.990280170f, 0.924075266f, 0.177827150f, 0.918684864f, 0.173497723f },
{ 0.984818279f, 0.841917936f, 0.139164195f, 0.832151968f, 0.133748443f },
{ 0.976528670f, 0.758036513f, 0.101832398f, 0.740761682f, 0.095635899f },
{ 0.964216485f, 0.675305244f, 0.067243474f, 0.645654855f, 0.061110348f },
// distance = 8
{ 0.946463038f, 0.596943020f, 0.036899688f, 0.547879974f, 0.032425772f },
{ 0.921823868f, 0.525770189f, 0.012060451f, 0.447952111f, 0.011702396f },
{ 0.890470015f, 0.463334299f, -0.001227816f, 0.347276405f, 0.005300092f },
{ 0.851335343f, 0.407521164f, -0.009353968f, 0.241900234f, 0.007602305f },
// distance = 16
{ 0.804237360f, 0.358139558f, -0.014293332f, 0.130934213f, 0.017149373f },
{ 0.750073259f, 0.314581568f, -0.016625381f, 0.014505388f, 0.033524057f },
{ 0.690412072f, 0.275936128f, -0.017054561f, -0.106682490f, 0.055976129f },
{ 0.627245545f, 0.241342015f, -0.016246850f, -0.231302564f, 0.083643275f },
// distance = 32
{ 0.562700627f, 0.210158533f, -0.014740899f, -0.357562697f, 0.115680957f },
{ 0.498787849f, 0.181982455f, -0.012925406f, -0.483461730f, 0.151306628f },
{ 0.437224055f, 0.156585449f, -0.011055180f, -0.607042210f, 0.189796534f },
{ 0.379336998f, 0.133834032f, -0.009281617f, -0.726580065f, 0.230469477f },
// distance = 64
{ 0.326040627f, 0.113624970f, -0.007683443f, -0.840693542f, 0.272675696f },
{ 0.277861727f, 0.095845793f, -0.006291936f, -0.948380091f, 0.315795676f },
{ 0.234997480f, 0.080357656f, -0.005109519f, -1.049001190f, 0.359246807f },
{ 0.197386484f, 0.066993521f, -0.004122547f, -1.142236313f, 0.402493771f },
// distance = 128
{ 0.164780457f, 0.055564709f, -0.003309645f, -1.228023442f, 0.445058962f },
{ 0.136808677f, 0.045870650f, -0.002646850f, -1.306498037f, 0.486530514f },
{ 0.113031290f, 0.037708627f, -0.002110591f, -1.377937457f, 0.526566783f },
{ 0.092980475f, 0.030881892f, -0.001679255f, -1.442713983f, 0.564897095f },
// distance = 256
{ 0.076190239f, 0.025205585f, -0.001333863f, -1.501257246f, 0.601319206f },
{ 0.062216509f, 0.020510496f, -0.001058229f, -1.554025452f, 0.635694228f },
{ 0.050649464f, 0.016644994f, -0.000838826f, -1.601484205f, 0.667939837f },
{ 0.041120009f, 0.013475547f, -0.000664513f, -1.644091518f, 0.698022561f },
// distance = 512
{ 0.033302044f, 0.010886252f, -0.000526217f, -1.682287704f, 0.725949783f },
{ 0.026911868f, 0.008777712f, -0.000416605f, -1.716488979f, 0.751761953f },
{ 0.021705773f, 0.007065551f, -0.000329788f, -1.747083800f, 0.775525335f },
{ 0.017476603f, 0.005678758f, -0.000261057f, -1.774431204f, 0.797325509f },
// distance = 1024
{ 0.014049828f, 0.004558012f, -0.000206658f, -1.798860530f, 0.817261711f },
{ 0.011279504f, 0.003654067f, -0.000163610f, -1.820672082f, 0.835442043f },
{ 0.009044384f, 0.002926264f, -0.000129544f, -1.840138412f, 0.851979516f },
{ 0.007244289f, 0.002341194f, -0.000102586f, -1.857505967f, 0.866988864f },
// distance = 2048
{ 0.005796846f, 0.001871515f, -0.000081250f, -1.872996926f, 0.880584038f },
{ 0.004634607f, 0.001494933f, -0.000064362f, -1.886811124f, 0.892876302f },
{ 0.003702543f, 0.001193324f, -0.000050993f, -1.899127955f, 0.903972829f },
{ 0.002955900f, 0.000951996f, -0.000040407f, -1.910108223f, 0.913975712f },
// distance = 4096
{ 0.002358382f, 0.000759068f, -0.000032024f, -1.919895894f, 0.922981321f },
{ 0.001880626f, 0.000604950f, -0.000025383f, -1.928619738f, 0.931079931f },
{ 0.001498926f, 0.000481920f, -0.000020123f, -1.936394836f, 0.938355560f },
{ 0.001194182f, 0.000383767f, -0.000015954f, -1.943323983f, 0.944885977f },
// distance = 8192
{ 0.000951028f, 0.000305502f, -0.000012651f, -1.949498943f, 0.950742822f },
{ 0.000757125f, 0.000243126f, -0.000010033f, -1.955001608f, 0.955991826f },
{ 0.000602572f, 0.000193434f, -0.000007957f, -1.959905036f, 0.960693085f },
{ 0.000479438f, 0.000153861f, -0.000006312f, -1.964274383f, 0.964901371f },
// distance = 16384
{ 0.000381374f, 0.000122359f, -0.000005007f, -1.968167752f, 0.968666478f },
{ 0.000303302f, 0.000097288f, -0.000003972f, -1.971636944f, 0.972033562f },
{ 0.000241166f, 0.000077342f, -0.000003151f, -1.974728138f, 0.975043493f },
{ 0.000191726f, 0.000061475f, -0.000002500f, -1.977482493f, 0.977733194f },
// distance = 32768
{ 0.000152399f, 0.000048857f, -0.000001984f, -1.979936697f, 0.980135969f },
{ 0.000121122f, 0.000038825f, -0.000001574f, -1.982123446f, 0.982281818f },
{ 0.000096252f, 0.000030849f, -0.000001249f, -1.984071877f, 0.984197728f },
{ 0.000076480f, 0.000024509f, -0.000000991f, -1.985807957f, 0.985907955f },
static const int NLOWPASS = 32;
static const float lowpassTable[NLOWPASS+1][5] = { // { b0, b1, b2, a1, a2 }
{ 0.9996582613f, 1.3644521648f, 0.4299107175f, 1.3643981990f, 0.4296229446f },
{ 0.9990601568f, 1.2627213717f, 0.3631477252f, 1.2625024258f, 0.3624268280f },
{ 0.9974547575f, 1.1378303854f, 0.2891398515f, 1.1369629374f, 0.2874620569f },
{ 0.9932384344f, 0.9872078424f, 0.2089943789f, 0.9839050501f, 0.2055356056f },
{ 0.9825457933f, 0.8153687744f, 0.1271135720f, 0.8036320348f, 0.1213961050f },
{ 0.9572356804f, 0.6404312275f, 0.0534129844f, 0.6033230637f, 0.0477568288f },
{ 0.9052878744f, 0.4902779401f, 0.0035032262f, 0.3924772681f, 0.0065917726f },
{ 0.8204774205f, 0.3736089028f, -0.0129974730f, 0.1678426876f, 0.0132461627f },
{ 0.7032096959f, 0.2836328681f, -0.0170877258f, -0.0810811878f, 0.0508360260f },
{ 0.5685067272f, 0.2128349296f, -0.0148937235f, -0.3461942779f, 0.1126422113f },
{ 0.4355093111f, 0.1558974062f, -0.0110025095f, -0.6105302595f, 0.1909344673f },
{ 0.3186188589f, 0.1108581568f, -0.0074653192f, -0.8569688248f, 0.2789805212f },
{ 0.2244962739f, 0.0766060095f, -0.0048289293f, -1.0745081373f, 0.3707814914f },
{ 0.1535044640f, 0.0516447640f, -0.0030384640f, -1.2590370066f, 0.4611477706f },
{ 0.1025113288f, 0.0341204303f, -0.0018818088f, -1.4113207964f, 0.5460707468f },
{ 0.0672016063f, 0.0221823522f, -0.0011552756f, -1.5347007285f, 0.6229294113f },
{ 0.0434202931f, 0.0142393067f, -0.0007060306f, -1.6334567973f, 0.6904103664f },
{ 0.0277383489f, 0.0090500025f, -0.0004305987f, -1.7118804671f, 0.7482382198f },
{ 0.0175636227f, 0.0057072537f, -0.0002624537f, -1.7738404438f, 0.7968488665f },
{ 0.0110441068f, 0.0035773504f, -0.0001599927f, -1.8226329785f, 0.8370944430f },
{ 0.0069069312f, 0.0022316608f, -0.0000975848f, -1.8609764152f, 0.8700174224f },
{ 0.0043012064f, 0.0013870046f, -0.0000595614f, -1.8910688315f, 0.8966974811f },
{ 0.0026696068f, 0.0008595333f, -0.0000363798f, -1.9146662133f, 0.9181589737f },
{ 0.0016526098f, 0.0005314445f, -0.0000222355f, -1.9331608518f, 0.9353226705f },
{ 0.0010209520f, 0.0003280036f, -0.0000135987f, -1.9476515008f, 0.9489868578f },
{ 0.0006297162f, 0.0002021591f, -0.0000083208f, -1.9590027292f, 0.9598262837f },
{ 0.0003879180f, 0.0001244611f, -0.0000050936f, -1.9678935939f, 0.9684008793f },
{ 0.0002387308f, 0.0000765601f, -0.0000031192f, -1.9748568416f, 0.9751690132f },
{ 0.0001468057f, 0.0000470631f, -0.0000019106f, -1.9803101382f, 0.9805020963f },
{ 0.0000902227f, 0.0000289155f, -0.0000011706f, -1.9845807858f, 0.9846987534f },
{ 0.0000554223f, 0.0000177584f, -0.0000007174f, -1.9879252038f, 0.9879976671f },
{ 0.0000340324f, 0.0000109027f, -0.0000004397f, -1.9905442465f, 0.9905887419f },
{ 0.0000208917f, 0.0000066920f, -0.0000002695f, -1.9925952275f, 0.9926225417f },
};
static const float HALFPI = 1.570796327f;
static const float PI = 3.141592654f;
static const float TWOPI = 6.283185307f;
//
// on x86 architecture, assume that SSE2 is present
//
@ -811,44 +747,38 @@ static void splitf(float x, int& expn, float& frac) {
expn = (bits.i >> IEEE754_MANT_BITS) - IEEE754_EXPN_BIAS;
}
static void distanceBiquad(float distance, float& b0, float& b1, float& b2, float& a1, float& a2) {
static void lowpassBiquad(float lpf, float& b0, float& b1, float& b2, float& a1, float& a2) {
//
// Computed from a lookup table quantized to distance = 2^(N/4)
// and reconstructed by piecewise linear interpolation.
// Computed from a lookup table and piecewise linear interpolation.
// Approximation error < 0.25dB
//
float x = lpf * NLOWPASS;
float x = distance;
x = MIN(x, 1<<30);
x *= x;
x *= x; // x = distance^4
// split x into e and frac, such that x = 2^(e+0) + frac * (2^(e+1) - 2^(e+0))
int e;
float frac;
splitf(x, e, frac);
// split x into index and fraction
int i = (int)x;
float frac = x - (float)i;
// clamp to table limits
if (e < 0) {
e = 0;
if (i < 0) {
i = 0;
frac = 0.0f;
}
if (e > NLOWPASS-2) {
e = NLOWPASS-2;
if (i > NLOWPASS-1) {
i = NLOWPASS-1;
frac = 1.0f;
}
assert(frac >= 0.0f);
assert(frac <= 1.0f);
assert(e+0 >= 0);
assert(e+1 < NLOWPASS);
assert(i+0 >= 0);
assert(i+1 <= NLOWPASS);
// piecewise linear interpolation
b0 = lowpassTable[e+0][0] + frac * (lowpassTable[e+1][0] - lowpassTable[e+0][0]);
b1 = lowpassTable[e+0][1] + frac * (lowpassTable[e+1][1] - lowpassTable[e+0][1]);
b2 = lowpassTable[e+0][2] + frac * (lowpassTable[e+1][2] - lowpassTable[e+0][2]);
a1 = lowpassTable[e+0][3] + frac * (lowpassTable[e+1][3] - lowpassTable[e+0][3]);
a2 = lowpassTable[e+0][4] + frac * (lowpassTable[e+1][4] - lowpassTable[e+0][4]);
b0 = lowpassTable[i+0][0] + frac * (lowpassTable[i+1][0] - lowpassTable[i+0][0]);
b1 = lowpassTable[i+0][1] + frac * (lowpassTable[i+1][1] - lowpassTable[i+0][1]);
b2 = lowpassTable[i+0][2] + frac * (lowpassTable[i+1][2] - lowpassTable[i+0][2]);
a1 = lowpassTable[i+0][3] + frac * (lowpassTable[i+1][3] - lowpassTable[i+0][3]);
a2 = lowpassTable[i+0][4] + frac * (lowpassTable[i+1][4] - lowpassTable[i+0][4]);
}
//
@ -903,13 +833,13 @@ static void nearFieldGainCorrection(float azimuth, float distance, float& gainL,
float d = (HRTF_NEARFIELD_MAX - distance) * (1.0f / (HRTF_NEARFIELD_MAX - HRTF_HEAD_RADIUS));
// angle of incidence at each ear
float angleL = azimuth + HALFPI;
float angleR = azimuth - HALFPI;
float angleL = azimuth + PI_OVER_TWO;
float angleR = azimuth - PI_OVER_TWO;
if (angleL > +PI) {
angleL -= TWOPI;
angleL -= TWO_PI;
}
if (angleR < -PI) {
angleR += TWOPI;
angleR += TWO_PI;
}
assert(angleL >= -PI);
assert(angleL <= +PI);
@ -968,7 +898,7 @@ static void nearFieldFilter(float gain, float& b0, float& b1, float& a1) {
static void azimuthToIndex(float azimuth, int& index0, int& index1, float& frac) {
// convert from radians to table units
azimuth *= (HRTF_AZIMUTHS / TWOPI);
azimuth *= (HRTF_AZIMUTHS / TWO_PI);
if (azimuth < 0.0f) {
azimuth += HRTF_AZIMUTHS;
@ -993,15 +923,15 @@ static void azimuthToIndex(float azimuth, int& index0, int& index1, float& frac)
// compute new filters for a given azimuth, distance and gain
static void setFilters(float firCoef[4][HRTF_TAPS], float bqCoef[5][8], int delay[4],
int index, float azimuth, float distance, float gain, int channel) {
int index, float azimuth, float distance, float gain, float lpf, int channel) {
if (azimuth > PI) {
azimuth -= TWOPI;
azimuth -= TWO_PI;
}
assert(azimuth >= -PI);
assert(azimuth <= +PI);
distance = MAX(distance, HRTF_NEARFIELD_MIN);
distance = std::max(distance, HRTF_NEARFIELD_MIN);
// compute the azimuth correction at each ear
float azimuthL = azimuth;
@ -1109,7 +1039,7 @@ static void setFilters(float firCoef[4][HRTF_TAPS], float bqCoef[5][8], int dela
} else {
distanceBiquad(distance, b0, b1, b2, a1, a2);
lowpassBiquad(lpf, b0, b1, b2, a1, a2);
bqCoef[0][channel+4] = b0;
bqCoef[1][channel+4] = b1;
@ -1125,7 +1055,8 @@ static void setFilters(float firCoef[4][HRTF_TAPS], float bqCoef[5][8], int dela
}
}
void AudioHRTF::render(int16_t* input, float* output, int index, float azimuth, float distance, float gain, int numFrames) {
void AudioHRTF::render(int16_t* input, float* output, int index, float azimuth, float distance, float gain, int numFrames,
float lpfDistance) {
assert(index >= 0);
assert(index < HRTF_TABLES);
@ -1141,23 +1072,29 @@ void AudioHRTF::render(int16_t* input, float* output, int index, float azimuth,
// apply global and local gain adjustment
gain *= _gainAdjust;
// apply distance filter
float lpf = 0.5f * fastLog2f(std::max(distance, 1.0f)) / fastLog2f(std::max(lpfDistance, 2.0f));
lpf = std::min(std::max(lpf, 0.0f), 1.0f);
// disable interpolation from reset state
if (_resetState) {
_azimuthState = azimuth;
_distanceState = distance;
_gainState = gain;
_lpfState = lpf;
}
// to avoid polluting the cache, old filters are recomputed instead of stored
setFilters(firCoef, bqCoef, delay, index, _azimuthState, _distanceState, _gainState, L0);
setFilters(firCoef, bqCoef, delay, index, _azimuthState, _distanceState, _gainState, _lpfState, L0);
// compute new filters
setFilters(firCoef, bqCoef, delay, index, azimuth, distance, gain, L1);
setFilters(firCoef, bqCoef, delay, index, azimuth, distance, gain, lpf, L1);
// new parameters become old
_azimuthState = azimuth;
_distanceState = distance;
_gainState = gain;
_lpfState = lpf;
// convert mono input to float
for (int i = 0; i < HRTF_BLOCK; i++) {

View file

@ -14,6 +14,9 @@
#include <stdint.h>
#include <string.h>
#include <algorithm>
#include "AudioHelpers.h"
static const int HRTF_AZIMUTHS = 72; // 360 / 5-degree steps
static const int HRTF_TAPS = 64; // minimum-phase FIR coefficients
@ -34,6 +37,9 @@ static const float HRTF_HEAD_RADIUS = 0.0875f; // average human head in meters
static const float ATTN_DISTANCE_REF = 2.0f; // distance where attn is 0dB
static const float ATTN_GAIN_MAX = 16.0f; // max gain allowed by distance attn (+24dB)
// Distance filter
static const float LPF_DISTANCE_REF = 256.0f; // approximation of sound propogation in air
class AudioHRTF {
public:
@ -47,8 +53,10 @@ public:
// distance: source distance in meters
// gain: gain factor for distance attenuation
// numFrames: must be HRTF_BLOCK in this version
// lpfDistance: distance filter adjustment (distance to 1kHz lowpass in meters)
//
void render(int16_t* input, float* output, int index, float azimuth, float distance, float gain, int numFrames);
void render(int16_t* input, float* output, int index, float azimuth, float distance, float gain, int numFrames,
float lpfDistance = LPF_DISTANCE_REF);
//
// Non-spatialized direct mix (accumulates into existing output)
@ -59,11 +67,14 @@ public:
//
// Fast path when input is known to be silent and state as been flushed
//
void setParameterHistory(float azimuth, float distance, float gain) {
void setParameterHistory(float azimuth, float distance, float gain, float lpfDistance = LPF_DISTANCE_REF) {
// new parameters become old
_azimuthState = azimuth;
_distanceState = distance;
_gainState = gain;
_lpfState = 0.5f * fastLog2f(std::max(distance, 1.0f)) / fastLog2f(std::max(lpfDistance, 2.0f));
_lpfState = std::min(std::max(_lpfState, 0.0f), 1.0f);
}
//
@ -88,6 +99,7 @@ public:
_azimuthState = 0.0f;
_distanceState = 0.0f;
_gainState = 0.0f;
_lpfState = 0.0f;
// _gainAdjust is retained
@ -123,6 +135,7 @@ private:
float _azimuthState = 0.0f;
float _distanceState = 0.0f;
float _gainState = 0.0f;
float _lpfState = 0.0f;
// global and local gain adjustment
float _gainAdjust = HRTF_GAIN;

View file

@ -386,8 +386,6 @@ namespace controller {
makeAxisPair(Action::LIPSSTRETCH_R, "LipsStretch_R"),
makeAxisPair(Action::LIPSUPPERCLOSE, "LipsUpperClose"),
makeAxisPair(Action::LIPSLOWERCLOSE, "LipsLowerClose"),
makeAxisPair(Action::LIPSUPPEROPEN, "LipsUpperOpen"),
makeAxisPair(Action::LIPSLOWEROPEN, "LipsLowerOpen"),
makeAxisPair(Action::LIPSFUNNEL, "LipsFunnel"),
makeAxisPair(Action::LIPSPUCKER, "LipsPucker"),
makeAxisPair(Action::PUFF, "Puff"),

View file

@ -220,8 +220,6 @@ enum class Action {
LIPSSTRETCH_R,
LIPSUPPERCLOSE,
LIPSLOWERCLOSE,
LIPSUPPEROPEN,
LIPSLOWEROPEN,
LIPSFUNNEL,
LIPSPUCKER,
PUFF,

View file

@ -392,8 +392,6 @@ Input::NamedVector StandardController::getAvailableInputs() const {
makePair(LIPSSTRETCH_R, "LipsStretch_R"),
makePair(LIPSUPPERCLOSE, "LipsUpperClose"),
makePair(LIPSLOWERCLOSE, "LipsLowerClose"),
makePair(LIPSUPPEROPEN, "LipsUpperOpen"),
makePair(LIPSLOWEROPEN, "LipsLowerOpen"),
makePair(LIPSFUNNEL, "LipsFunnel"),
makePair(LIPSPUCKER, "LipsPucker"),
makePair(PUFF, "Puff"),

View file

@ -127,8 +127,6 @@ namespace controller {
LIPSSTRETCH_R,
LIPSUPPERCLOSE,
LIPSLOWERCLOSE,
LIPSUPPEROPEN,
LIPSLOWEROPEN,
LIPSFUNNEL,
LIPSPUCKER,
PUFF,

View file

@ -82,6 +82,8 @@ static void fixUpLegacyBlendshapes(QVariantHash& properties) {
removeBlendshape(bs, "JawChew");
removeBlendshape(bs, "ChinLowerRaise");
removeBlendshape(bs, "ChinUpperRaise");
removeBlendshape(bs, "LipsUpperOpen");
removeBlendshape(bs, "LipsLowerOpen");
// These blendshapes are split in ARKit, we replace them with their left and right sides with a weight of 1/2.
splitBlendshapes(bs, "LipsUpperUp", "MouthUpperUp_L", "MouthUpperUp_R");

View file

@ -257,7 +257,9 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con
ShapeKey::Builder(), ShapeKey::Builder().withFade(),
ShapeKey::Builder().withDeformed(), ShapeKey::Builder().withDeformed().withFade(),
ShapeKey::Builder().withDeformed().withDualQuatSkinned(), ShapeKey::Builder().withDeformed().withDualQuatSkinned().withFade(),
ShapeKey::Builder().withOwnPipeline(), ShapeKey::Builder().withOwnPipeline().withFade()
ShapeKey::Builder().withOwnPipeline(), ShapeKey::Builder().withOwnPipeline().withFade(),
ShapeKey::Builder().withDeformed().withOwnPipeline(), ShapeKey::Builder().withDeformed().withOwnPipeline().withFade(),
ShapeKey::Builder().withDeformed().withDualQuatSkinned().withOwnPipeline(), ShapeKey::Builder().withDeformed().withDualQuatSkinned().withOwnPipeline().withFade(),
};
std::vector<std::vector<ShapeKey>> sortedShapeKeys(keys.size());

View file

@ -47,8 +47,6 @@ const char* FACESHIFT_BLENDSHAPES[] = {
"LipsStretch_R",
"LipsUpperClose",
"LipsLowerClose",
"LipsUpperOpen",
"LipsLowerOpen",
"LipsFunnel",
"LipsPucker",
"Puff",

View file

@ -51,8 +51,6 @@ enum class Blendshapes : int {
LipsStretch_R,
LipsUpperClose,
LipsLowerClose,
LipsUpperOpen,
LipsLowerOpen,
LipsFunnel,
LipsPucker,
Puff,
@ -114,5 +112,8 @@ enum class LegacyBlendshpaes : int {
// * Sneer (split in ARKit)
// * ChinLowerRaise (not in ARKit)
// * ChinUpperRaise (not in ARKit)
// * LipsUpperOpen (not in ARKit)
// * LipsLowerOpen (not in ARKit)
#endif // hifi_BlendshapeConstants_h

View file

@ -25,38 +25,46 @@
* <tr>
* <td><strong>First&nbsp;Person</strong></td>
* <td><code>"first&nbsp;person"</code></td>
* <td>Legacy first person camera mode. The camera is positioned such that you have the same view as your avatar.
* The camera moves and rotates with your avatar.</td>
* <td><p>The camera is positioned such that you have the same view as your avatar. The camera moves and rotates with
* your avatar.</p>
* <p><em>Legacy first person camera mode.</em></p></td>
* </tr>
* <tr>
* <td><strong>First&nbsp;Person&nbsp;Look&nbsp;At</strong></td>
* <td><code>"first&nbsp;person&nbsp;look&nbsp;at"</code></td>
* <td>Default first person camera mode. The camera is positioned such that you have the same view as your avatar.
* The camera moves and rotates with your avatar's head.</td>
* <td><p>The camera is positioned such that you have the same view as your avatar. The camera moves and rotates with
* your avatar's head.</p>
* <p><em>Default first person camera mode.</em></p></td>
* </tr>
* <tr>
* <td><strong>Third&nbsp;Person</strong></td>
* <td><code>"third&nbsp;person"</code></td>
* <td>The camera is positioned such that you have a view from just behind your avatar. The camera moves and rotates with
* your avatar.</td>
* <td><p>The camera is positioned such that you have a view from just behind your avatar. The camera moves and rotates
* with your avatar.</p>
* <p><em>Legacy third person camera camera mode.</em></p>
* <pre class="prettyprint"><code>Camera.mode = "third person";</code></pre></td>
* </tr>
* <tr>
* <td><strong>Look&nbsp;At</strong></td>
* <td><code>"look&nbsp;at"</code></td>
* <td>The camera is positioned behind your avatar. The camera moves and rotates independently from your avatar.
* The avatar's head always faces the camera look at point.</td>
* <td><p>The camera is positioned behind your avatar. The camera moves and rotates independently from your avatar. The
* avatar's head always faces the camera look at point.</p>
* <p><em>Default third person camera mode.</em></td>
* </tr>
* <tr>
* <td><strong>Selfie</strong></td>
* <td><code>"selfie"</code></td>
* <td>The camera is positioned in front of your avatar. The camera moves and rotates independently from your avatar.
* Your avatar's head is always facing the camera.</td>
* <td><p>The camera is positioned in front of your avatar. The camera moves and rotates independently from your avatar.
* Your avatar's head is always facing the camera.</p>
* <p><em>Default "look at myself" camera mode.</em></p></td>
* </tr>
* <tr>
* <td><strong>Mirror</strong></td>
* <td><code>"mirror"</code></td>
* <td>The camera is positioned such that you are looking directly at your avatar. The camera moves and rotates with your
* avatar.</td>
* <td><p>The camera is positioned such that you are looking directly at your avatar. The camera is fixed and does not
* move with your avatar.</p>
* <p><em>Legacy "look at myself" behavior.</em></p>
* <pre class="prettyprint"><code>Camera.mode = "mirror";</code></pre></td>
* </tr>
* <tr>
* <td><strong>Independent</strong></td>

View file

@ -561,7 +561,8 @@ var toolBar = (function () {
if (!properties.grab) {
properties.grab = {};
if (Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE) &&
!(properties.type === "Zone" || properties.type === "Light" || properties.type === "ParticleEffect")) {
!(properties.type === "Zone" || properties.type === "Light"
|| properties.type === "ParticleEffect" || properties.type === "Web")) {
properties.grab.grabbable = true;
} else {
properties.grab.grabbable = false;

View file

@ -177,7 +177,7 @@ EntityListTool = function(shouldUseEditTabletApp) {
var cameraPosition = Camera.position;
PROFILE("getMultipleProperties", function () {
var multipleProperties = Entities.getMultipleEntityProperties(ids, ['name', 'type', 'locked',
var multipleProperties = Entities.getMultipleEntityProperties(ids, ['position', 'name', 'type', 'locked',
'visible', 'renderInfo', 'modelURL', 'materialURL', 'imageURL', 'script', 'certificateID',
'skybox.url', 'ambientLight.url']);
for (var i = 0; i < multipleProperties.length; i++) {
@ -275,23 +275,6 @@ EntityListTool = function(shouldUseEditTabletApp) {
Window.saveFileChanged.connect(onFileSaveChanged);
Window.saveAsync("Select Where to Save", "", "*.json");
}
} else if (data.type === "pal") {
var sessionIds = {}; // Collect the sessionsIds of all selected entities, w/o duplicates.
selectionManager.selections.forEach(function (id) {
var lastEditedBy = Entities.getEntityProperties(id, 'lastEditedBy').lastEditedBy;
if (lastEditedBy) {
sessionIds[lastEditedBy] = true;
}
});
var dedupped = Object.keys(sessionIds);
if (!selectionManager.selections.length) {
Window.alert('No objects selected.');
} else if (!dedupped.length) {
Window.alert('There were no recent users of the ' + selectionManager.selections.length + ' selected objects.');
} else {
// No need to subscribe if we're just sending.
Messages.sendMessage('com.highfidelity.pal', JSON.stringify({method: 'select', params: [dedupped, true, false]}), 'local');
}
} else if (data.type === "delete") {
deleteSelectedEntities();
} else if (data.type === "toggleLocked") {

View file

@ -29,7 +29,6 @@
<input type="button" id="locked" class="glyph" value="&#xe006;" />
<input type="button" id="visible" class="glyph" value="&#xe007;" />
</div>
<input type="button" id="pal" class="glyph" value="&#xe00c;" />
<button id="toggle-space-mode" class="hifi-edit-button space-mode-local">Local</button>
<input type="button" class="red glyph" id="delete" value="{" />
</div>

View file

@ -209,7 +209,6 @@ let elEntityTable,
elFilterInView,
elFilterRadius,
elExport,
elPal,
elSelectedEntitiesCount,
elVisibleEntitiesCount,
elNoEntitiesMessage,
@ -254,7 +253,6 @@ function loaded() {
elFilterInView = document.getElementById("filter-in-view");
elFilterRadius = document.getElementById("filter-radius");
elExport = document.getElementById("export");
elPal = document.getElementById("pal");
elSelectedEntitiesCount = document.getElementById("selected-entities-count");
elVisibleEntitiesCount = document.getElementById("visible-entities-count");
elNoEntitiesMessage = document.getElementById("no-entities");
@ -272,9 +270,6 @@ function loaded() {
elExport.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'export'}));
};
elPal.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'pal' }));
};
elDelete.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
};
@ -541,8 +536,9 @@ function loaded() {
function onRowClicked(clickEvent) {
let entityID = this.dataset.entityID;
let selection = [entityID];
let controlKey = window.navigator.platform.startsWith("Mac") ? clickEvent.metaKey : clickEvent.ctrlKey;
if (clickEvent.ctrlKey) {
if (controlKey) {
let selectedIndex = selectedEntities.indexOf(entityID);
if (selectedIndex >= 0) {
selection = [];
@ -573,7 +569,7 @@ function loaded() {
selection.reverse();
}
}
} else if (!clickEvent.ctrlKey && !clickEvent.shiftKey && selectedEntities.length === 1) {
} else if (!controlKey && !clickEvent.shiftKey && selectedEntities.length === 1) {
// if reselecting the same entity then start renaming it
if (selectedEntities[0] === entityID) {
if (renameLastBlur && renameLastEntityID === entityID && (Date.now() - renameLastBlur) < RENAME_COOLDOWN) {

View file

@ -398,8 +398,8 @@ const GROUPS = [
{
label: "Base",
type: "number-draggable",
min: -1000,
max: 1000,
min: -16000,
max: 16000,
step: 1,
decimals: 0,
unit: "m",
@ -409,8 +409,8 @@ const GROUPS = [
{
label: "Ceiling",
type: "number-draggable",
min: -1000,
max: 5000,
min: -16000,
max: 16000,
step: 1,
decimals: 0,
unit: "m",