mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 01:00:44 +02:00
Merge branch 'master' of https://github.com/amerhifi/hifi
This commit is contained in:
commit
89d494cf81
44 changed files with 450 additions and 260 deletions
|
@ -15,6 +15,7 @@
|
||||||
<uses-feature android:name="android.hardware.sensor.gyroscope" android:required="true"/>
|
<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.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.high_performance" android:required="true"/>
|
||||||
|
<uses-feature android:name="android.hardware.vr.headtracking" android:version="1" android:required="true" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name="org.qtproject.qt5.android.bindings.QtApplication"
|
android:name="org.qtproject.qt5.android.bindings.QtApplication"
|
||||||
|
|
|
@ -399,6 +399,7 @@ void Agent::executeScript() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// these procedural movements are included in the recordings
|
// these procedural movements are included in the recordings
|
||||||
|
scriptedAvatar->setHasScriptedBlendshapes(true);
|
||||||
scriptedAvatar->setHasProceduralEyeFaceMovement(false);
|
scriptedAvatar->setHasProceduralEyeFaceMovement(false);
|
||||||
scriptedAvatar->setHasProceduralBlinkFaceMovement(false);
|
scriptedAvatar->setHasProceduralBlinkFaceMovement(false);
|
||||||
scriptedAvatar->setHasAudioEnabledFaceMovement(false);
|
scriptedAvatar->setHasAudioEnabledFaceMovement(false);
|
||||||
|
@ -406,6 +407,7 @@ void Agent::executeScript() {
|
||||||
scriptedAvatar->clearRecordingBasis();
|
scriptedAvatar->clearRecordingBasis();
|
||||||
|
|
||||||
// restore procedural blendshape movement
|
// restore procedural blendshape movement
|
||||||
|
scriptedAvatar->setHasScriptedBlendshapes(false);
|
||||||
scriptedAvatar->setHasProceduralEyeFaceMovement(true);
|
scriptedAvatar->setHasProceduralEyeFaceMovement(true);
|
||||||
scriptedAvatar->setHasProceduralBlinkFaceMovement(true);
|
scriptedAvatar->setHasProceduralBlinkFaceMovement(true);
|
||||||
scriptedAvatar->setHasAudioEnabledFaceMovement(true);
|
scriptedAvatar->setHasAudioEnabledFaceMovement(true);
|
||||||
|
|
|
@ -782,7 +782,7 @@ float computeGain(float masterAvatarGain,
|
||||||
gain *= std::max(1.0f - d / (distanceLimit - ATTN_DISTANCE_REF), 0.0f);
|
gain *= std::max(1.0f - d / (distanceLimit - ATTN_DISTANCE_REF), 0.0f);
|
||||||
gain = std::min(gain, ATTN_GAIN_MAX);
|
gain = std::min(gain, ATTN_GAIN_MAX);
|
||||||
|
|
||||||
} else {
|
} else if (attenuationPerDoublingInDistance < 1.0f) {
|
||||||
// translate a positive zone setting to gain per log2(distance)
|
// translate a positive zone setting to gain per log2(distance)
|
||||||
const float MIN_ATTENUATION_COEFFICIENT = 0.001f; // -60dB 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);
|
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);
|
float d = (1.0f / ATTN_DISTANCE_REF) * std::max(distance, HRTF_NEARFIELD_MIN);
|
||||||
gain *= fastExp2f(fastLog2f(g) * fastLog2f(d));
|
gain *= fastExp2f(fastLog2f(g) * fastLog2f(d));
|
||||||
gain = std::min(gain, ATTN_GAIN_MAX);
|
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;
|
return gain;
|
||||||
|
|
|
@ -58,3 +58,7 @@ if (ANDROID)
|
||||||
list(APPEND EXTERNAL_ARGS -DANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN})
|
list(APPEND EXTERNAL_ARGS -DANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN})
|
||||||
list(APPEND EXTERNAL_ARGS -DANDROID_STL=${ANDROID_STL})
|
list(APPEND EXTERNAL_ARGS -DANDROID_STL=${ANDROID_STL})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep")
|
||||||
|
endif()
|
BIN
interface/resources/avatar/animations/settle_to_idle.fbx
Normal file
BIN
interface/resources/avatar/animations/settle_to_idle.fbx
Normal file
Binary file not shown.
BIN
interface/resources/avatar/animations/settle_to_idle02.fbx
Normal file
BIN
interface/resources/avatar/animations/settle_to_idle02.fbx
Normal file
Binary file not shown.
BIN
interface/resources/avatar/animations/settle_to_idle03.fbx
Normal file
BIN
interface/resources/avatar/animations/settle_to_idle03.fbx
Normal file
Binary file not shown.
BIN
interface/resources/avatar/animations/settle_to_idle04.fbx
Normal file
BIN
interface/resources/avatar/animations/settle_to_idle04.fbx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -4804,16 +4804,117 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"children": [
|
"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": {
|
"data": {
|
||||||
|
"currentState": "idleSettle01",
|
||||||
"endFrame": 59,
|
"endFrame": 59,
|
||||||
"loopFlag": false,
|
"loopFlag": false,
|
||||||
|
"randomSwitchTimeMin": 1,
|
||||||
"startFrame": 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,
|
"timeScale": 1,
|
||||||
"url": "qrc:///avatar/animations/settle_to_idle_small.fbx"
|
"url": "qrc:///avatar/animations/settle_to_idle.fbx"
|
||||||
},
|
},
|
||||||
"id": "idleSettle",
|
"id": "idleSettle",
|
||||||
"type": "clip"
|
"type": "randomSwitchStateMachine"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"children": [
|
"children": [
|
||||||
|
@ -5346,6 +5447,19 @@
|
||||||
},
|
},
|
||||||
"id": "LANDRUN",
|
"id": "LANDRUN",
|
||||||
"type": "clip"
|
"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": {
|
"data": {
|
||||||
|
@ -5371,7 +5485,7 @@
|
||||||
{
|
{
|
||||||
"easingType": "easeInOutQuad",
|
"easingType": "easeInOutQuad",
|
||||||
"id": "idle",
|
"id": "idle",
|
||||||
"interpDuration": 15,
|
"interpDuration": 20,
|
||||||
"interpTarget": 20,
|
"interpTarget": 20,
|
||||||
"interpType": "evaluateBoth",
|
"interpType": "evaluateBoth",
|
||||||
"transitions": [
|
"transitions": [
|
||||||
|
@ -5503,13 +5617,114 @@
|
||||||
{
|
{
|
||||||
"easingType": "easeInOutQuad",
|
"easingType": "easeInOutQuad",
|
||||||
"id": "idleSettle",
|
"id": "idleSettle",
|
||||||
"interpDuration": 13,
|
"interpDuration": 15,
|
||||||
"interpTarget": 14,
|
"interpTarget": 15,
|
||||||
"interpType": "snapshotPrev",
|
"interpType": "snapshotPrev",
|
||||||
"transitions": [
|
"transitions": [
|
||||||
{
|
{
|
||||||
"state": "idle",
|
"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",
|
"state": "idle",
|
||||||
|
@ -5595,6 +5810,10 @@
|
||||||
"interpTarget": 35,
|
"interpTarget": 35,
|
||||||
"interpType": "snapshotPrev",
|
"interpType": "snapshotPrev",
|
||||||
"transitions": [
|
"transitions": [
|
||||||
|
{
|
||||||
|
"state": "idleSettleSmall",
|
||||||
|
"var": "isNotInputNoMomentum"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"state": "idleSettle",
|
"state": "idleSettle",
|
||||||
"var": "isNotInputSlow"
|
"var": "isNotInputSlow"
|
||||||
|
@ -5659,6 +5878,10 @@
|
||||||
"interpTarget": 35,
|
"interpTarget": 35,
|
||||||
"interpType": "snapshotPrev",
|
"interpType": "snapshotPrev",
|
||||||
"transitions": [
|
"transitions": [
|
||||||
|
{
|
||||||
|
"state": "idleSettleSmall",
|
||||||
|
"var": "isNotInputNoMomentum"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"state": "idleSettle",
|
"state": "idleSettle",
|
||||||
"var": "isNotInputSlow"
|
"var": "isNotInputSlow"
|
||||||
|
@ -5723,6 +5946,10 @@
|
||||||
"interpTarget": 25,
|
"interpTarget": 25,
|
||||||
"interpType": "snapshotPrev",
|
"interpType": "snapshotPrev",
|
||||||
"transitions": [
|
"transitions": [
|
||||||
|
{
|
||||||
|
"state": "idleSettleSmall",
|
||||||
|
"var": "isNotInputNoMomentum"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"state": "idleSettle",
|
"state": "idleSettle",
|
||||||
"var": "isNotInputSlow"
|
"var": "isNotInputSlow"
|
||||||
|
@ -5787,6 +6014,10 @@
|
||||||
"interpTarget": 25,
|
"interpTarget": 25,
|
||||||
"interpType": "snapshotPrev",
|
"interpType": "snapshotPrev",
|
||||||
"transitions": [
|
"transitions": [
|
||||||
|
{
|
||||||
|
"state": "idleSettleSmall",
|
||||||
|
"var": "isNotInputNoMomentum"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"state": "idleSettle",
|
"state": "idleSettle",
|
||||||
"var": "isNotInputSlow"
|
"var": "isNotInputSlow"
|
||||||
|
|
|
@ -201,8 +201,6 @@
|
||||||
{ "from": "Standard.LipsStretch_R", "to": "Actions.LipsStretch_R" },
|
{ "from": "Standard.LipsStretch_R", "to": "Actions.LipsStretch_R" },
|
||||||
{ "from": "Standard.LipsUpperClose", "to": "Actions.LipsUpperClose" },
|
{ "from": "Standard.LipsUpperClose", "to": "Actions.LipsUpperClose" },
|
||||||
{ "from": "Standard.LipsLowerClose", "to": "Actions.LipsLowerClose" },
|
{ "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.LipsFunnel", "to": "Actions.LipsFunnel" },
|
||||||
{ "from": "Standard.LipsPucker", "to": "Actions.LipsPucker" },
|
{ "from": "Standard.LipsPucker", "to": "Actions.LipsPucker" },
|
||||||
{ "from": "Standard.Puff", "to": "Actions.Puff" },
|
{ "from": "Standard.Puff", "to": "Actions.Puff" },
|
||||||
|
|
|
@ -96,8 +96,6 @@
|
||||||
{ "from": "Standard.LipsStretch_R", "to": "Actions.LipsStretch_R" },
|
{ "from": "Standard.LipsStretch_R", "to": "Actions.LipsStretch_R" },
|
||||||
{ "from": "Standard.LipsUpperClose", "to": "Actions.LipsUpperClose" },
|
{ "from": "Standard.LipsUpperClose", "to": "Actions.LipsUpperClose" },
|
||||||
{ "from": "Standard.LipsLowerClose", "to": "Actions.LipsLowerClose" },
|
{ "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.LipsFunnel", "to": "Actions.LipsFunnel" },
|
||||||
{ "from": "Standard.LipsPucker", "to": "Actions.LipsPucker" },
|
{ "from": "Standard.LipsPucker", "to": "Actions.LipsPucker" },
|
||||||
{ "from": "Standard.Puff", "to": "Actions.Puff" },
|
{ "from": "Standard.Puff", "to": "Actions.Puff" },
|
||||||
|
|
|
@ -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 {
|
AvatarAppComponents.DisplayNameHeader {
|
||||||
id: displayNameHeader
|
id: displayNameHeader
|
||||||
previewUrl: root.avatarPreviewUrl
|
previewUrl: root.avatarPreviewUrl
|
||||||
|
|
|
@ -232,12 +232,6 @@ void AvatarBookmarks::loadBookmark(const QString& bookmarkName) {
|
||||||
emit bookmarkLoaded(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;
|
qCDebug(interfaceapp) << "Start loading avatar bookmark" << bookmarkName;
|
||||||
|
|
||||||
const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString();
|
const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString();
|
||||||
|
|
|
@ -3452,7 +3452,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
||||||
bool isCameraYawing = getDriveKey(DELTA_YAW) + getDriveKey(STEP_YAW) + getDriveKey(YAW) != 0.0f;
|
bool isCameraYawing = getDriveKey(DELTA_YAW) + getDriveKey(STEP_YAW) + getDriveKey(YAW) != 0.0f;
|
||||||
bool isRotatingWhileSeated = !isCameraYawing && isMovingSideways && _characterController.getSeated();
|
bool isRotatingWhileSeated = !isCameraYawing && isMovingSideways && _characterController.getSeated();
|
||||||
glm::quat previousOrientation = getWorldOrientation();
|
glm::quat previousOrientation = getWorldOrientation();
|
||||||
|
glm::quat previousYaw = _lookAtYaw;
|
||||||
if (!computeLookAt) {
|
if (!computeLookAt) {
|
||||||
setWorldOrientation(getWorldOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f))));
|
setWorldOrientation(getWorldOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f))));
|
||||||
_lookAtCameraTarget = eyesPosition + getWorldOrientation() * Vectors::FRONT;
|
_lookAtCameraTarget = eyesPosition + getWorldOrientation() * Vectors::FRONT;
|
||||||
|
@ -3462,6 +3462,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
||||||
// Compute new look at vectors
|
// Compute new look at vectors
|
||||||
if (totalBodyYaw != 0.0f) {
|
if (totalBodyYaw != 0.0f) {
|
||||||
_lookAtYaw = _lookAtYaw * glm::quat(glm::radians(glm::vec3(0.0f, 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
|
float pitchIncrement = getDriveKey(PITCH) * _pitchSpeed * deltaTime
|
||||||
+ getDriveKey(DELTA_PITCH) * _pitchSpeed / PITCH_SPEED_DEFAULT;
|
+ 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_FORWARD_BLEND = 0.25f;
|
||||||
const float REORIENT_TURN_BLEND = 0.03f;
|
const float REORIENT_TURN_BLEND = 0.03f;
|
||||||
const float DIAGONAL_TURN_BLEND = 0.1f;
|
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;
|
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) {
|
if (blend > 1.0f) {
|
||||||
blend = 1.0f;
|
blend = 1.0f;
|
||||||
}
|
}
|
||||||
|
@ -3573,7 +3586,6 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
||||||
if (frontBackDot < limitAngle) {
|
if (frontBackDot < limitAngle) {
|
||||||
if (frontBackDot < 0.0f) {
|
if (frontBackDot < 0.0f) {
|
||||||
ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight);
|
ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight);
|
||||||
cameraVector = (ajustedYawVector * _lookAtPitch) * Vectors::FRONT;
|
|
||||||
}
|
}
|
||||||
if (!isRotatingWhileSeated) {
|
if (!isRotatingWhileSeated) {
|
||||||
if (frontBackDot < triggerAngle) {
|
if (frontBackDot < triggerAngle) {
|
||||||
|
@ -6762,19 +6774,18 @@ glm::vec3 MyAvatar::getLookAtPivotPoint() {
|
||||||
|
|
||||||
glm::vec3 MyAvatar::getCameraEyesPosition(float deltaTime) {
|
glm::vec3 MyAvatar::getCameraEyesPosition(float deltaTime) {
|
||||||
glm::vec3 defaultEyesPosition = getLookAtPivotPoint();
|
glm::vec3 defaultEyesPosition = getLookAtPivotPoint();
|
||||||
if (isFlying()) {
|
|
||||||
return defaultEyesPosition;
|
|
||||||
}
|
|
||||||
glm::vec3 avatarFrontVector = getWorldOrientation() * Vectors::FRONT;
|
glm::vec3 avatarFrontVector = getWorldOrientation() * Vectors::FRONT;
|
||||||
glm::vec3 avatarUpVector = getWorldOrientation() * Vectors::UP;
|
glm::vec3 avatarUpVector = getWorldOrientation() * Vectors::UP;
|
||||||
// Compute the offset between the default and real eye positions.
|
// Compute the offset between the default and real eye positions.
|
||||||
glm::vec3 defaultEyesToEyesVector = getHead()->getEyePosition() - defaultEyesPosition;
|
glm::vec3 defaultEyesToEyesVector = getHead()->getEyePosition() - defaultEyesPosition;
|
||||||
float FRONT_OFFSET_IDLE_MULTIPLIER = 2.5f;
|
const float FRONT_OFFSET_IDLE_MULTIPLIER = 3.5f;
|
||||||
float FRONT_OFFSET_JUMP_MULTIPLIER = 1.5f;
|
const float FRONT_OFFSET_JUMP_MULTIPLIER = 1.5f;
|
||||||
float frontOffset = FRONT_OFFSET_IDLE_MULTIPLIER * glm::length(defaultEyesPosition - getDefaultEyePosition());
|
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);
|
float mixAlpha = glm::dot(_lookAtPitch * Vectors::FRONT, -avatarUpVector);
|
||||||
|
|
||||||
bool isLanding = false;
|
bool isLanding = false;
|
||||||
// When jumping the camera should follow the real eye on the Y coordenate
|
// When jumping the camera should follow the real eye on the Y coordenate
|
||||||
float upOffset = 0.0f;
|
float upOffset = 0.0f;
|
||||||
|
|
|
@ -2693,6 +2693,7 @@ private:
|
||||||
const float MAX_LOOK_AT_TIME_SCRIPT_CONTROL = 2.0f;
|
const float MAX_LOOK_AT_TIME_SCRIPT_CONTROL = 2.0f;
|
||||||
glm::quat _lookAtPitch;
|
glm::quat _lookAtPitch;
|
||||||
glm::quat _lookAtYaw;
|
glm::quat _lookAtYaw;
|
||||||
|
float _lookAtYawSpeed { 0.0f };
|
||||||
glm::vec3 _lookAtCameraTarget;
|
glm::vec3 _lookAtCameraTarget;
|
||||||
glm::vec3 _lookAtScriptTarget;
|
glm::vec3 _lookAtScriptTarget;
|
||||||
bool _headLookAtActive { false };
|
bool _headLookAtActive { false };
|
||||||
|
|
|
@ -57,8 +57,6 @@ static controller::Action blendshapeActions[] = {
|
||||||
controller::Action::LIPSSTRETCH_R,
|
controller::Action::LIPSSTRETCH_R,
|
||||||
controller::Action::LIPSUPPERCLOSE,
|
controller::Action::LIPSUPPERCLOSE,
|
||||||
controller::Action::LIPSLOWERCLOSE,
|
controller::Action::LIPSLOWERCLOSE,
|
||||||
controller::Action::LIPSUPPEROPEN,
|
|
||||||
controller::Action::LIPSLOWEROPEN,
|
|
||||||
controller::Action::LIPSFUNNEL,
|
controller::Action::LIPSFUNNEL,
|
||||||
controller::Action::LIPSPUCKER,
|
controller::Action::LIPSPUCKER,
|
||||||
controller::Action::PUFF,
|
controller::Action::PUFF,
|
||||||
|
|
|
@ -206,7 +206,7 @@ public slots:
|
||||||
void browseAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
|
void browseAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
|
||||||
|
|
||||||
/**jsdoc
|
/**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.
|
* tree and allows the user to type in a file name.
|
||||||
* @function Window.save
|
* @function Window.save
|
||||||
* @param {string} [title=""] - The title to display at the top of the dialog.
|
* @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 = "");
|
QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
|
||||||
|
|
||||||
/**jsdoc
|
/**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
|
* 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.
|
* emitted when a file is specified; no signal is emitted if the user cancels the dialog.
|
||||||
* @function Window.saveAsync
|
* @function Window.saveAsync
|
||||||
|
|
|
@ -96,7 +96,9 @@ const AnimPoseVec& AnimBlendDirectional::evaluate(const AnimVariantMap& animVars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_poses.resize(minSize);
|
_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
|
// animation stack debug stats
|
||||||
for (int i = 0; i < 9; i++) {
|
for (int i = 0; i < 9; i++) {
|
||||||
|
|
|
@ -1171,6 +1171,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
|
|
||||||
_desiredStateAge += deltaTime;
|
_desiredStateAge += deltaTime;
|
||||||
|
|
||||||
|
|
||||||
if (_state == RigRole::Move) {
|
if (_state == RigRole::Move) {
|
||||||
glm::vec3 horizontalVel = localVel - glm::vec3(0.0f, localVel.y, 0.0f);
|
glm::vec3 horizontalVel = localVel - glm::vec3(0.0f, localVel.y, 0.0f);
|
||||||
if (glm::length(horizontalVel) > MOVE_ENTER_SPEED_THRESHOLD) {
|
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
|
//stategraph vars based on input
|
||||||
const float INPUT_DEADZONE_THRESHOLD = 0.05f;
|
const float INPUT_DEADZONE_THRESHOLD = 0.05f;
|
||||||
const float SLOW_SPEED_THRESHOLD = 1.5f;
|
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 &&
|
if (fabsf(_previousControllerParameters.inputX) <= INPUT_DEADZONE_THRESHOLD &&
|
||||||
fabsf(_previousControllerParameters.inputZ) <= INPUT_DEADZONE_THRESHOLD) {
|
fabsf(_previousControllerParameters.inputZ) <= INPUT_DEADZONE_THRESHOLD) {
|
||||||
// no WASD input
|
// no WASD input
|
||||||
if (fabsf(forwardSpeed) <= SLOW_SPEED_THRESHOLD && fabsf(lateralSpeed) <= SLOW_SPEED_THRESHOLD) {
|
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("isInputForward", false);
|
||||||
_animVars.set("isInputBackward", false);
|
_animVars.set("isInputBackward", false);
|
||||||
_animVars.set("isInputRight", false);
|
_animVars.set("isInputRight", false);
|
||||||
_animVars.set("isInputLeft", 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 {
|
} else {
|
||||||
_animVars.set("isInputForward", false);
|
_animVars.set("isInputForward", false);
|
||||||
|
@ -1456,8 +1477,13 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
_animVars.set("isInputLeft", false);
|
_animVars.set("isInputLeft", false);
|
||||||
_animVars.set("isNotInput", true);
|
_animVars.set("isNotInput", true);
|
||||||
_animVars.set("isNotInputSlow", false);
|
_animVars.set("isNotInputSlow", false);
|
||||||
|
_animVars.set("isNotInputNoMomentum", false);
|
||||||
}
|
}
|
||||||
} else if (fabsf(_previousControllerParameters.inputZ) >= fabsf(_previousControllerParameters.inputX)) {
|
} else if (fabsf(_previousControllerParameters.inputZ) >= fabsf(_previousControllerParameters.inputX)) {
|
||||||
|
if (fabsf(forwardSpeed) > HAS_MOMENTUM_THRESHOLD) {
|
||||||
|
_isMovingWithMomentum = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_previousControllerParameters.inputZ > 0.0f) {
|
if (_previousControllerParameters.inputZ > 0.0f) {
|
||||||
// forward
|
// forward
|
||||||
_animVars.set("isInputForward", true);
|
_animVars.set("isInputForward", true);
|
||||||
|
@ -1466,6 +1492,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
_animVars.set("isInputLeft", false);
|
_animVars.set("isInputLeft", false);
|
||||||
_animVars.set("isNotInput", false);
|
_animVars.set("isNotInput", false);
|
||||||
_animVars.set("isNotInputSlow", false);
|
_animVars.set("isNotInputSlow", false);
|
||||||
|
_animVars.set("isNotInputNoMomentum", false);
|
||||||
} else {
|
} else {
|
||||||
// backward
|
// backward
|
||||||
_animVars.set("isInputForward", false);
|
_animVars.set("isInputForward", false);
|
||||||
|
@ -1474,8 +1501,13 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
_animVars.set("isInputLeft", false);
|
_animVars.set("isInputLeft", false);
|
||||||
_animVars.set("isNotInput", false);
|
_animVars.set("isNotInput", false);
|
||||||
_animVars.set("isNotInputSlow", false);
|
_animVars.set("isNotInputSlow", false);
|
||||||
|
_animVars.set("isNotInputNoMomentum", false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (fabsf(lateralSpeed) > HAS_MOMENTUM_THRESHOLD) {
|
||||||
|
_isMovingWithMomentum = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_previousControllerParameters.inputX > 0.0f) {
|
if (_previousControllerParameters.inputX > 0.0f) {
|
||||||
// right
|
// right
|
||||||
_animVars.set("isInputForward", false);
|
_animVars.set("isInputForward", false);
|
||||||
|
@ -1484,6 +1516,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
_animVars.set("isInputLeft", false);
|
_animVars.set("isInputLeft", false);
|
||||||
_animVars.set("isNotInput", false);
|
_animVars.set("isNotInput", false);
|
||||||
_animVars.set("isNotInputSlow", false);
|
_animVars.set("isNotInputSlow", false);
|
||||||
|
_animVars.set("isNotInputNoMomentum", false);
|
||||||
} else {
|
} else {
|
||||||
// left
|
// left
|
||||||
_animVars.set("isInputForward", false);
|
_animVars.set("isInputForward", false);
|
||||||
|
@ -1492,6 +1525,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
_animVars.set("isInputLeft", true);
|
_animVars.set("isInputLeft", true);
|
||||||
_animVars.set("isNotInput", false);
|
_animVars.set("isNotInput", false);
|
||||||
_animVars.set("isNotInputSlow", false);
|
_animVars.set("isNotInputSlow", false);
|
||||||
|
_animVars.set("isNotInputNoMomentum", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -330,6 +330,7 @@ protected:
|
||||||
glm::vec3 _lastForward;
|
glm::vec3 _lastForward;
|
||||||
glm::vec3 _lastPosition;
|
glm::vec3 _lastPosition;
|
||||||
glm::vec3 _lastVelocity;
|
glm::vec3 _lastVelocity;
|
||||||
|
bool _isMovingWithMomentum{ false };
|
||||||
|
|
||||||
QUrl _animGraphURL;
|
QUrl _animGraphURL;
|
||||||
std::shared_ptr<AnimNode> _animNode;
|
std::shared_ptr<AnimNode> _animNode;
|
||||||
|
|
|
@ -111,11 +111,17 @@ QList<HifiAudioDeviceInfo> getAvailableDevices(QAudio::Mode mode, const QString&
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defaultDesktopDevice.getDevice().isNull()) {
|
if (defaultDesktopDevice.getDevice().isNull()) {
|
||||||
qCDebug(audioclient) << __FUNCTION__ << "Default device not found in list:" << defDeviceName
|
if (devices.size() > 0) {
|
||||||
<< "Setting Default to: " << devices.first().deviceName();
|
qCDebug(audioclient) << __FUNCTION__ << "Default device not found in list:" << defDeviceName
|
||||||
defaultDesktopDevice = HifiAudioDeviceInfo(devices.first(), true, mode, HifiAudioDeviceInfo::desktop);
|
<< "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()) {
|
if (!hmdName.isNull()) {
|
||||||
HifiAudioDeviceInfo hmdDevice;
|
HifiAudioDeviceInfo hmdDevice;
|
||||||
|
|
|
@ -25,13 +25,6 @@
|
||||||
#define ALIGN32
|
#define ALIGN32
|
||||||
#endif
|
#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
|
// 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,
|
// lpf = 0.0 -> -3dB @ 50kHz
|
||||||
// loosely based on data from Handbook of Acoustics. Only the onset of significant
|
// lpf = 0.5 -> -3dB @ 1kHz
|
||||||
// attenuation is modelled, not the filter slope.
|
// lpf = 1.0 -> -3dB @ 20Hz
|
||||||
//
|
//
|
||||||
// 1m -> -3dB @ 55kHz
|
static const int NLOWPASS = 32;
|
||||||
// 10m -> -3dB @ 12kHz
|
static const float lowpassTable[NLOWPASS+1][5] = { // { b0, b1, b2, a1, a2 }
|
||||||
// 100m -> -3dB @ 2.5kHz
|
{ 0.9996582613f, 1.3644521648f, 0.4299107175f, 1.3643981990f, 0.4296229446f },
|
||||||
// 1km -> -3dB @ 0.6kHz
|
{ 0.9990601568f, 1.2627213717f, 0.3631477252f, 1.2625024258f, 0.3624268280f },
|
||||||
// 10km -> -3dB @ 0.1kHz
|
{ 0.9974547575f, 1.1378303854f, 0.2891398515f, 1.1369629374f, 0.2874620569f },
|
||||||
//
|
{ 0.9932384344f, 0.9872078424f, 0.2089943789f, 0.9839050501f, 0.2055356056f },
|
||||||
static const int NLOWPASS = 64;
|
{ 0.9825457933f, 0.8153687744f, 0.1271135720f, 0.8036320348f, 0.1213961050f },
|
||||||
static const float lowpassTable[NLOWPASS][5] = { // { b0, b1, b2, a1, a2 }
|
{ 0.9572356804f, 0.6404312275f, 0.0534129844f, 0.6033230637f, 0.0477568288f },
|
||||||
// distance = 1
|
{ 0.9052878744f, 0.4902779401f, 0.0035032262f, 0.3924772681f, 0.0065917726f },
|
||||||
{ 0.999772371f, 1.399489756f, 0.454495527f, 1.399458985f, 0.454298669f },
|
{ 0.8204774205f, 0.3736089028f, -0.0129974730f, 0.1678426876f, 0.0132461627f },
|
||||||
{ 0.999631480f, 1.357609808f, 0.425210203f, 1.357549905f, 0.424901586f },
|
{ 0.7032096959f, 0.2836328681f, -0.0170877258f, -0.0810811878f, 0.0508360260f },
|
||||||
{ 0.999405154f, 1.311503050f, 0.394349994f, 1.311386830f, 0.393871368f },
|
{ 0.5685067272f, 0.2128349296f, -0.0148937235f, -0.3461942779f, 0.1126422113f },
|
||||||
{ 0.999042876f, 1.260674595f, 0.361869089f, 1.260450057f, 0.361136504f },
|
{ 0.4355093111f, 0.1558974062f, -0.0110025095f, -0.6105302595f, 0.1909344673f },
|
||||||
// distance = 2
|
{ 0.3186188589f, 0.1108581568f, -0.0074653192f, -0.8569688248f, 0.2789805212f },
|
||||||
{ 0.998465222f, 1.204646525f, 0.327757118f, 1.204214978f, 0.326653886f },
|
{ 0.2244962739f, 0.0766060095f, -0.0048289293f, -1.0745081373f, 0.3707814914f },
|
||||||
{ 0.997548106f, 1.143019308f, 0.292064663f, 1.142195387f, 0.290436690f },
|
{ 0.1535044640f, 0.0516447640f, -0.0030384640f, -1.2590370066f, 0.4611477706f },
|
||||||
{ 0.996099269f, 1.075569152f, 0.254941286f, 1.074009405f, 0.252600301f },
|
{ 0.1025113288f, 0.0341204303f, -0.0018818088f, -1.4113207964f, 0.5460707468f },
|
||||||
{ 0.993824292f, 1.002389610f, 0.216688640f, 0.999469185f, 0.213433357f },
|
{ 0.0672016063f, 0.0221823522f, -0.0011552756f, -1.5347007285f, 0.6229294113f },
|
||||||
// distance = 4
|
{ 0.0434202931f, 0.0142393067f, -0.0007060306f, -1.6334567973f, 0.6904103664f },
|
||||||
{ 0.990280170f, 0.924075266f, 0.177827150f, 0.918684864f, 0.173497723f },
|
{ 0.0277383489f, 0.0090500025f, -0.0004305987f, -1.7118804671f, 0.7482382198f },
|
||||||
{ 0.984818279f, 0.841917936f, 0.139164195f, 0.832151968f, 0.133748443f },
|
{ 0.0175636227f, 0.0057072537f, -0.0002624537f, -1.7738404438f, 0.7968488665f },
|
||||||
{ 0.976528670f, 0.758036513f, 0.101832398f, 0.740761682f, 0.095635899f },
|
{ 0.0110441068f, 0.0035773504f, -0.0001599927f, -1.8226329785f, 0.8370944430f },
|
||||||
{ 0.964216485f, 0.675305244f, 0.067243474f, 0.645654855f, 0.061110348f },
|
{ 0.0069069312f, 0.0022316608f, -0.0000975848f, -1.8609764152f, 0.8700174224f },
|
||||||
// distance = 8
|
{ 0.0043012064f, 0.0013870046f, -0.0000595614f, -1.8910688315f, 0.8966974811f },
|
||||||
{ 0.946463038f, 0.596943020f, 0.036899688f, 0.547879974f, 0.032425772f },
|
{ 0.0026696068f, 0.0008595333f, -0.0000363798f, -1.9146662133f, 0.9181589737f },
|
||||||
{ 0.921823868f, 0.525770189f, 0.012060451f, 0.447952111f, 0.011702396f },
|
{ 0.0016526098f, 0.0005314445f, -0.0000222355f, -1.9331608518f, 0.9353226705f },
|
||||||
{ 0.890470015f, 0.463334299f, -0.001227816f, 0.347276405f, 0.005300092f },
|
{ 0.0010209520f, 0.0003280036f, -0.0000135987f, -1.9476515008f, 0.9489868578f },
|
||||||
{ 0.851335343f, 0.407521164f, -0.009353968f, 0.241900234f, 0.007602305f },
|
{ 0.0006297162f, 0.0002021591f, -0.0000083208f, -1.9590027292f, 0.9598262837f },
|
||||||
// distance = 16
|
{ 0.0003879180f, 0.0001244611f, -0.0000050936f, -1.9678935939f, 0.9684008793f },
|
||||||
{ 0.804237360f, 0.358139558f, -0.014293332f, 0.130934213f, 0.017149373f },
|
{ 0.0002387308f, 0.0000765601f, -0.0000031192f, -1.9748568416f, 0.9751690132f },
|
||||||
{ 0.750073259f, 0.314581568f, -0.016625381f, 0.014505388f, 0.033524057f },
|
{ 0.0001468057f, 0.0000470631f, -0.0000019106f, -1.9803101382f, 0.9805020963f },
|
||||||
{ 0.690412072f, 0.275936128f, -0.017054561f, -0.106682490f, 0.055976129f },
|
{ 0.0000902227f, 0.0000289155f, -0.0000011706f, -1.9845807858f, 0.9846987534f },
|
||||||
{ 0.627245545f, 0.241342015f, -0.016246850f, -0.231302564f, 0.083643275f },
|
{ 0.0000554223f, 0.0000177584f, -0.0000007174f, -1.9879252038f, 0.9879976671f },
|
||||||
// distance = 32
|
{ 0.0000340324f, 0.0000109027f, -0.0000004397f, -1.9905442465f, 0.9905887419f },
|
||||||
{ 0.562700627f, 0.210158533f, -0.014740899f, -0.357562697f, 0.115680957f },
|
{ 0.0000208917f, 0.0000066920f, -0.0000002695f, -1.9925952275f, 0.9926225417f },
|
||||||
{ 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 float HALFPI = 1.570796327f;
|
|
||||||
static const float PI = 3.141592654f;
|
|
||||||
static const float TWOPI = 6.283185307f;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// on x86 architecture, assume that SSE2 is present
|
// 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;
|
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)
|
// Computed from a lookup table and piecewise linear interpolation.
|
||||||
// and reconstructed by piecewise linear interpolation.
|
|
||||||
// Approximation error < 0.25dB
|
// Approximation error < 0.25dB
|
||||||
//
|
//
|
||||||
|
float x = lpf * NLOWPASS;
|
||||||
|
|
||||||
float x = distance;
|
// split x into index and fraction
|
||||||
x = MIN(x, 1<<30);
|
int i = (int)x;
|
||||||
x *= x;
|
float frac = x - (float)i;
|
||||||
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);
|
|
||||||
|
|
||||||
// clamp to table limits
|
// clamp to table limits
|
||||||
if (e < 0) {
|
if (i < 0) {
|
||||||
e = 0;
|
i = 0;
|
||||||
frac = 0.0f;
|
frac = 0.0f;
|
||||||
}
|
}
|
||||||
if (e > NLOWPASS-2) {
|
if (i > NLOWPASS-1) {
|
||||||
e = NLOWPASS-2;
|
i = NLOWPASS-1;
|
||||||
frac = 1.0f;
|
frac = 1.0f;
|
||||||
}
|
}
|
||||||
assert(frac >= 0.0f);
|
assert(frac >= 0.0f);
|
||||||
assert(frac <= 1.0f);
|
assert(frac <= 1.0f);
|
||||||
assert(e+0 >= 0);
|
assert(i+0 >= 0);
|
||||||
assert(e+1 < NLOWPASS);
|
assert(i+1 <= NLOWPASS);
|
||||||
|
|
||||||
// piecewise linear interpolation
|
// piecewise linear interpolation
|
||||||
b0 = lowpassTable[e+0][0] + frac * (lowpassTable[e+1][0] - lowpassTable[e+0][0]);
|
b0 = lowpassTable[i+0][0] + frac * (lowpassTable[i+1][0] - lowpassTable[i+0][0]);
|
||||||
b1 = lowpassTable[e+0][1] + frac * (lowpassTable[e+1][1] - lowpassTable[e+0][1]);
|
b1 = lowpassTable[i+0][1] + frac * (lowpassTable[i+1][1] - lowpassTable[i+0][1]);
|
||||||
b2 = lowpassTable[e+0][2] + frac * (lowpassTable[e+1][2] - lowpassTable[e+0][2]);
|
b2 = lowpassTable[i+0][2] + frac * (lowpassTable[i+1][2] - lowpassTable[i+0][2]);
|
||||||
a1 = lowpassTable[e+0][3] + frac * (lowpassTable[e+1][3] - lowpassTable[e+0][3]);
|
a1 = lowpassTable[i+0][3] + frac * (lowpassTable[i+1][3] - lowpassTable[i+0][3]);
|
||||||
a2 = lowpassTable[e+0][4] + frac * (lowpassTable[e+1][4] - lowpassTable[e+0][4]);
|
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));
|
float d = (HRTF_NEARFIELD_MAX - distance) * (1.0f / (HRTF_NEARFIELD_MAX - HRTF_HEAD_RADIUS));
|
||||||
|
|
||||||
// angle of incidence at each ear
|
// angle of incidence at each ear
|
||||||
float angleL = azimuth + HALFPI;
|
float angleL = azimuth + PI_OVER_TWO;
|
||||||
float angleR = azimuth - HALFPI;
|
float angleR = azimuth - PI_OVER_TWO;
|
||||||
if (angleL > +PI) {
|
if (angleL > +PI) {
|
||||||
angleL -= TWOPI;
|
angleL -= TWO_PI;
|
||||||
}
|
}
|
||||||
if (angleR < -PI) {
|
if (angleR < -PI) {
|
||||||
angleR += TWOPI;
|
angleR += TWO_PI;
|
||||||
}
|
}
|
||||||
assert(angleL >= -PI);
|
assert(angleL >= -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) {
|
static void azimuthToIndex(float azimuth, int& index0, int& index1, float& frac) {
|
||||||
|
|
||||||
// convert from radians to table units
|
// convert from radians to table units
|
||||||
azimuth *= (HRTF_AZIMUTHS / TWOPI);
|
azimuth *= (HRTF_AZIMUTHS / TWO_PI);
|
||||||
|
|
||||||
if (azimuth < 0.0f) {
|
if (azimuth < 0.0f) {
|
||||||
azimuth += HRTF_AZIMUTHS;
|
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
|
// 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],
|
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) {
|
if (azimuth > PI) {
|
||||||
azimuth -= TWOPI;
|
azimuth -= TWO_PI;
|
||||||
}
|
}
|
||||||
assert(azimuth >= -PI);
|
assert(azimuth >= -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
|
// compute the azimuth correction at each ear
|
||||||
float azimuthL = azimuth;
|
float azimuthL = azimuth;
|
||||||
|
@ -1109,7 +1039,7 @@ static void setFilters(float firCoef[4][HRTF_TAPS], float bqCoef[5][8], int dela
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
distanceBiquad(distance, b0, b1, b2, a1, a2);
|
lowpassBiquad(lpf, b0, b1, b2, a1, a2);
|
||||||
|
|
||||||
bqCoef[0][channel+4] = b0;
|
bqCoef[0][channel+4] = b0;
|
||||||
bqCoef[1][channel+4] = b1;
|
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 >= 0);
|
||||||
assert(index < HRTF_TABLES);
|
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
|
// apply global and local gain adjustment
|
||||||
gain *= _gainAdjust;
|
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
|
// disable interpolation from reset state
|
||||||
if (_resetState) {
|
if (_resetState) {
|
||||||
_azimuthState = azimuth;
|
_azimuthState = azimuth;
|
||||||
_distanceState = distance;
|
_distanceState = distance;
|
||||||
_gainState = gain;
|
_gainState = gain;
|
||||||
|
_lpfState = lpf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// to avoid polluting the cache, old filters are recomputed instead of stored
|
// 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
|
// 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
|
// new parameters become old
|
||||||
_azimuthState = azimuth;
|
_azimuthState = azimuth;
|
||||||
_distanceState = distance;
|
_distanceState = distance;
|
||||||
_gainState = gain;
|
_gainState = gain;
|
||||||
|
_lpfState = lpf;
|
||||||
|
|
||||||
// convert mono input to float
|
// convert mono input to float
|
||||||
for (int i = 0; i < HRTF_BLOCK; i++) {
|
for (int i = 0; i < HRTF_BLOCK; i++) {
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "AudioHelpers.h"
|
||||||
|
|
||||||
static const int HRTF_AZIMUTHS = 72; // 360 / 5-degree steps
|
static const int HRTF_AZIMUTHS = 72; // 360 / 5-degree steps
|
||||||
static const int HRTF_TAPS = 64; // minimum-phase FIR coefficients
|
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_DISTANCE_REF = 2.0f; // distance where attn is 0dB
|
||||||
static const float ATTN_GAIN_MAX = 16.0f; // max gain allowed by distance attn (+24dB)
|
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 {
|
class AudioHRTF {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -47,8 +53,10 @@ public:
|
||||||
// distance: source distance in meters
|
// distance: source distance in meters
|
||||||
// gain: gain factor for distance attenuation
|
// gain: gain factor for distance attenuation
|
||||||
// numFrames: must be HRTF_BLOCK in this version
|
// 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)
|
// 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
|
// 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
|
// new parameters become old
|
||||||
_azimuthState = azimuth;
|
_azimuthState = azimuth;
|
||||||
_distanceState = distance;
|
_distanceState = distance;
|
||||||
_gainState = gain;
|
_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;
|
_azimuthState = 0.0f;
|
||||||
_distanceState = 0.0f;
|
_distanceState = 0.0f;
|
||||||
_gainState = 0.0f;
|
_gainState = 0.0f;
|
||||||
|
_lpfState = 0.0f;
|
||||||
|
|
||||||
// _gainAdjust is retained
|
// _gainAdjust is retained
|
||||||
|
|
||||||
|
@ -123,6 +135,7 @@ private:
|
||||||
float _azimuthState = 0.0f;
|
float _azimuthState = 0.0f;
|
||||||
float _distanceState = 0.0f;
|
float _distanceState = 0.0f;
|
||||||
float _gainState = 0.0f;
|
float _gainState = 0.0f;
|
||||||
|
float _lpfState = 0.0f;
|
||||||
|
|
||||||
// global and local gain adjustment
|
// global and local gain adjustment
|
||||||
float _gainAdjust = HRTF_GAIN;
|
float _gainAdjust = HRTF_GAIN;
|
||||||
|
|
|
@ -386,8 +386,6 @@ namespace controller {
|
||||||
makeAxisPair(Action::LIPSSTRETCH_R, "LipsStretch_R"),
|
makeAxisPair(Action::LIPSSTRETCH_R, "LipsStretch_R"),
|
||||||
makeAxisPair(Action::LIPSUPPERCLOSE, "LipsUpperClose"),
|
makeAxisPair(Action::LIPSUPPERCLOSE, "LipsUpperClose"),
|
||||||
makeAxisPair(Action::LIPSLOWERCLOSE, "LipsLowerClose"),
|
makeAxisPair(Action::LIPSLOWERCLOSE, "LipsLowerClose"),
|
||||||
makeAxisPair(Action::LIPSUPPEROPEN, "LipsUpperOpen"),
|
|
||||||
makeAxisPair(Action::LIPSLOWEROPEN, "LipsLowerOpen"),
|
|
||||||
makeAxisPair(Action::LIPSFUNNEL, "LipsFunnel"),
|
makeAxisPair(Action::LIPSFUNNEL, "LipsFunnel"),
|
||||||
makeAxisPair(Action::LIPSPUCKER, "LipsPucker"),
|
makeAxisPair(Action::LIPSPUCKER, "LipsPucker"),
|
||||||
makeAxisPair(Action::PUFF, "Puff"),
|
makeAxisPair(Action::PUFF, "Puff"),
|
||||||
|
|
|
@ -220,8 +220,6 @@ enum class Action {
|
||||||
LIPSSTRETCH_R,
|
LIPSSTRETCH_R,
|
||||||
LIPSUPPERCLOSE,
|
LIPSUPPERCLOSE,
|
||||||
LIPSLOWERCLOSE,
|
LIPSLOWERCLOSE,
|
||||||
LIPSUPPEROPEN,
|
|
||||||
LIPSLOWEROPEN,
|
|
||||||
LIPSFUNNEL,
|
LIPSFUNNEL,
|
||||||
LIPSPUCKER,
|
LIPSPUCKER,
|
||||||
PUFF,
|
PUFF,
|
||||||
|
|
|
@ -392,8 +392,6 @@ Input::NamedVector StandardController::getAvailableInputs() const {
|
||||||
makePair(LIPSSTRETCH_R, "LipsStretch_R"),
|
makePair(LIPSSTRETCH_R, "LipsStretch_R"),
|
||||||
makePair(LIPSUPPERCLOSE, "LipsUpperClose"),
|
makePair(LIPSUPPERCLOSE, "LipsUpperClose"),
|
||||||
makePair(LIPSLOWERCLOSE, "LipsLowerClose"),
|
makePair(LIPSLOWERCLOSE, "LipsLowerClose"),
|
||||||
makePair(LIPSUPPEROPEN, "LipsUpperOpen"),
|
|
||||||
makePair(LIPSLOWEROPEN, "LipsLowerOpen"),
|
|
||||||
makePair(LIPSFUNNEL, "LipsFunnel"),
|
makePair(LIPSFUNNEL, "LipsFunnel"),
|
||||||
makePair(LIPSPUCKER, "LipsPucker"),
|
makePair(LIPSPUCKER, "LipsPucker"),
|
||||||
makePair(PUFF, "Puff"),
|
makePair(PUFF, "Puff"),
|
||||||
|
|
|
@ -127,8 +127,6 @@ namespace controller {
|
||||||
LIPSSTRETCH_R,
|
LIPSSTRETCH_R,
|
||||||
LIPSUPPERCLOSE,
|
LIPSUPPERCLOSE,
|
||||||
LIPSLOWERCLOSE,
|
LIPSLOWERCLOSE,
|
||||||
LIPSUPPEROPEN,
|
|
||||||
LIPSLOWEROPEN,
|
|
||||||
LIPSFUNNEL,
|
LIPSFUNNEL,
|
||||||
LIPSPUCKER,
|
LIPSPUCKER,
|
||||||
PUFF,
|
PUFF,
|
||||||
|
|
|
@ -82,6 +82,8 @@ static void fixUpLegacyBlendshapes(QVariantHash& properties) {
|
||||||
removeBlendshape(bs, "JawChew");
|
removeBlendshape(bs, "JawChew");
|
||||||
removeBlendshape(bs, "ChinLowerRaise");
|
removeBlendshape(bs, "ChinLowerRaise");
|
||||||
removeBlendshape(bs, "ChinUpperRaise");
|
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.
|
// 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");
|
splitBlendshapes(bs, "LipsUpperUp", "MouthUpperUp_L", "MouthUpperUp_R");
|
||||||
|
|
|
@ -257,7 +257,9 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con
|
||||||
ShapeKey::Builder(), ShapeKey::Builder().withFade(),
|
ShapeKey::Builder(), ShapeKey::Builder().withFade(),
|
||||||
ShapeKey::Builder().withDeformed(), ShapeKey::Builder().withDeformed().withFade(),
|
ShapeKey::Builder().withDeformed(), ShapeKey::Builder().withDeformed().withFade(),
|
||||||
ShapeKey::Builder().withDeformed().withDualQuatSkinned(), ShapeKey::Builder().withDeformed().withDualQuatSkinned().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());
|
std::vector<std::vector<ShapeKey>> sortedShapeKeys(keys.size());
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,6 @@ const char* FACESHIFT_BLENDSHAPES[] = {
|
||||||
"LipsStretch_R",
|
"LipsStretch_R",
|
||||||
"LipsUpperClose",
|
"LipsUpperClose",
|
||||||
"LipsLowerClose",
|
"LipsLowerClose",
|
||||||
"LipsUpperOpen",
|
|
||||||
"LipsLowerOpen",
|
|
||||||
"LipsFunnel",
|
"LipsFunnel",
|
||||||
"LipsPucker",
|
"LipsPucker",
|
||||||
"Puff",
|
"Puff",
|
||||||
|
|
|
@ -51,8 +51,6 @@ enum class Blendshapes : int {
|
||||||
LipsStretch_R,
|
LipsStretch_R,
|
||||||
LipsUpperClose,
|
LipsUpperClose,
|
||||||
LipsLowerClose,
|
LipsLowerClose,
|
||||||
LipsUpperOpen,
|
|
||||||
LipsLowerOpen,
|
|
||||||
LipsFunnel,
|
LipsFunnel,
|
||||||
LipsPucker,
|
LipsPucker,
|
||||||
Puff,
|
Puff,
|
||||||
|
@ -114,5 +112,8 @@ enum class LegacyBlendshpaes : int {
|
||||||
// * Sneer (split in ARKit)
|
// * Sneer (split in ARKit)
|
||||||
// * ChinLowerRaise (not in ARKit)
|
// * ChinLowerRaise (not in ARKit)
|
||||||
// * ChinUpperRaise (not in ARKit)
|
// * ChinUpperRaise (not in ARKit)
|
||||||
|
// * LipsUpperOpen (not in ARKit)
|
||||||
|
// * LipsLowerOpen (not in ARKit)
|
||||||
|
|
||||||
|
|
||||||
#endif // hifi_BlendshapeConstants_h
|
#endif // hifi_BlendshapeConstants_h
|
||||||
|
|
|
@ -25,38 +25,46 @@
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td><strong>First Person</strong></td>
|
* <td><strong>First Person</strong></td>
|
||||||
* <td><code>"first person"</code></td>
|
* <td><code>"first person"</code></td>
|
||||||
* <td>Legacy first person camera mode. The camera is positioned such that you have the same view as your avatar.
|
* <td><p>The camera is positioned such that you have the same view as your avatar. The camera moves and rotates with
|
||||||
* The camera moves and rotates with your avatar.</td>
|
* your avatar.</p>
|
||||||
|
* <p><em>Legacy first person camera mode.</em></p></td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td><strong>First Person Look At</strong></td>
|
* <td><strong>First Person Look At</strong></td>
|
||||||
* <td><code>"first person look at"</code></td>
|
* <td><code>"first person look at"</code></td>
|
||||||
* <td>Default first person camera mode. The camera is positioned such that you have the same view as your avatar.
|
* <td><p>The camera is positioned such that you have the same view as your avatar. The camera moves and rotates with
|
||||||
* The camera moves and rotates with your avatar's head.</td>
|
* your avatar's head.</p>
|
||||||
|
* <p><em>Default first person camera mode.</em></p></td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td><strong>Third Person</strong></td>
|
* <td><strong>Third Person</strong></td>
|
||||||
* <td><code>"third person"</code></td>
|
* <td><code>"third 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
|
* <td><p>The camera is positioned such that you have a view from just behind your avatar. The camera moves and rotates
|
||||||
* your avatar.</td>
|
* 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>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td><strong>Look At</strong></td>
|
* <td><strong>Look At</strong></td>
|
||||||
* <td><code>"look at"</code></td>
|
* <td><code>"look at"</code></td>
|
||||||
* <td>The camera is positioned behind your avatar. The camera moves and rotates independently from your avatar.
|
* <td><p>The camera is positioned behind your avatar. The camera moves and rotates independently from your avatar. The
|
||||||
* The avatar's head always faces the camera look at point.</td>
|
* avatar's head always faces the camera look at point.</p>
|
||||||
|
* <p><em>Default third person camera mode.</em></td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td><strong>Selfie</strong></td>
|
* <td><strong>Selfie</strong></td>
|
||||||
* <td><code>"selfie"</code></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.
|
* <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.</td>
|
* Your avatar's head is always facing the camera.</p>
|
||||||
|
* <p><em>Default "look at myself" camera mode.</em></p></td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td><strong>Mirror</strong></td>
|
* <td><strong>Mirror</strong></td>
|
||||||
* <td><code>"mirror"</code></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
|
* <td><p>The camera is positioned such that you are looking directly at your avatar. The camera is fixed and does not
|
||||||
* avatar.</td>
|
* 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>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td><strong>Independent</strong></td>
|
* <td><strong>Independent</strong></td>
|
||||||
|
|
|
@ -561,7 +561,8 @@ var toolBar = (function () {
|
||||||
if (!properties.grab) {
|
if (!properties.grab) {
|
||||||
properties.grab = {};
|
properties.grab = {};
|
||||||
if (Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE) &&
|
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;
|
properties.grab.grabbable = true;
|
||||||
} else {
|
} else {
|
||||||
properties.grab.grabbable = false;
|
properties.grab.grabbable = false;
|
||||||
|
|
|
@ -177,7 +177,7 @@ EntityListTool = function(shouldUseEditTabletApp) {
|
||||||
|
|
||||||
var cameraPosition = Camera.position;
|
var cameraPosition = Camera.position;
|
||||||
PROFILE("getMultipleProperties", function () {
|
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',
|
'visible', 'renderInfo', 'modelURL', 'materialURL', 'imageURL', 'script', 'certificateID',
|
||||||
'skybox.url', 'ambientLight.url']);
|
'skybox.url', 'ambientLight.url']);
|
||||||
for (var i = 0; i < multipleProperties.length; i++) {
|
for (var i = 0; i < multipleProperties.length; i++) {
|
||||||
|
@ -275,23 +275,6 @@ EntityListTool = function(shouldUseEditTabletApp) {
|
||||||
Window.saveFileChanged.connect(onFileSaveChanged);
|
Window.saveFileChanged.connect(onFileSaveChanged);
|
||||||
Window.saveAsync("Select Where to Save", "", "*.json");
|
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") {
|
} else if (data.type === "delete") {
|
||||||
deleteSelectedEntities();
|
deleteSelectedEntities();
|
||||||
} else if (data.type === "toggleLocked") {
|
} else if (data.type === "toggleLocked") {
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
<input type="button" id="locked" class="glyph" value="" />
|
<input type="button" id="locked" class="glyph" value="" />
|
||||||
<input type="button" id="visible" class="glyph" value="" />
|
<input type="button" id="visible" class="glyph" value="" />
|
||||||
</div>
|
</div>
|
||||||
<input type="button" id="pal" class="glyph" value="" />
|
|
||||||
<button id="toggle-space-mode" class="hifi-edit-button space-mode-local">Local</button>
|
<button id="toggle-space-mode" class="hifi-edit-button space-mode-local">Local</button>
|
||||||
<input type="button" class="red glyph" id="delete" value="{" />
|
<input type="button" class="red glyph" id="delete" value="{" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -209,7 +209,6 @@ let elEntityTable,
|
||||||
elFilterInView,
|
elFilterInView,
|
||||||
elFilterRadius,
|
elFilterRadius,
|
||||||
elExport,
|
elExport,
|
||||||
elPal,
|
|
||||||
elSelectedEntitiesCount,
|
elSelectedEntitiesCount,
|
||||||
elVisibleEntitiesCount,
|
elVisibleEntitiesCount,
|
||||||
elNoEntitiesMessage,
|
elNoEntitiesMessage,
|
||||||
|
@ -254,7 +253,6 @@ function loaded() {
|
||||||
elFilterInView = document.getElementById("filter-in-view");
|
elFilterInView = document.getElementById("filter-in-view");
|
||||||
elFilterRadius = document.getElementById("filter-radius");
|
elFilterRadius = document.getElementById("filter-radius");
|
||||||
elExport = document.getElementById("export");
|
elExport = document.getElementById("export");
|
||||||
elPal = document.getElementById("pal");
|
|
||||||
elSelectedEntitiesCount = document.getElementById("selected-entities-count");
|
elSelectedEntitiesCount = document.getElementById("selected-entities-count");
|
||||||
elVisibleEntitiesCount = document.getElementById("visible-entities-count");
|
elVisibleEntitiesCount = document.getElementById("visible-entities-count");
|
||||||
elNoEntitiesMessage = document.getElementById("no-entities");
|
elNoEntitiesMessage = document.getElementById("no-entities");
|
||||||
|
@ -272,9 +270,6 @@ function loaded() {
|
||||||
elExport.onclick = function() {
|
elExport.onclick = function() {
|
||||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'export'}));
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'export'}));
|
||||||
};
|
};
|
||||||
elPal.onclick = function() {
|
|
||||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'pal' }));
|
|
||||||
};
|
|
||||||
elDelete.onclick = function() {
|
elDelete.onclick = function() {
|
||||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
||||||
};
|
};
|
||||||
|
@ -541,8 +536,9 @@ function loaded() {
|
||||||
function onRowClicked(clickEvent) {
|
function onRowClicked(clickEvent) {
|
||||||
let entityID = this.dataset.entityID;
|
let entityID = this.dataset.entityID;
|
||||||
let selection = [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);
|
let selectedIndex = selectedEntities.indexOf(entityID);
|
||||||
if (selectedIndex >= 0) {
|
if (selectedIndex >= 0) {
|
||||||
selection = [];
|
selection = [];
|
||||||
|
@ -573,7 +569,7 @@ function loaded() {
|
||||||
selection.reverse();
|
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 reselecting the same entity then start renaming it
|
||||||
if (selectedEntities[0] === entityID) {
|
if (selectedEntities[0] === entityID) {
|
||||||
if (renameLastBlur && renameLastEntityID === entityID && (Date.now() - renameLastBlur) < RENAME_COOLDOWN) {
|
if (renameLastBlur && renameLastEntityID === entityID && (Date.now() - renameLastBlur) < RENAME_COOLDOWN) {
|
||||||
|
|
|
@ -398,8 +398,8 @@ const GROUPS = [
|
||||||
{
|
{
|
||||||
label: "Base",
|
label: "Base",
|
||||||
type: "number-draggable",
|
type: "number-draggable",
|
||||||
min: -1000,
|
min: -16000,
|
||||||
max: 1000,
|
max: 16000,
|
||||||
step: 1,
|
step: 1,
|
||||||
decimals: 0,
|
decimals: 0,
|
||||||
unit: "m",
|
unit: "m",
|
||||||
|
@ -409,8 +409,8 @@ const GROUPS = [
|
||||||
{
|
{
|
||||||
label: "Ceiling",
|
label: "Ceiling",
|
||||||
type: "number-draggable",
|
type: "number-draggable",
|
||||||
min: -1000,
|
min: -16000,
|
||||||
max: 5000,
|
max: 16000,
|
||||||
step: 1,
|
step: 1,
|
||||||
decimals: 0,
|
decimals: 0,
|
||||||
unit: "m",
|
unit: "m",
|
||||||
|
|
Loading…
Reference in a new issue