mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 01:24:03 +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;
|
||||
RDT.AmbientOcclusion.enabled = true;
|
||||
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
|
||||
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};
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
Repeater {
|
||||
model: [ "Opaque:DrawOpaqueDeferred", "Transparent:DrawTransparentDeferred",
|
||||
"Opaque Overlays:DrawOverlay3DOpaque", "Transparent Overlays:DrawOverlay3DTransparent" ]
|
||||
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
|
||||
id: root
|
||||
spacing: 16
|
||||
Switch {
|
||||
checked: true
|
||||
onClicked: ui.visible = checked
|
||||
}
|
||||
|
||||
Column {
|
||||
id: ambientOcclusion
|
||||
property var config: Render.getConfig("AmbientOcclusion")
|
||||
id: ui
|
||||
spacing: 8
|
||||
|
||||
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:"
|
||||
]
|
||||
model: [ "Opaque:DrawOpaqueDeferred", "Transparent:DrawTransparentDeferred",
|
||||
"Opaque Overlays:DrawOverlay3DOpaque", "Transparent Overlays:DrawOverlay3DTransparent" ]
|
||||
ConfigSlider {
|
||||
label: qsTr(modelData.split(":")[0])
|
||||
integral: true
|
||||
config: ambientOcclusion.config
|
||||
property: modelData.split(":")[1]
|
||||
max: modelData.split(":")[2]
|
||||
config: Render.getConfig(modelData.split(":")[1])
|
||||
property: "maxDrawn"
|
||||
max: config.numDrawn
|
||||
min: -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: debug
|
||||
property var config: Render.getConfig("DebugDeferredBuffer")
|
||||
|
||||
function setDebugMode(mode) {
|
||||
debug.config.enabled = (mode != 0);
|
||||
debug.config.mode = mode;
|
||||
Row {
|
||||
CheckBox {
|
||||
text: qsTr("Display Status")
|
||||
onCheckedChanged: { Render.getConfig("DrawStatus").showDisplay = checked }
|
||||
}
|
||||
CheckBox {
|
||||
text: qsTr("Network/Physics Status")
|
||||
onCheckedChanged: { Render.getConfig("DrawStatus").showNetwork = checked }
|
||||
}
|
||||
}
|
||||
|
||||
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) debug.setDebugMode(index);
|
||||
ConfigSlider {
|
||||
label: qsTr("Tone Mapping Exposure")
|
||||
config: Render.getConfig("ToneMapping")
|
||||
property: "exposure"
|
||||
min: -10; max: 10
|
||||
}
|
||||
|
||||
Column {
|
||||
id: ambientOcclusion
|
||||
property var config: Render.getConfig("AmbientOcclusion")
|
||||
|
||||
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
|
||||
width: 800
|
||||
height: 600
|
||||
|
||||
property alias webView: webview
|
||||
|
||||
Component.onCompleted: {
|
||||
visible = true
|
||||
addressBar.text = webview.url
|
||||
|
@ -28,6 +29,7 @@ Window {
|
|||
}
|
||||
|
||||
Item {
|
||||
id:item
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
|
@ -125,12 +127,10 @@ Window {
|
|||
console.log("New icon: " + icon)
|
||||
}
|
||||
|
||||
profile: WebEngineProfile {
|
||||
id: webviewProfile
|
||||
storageName: "qmlUserBrowser"
|
||||
}
|
||||
|
||||
profile: desktop.browserProfile
|
||||
|
||||
}
|
||||
|
||||
} // item
|
||||
|
||||
Keys.onPressed: {
|
||||
|
|
|
@ -11,6 +11,7 @@ WebEngineView {
|
|||
root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
|
||||
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
|
||||
|
@ -36,6 +37,10 @@ WebEngineView {
|
|||
}
|
||||
}
|
||||
|
||||
onFeaturePermissionRequested: {
|
||||
grantFeaturePermission(securityOrigin, feature, true);
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
// Required to support clicking on "hifi://" links
|
||||
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
||||
|
@ -48,9 +53,12 @@ WebEngineView {
|
|||
}
|
||||
}
|
||||
|
||||
profile: WebEngineProfile {
|
||||
id: webviewProfile
|
||||
httpUserAgent: "Mozilla/5.0 (HighFidelityInterface)"
|
||||
storageName: "qmlWebEngine"
|
||||
onNewViewRequested:{
|
||||
var component = Qt.createComponent("../Browser.qml");
|
||||
var newWindow = component.createObject(desktop);
|
||||
request.openIn(newWindow.webView)
|
||||
}
|
||||
|
||||
|
||||
profile: desktop.browserProfile
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ Desktop {
|
|||
id: desktop
|
||||
|
||||
Component.onCompleted: {
|
||||
WebEngine.settings.javascriptCanOpenWindows = false;
|
||||
WebEngine.settings.javascriptCanOpenWindows = true;
|
||||
WebEngine.settings.javascriptCanAccessClipboard = false;
|
||||
WebEngine.settings.spatialNavigationEnabled = true;
|
||||
WebEngine.settings.localContentCanAccessRemoteUrls = true;
|
||||
|
@ -19,6 +19,12 @@ Desktop {
|
|||
property alias toolWindow: toolWindow
|
||||
ToolWindow { id: toolWindow }
|
||||
|
||||
property var browserProfile: WebEngineProfile {
|
||||
id: webviewProfile
|
||||
httpUserAgent: "Chrome/48.0 (HighFidelityInterface)"
|
||||
storageName: "qmlWebEngine"
|
||||
}
|
||||
|
||||
Action {
|
||||
text: "Open Browser"
|
||||
shortcut: "Ctrl+B"
|
||||
|
|
|
@ -421,8 +421,8 @@ private:
|
|||
AtRestDetector _hmdAtRestDetector;
|
||||
bool _lastIsMoving { 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 AUDIO_ENERGY_CONSTANT { 0.000001f };
|
||||
float MAX_AVATAR_MOVEMENT_PER_FRAME { 30.0f };
|
||||
|
|
|
@ -144,6 +144,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
} else {
|
||||
handParams.isRightEnabled = false;
|
||||
}
|
||||
handParams.bodyCapsuleRadius = myAvatar->getCharacterController()->getCapsuleRadius();
|
||||
|
||||
_rig->updateFromHandParameters(handParams, deltaTime);
|
||||
|
||||
|
|
|
@ -670,7 +670,7 @@ void AnimInverseKinematics::initConstraints() {
|
|||
stConstraint->setTwistLimits(-MAX_SHOULDER_TWIST, MAX_SHOULDER_TWIST);
|
||||
|
||||
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));
|
||||
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) {
|
||||
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) {
|
||||
_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("leftHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||
} else {
|
||||
|
@ -1089,8 +1112,23 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) {
|
|||
_animVars.unset("leftHandRotation");
|
||||
_animVars.set("leftHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition);
|
||||
}
|
||||
|
||||
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("rightHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||
} else {
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
struct HandParameters {
|
||||
bool isLeftEnabled;
|
||||
bool isRightEnabled;
|
||||
float bodyCapsuleRadius;
|
||||
glm::vec3 leftPosition = glm::vec3(); // rig space
|
||||
glm::quat leftOrientation = glm::quat(); // rig space (z forward)
|
||||
glm::vec3 rightPosition = glm::vec3(); // rig space
|
||||
|
|
|
@ -78,6 +78,8 @@ public:
|
|||
|
||||
glm::vec3 getLinearVelocity() const;
|
||||
|
||||
float getCapsuleRadius() const { return _radius; }
|
||||
|
||||
enum class State {
|
||||
Ground = 0,
|
||||
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
|
||||
AudioInjectorOptions optionsCopy = injectorOptions;
|
||||
optionsCopy.stereo = sound->isStereo();
|
||||
|
||||
return new ScriptAudioInjector(AudioInjector::playSound(sound->getByteArray(), optionsCopy, _localAudioInterface));
|
||||
auto injector = AudioInjector::playSound(sound->getByteArray(), optionsCopy, _localAudioInterface);
|
||||
if (!injector) {
|
||||
return NULL;
|
||||
}
|
||||
return new ScriptAudioInjector(injector);
|
||||
|
||||
} else {
|
||||
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
|
||||
|
||||
static vr::IVRCompositor* _compositor{ nullptr };
|
||||
static vr::TrackedDevicePose_t _presentThreadTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||
vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||
mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
|
||||
static mat4 _sensorResetMat;
|
||||
|
@ -43,12 +42,12 @@ bool OpenVrDisplayPlugin::isSupported() const {
|
|||
void OpenVrDisplayPlugin::activate() {
|
||||
_container->setIsOptionChecked(StandingHMDSensorMode, true);
|
||||
|
||||
if (!_hmd) {
|
||||
_hmd = acquireOpenVrSystem();
|
||||
if (!_system) {
|
||||
_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
|
||||
// left + right eyes
|
||||
_renderTargetSize.x *= 2;
|
||||
|
@ -56,8 +55,8 @@ void OpenVrDisplayPlugin::activate() {
|
|||
{
|
||||
Lock lock(_poseMutex);
|
||||
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
|
||||
_eyeOffsets[eye] = toGlm(_hmd->GetEyeToHeadTransform(eye));
|
||||
_eyeProjections[eye] = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL));
|
||||
_eyeOffsets[eye] = toGlm(_system->GetEyeToHeadTransform(eye));
|
||||
_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
|
||||
_cullingProjection = _eyeProjections[0];
|
||||
|
@ -71,9 +70,9 @@ void OpenVrDisplayPlugin::activate() {
|
|||
|
||||
void OpenVrDisplayPlugin::deactivate() {
|
||||
_container->setIsOptionChecked(StandingHMDSensorMode, false);
|
||||
if (_hmd) {
|
||||
if (_system) {
|
||||
releaseOpenVrSystem();
|
||||
_hmd = nullptr;
|
||||
_system = nullptr;
|
||||
}
|
||||
_compositor = nullptr;
|
||||
HmdDisplayPlugin::deactivate();
|
||||
|
@ -96,9 +95,24 @@ void OpenVrDisplayPlugin::resetSensors() {
|
|||
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(m));
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
|
@ -114,16 +128,8 @@ void OpenVrDisplayPlugin::internalPresent() {
|
|||
|
||||
glFinish();
|
||||
|
||||
_compositor->WaitGetPoses(_presentThreadTrackedDevicePose, 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);
|
||||
}
|
||||
}
|
||||
vr::TrackedDevicePose_t currentTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||
_compositor->WaitGetPoses(currentTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0);
|
||||
|
||||
// Handle the mirroring in the base class
|
||||
HmdDisplayPlugin::internalPresent();
|
||||
|
|
|
@ -35,7 +35,7 @@ protected:
|
|||
virtual void internalPresent() override;
|
||||
|
||||
private:
|
||||
vr::IVRSystem* _hmd { nullptr };
|
||||
vr::IVRSystem* _system { nullptr };
|
||||
static const QString NAME;
|
||||
mutable Mutex _poseMutex;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue