mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into orange
This commit is contained in:
commit
9b2a90b430
15 changed files with 290 additions and 123 deletions
94
examples/audioExamples/injectorLoadTest.js
Normal file
94
examples/audioExamples/injectorLoadTest.js
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
//
|
||||||
|
// injectorLoadTest.js
|
||||||
|
// audio
|
||||||
|
//
|
||||||
|
// Created by Eric Levin 2/1/2016
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
|
||||||
|
// This script tests what happens when many audio injectors are created and played
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
|
||||||
|
|
||||||
|
Script.include("../libraries/utils.js");
|
||||||
|
|
||||||
|
|
||||||
|
var numSoundsToPlayPerBatch = 35 // Number of simultaneously playing sounds
|
||||||
|
var numSoundsPlaying = 0;
|
||||||
|
var timeBetweenBatch = 30000;
|
||||||
|
// A green box represents an injector that is playing
|
||||||
|
|
||||||
|
var basePosition = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var soundBoxes = [];
|
||||||
|
|
||||||
|
var testSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/eric/Sounds/dove.wav");
|
||||||
|
var totalInjectors = 0;
|
||||||
|
var clipDuration;
|
||||||
|
|
||||||
|
if(!testSound.downloaded) {
|
||||||
|
|
||||||
|
print("SOUND IS NOT READY YET")
|
||||||
|
testSound.ready.connect(function() {
|
||||||
|
playSounds();
|
||||||
|
clipDuration = testSound.duration;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// otherwise play sounds right away
|
||||||
|
playSounds();
|
||||||
|
clipDuration = testSound.duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
function playSounds() {
|
||||||
|
print("PLAY SOUNDS!")
|
||||||
|
for (var i = 0; i < numSoundsToPlayPerBatch; i++) {
|
||||||
|
playSound();
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.setTimeout(function() {
|
||||||
|
numSoundsPlaying = 0;
|
||||||
|
}, clipDuration);
|
||||||
|
print("EBL Total Number of Injectors: " + totalInjectors);
|
||||||
|
|
||||||
|
Script.setTimeout(function() {
|
||||||
|
playSounds();
|
||||||
|
}, timeBetweenBatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function playSound() {
|
||||||
|
var position = Vec3.sum(basePosition, {x: randFloat(-.1, .1), y: randFloat(-1, 1), z: randFloat(-3, -.1)});
|
||||||
|
var injector = Audio.playSound(testSound, {
|
||||||
|
position: position,
|
||||||
|
volume: 0.2
|
||||||
|
});
|
||||||
|
|
||||||
|
numSoundsPlaying++;
|
||||||
|
print("NUM SOUNDS PLAYING: " + numSoundsPlaying);
|
||||||
|
print("*******************************************");
|
||||||
|
print("INJECTOR VALUE: ")
|
||||||
|
print(JSON.stringify(injector));
|
||||||
|
totalInjectors++;
|
||||||
|
|
||||||
|
var soundBox = Entities.addEntity({
|
||||||
|
type: "Box",
|
||||||
|
name: "Debug Sound Box",
|
||||||
|
color: {red: 200, green: 10, blue: 200},
|
||||||
|
dimensions: {x: 0.1, y: 0.1, z: 0.1},
|
||||||
|
position: position
|
||||||
|
});
|
||||||
|
|
||||||
|
soundBoxes.push(soundBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
soundBoxes.forEach( function(soundBox) {
|
||||||
|
Entities.deleteEntity(soundBox);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
|
@ -14,9 +14,6 @@ Render.RenderShadowTask.enabled = true;
|
||||||
var RDT = Render.RenderDeferredTask;
|
var RDT = Render.RenderDeferredTask;
|
||||||
RDT.AmbientOcclusion.enabled = true;
|
RDT.AmbientOcclusion.enabled = true;
|
||||||
RDT.DebugDeferredBuffer.enabled = false;
|
RDT.DebugDeferredBuffer.enabled = false;
|
||||||
["DrawOpaqueDeferred", "DrawTransparentDeferred", "DrawOverlay3DOpaque", "DrawOverlay3DTransparent"]
|
|
||||||
.map(function(name) { return RDT[name]; })
|
|
||||||
.forEach(function(job) { job.maxDrawn = job.numDrawn; });
|
|
||||||
|
|
||||||
// Set up the qml ui
|
// Set up the qml ui
|
||||||
var qml = Script.resolvePath('main.qml');
|
var qml = Script.resolvePath('main.qml');
|
||||||
|
@ -39,4 +36,4 @@ function setDebugBufferSize(x) {
|
||||||
Render.RenderDeferredTask.DebugDeferredBuffer.size = {x: x, y: -1, z: 1, w: 1};
|
Render.RenderDeferredTask.DebugDeferredBuffer.size = {x: x, y: -1, z: 1, w: 1};
|
||||||
}
|
}
|
||||||
|
|
||||||
Script.scriptEnding.connect(function() { Render.fromJSON(oldConfig); } );
|
Script.scriptEnding.connect(function() { Render.load(oldConfig); } );
|
||||||
|
|
|
@ -12,98 +12,109 @@ import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
spacing: 8
|
id: root
|
||||||
|
spacing: 16
|
||||||
Repeater {
|
Switch {
|
||||||
model: [ "Opaque:DrawOpaqueDeferred", "Transparent:DrawTransparentDeferred",
|
checked: true
|
||||||
"Opaque Overlays:DrawOverlay3DOpaque", "Transparent Overlays:DrawOverlay3DTransparent" ]
|
onClicked: ui.visible = checked
|
||||||
ConfigSlider {
|
|
||||||
label: qsTr(modelData.split(":")[0])
|
|
||||||
integral: true
|
|
||||||
config: Render.getConfig(modelData.split(":")[1])
|
|
||||||
property: "maxDrawn"
|
|
||||||
max: config.numDrawn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
CheckBox {
|
|
||||||
text: qsTr("Display Status")
|
|
||||||
onCheckedChanged: { Render.getConfig("DrawStatus").showDisplay = checked }
|
|
||||||
}
|
|
||||||
CheckBox {
|
|
||||||
text: qsTr("Network/Physics Status")
|
|
||||||
onCheckedChanged: { Render.getConfig("DrawStatus").showNetwork = checked }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigSlider {
|
|
||||||
label: qsTr("Tone Mapping Exposure")
|
|
||||||
config: Render.getConfig("ToneMapping")
|
|
||||||
property: "exposure"
|
|
||||||
min: -10; max: 10
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: ambientOcclusion
|
id: ui
|
||||||
property var config: Render.getConfig("AmbientOcclusion")
|
spacing: 8
|
||||||
|
|
||||||
Label { text: qsTr("Ambient Occlusion") }
|
|
||||||
// TODO: Add gpuTimer
|
|
||||||
CheckBox { text: qsTr("Dithering"); checked: ambientOcclusion.config.ditheringEnabled }
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: [
|
model: [ "Opaque:DrawOpaqueDeferred", "Transparent:DrawTransparentDeferred",
|
||||||
"Resolution Level:resolutionLevel:4",
|
"Opaque Overlays:DrawOverlay3DOpaque", "Transparent Overlays:DrawOverlay3DTransparent" ]
|
||||||
"Obscurance Level:obscuranceLevel:1",
|
|
||||||
"Radius:radius:2",
|
|
||||||
"Falloff Bias:falloffBias:0.2",
|
|
||||||
"Edge Sharpness:edgeSharpness:1",
|
|
||||||
"Blur Radius:blurRadius:6",
|
|
||||||
"Blur Deviation:blurDeviation:3"
|
|
||||||
]
|
|
||||||
ConfigSlider {
|
|
||||||
label: qsTr(modelData.split(":")[0])
|
|
||||||
config: ambientOcclusion.config
|
|
||||||
property: modelData.split(":")[1]
|
|
||||||
max: modelData.split(":")[2]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Repeater {
|
|
||||||
model: [
|
|
||||||
"Samples:numSamples:32",
|
|
||||||
"Spiral Turns:numSpiralTurns:30:"
|
|
||||||
]
|
|
||||||
ConfigSlider {
|
ConfigSlider {
|
||||||
label: qsTr(modelData.split(":")[0])
|
label: qsTr(modelData.split(":")[0])
|
||||||
integral: true
|
integral: true
|
||||||
config: ambientOcclusion.config
|
config: Render.getConfig(modelData.split(":")[1])
|
||||||
property: modelData.split(":")[1]
|
property: "maxDrawn"
|
||||||
max: modelData.split(":")[2]
|
max: config.numDrawn
|
||||||
|
min: -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
Row {
|
||||||
id: debug
|
CheckBox {
|
||||||
property var config: Render.getConfig("DebugDeferredBuffer")
|
text: qsTr("Display Status")
|
||||||
|
onCheckedChanged: { Render.getConfig("DrawStatus").showDisplay = checked }
|
||||||
function setDebugMode(mode) {
|
}
|
||||||
debug.config.enabled = (mode != 0);
|
CheckBox {
|
||||||
debug.config.mode = mode;
|
text: qsTr("Network/Physics Status")
|
||||||
|
onCheckedChanged: { Render.getConfig("DrawStatus").showNetwork = checked }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label { text: qsTr("Debug Buffer") }
|
ConfigSlider {
|
||||||
ExclusiveGroup { id: bufferGroup }
|
label: qsTr("Tone Mapping Exposure")
|
||||||
Repeater {
|
config: Render.getConfig("ToneMapping")
|
||||||
model: [
|
property: "exposure"
|
||||||
"Off", "Diffuse", "Metallic", "Roughness", "Normal", "Depth",
|
min: -10; max: 10
|
||||||
"Lighting", "Shadow", "Pyramid Depth", "Ambient Occlusion", "Custom Shader"
|
}
|
||||||
]
|
|
||||||
RadioButton {
|
Column {
|
||||||
text: qsTr(modelData)
|
id: ambientOcclusion
|
||||||
exclusiveGroup: bufferGroup
|
property var config: Render.getConfig("AmbientOcclusion")
|
||||||
checked: index == 0
|
|
||||||
onCheckedChanged: if (checked) debug.setDebugMode(index);
|
Label { text: qsTr("Ambient Occlusion") }
|
||||||
|
// TODO: Add gpuTimer
|
||||||
|
CheckBox { text: qsTr("Dithering"); checked: ambientOcclusion.config.ditheringEnabled }
|
||||||
|
Repeater {
|
||||||
|
model: [
|
||||||
|
"Resolution Level:resolutionLevel:4",
|
||||||
|
"Obscurance Level:obscuranceLevel:1",
|
||||||
|
"Radius:radius:2",
|
||||||
|
"Falloff Bias:falloffBias:0.2",
|
||||||
|
"Edge Sharpness:edgeSharpness:1",
|
||||||
|
"Blur Radius:blurRadius:6",
|
||||||
|
"Blur Deviation:blurDeviation:3"
|
||||||
|
]
|
||||||
|
ConfigSlider {
|
||||||
|
label: qsTr(modelData.split(":")[0])
|
||||||
|
config: ambientOcclusion.config
|
||||||
|
property: modelData.split(":")[1]
|
||||||
|
max: modelData.split(":")[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Repeater {
|
||||||
|
model: [
|
||||||
|
"Samples:numSamples:32",
|
||||||
|
"Spiral Turns:numSpiralTurns:30:"
|
||||||
|
]
|
||||||
|
ConfigSlider {
|
||||||
|
label: qsTr(modelData.split(":")[0])
|
||||||
|
integral: true
|
||||||
|
config: ambientOcclusion.config
|
||||||
|
property: modelData.split(":")[1]
|
||||||
|
max: modelData.split(":")[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: debug
|
||||||
|
property var config: Render.getConfig("DebugDeferredBuffer")
|
||||||
|
|
||||||
|
function setDebugMode(mode) {
|
||||||
|
debug.config.enabled = (mode != 0);
|
||||||
|
debug.config.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label { text: qsTr("Debug Buffer") }
|
||||||
|
ExclusiveGroup { id: bufferGroup }
|
||||||
|
Repeater {
|
||||||
|
model: [
|
||||||
|
"Off", "Diffuse", "Metallic", "Roughness", "Normal", "Depth",
|
||||||
|
"Lighting", "Shadow", "Pyramid Depth", "Ambient Occlusion", "Custom Shader"
|
||||||
|
]
|
||||||
|
RadioButton {
|
||||||
|
text: qsTr(modelData)
|
||||||
|
exclusiveGroup: bufferGroup
|
||||||
|
checked: index == 0
|
||||||
|
onCheckedChanged: if (checked && index > 0) debug.setDebugMode(index - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,8 @@ Window {
|
||||||
destroyOnInvisible: true
|
destroyOnInvisible: true
|
||||||
width: 800
|
width: 800
|
||||||
height: 600
|
height: 600
|
||||||
|
property alias webView: webview
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
visible = true
|
visible = true
|
||||||
addressBar.text = webview.url
|
addressBar.text = webview.url
|
||||||
|
@ -28,6 +29,7 @@ Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
id:item
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -125,12 +127,10 @@ Window {
|
||||||
console.log("New icon: " + icon)
|
console.log("New icon: " + icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
profile: WebEngineProfile {
|
profile: desktop.browserProfile
|
||||||
id: webviewProfile
|
|
||||||
storageName: "qmlUserBrowser"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // item
|
} // item
|
||||||
|
|
||||||
Keys.onPressed: {
|
Keys.onPressed: {
|
||||||
|
|
|
@ -11,6 +11,7 @@ WebEngineView {
|
||||||
root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
|
root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
|
||||||
console.log("Web Window JS message: " + sourceID + " " + lineNumber + " " + message);
|
console.log("Web Window JS message: " + sourceID + " " + lineNumber + " " + message);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME hack to get the URL with the auth token included. Remove when we move to Qt 5.6
|
// FIXME hack to get the URL with the auth token included. Remove when we move to Qt 5.6
|
||||||
|
@ -36,6 +37,10 @@ WebEngineView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFeaturePermissionRequested: {
|
||||||
|
grantFeaturePermission(securityOrigin, feature, true);
|
||||||
|
}
|
||||||
|
|
||||||
onLoadingChanged: {
|
onLoadingChanged: {
|
||||||
// Required to support clicking on "hifi://" links
|
// Required to support clicking on "hifi://" links
|
||||||
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
||||||
|
@ -48,9 +53,12 @@ WebEngineView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
profile: WebEngineProfile {
|
onNewViewRequested:{
|
||||||
id: webviewProfile
|
var component = Qt.createComponent("../Browser.qml");
|
||||||
httpUserAgent: "Mozilla/5.0 (HighFidelityInterface)"
|
var newWindow = component.createObject(desktop);
|
||||||
storageName: "qmlWebEngine"
|
request.openIn(newWindow.webView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
profile: desktop.browserProfile
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ Desktop {
|
||||||
id: desktop
|
id: desktop
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
WebEngine.settings.javascriptCanOpenWindows = false;
|
WebEngine.settings.javascriptCanOpenWindows = true;
|
||||||
WebEngine.settings.javascriptCanAccessClipboard = false;
|
WebEngine.settings.javascriptCanAccessClipboard = false;
|
||||||
WebEngine.settings.spatialNavigationEnabled = true;
|
WebEngine.settings.spatialNavigationEnabled = true;
|
||||||
WebEngine.settings.localContentCanAccessRemoteUrls = true;
|
WebEngine.settings.localContentCanAccessRemoteUrls = true;
|
||||||
|
@ -19,6 +19,12 @@ Desktop {
|
||||||
property alias toolWindow: toolWindow
|
property alias toolWindow: toolWindow
|
||||||
ToolWindow { id: toolWindow }
|
ToolWindow { id: toolWindow }
|
||||||
|
|
||||||
|
property var browserProfile: WebEngineProfile {
|
||||||
|
id: webviewProfile
|
||||||
|
httpUserAgent: "Chrome/48.0 (HighFidelityInterface)"
|
||||||
|
storageName: "qmlWebEngine"
|
||||||
|
}
|
||||||
|
|
||||||
Action {
|
Action {
|
||||||
text: "Open Browser"
|
text: "Open Browser"
|
||||||
shortcut: "Ctrl+B"
|
shortcut: "Ctrl+B"
|
||||||
|
|
|
@ -421,8 +421,8 @@ private:
|
||||||
AtRestDetector _hmdAtRestDetector;
|
AtRestDetector _hmdAtRestDetector;
|
||||||
bool _lastIsMoving { false };
|
bool _lastIsMoving { false };
|
||||||
bool _hoverReferenceCameraFacingIsCaptured { false };
|
bool _hoverReferenceCameraFacingIsCaptured { false };
|
||||||
glm::vec3 _hoverReferenceCameraFacing; // hmd sensor space
|
glm::vec3 _hoverReferenceCameraFacing { 0.0f, 0.0f, -1.0f }; // hmd sensor space
|
||||||
|
|
||||||
float AVATAR_MOVEMENT_ENERGY_CONSTANT { 0.001f };
|
float AVATAR_MOVEMENT_ENERGY_CONSTANT { 0.001f };
|
||||||
float AUDIO_ENERGY_CONSTANT { 0.000001f };
|
float AUDIO_ENERGY_CONSTANT { 0.000001f };
|
||||||
float MAX_AVATAR_MOVEMENT_PER_FRAME { 30.0f };
|
float MAX_AVATAR_MOVEMENT_PER_FRAME { 30.0f };
|
||||||
|
|
|
@ -144,6 +144,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
} else {
|
} else {
|
||||||
handParams.isRightEnabled = false;
|
handParams.isRightEnabled = false;
|
||||||
}
|
}
|
||||||
|
handParams.bodyCapsuleRadius = myAvatar->getCharacterController()->getCapsuleRadius();
|
||||||
|
|
||||||
_rig->updateFromHandParameters(handParams, deltaTime);
|
_rig->updateFromHandParameters(handParams, deltaTime);
|
||||||
|
|
||||||
|
|
|
@ -670,7 +670,7 @@ void AnimInverseKinematics::initConstraints() {
|
||||||
stConstraint->setTwistLimits(-MAX_SHOULDER_TWIST, MAX_SHOULDER_TWIST);
|
stConstraint->setTwistLimits(-MAX_SHOULDER_TWIST, MAX_SHOULDER_TWIST);
|
||||||
|
|
||||||
std::vector<float> minDots;
|
std::vector<float> minDots;
|
||||||
const float MAX_SHOULDER_SWING = PI / 20.0f;
|
const float MAX_SHOULDER_SWING = PI / 6.0f;
|
||||||
minDots.push_back(cosf(MAX_SHOULDER_SWING));
|
minDots.push_back(cosf(MAX_SHOULDER_SWING));
|
||||||
stConstraint->setSwingLimits(minDots);
|
stConstraint->setSwingLimits(minDots);
|
||||||
|
|
||||||
|
|
|
@ -1080,8 +1080,31 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm
|
||||||
|
|
||||||
void Rig::updateFromHandParameters(const HandParameters& params, float dt) {
|
void Rig::updateFromHandParameters(const HandParameters& params, float dt) {
|
||||||
if (_animSkeleton && _animNode) {
|
if (_animSkeleton && _animNode) {
|
||||||
|
|
||||||
|
const float HAND_RADIUS = 0.05f;
|
||||||
|
const float BODY_RADIUS = params.bodyCapsuleRadius;
|
||||||
|
const float MIN_LENGTH = 1.0e-4f;
|
||||||
|
|
||||||
|
// project the hips onto the xz plane.
|
||||||
|
auto hipsTrans = _internalPoseSet._absolutePoses[_animSkeleton->nameToJointIndex("Hips")].trans;
|
||||||
|
const glm::vec2 bodyCircleCenter(hipsTrans.x, hipsTrans.z);
|
||||||
|
|
||||||
if (params.isLeftEnabled) {
|
if (params.isLeftEnabled) {
|
||||||
_animVars.set("leftHandPosition", params.leftPosition);
|
|
||||||
|
// project the hand position onto the xz plane.
|
||||||
|
glm::vec2 handCircleCenter(params.leftPosition.x, params.leftPosition.z);
|
||||||
|
|
||||||
|
// check for 2d overlap of the hand and body circles.
|
||||||
|
auto circleToCircle = handCircleCenter - bodyCircleCenter;
|
||||||
|
const float circleToCircleLength = glm::length(circleToCircle);
|
||||||
|
const float penetrationDistance = HAND_RADIUS + BODY_RADIUS - circleToCircleLength;
|
||||||
|
if (penetrationDistance > 0.0f && circleToCircleLength > MIN_LENGTH) {
|
||||||
|
// push the hands out of the body
|
||||||
|
handCircleCenter += penetrationDistance * glm::normalize(circleToCircle);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 handPosition(handCircleCenter.x, params.leftPosition.y, handCircleCenter.y);
|
||||||
|
_animVars.set("leftHandPosition", handPosition);
|
||||||
_animVars.set("leftHandRotation", params.leftOrientation);
|
_animVars.set("leftHandRotation", params.leftOrientation);
|
||||||
_animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition);
|
_animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1089,8 +1112,23 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) {
|
||||||
_animVars.unset("leftHandRotation");
|
_animVars.unset("leftHandRotation");
|
||||||
_animVars.set("leftHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition);
|
_animVars.set("leftHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.isRightEnabled) {
|
if (params.isRightEnabled) {
|
||||||
_animVars.set("rightHandPosition", params.rightPosition);
|
|
||||||
|
// project the hand position onto the xz plane.
|
||||||
|
glm::vec2 handCircleCenter(params.rightPosition.x, params.rightPosition.z);
|
||||||
|
|
||||||
|
// check for 2d overlap of the hand and body circles.
|
||||||
|
auto circleToCircle = handCircleCenter - bodyCircleCenter;
|
||||||
|
const float circleToCircleLength = glm::length(circleToCircle);
|
||||||
|
const float penetrationDistance = HAND_RADIUS + BODY_RADIUS - circleToCircleLength;
|
||||||
|
if (penetrationDistance > 0.0f && circleToCircleLength > MIN_LENGTH) {
|
||||||
|
// push the hands out of the body
|
||||||
|
handCircleCenter += penetrationDistance * glm::normalize(circleToCircle);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 handPosition(handCircleCenter.x, params.rightPosition.y, handCircleCenter.y);
|
||||||
|
_animVars.set("rightHandPosition", handPosition);
|
||||||
_animVars.set("rightHandRotation", params.rightOrientation);
|
_animVars.set("rightHandRotation", params.rightOrientation);
|
||||||
_animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition);
|
_animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -67,6 +67,7 @@ public:
|
||||||
struct HandParameters {
|
struct HandParameters {
|
||||||
bool isLeftEnabled;
|
bool isLeftEnabled;
|
||||||
bool isRightEnabled;
|
bool isRightEnabled;
|
||||||
|
float bodyCapsuleRadius;
|
||||||
glm::vec3 leftPosition = glm::vec3(); // rig space
|
glm::vec3 leftPosition = glm::vec3(); // rig space
|
||||||
glm::quat leftOrientation = glm::quat(); // rig space (z forward)
|
glm::quat leftOrientation = glm::quat(); // rig space (z forward)
|
||||||
glm::vec3 rightPosition = glm::vec3(); // rig space
|
glm::vec3 rightPosition = glm::vec3(); // rig space
|
||||||
|
|
|
@ -78,6 +78,8 @@ public:
|
||||||
|
|
||||||
glm::vec3 getLinearVelocity() const;
|
glm::vec3 getLinearVelocity() const;
|
||||||
|
|
||||||
|
float getCapsuleRadius() const { return _radius; }
|
||||||
|
|
||||||
enum class State {
|
enum class State {
|
||||||
Ground = 0,
|
Ground = 0,
|
||||||
Takeoff,
|
Takeoff,
|
||||||
|
|
|
@ -45,8 +45,11 @@ ScriptAudioInjector* AudioScriptingInterface::playSound(Sound* sound, const Audi
|
||||||
// stereo option isn't set from script, this comes from sound metadata or filename
|
// stereo option isn't set from script, this comes from sound metadata or filename
|
||||||
AudioInjectorOptions optionsCopy = injectorOptions;
|
AudioInjectorOptions optionsCopy = injectorOptions;
|
||||||
optionsCopy.stereo = sound->isStereo();
|
optionsCopy.stereo = sound->isStereo();
|
||||||
|
auto injector = AudioInjector::playSound(sound->getByteArray(), optionsCopy, _localAudioInterface);
|
||||||
return new ScriptAudioInjector(AudioInjector::playSound(sound->getByteArray(), optionsCopy, _localAudioInterface));
|
if (!injector) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return new ScriptAudioInjector(injector);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
qCDebug(scriptengine) << "AudioScriptingInterface::playSound called with null Sound object.";
|
qCDebug(scriptengine) << "AudioScriptingInterface::playSound called with null Sound object.";
|
||||||
|
|
|
@ -30,7 +30,6 @@ const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)");
|
||||||
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here
|
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here
|
||||||
|
|
||||||
static vr::IVRCompositor* _compositor{ nullptr };
|
static vr::IVRCompositor* _compositor{ nullptr };
|
||||||
static vr::TrackedDevicePose_t _presentThreadTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
|
||||||
vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||||
mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
|
mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
|
||||||
static mat4 _sensorResetMat;
|
static mat4 _sensorResetMat;
|
||||||
|
@ -43,12 +42,12 @@ bool OpenVrDisplayPlugin::isSupported() const {
|
||||||
void OpenVrDisplayPlugin::activate() {
|
void OpenVrDisplayPlugin::activate() {
|
||||||
_container->setIsOptionChecked(StandingHMDSensorMode, true);
|
_container->setIsOptionChecked(StandingHMDSensorMode, true);
|
||||||
|
|
||||||
if (!_hmd) {
|
if (!_system) {
|
||||||
_hmd = acquireOpenVrSystem();
|
_system = acquireOpenVrSystem();
|
||||||
}
|
}
|
||||||
Q_ASSERT(_hmd);
|
Q_ASSERT(_system);
|
||||||
|
|
||||||
_hmd->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y);
|
_system->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y);
|
||||||
// Recommended render target size is per-eye, so double the X size for
|
// Recommended render target size is per-eye, so double the X size for
|
||||||
// left + right eyes
|
// left + right eyes
|
||||||
_renderTargetSize.x *= 2;
|
_renderTargetSize.x *= 2;
|
||||||
|
@ -56,8 +55,8 @@ void OpenVrDisplayPlugin::activate() {
|
||||||
{
|
{
|
||||||
Lock lock(_poseMutex);
|
Lock lock(_poseMutex);
|
||||||
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
||||||
_eyeOffsets[eye] = toGlm(_hmd->GetEyeToHeadTransform(eye));
|
_eyeOffsets[eye] = toGlm(_system->GetEyeToHeadTransform(eye));
|
||||||
_eyeProjections[eye] = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL));
|
_eyeProjections[eye] = toGlm(_system->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL));
|
||||||
});
|
});
|
||||||
// FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes
|
// FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes
|
||||||
_cullingProjection = _eyeProjections[0];
|
_cullingProjection = _eyeProjections[0];
|
||||||
|
@ -71,9 +70,9 @@ void OpenVrDisplayPlugin::activate() {
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::deactivate() {
|
void OpenVrDisplayPlugin::deactivate() {
|
||||||
_container->setIsOptionChecked(StandingHMDSensorMode, false);
|
_container->setIsOptionChecked(StandingHMDSensorMode, false);
|
||||||
if (_hmd) {
|
if (_system) {
|
||||||
releaseOpenVrSystem();
|
releaseOpenVrSystem();
|
||||||
_hmd = nullptr;
|
_system = nullptr;
|
||||||
}
|
}
|
||||||
_compositor = nullptr;
|
_compositor = nullptr;
|
||||||
HmdDisplayPlugin::deactivate();
|
HmdDisplayPlugin::deactivate();
|
||||||
|
@ -96,9 +95,24 @@ void OpenVrDisplayPlugin::resetSensors() {
|
||||||
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(m));
|
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
|
glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
|
||||||
Lock lock(_poseMutex);
|
|
||||||
|
float displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
|
||||||
|
float frameDuration = 1.f / displayFrequency;
|
||||||
|
float vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
|
||||||
|
|
||||||
|
// TODO: this seems awfuly long, 44ms total, but it produced the best results.
|
||||||
|
const float NUM_PREDICTION_FRAMES = 3.0f;
|
||||||
|
float predictedSecondsFromNow = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons;
|
||||||
|
|
||||||
|
vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||||
|
_system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseSeated, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount);
|
||||||
|
|
||||||
|
// copy and process predictedTrackedDevicePoses
|
||||||
|
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
||||||
|
_trackedDevicePose[i] = predictedTrackedDevicePose[i];
|
||||||
|
_trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking);
|
||||||
|
}
|
||||||
return _trackedDevicePoseMat4[0];
|
return _trackedDevicePoseMat4[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,16 +128,8 @@ void OpenVrDisplayPlugin::internalPresent() {
|
||||||
|
|
||||||
glFinish();
|
glFinish();
|
||||||
|
|
||||||
_compositor->WaitGetPoses(_presentThreadTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0);
|
vr::TrackedDevicePose_t currentTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||||
|
_compositor->WaitGetPoses(currentTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0);
|
||||||
{
|
|
||||||
// copy and process _presentThreadTrackedDevicePoses
|
|
||||||
Lock lock(_poseMutex);
|
|
||||||
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
|
||||||
_trackedDevicePose[i] = _presentThreadTrackedDevicePose[i];
|
|
||||||
_trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle the mirroring in the base class
|
// Handle the mirroring in the base class
|
||||||
HmdDisplayPlugin::internalPresent();
|
HmdDisplayPlugin::internalPresent();
|
||||||
|
|
|
@ -35,7 +35,7 @@ protected:
|
||||||
virtual void internalPresent() override;
|
virtual void internalPresent() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vr::IVRSystem* _hmd { nullptr };
|
vr::IVRSystem* _system { nullptr };
|
||||||
static const QString NAME;
|
static const QString NAME;
|
||||||
mutable Mutex _poseMutex;
|
mutable Mutex _poseMutex;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue