mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Merge branch 'master' into DOC-102
This commit is contained in:
commit
0a32386f45
306 changed files with 3683 additions and 4996 deletions
|
@ -268,6 +268,7 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
set(PROGRAM_ENUMS "namespace program { enum {\n")
|
||||
foreach(PROGRAM_FILE ${SHADER_PROGRAM_FILES})
|
||||
get_filename_component(PROGRAM_NAME ${PROGRAM_FILE} NAME_WE)
|
||||
get_filename_component(PROGRAM_FOLDER ${PROGRAM_FILE} DIRECTORY)
|
||||
file(READ ${PROGRAM_FILE} PROGRAM_CONFIG)
|
||||
set(AUTOSCRIBE_PROGRAM_VERTEX ${PROGRAM_NAME})
|
||||
set(AUTOSCRIBE_PROGRAM_FRAGMENT ${PROGRAM_NAME})
|
||||
|
@ -315,7 +316,11 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
if (HAS_FRAGMENT EQUAL -1)
|
||||
set(DEFINES "${VERTEX_DEFINES}")
|
||||
set(SHADER_LIST "")
|
||||
set(SHADER_FILE "${SRC_FOLDER}/${VERTEX_NAME}.slv")
|
||||
set(SHADER_FILE "${PROGRAM_FOLDER}/${VERTEX_NAME}.slv")
|
||||
if (NOT EXISTS "${SHADER_FILE}")
|
||||
set(SHADER_FILE "${PROGRAM_FOLDER}/../${VERTEX_NAME}.slv")
|
||||
endif()
|
||||
find_file(SHADER_FILE "" PATHS "${PROGRAM_FOLDER}" PATH_SUFFIXES ".." NO_DEFAULT_PATH)
|
||||
AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS})
|
||||
string(CONCAT VERTEX_ENUMS "${VERTEX_ENUMS}" "${SHADER_LIST}")
|
||||
else()
|
||||
|
@ -331,7 +336,10 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
if (HAS_VERTEX EQUAL -1)
|
||||
set(DEFINES "${FRAGMENT_DEFINES}")
|
||||
set(SHADER_LIST "")
|
||||
set(SHADER_FILE "${SRC_FOLDER}/${FRAGMENT_NAME}.slf")
|
||||
set(SHADER_FILE "${PROGRAM_FOLDER}/${FRAGMENT_NAME}.slf")
|
||||
if (NOT EXISTS "${SHADER_FILE}")
|
||||
set(SHADER_FILE "${PROGRAM_FOLDER}/../${FRAGMENT_NAME}.slf")
|
||||
endif()
|
||||
AUTOSCRIBE_SHADER(${ALL_SHADER_HEADERS})
|
||||
string(CONCAT FRAGMENT_ENUMS "${FRAGMENT_ENUMS}" "${SHADER_LIST}")
|
||||
else()
|
||||
|
|
|
@ -52,14 +52,8 @@ macro(setup_qt)
|
|||
message(FATAL_ERROR "VCPKG_QT_CMAKE_PREFIX_PATH should have been set by hifi_vcpkg.py")
|
||||
endif()
|
||||
if (NOT DEV_BUILD)
|
||||
if (UNIX AND DEFINED ENV{QT_CMAKE_PREFIX_PATH} AND NOT APPLE)
|
||||
# HACK: obey QT_CMAKE_PREFIX_PATH to allow UNIX to use older QT libs
|
||||
message("HACK: obey QT_CMAKE_PREFIX_PATH on UNIX")
|
||||
set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
|
||||
else()
|
||||
message("override QT_CMAKE_PREFIX_PATH with VCPKG_QT_CMAKE_PREFIX_PATH")
|
||||
set(QT_CMAKE_PREFIX_PATH ${VCPKG_QT_CMAKE_PREFIX_PATH})
|
||||
endif()
|
||||
message("override QT_CMAKE_PREFIX_PATH with VCPKG_QT_CMAKE_PREFIX_PATH")
|
||||
set(QT_CMAKE_PREFIX_PATH ${VCPKG_QT_CMAKE_PREFIX_PATH})
|
||||
else()
|
||||
# DEV_BUILD
|
||||
if (DEFINED ENV{QT_CMAKE_PREFIX_PATH})
|
||||
|
|
|
@ -259,7 +259,7 @@ endif()
|
|||
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos3.tar.gz'
|
||||
elif platform.system() == 'Linux':
|
||||
if platform.linux_distribution()[1][:3] == '16.':
|
||||
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04.tar.gz'
|
||||
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04-with-symbols.tar.gz'
|
||||
elif platform.linux_distribution()[1][:3] == '18.':
|
||||
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-18.04.tar.gz'
|
||||
else:
|
||||
|
|
BIN
interface/resources/avatar/animations/teleport.fbx
Normal file
BIN
interface/resources/avatar/animations/teleport.fbx
Normal file
Binary file not shown.
|
@ -30,7 +30,6 @@ Windows.Window {
|
|||
|
||||
signal selfDestruct();
|
||||
|
||||
property var flags: 0;
|
||||
property var additionalFlags: 0;
|
||||
property var overrideFlags: 0;
|
||||
|
||||
|
@ -158,8 +157,7 @@ Windows.Window {
|
|||
if (Qt.platform.os !== "windows" && (root.additionalFlags & Desktop.ALWAYS_ON_TOP)) {
|
||||
nativeWindowFlags |= Qt.WindowStaysOnTopHint;
|
||||
}
|
||||
root.flags = root.overrideFlags || nativeWindowFlags;
|
||||
nativeWindow.flags = root.flags;
|
||||
nativeWindow.flags = root.overrideFlags || nativeWindowFlags;
|
||||
|
||||
nativeWindow.x = interactiveWindowPosition.x;
|
||||
nativeWindow.y = interactiveWindowPosition.y;
|
||||
|
@ -317,7 +315,7 @@ Windows.Window {
|
|||
// set invisible on close, to make it not re-appear unintended after switching PresentationMode
|
||||
interactiveWindowVisible = false;
|
||||
|
||||
if ((root.flags & Desktop.CLOSE_BUTTON_HIDES) !== Desktop.CLOSE_BUTTON_HIDES) {
|
||||
if ((root.additionalFlags & Desktop.CLOSE_BUTTON_HIDES) !== Desktop.CLOSE_BUTTON_HIDES) {
|
||||
selfDestruct();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ FocusScope {
|
|||
property alias editable: comboBox.editable
|
||||
property alias comboBox: comboBox
|
||||
readonly property alias currentText: comboBox.currentText;
|
||||
property alias displayText: comboBox.displayText;
|
||||
property alias currentIndex: comboBox.currentIndex;
|
||||
property int currentHighLightedIndex: comboBox.currentIndex;
|
||||
|
||||
|
|
|
@ -0,0 +1,379 @@
|
|||
//
|
||||
// GraphicsSettings.qml
|
||||
// qml\hifi\dialogs\graphics
|
||||
//
|
||||
// Created by Zach Fox on 2019-07-10
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Layouts 1.12
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
import "qrc:////qml//controls" as HifiControls
|
||||
import PerformanceEnums 1.0
|
||||
|
||||
Item {
|
||||
HifiStylesUit.HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
anchors.fill: parent
|
||||
|
||||
ColumnLayout {
|
||||
id: graphicsSettingsColumnLayout
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 26
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 26
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: HMD.active ? 80 : 0
|
||||
spacing: 8
|
||||
|
||||
ColumnLayout {
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.topMargin: 18
|
||||
spacing: 0
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
text: "GRAPHICS SETTINGS"
|
||||
Layout.maximumWidth: parent.width
|
||||
height: 30
|
||||
size: 16
|
||||
color: "#FFFFFF"
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.topMargin: 10
|
||||
Layout.preferredWidth: parent.width
|
||||
spacing: 0
|
||||
|
||||
HifiControlsUit.RadioButton {
|
||||
id: performanceLow
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
height: 18
|
||||
fontSize: 16
|
||||
leftPadding: 0
|
||||
text: "Low"
|
||||
checked: Performance.getPerformancePreset() === PerformanceEnums.LOW
|
||||
onClicked: {
|
||||
Performance.setPerformancePreset(PerformanceEnums.LOW);
|
||||
root.refreshAllDropdowns();
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.RadioButton {
|
||||
id: performanceMedium
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
height: 18
|
||||
fontSize: 16
|
||||
leftPadding: 0
|
||||
text: "Medium"
|
||||
checked: Performance.getPerformancePreset() === PerformanceEnums.MID
|
||||
onClicked: {
|
||||
Performance.setPerformancePreset(PerformanceEnums.MID);
|
||||
root.refreshAllDropdowns();
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.RadioButton {
|
||||
id: performanceHigh
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
height: 18
|
||||
fontSize: 16
|
||||
leftPadding: 0
|
||||
text: "High"
|
||||
checked: Performance.getPerformancePreset() === PerformanceEnums.HIGH
|
||||
onClicked: {
|
||||
Performance.setPerformancePreset(PerformanceEnums.HIGH);
|
||||
root.refreshAllDropdowns();
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.RadioButton {
|
||||
id: performanceCustom
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
height: 18
|
||||
fontSize: 16
|
||||
leftPadding: 0
|
||||
text: "Custom"
|
||||
checked: Performance.getPerformancePreset() === PerformanceEnums.UNKNOWN
|
||||
onClicked: {
|
||||
Performance.setPerformancePreset(PerformanceEnums.UNKNOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.topMargin: 10
|
||||
Layout.preferredWidth: parent.width
|
||||
spacing: 0
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: 35
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: worldDetailHeader
|
||||
text: "World Detail"
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
width: 130
|
||||
height: parent.height
|
||||
size: 16
|
||||
color: "#FFFFFF"
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: worldDetailModel
|
||||
|
||||
ListElement {
|
||||
text: "Low World Detail"
|
||||
worldDetailQualityValue: 0.25
|
||||
}
|
||||
ListElement {
|
||||
text: "Medium World Detail"
|
||||
worldDetailQualityValue: 0.5
|
||||
}
|
||||
ListElement {
|
||||
text: "Full World Detail"
|
||||
worldDetailQualityValue: 0.75
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.ComboBox {
|
||||
id: worldDetailDropdown
|
||||
enabled: performanceCustom.checked
|
||||
anchors.left: worldDetailHeader.right
|
||||
anchors.leftMargin: 20
|
||||
anchors.top: parent.top
|
||||
width: 280
|
||||
height: parent.height
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
model: worldDetailModel
|
||||
currentIndex: -1
|
||||
|
||||
function refreshWorldDetailDropdown() {
|
||||
var currentWorldDetailQuality = LODManager.worldDetailQuality;
|
||||
if (currentWorldDetailQuality <= 0.25) {
|
||||
worldDetailDropdown.currentIndex = 0;
|
||||
} else if (currentWorldDetailQuality <= 0.5) {
|
||||
worldDetailDropdown.currentIndex = 1;
|
||||
} else {
|
||||
worldDetailDropdown.currentIndex = 2;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
worldDetailDropdown.refreshWorldDetailDropdown();
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
LODManager.worldDetailQuality = model.get(currentIndex).worldDetailQualityValue;
|
||||
worldDetailDropdown.displayText = model.get(currentIndex).text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: 35
|
||||
Layout.topMargin: 20
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: renderingEffectsHeader
|
||||
text: "Rendering Effects"
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
width: 130
|
||||
height: parent.height
|
||||
size: 16
|
||||
color: "#FFFFFF"
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: renderingEffectsModel
|
||||
|
||||
ListElement {
|
||||
text: "No Rendering Effects"
|
||||
preferredRenderMethod: 1 // "FORWARD"
|
||||
shadowsEnabled: false
|
||||
}
|
||||
ListElement {
|
||||
text: "Local Lights, Fog, Bloom"
|
||||
preferredRenderMethod: 0 // "DEFERRED"
|
||||
shadowsEnabled: false
|
||||
}
|
||||
ListElement {
|
||||
text: "Local Lights, Fog, Bloom, Shadows"
|
||||
preferredRenderMethod: 0 // "DEFERRED"
|
||||
shadowsEnabled: true
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.ComboBox {
|
||||
id: renderingEffectsDropdown
|
||||
enabled: performanceCustom.checked
|
||||
anchors.left: renderingEffectsHeader.right
|
||||
anchors.leftMargin: 20
|
||||
anchors.top: parent.top
|
||||
width: 280
|
||||
height: parent.height
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
model: renderingEffectsModel
|
||||
currentIndex: -1
|
||||
|
||||
function refreshRenderingEffectsDropdownDisplay() {
|
||||
if (Render.shadowsEnabled) {
|
||||
renderingEffectsDropdown.currentIndex = 2;
|
||||
} else if (Render.renderMethod === 0) {
|
||||
renderingEffectsDropdown.currentIndex = 1;
|
||||
} else {
|
||||
renderingEffectsDropdown.currentIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
renderingEffectsDropdown.refreshRenderingEffectsDropdownDisplay();
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
var renderMethodToSet = 1;
|
||||
if (model.get(currentIndex).preferredRenderMethod === 0 &&
|
||||
PlatformInfo.isRenderMethodDeferredCapable()) {
|
||||
renderMethodToSet = 0;
|
||||
}
|
||||
Render.renderMethod = renderMethodToSet;
|
||||
Render.shadowsEnabled = model.get(currentIndex).shadowsEnabled;
|
||||
renderingEffectsDropdown.displayText = model.get(currentIndex).text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: 35
|
||||
Layout.topMargin: 20
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: refreshRateHeader
|
||||
text: "Refresh Rate"
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
width: 130
|
||||
height: parent.height
|
||||
size: 16
|
||||
color: "#FFFFFF"
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: refreshRateModel
|
||||
|
||||
ListElement {
|
||||
text: "Economical"
|
||||
refreshRatePreset: 0 // RefreshRateProfile::ECO
|
||||
}
|
||||
ListElement {
|
||||
text: "Interactive"
|
||||
refreshRatePreset: 1 // RefreshRateProfile::INTERACTIVE
|
||||
}
|
||||
ListElement {
|
||||
text: "Real-Time"
|
||||
refreshRatePreset: 2 // RefreshRateProfile::REALTIME
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.ComboBox {
|
||||
id: refreshRateDropdown
|
||||
enabled: performanceCustom.checked
|
||||
anchors.left: refreshRateHeader.right
|
||||
anchors.leftMargin: 20
|
||||
anchors.top: parent.top
|
||||
width: 280
|
||||
height: parent.height
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
model: refreshRateModel
|
||||
currentIndex: -1
|
||||
|
||||
function refreshRefreshRateDropdownDisplay() {
|
||||
if (Performance.getRefreshRateProfile() === 0) {
|
||||
refreshRateDropdown.currentIndex = 0;
|
||||
} else if (Performance.getRefreshRateProfile() === 1) {
|
||||
refreshRateDropdown.currentIndex = 1;
|
||||
} else {
|
||||
refreshRateDropdown.currentIndex = 2;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
refreshRateDropdown.refreshRefreshRateDropdownDisplay();
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
Performance.setRefreshRateProfile(model.get(currentIndex).refreshRatePreset);
|
||||
refreshRateDropdown.displayText = model.get(currentIndex).text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: 35
|
||||
Layout.topMargin: 16
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: resolutionHeader
|
||||
text: "Resolution Scale (" + Number.parseFloat(Render.viewportResolutionScale).toPrecision(3) + ")"
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
width: 130
|
||||
height: parent.height
|
||||
size: 16
|
||||
color: "#FFFFFF"
|
||||
}
|
||||
|
||||
HifiControlsUit.Slider {
|
||||
id: resolutionScaleSlider
|
||||
enabled: performanceCustom.checked
|
||||
anchors.left: resolutionHeader.right
|
||||
anchors.leftMargin: 57
|
||||
anchors.top: parent.top
|
||||
width: 150
|
||||
height: parent.height
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
minimumValue: 0.25
|
||||
maximumValue: 1.0
|
||||
stepSize: 0.02
|
||||
value: Render.viewportResolutionScale
|
||||
live: true
|
||||
|
||||
function updateResolutionScale(sliderValue) {
|
||||
if (Render.viewportResolutionScale !== sliderValue) {
|
||||
Render.viewportResolutionScale = sliderValue;
|
||||
}
|
||||
}
|
||||
|
||||
onValueChanged: {
|
||||
updateResolutionScale(value);
|
||||
}
|
||||
onPressedChanged: {
|
||||
if (!pressed) {
|
||||
updateResolutionScale(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function refreshAllDropdowns() {
|
||||
worldDetailDropdown.refreshWorldDetailDropdown();
|
||||
renderingEffectsDropdown.refreshRenderingEffectsDropdownDisplay();
|
||||
refreshRateDropdown.refreshRefreshRateDropdownDisplay();
|
||||
}
|
||||
}
|
|
@ -91,7 +91,7 @@ Item {
|
|||
|
||||
SimplifiedControls.TextField {
|
||||
id: myDisplayNameText
|
||||
text: MyAvatar.sessionDisplayName === "" ? MyAvatar.displayName : MyAvatar.sessionDisplayName
|
||||
text: MyAvatar.displayName
|
||||
maximumLength: 256
|
||||
clip: true
|
||||
selectByMouse: true
|
||||
|
|
|
@ -257,6 +257,10 @@ extern "C" {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "MacHelper.h"
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
#include <android/log.h>
|
||||
#include "AndroidHelper.h"
|
||||
|
@ -960,6 +964,9 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<KeyboardScriptingInterface>();
|
||||
DependencyManager::set<GrabManager>();
|
||||
DependencyManager::set<AvatarPackager>();
|
||||
#ifdef Q_OS_MAC
|
||||
DependencyManager::set<MacHelper>();
|
||||
#endif
|
||||
|
||||
QString setBookmarkValue = getCmdOption(argc, constArgv, "--setBookmark");
|
||||
if (!setBookmarkValue.isEmpty()) {
|
||||
|
@ -1187,6 +1194,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
}
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
|
||||
// set the account manager's root URL and trigger a login request if we don't have the access token
|
||||
accountManager->setIsAgent(true);
|
||||
accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL());
|
||||
if (!accountManager->hasKeyPair()) {
|
||||
accountManager->generateNewUserKeypair();
|
||||
}
|
||||
|
||||
#ifndef Q_OS_ANDROID
|
||||
_logger->setSessionID(accountManager->getSessionID());
|
||||
#endif
|
||||
|
@ -1334,10 +1348,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
#endif
|
||||
connect(accountManager.data(), &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
|
||||
|
||||
// set the account manager's root URL and trigger a login request if we don't have the access token
|
||||
accountManager->setIsAgent(true);
|
||||
accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL());
|
||||
|
||||
// use our MyAvatar position and quat for address manager path
|
||||
addressManager->setPositionGetter([] {
|
||||
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||
|
@ -2807,7 +2817,7 @@ void Application::cleanupBeforeQuit() {
|
|||
DependencyManager::destroy<TabletScriptingInterface>();
|
||||
DependencyManager::destroy<ToolbarScriptingInterface>();
|
||||
DependencyManager::destroy<OffscreenUi>();
|
||||
|
||||
|
||||
DependencyManager::destroy<OffscreenQmlSurfaceCache>();
|
||||
|
||||
_snapshotSoundInjector = nullptr;
|
||||
|
@ -2853,6 +2863,9 @@ Application::~Application() {
|
|||
_gameWorkload.shutdown();
|
||||
|
||||
DependencyManager::destroy<Preferences>();
|
||||
#ifdef Q_OS_MAC
|
||||
DependencyManager::destroy<MacHelper>();
|
||||
#endif
|
||||
|
||||
_entityClipboard->eraseAllOctreeElements();
|
||||
_entityClipboard.reset();
|
||||
|
@ -4429,27 +4442,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_P: {
|
||||
if (!isShifted && !isMeta && !isOption && !event->isAutoRepeat()) {
|
||||
AudioInjectorOptions options;
|
||||
options.localOnly = true;
|
||||
options.positionSet = false; // system sound
|
||||
options.stereo = true;
|
||||
|
||||
Setting::Handle<bool> notificationSounds{ MenuOption::NotificationSounds, true };
|
||||
Setting::Handle<bool> notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true };
|
||||
if (notificationSounds.get() && notificationSoundSnapshot.get()) {
|
||||
if (_snapshotSoundInjector) {
|
||||
DependencyManager::get<AudioInjectorManager>()->setOptionsAndRestart(_snapshotSoundInjector, options);
|
||||
} else {
|
||||
_snapshotSoundInjector = DependencyManager::get<AudioInjectorManager>()->playSound(_snapshotSound, options);
|
||||
}
|
||||
}
|
||||
takeSnapshot(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::Key_Apostrophe: {
|
||||
if (isMeta) {
|
||||
auto cursor = Cursor::Manager::instance().getCursor();
|
||||
|
@ -5994,6 +5986,7 @@ void Application::resetPhysicsReadyInformation() {
|
|||
_gpuTextureMemSizeStabilityCount = 0;
|
||||
_gpuTextureMemSizeAtLastCheck = 0;
|
||||
_physicsEnabled = false;
|
||||
_octreeProcessor.stopSafeLanding();
|
||||
}
|
||||
|
||||
void Application::reloadResourceCaches() {
|
||||
|
@ -6253,6 +6246,7 @@ void Application::tryToEnablePhysics() {
|
|||
// We keep physics disabled until we've received a full scene and everything near the avatar in that
|
||||
// scene is ready to compute its collision shape.
|
||||
if (getMyAvatar()->isReadyForPhysics()) {
|
||||
_octreeProcessor.resetSafeLanding();
|
||||
_physicsEnabled = true;
|
||||
setIsInterstitialMode(false);
|
||||
getMyAvatar()->updateMotionBehaviorFromMenu();
|
||||
|
@ -6776,6 +6770,12 @@ void Application::update(float deltaTime) {
|
|||
if (!getActiveDisplayPlugin()->isActive()) {
|
||||
getMain3DScene()->processTransactionQueue();
|
||||
}
|
||||
|
||||
// decide if the sensorToWorldMatrix is changing in a way that warrents squeezing the edges of the view down
|
||||
if (getActiveDisplayPlugin()->isHmd()) {
|
||||
PerformanceTimer perfTimer("squeezeVision");
|
||||
_visionSqueeze.updateVisionSqueeze(myAvatar->getSensorToWorldMatrix(), deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateRenderArgs(float deltaTime) {
|
||||
|
@ -6982,13 +6982,16 @@ int Application::sendNackPackets() {
|
|||
}
|
||||
|
||||
void Application::queryOctree(NodeType_t serverType, PacketType packetType) {
|
||||
|
||||
if (!_settingsLoaded) {
|
||||
return; // bail early if settings are not loaded
|
||||
}
|
||||
|
||||
const bool isModifiedQuery = !_physicsEnabled;
|
||||
if (isModifiedQuery) {
|
||||
if (!_octreeProcessor.safeLandingIsActive()) {
|
||||
// don't send the octreeQuery until SafeLanding knows it has started
|
||||
return;
|
||||
}
|
||||
// Create modified view that is a simple sphere.
|
||||
bool interstitialModeEnabled = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
|
||||
|
||||
|
@ -7211,7 +7214,6 @@ void Application::clearDomainOctreeDetails(bool clearAll) {
|
|||
|
||||
void Application::domainURLChanged(QUrl domainURL) {
|
||||
// disable physics until we have enough information about our new location to not cause craziness.
|
||||
resetPhysicsReadyInformation();
|
||||
setIsServerlessMode(domainURL.scheme() != URL_SCHEME_HIFI);
|
||||
if (isServerlessMode()) {
|
||||
loadServerlessDomain(domainURL);
|
||||
|
@ -7221,7 +7223,6 @@ void Application::domainURLChanged(QUrl domainURL) {
|
|||
|
||||
void Application::goToErrorDomainURL(QUrl errorDomainURL) {
|
||||
// disable physics until we have enough information about our new location to not cause craziness.
|
||||
resetPhysicsReadyInformation();
|
||||
setIsServerlessMode(errorDomainURL.scheme() != URL_SCHEME_HIFI);
|
||||
if (isServerlessMode()) {
|
||||
loadErrorDomain(errorDomainURL);
|
||||
|
@ -7238,12 +7239,12 @@ void Application::resettingDomain() {
|
|||
void Application::nodeAdded(SharedNodePointer node) {
|
||||
if (node->getType() == NodeType::EntityServer) {
|
||||
if (_failedToConnectToEntityServer && !_entityServerConnectionTimer.isActive()) {
|
||||
_failedToConnectToEntityServer = false;
|
||||
_octreeProcessor.stopSafeLanding();
|
||||
_octreeProcessor.startSafeLanding();
|
||||
_failedToConnectToEntityServer = false;
|
||||
} else if (_entityServerConnectionTimer.isActive()) {
|
||||
_entityServerConnectionTimer.stop();
|
||||
}
|
||||
_octreeProcessor.startSafeLanding();
|
||||
_entityServerConnectionTimer.setInterval(ENTITY_SERVER_CONNECTION_TIMEOUT);
|
||||
_entityServerConnectionTimer.start();
|
||||
}
|
||||
|
@ -7318,7 +7319,7 @@ void Application::nodeKilled(SharedNodePointer node) {
|
|||
_octreeProcessor.nodeKilled(node);
|
||||
|
||||
_entityEditSender.nodeKilled(node);
|
||||
|
||||
|
||||
if (node->getType() == NodeType::AudioMixer) {
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "audioMixerKilled");
|
||||
} else if (node->getType() == NodeType::EntityServer) {
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
#include <ModelScriptingInterface.h>
|
||||
|
||||
#include "Sound.h"
|
||||
#include "VisionSqueeze.h"
|
||||
|
||||
class GLCanvas;
|
||||
class FaceTracker;
|
||||
|
@ -364,6 +365,9 @@ public:
|
|||
void forceLoginWithTokens(const QString& tokens);
|
||||
void setConfigFileURL(const QString& fileUrl);
|
||||
|
||||
// used by preferences and HMDScriptingInterface...
|
||||
VisionSqueeze& getVisionSqueeze() { return _visionSqueeze; }
|
||||
|
||||
signals:
|
||||
void svoImportRequested(const QString& url);
|
||||
|
||||
|
@ -731,6 +735,7 @@ private:
|
|||
|
||||
bool _loginDialogPoppedUp{ false };
|
||||
bool _desktopRootItemCreated{ false };
|
||||
|
||||
bool _developerMenuVisible{ false };
|
||||
QString _previousAvatarSkeletonModel;
|
||||
float _previousAvatarTargetScale;
|
||||
|
@ -837,5 +842,7 @@ private:
|
|||
bool _resumeAfterLoginDialogActionTaken_SafeToRun { false };
|
||||
bool _startUpFinished { false };
|
||||
bool _overrideEntry { false };
|
||||
|
||||
VisionSqueeze _visionSqueeze;
|
||||
};
|
||||
#endif // hifi_Application_h
|
||||
|
|
58
interface/src/MacHelper.cpp
Executable file
58
interface/src/MacHelper.cpp
Executable file
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// MacHelper.h
|
||||
// interface/src
|
||||
//
|
||||
// Created by Howard Stearns
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "InterfaceLogging.h"
|
||||
#include "MacHelper.h"
|
||||
#include <NodeList.h>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <IOKit/IOMessage.h>
|
||||
#include <IOKit/pwr_mgt/IOPMLib.h>
|
||||
|
||||
// The type definitions in these variables come from IOKit, which includes a definition of Duration that conflicts with ours.
|
||||
// So... we include these definitions here rather than in the .h, as the .h is included in Application.cpp which
|
||||
// uses Duration.
|
||||
static io_connect_t root_port;
|
||||
static IONotificationPortRef notifyPortRef;
|
||||
static io_object_t notifierObject;
|
||||
static void* refCon;
|
||||
|
||||
static void sleepHandler(void* refCon, io_service_t service, natural_t messageType, void* messageArgument) {
|
||||
if (messageType == kIOMessageSystemHasPoweredOn) {
|
||||
qCInfo(interfaceapp) << "Waking up from sleep or hybernation.";
|
||||
QMetaObject::invokeMethod(DependencyManager::get<NodeList>().data(), "noteAwakening", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MacHelper::MacHelper() {
|
||||
#ifdef Q_OS_MAC
|
||||
root_port = IORegisterForSystemPower(refCon, ¬ifyPortRef, sleepHandler, ¬ifierObject);
|
||||
if (root_port == 0) {
|
||||
qCWarning(interfaceapp) << "IORegisterForSystemPower failed";
|
||||
return;
|
||||
}
|
||||
CFRunLoopAddSource(CFRunLoopGetCurrent(),
|
||||
IONotificationPortGetRunLoopSource(notifyPortRef),
|
||||
kCFRunLoopCommonModes);
|
||||
#endif
|
||||
}
|
||||
|
||||
MacHelper::~MacHelper() {
|
||||
#ifdef Q_OS_MAC
|
||||
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
|
||||
IONotificationPortGetRunLoopSource(notifyPortRef),
|
||||
kCFRunLoopCommonModes);
|
||||
IODeregisterForSystemPower(¬ifierObject);
|
||||
IOServiceClose(root_port);
|
||||
IONotificationPortDestroy(notifyPortRef);
|
||||
#endif
|
||||
}
|
21
interface/src/MacHelper.h
Executable file
21
interface/src/MacHelper.h
Executable file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// MacHelper.h
|
||||
// interface/src
|
||||
//
|
||||
// Created by Howard Stearns
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DependencyManager.h"
|
||||
|
||||
class MacHelper : public Dependency {
|
||||
public:
|
||||
MacHelper();
|
||||
~MacHelper();
|
||||
};
|
||||
|
|
@ -266,8 +266,13 @@ Menu::Menu() {
|
|||
// Settings > Graphics...
|
||||
action = addActionToQMenuAndActionHash(settingsMenu, "Graphics...");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
qApp->showDialog(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"),
|
||||
QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
|
||||
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
|
||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||
tablet->pushOntoStack("hifi/dialogs/graphics/GraphicsSettings.qml");
|
||||
|
||||
if (!hmd->getShouldShowTablet()) {
|
||||
hmd->toggleShouldShowTablet();
|
||||
}
|
||||
});
|
||||
|
||||
// Settings > Security...
|
||||
|
|
|
@ -92,7 +92,7 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
|
|||
RenderScriptingInterface::getInstance()->setShadowsEnabled(true);
|
||||
qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME);
|
||||
|
||||
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.5f);
|
||||
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.75f);
|
||||
|
||||
break;
|
||||
case PerformancePreset::MID:
|
||||
|
@ -114,7 +114,7 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
|
|||
|
||||
RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale);
|
||||
|
||||
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.75f);
|
||||
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.25f);
|
||||
|
||||
break;
|
||||
case PerformancePreset::UNKNOWN:
|
||||
|
|
213
interface/src/VisionSqueeze.cpp
Normal file
213
interface/src/VisionSqueeze.cpp
Normal file
|
@ -0,0 +1,213 @@
|
|||
//
|
||||
// VisionSqueeze.cpp
|
||||
// interface/src
|
||||
//
|
||||
// Created by Seth Alves on 2019-3-13.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "VisionSqueeze.h"
|
||||
|
||||
#include <glm/gtx/matrix_decompose.hpp>
|
||||
#include <glm/gtc/epsilon.hpp>
|
||||
|
||||
#include <display-plugins/hmd/HmdDisplayPlugin.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
VisionSqueeze::VisionSqueeze() :
|
||||
_visionSqueezeEnabled(_visionSqueezeEnabledSetting.get()),
|
||||
_visionSqueezeRatioX(_visionSqueezeRatioXSetting.get()),
|
||||
_visionSqueezeRatioY(_visionSqueezeRatioYSetting.get()),
|
||||
_visionSqueezeUnSqueezeDelay(_visionSqueezeUnSqueezeDelaySetting.get()),
|
||||
_visionSqueezeUnSqueezeSpeed(_visionSqueezeUnSqueezeSpeedSetting.get()),
|
||||
_visionSqueezeTransition(_visionSqueezeTransitionSetting.get()),
|
||||
_visionSqueezePerEye(_visionSqueezePerEyeSetting.get()),
|
||||
_visionSqueezeGroundPlaneY(_visionSqueezeGroundPlaneYSetting.get()),
|
||||
_visionSqueezeSpotlightSize(_visionSqueezeSpotlightSizeSetting.get()),
|
||||
_visionSqueezeTurningXFactor(_visionSqueezeTurningXFactorSetting.get()),
|
||||
_visionSqueezeTurningYFactor(_visionSqueezeTurningYFactorSetting.get()) {
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeEnabled(bool value) {
|
||||
if (value != _visionSqueezeEnabled) {
|
||||
_visionSqueezeEnabled = value;
|
||||
_visionSqueezeEnabledSetting.set(_visionSqueezeEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeRatioX(float value) {
|
||||
if (value != _visionSqueezeRatioX) {
|
||||
_visionSqueezeRatioX = value;
|
||||
_visionSqueezeRatioXSetting.set(_visionSqueezeRatioX);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeRatioY(float value) {
|
||||
if (value != _visionSqueezeRatioY) {
|
||||
_visionSqueezeRatioY = value;
|
||||
_visionSqueezeRatioYSetting.set(_visionSqueezeRatioY);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeUnSqueezeDelay(float value) {
|
||||
if (value != _visionSqueezeUnSqueezeDelay) {
|
||||
_visionSqueezeUnSqueezeDelay = value;
|
||||
_visionSqueezeUnSqueezeDelaySetting.set(_visionSqueezeUnSqueezeDelay);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeUnSqueezeSpeed(float value) {
|
||||
if (value != _visionSqueezeUnSqueezeSpeed) {
|
||||
_visionSqueezeUnSqueezeSpeed = value;
|
||||
_visionSqueezeUnSqueezeSpeedSetting.set(_visionSqueezeUnSqueezeSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeTransition(float value) {
|
||||
if (value != _visionSqueezeTransition) {
|
||||
_visionSqueezeTransition = value;
|
||||
_visionSqueezeTransitionSetting.set(_visionSqueezeTransition);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezePerEye(int value) {
|
||||
if (value != _visionSqueezePerEye) {
|
||||
_visionSqueezePerEye = value;
|
||||
_visionSqueezePerEyeSetting.set(_visionSqueezePerEye);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeGroundPlaneY(float value) {
|
||||
if (value != _visionSqueezeGroundPlaneY) {
|
||||
_visionSqueezeGroundPlaneY = value;
|
||||
_visionSqueezeGroundPlaneYSetting.set(_visionSqueezeGroundPlaneY);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeSpotlightSize(float value) {
|
||||
if (value != _visionSqueezeSpotlightSize) {
|
||||
_visionSqueezeSpotlightSize = value;
|
||||
_visionSqueezeSpotlightSizeSetting.set(_visionSqueezeSpotlightSize);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeTurningXFactor(float value) {
|
||||
if (value != _visionSqueezeTurningXFactor) {
|
||||
_visionSqueezeTurningXFactor = value;
|
||||
_visionSqueezeTurningXFactorSetting.set(_visionSqueezeTurningXFactor);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeTurningYFactor(float value) {
|
||||
if (value != _visionSqueezeTurningYFactor) {
|
||||
_visionSqueezeTurningYFactor = value;
|
||||
_visionSqueezeTurningYFactorSetting.set(_visionSqueezeTurningYFactor);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::updateVisionSqueeze(const glm::mat4& sensorToWorldMatrix, float deltaTime) {
|
||||
|
||||
const float SENSOR_TO_WORLD_TRANS_EPSILON = 0.0001f;
|
||||
const float SENSOR_TO_WORLD_TRANS_Y_EPSILON = 0.01f;
|
||||
const float SENSOR_TO_WORLD_TRANS_ITS_A_TELEPORT_SQUARED = 2.0f;
|
||||
const float SENSOR_TO_WORLD_ROT_EPSILON = 0.000005f;
|
||||
const float SENSOR_TO_WORLD_ROT_ITS_A_SNAP_TURN = 0.99f;
|
||||
const float VISION_SQUEEZE_TP_LOCKOUT = 0.1f; // seconds
|
||||
|
||||
glm::vec3 scale;
|
||||
glm::quat rotation;
|
||||
glm::vec3 translation;
|
||||
glm::vec3 skew;
|
||||
glm::vec4 perspective;
|
||||
glm::decompose(sensorToWorldMatrix, scale, rotation, translation, skew, perspective);
|
||||
|
||||
if (!_visionSqueezeEnabled) {
|
||||
_squeezeVision = false;
|
||||
_squeezeVisionTurning = false;
|
||||
} else if (_visionSqueezeLockout > 0.0f) {
|
||||
_visionSqueezeLockout -= deltaTime;
|
||||
} else {
|
||||
_squeezeVision = false;
|
||||
_squeezeVisionTurning = false;
|
||||
glm::vec3 absTransDelta = glm::abs(translation - _prevTranslation);
|
||||
float rotDot = fabsf(glm::dot(rotation, _prevRotation));
|
||||
|
||||
// if the avatar has just teleported or snap-turned, briefly disable triggering of vision-squeeze
|
||||
if (glm::length2(translation - _prevTranslation) > SENSOR_TO_WORLD_TRANS_ITS_A_TELEPORT_SQUARED ||
|
||||
rotDot < SENSOR_TO_WORLD_ROT_ITS_A_SNAP_TURN) {
|
||||
_visionSqueezeLockout = VISION_SQUEEZE_TP_LOCKOUT;
|
||||
_squeezeVision = true;
|
||||
_squeezeVisionTurning = true;
|
||||
} else if (rotDot < 1.0f - SENSOR_TO_WORLD_ROT_EPSILON) {
|
||||
_squeezeVision = true;
|
||||
_squeezeVisionTurning = true;
|
||||
} else if (absTransDelta.x > SENSOR_TO_WORLD_TRANS_EPSILON ||
|
||||
absTransDelta.y > SENSOR_TO_WORLD_TRANS_Y_EPSILON ||
|
||||
absTransDelta.z > SENSOR_TO_WORLD_TRANS_EPSILON) {
|
||||
_squeezeVision = true;
|
||||
_squeezeVisionTurning = false;
|
||||
}
|
||||
}
|
||||
|
||||
_prevTranslation = translation;
|
||||
_prevRotation = rotation;
|
||||
|
||||
static quint64 lastSqueezeTime = 0;
|
||||
quint64 now = usecTimestampNow();
|
||||
static float visionSqueezeX = 0.0f; // 0.0 -- unobstructed, 1.0 -- fully blocked
|
||||
static float visionSqueezeY = 0.0f; // 0.0 -- unobstructed, 1.0 -- fully blocked
|
||||
|
||||
if (_squeezeVision) {
|
||||
float ratioX = getVisionSqueezeRatioX();
|
||||
float ratioY = getVisionSqueezeRatioY();
|
||||
|
||||
if (ratioX >= 0.0f) {
|
||||
if (_squeezeVisionTurning) {
|
||||
ratioX += (1.0f - ratioX) * getVisionSqueezeTurningXFactor();
|
||||
}
|
||||
float newVisionSqueezeX = ratioX;
|
||||
if (newVisionSqueezeX >= visionSqueezeX) {
|
||||
lastSqueezeTime = now;
|
||||
visionSqueezeX = newVisionSqueezeX;
|
||||
}
|
||||
} else {
|
||||
visionSqueezeX = -1.0f;
|
||||
}
|
||||
|
||||
if (ratioY >= 0.0f) {
|
||||
float newVisionSqueezeY = ratioY;
|
||||
if (newVisionSqueezeY >= visionSqueezeY) {
|
||||
lastSqueezeTime = now;
|
||||
visionSqueezeY = newVisionSqueezeY;
|
||||
}
|
||||
} else {
|
||||
visionSqueezeY = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float unsqueezeAmount = deltaTime * getVisionSqueezeUnSqueezeSpeed();
|
||||
if (now - lastSqueezeTime > getVisionSqueezeUnSqueezeDelay() * USECS_PER_SECOND) {
|
||||
visionSqueezeX -= unsqueezeAmount;
|
||||
if (visionSqueezeX < 0.0f) {
|
||||
visionSqueezeX = -1.0f;
|
||||
}
|
||||
visionSqueezeY -= unsqueezeAmount;
|
||||
if (visionSqueezeY < 0.0f) {
|
||||
visionSqueezeY = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<HmdDisplayPlugin> hmdDisplayPlugin =
|
||||
std::dynamic_pointer_cast<HmdDisplayPlugin>(qApp->getActiveDisplayPlugin());
|
||||
if (hmdDisplayPlugin) {
|
||||
hmdDisplayPlugin->updateVisionSqueezeParameters(visionSqueezeX, visionSqueezeY,
|
||||
getVisionSqueezeTransition(),
|
||||
getVisionSqueezePerEye(),
|
||||
getVisionSqueezeGroundPlaneY(),
|
||||
getVisionSqueezeSpotlightSize());
|
||||
}
|
||||
}
|
108
interface/src/VisionSqueeze.h
Normal file
108
interface/src/VisionSqueeze.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// VisionSqueeze.h
|
||||
// interface/src
|
||||
//
|
||||
// Created by Seth Alves on 2019-3-13.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_VisionSqueeze_h
|
||||
#define hifi_VisionSqueeze_h
|
||||
|
||||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <SettingHandle.h>
|
||||
|
||||
static const float DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR = 0.51f;
|
||||
static const float DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR = 0.36f;
|
||||
static const float DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY = 0.2f; // seconds
|
||||
static const float DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED = 3.0f;
|
||||
static const float DEFAULT_VISION_SQUEEZE_TRANSITION = 0.25f;
|
||||
static const int DEFAULT_VISION_SQUEEZE_PER_EYE = 1;
|
||||
static const float DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y = 0.0f;
|
||||
static const float DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE = 6.0f;
|
||||
|
||||
|
||||
class VisionSqueeze {
|
||||
|
||||
public:
|
||||
|
||||
VisionSqueeze();
|
||||
|
||||
bool getVisionSqueezeEnabled() const { return _visionSqueezeEnabled; }
|
||||
void setVisionSqueezeEnabled(bool value);
|
||||
float getVisionSqueezeRatioX() const { return _visionSqueezeRatioX; }
|
||||
float getVisionSqueezeRatioY() const { return _visionSqueezeRatioY; }
|
||||
void setVisionSqueezeRatioX(float value);
|
||||
void setVisionSqueezeRatioY(float value);
|
||||
float getVisionSqueezeUnSqueezeDelay() const { return _visionSqueezeUnSqueezeDelay; }
|
||||
void setVisionSqueezeUnSqueezeDelay(float value);
|
||||
float getVisionSqueezeUnSqueezeSpeed() const { return _visionSqueezeUnSqueezeSpeed; }
|
||||
void setVisionSqueezeUnSqueezeSpeed(float value);
|
||||
float getVisionSqueezeTransition() const { return _visionSqueezeTransition; }
|
||||
void setVisionSqueezeTransition(float value);
|
||||
int getVisionSqueezePerEye() const { return _visionSqueezePerEye; }
|
||||
void setVisionSqueezePerEye(int value);
|
||||
float getVisionSqueezeGroundPlaneY() const { return _visionSqueezeGroundPlaneY; }
|
||||
void setVisionSqueezeGroundPlaneY(float value);
|
||||
float getVisionSqueezeSpotlightSize() const { return _visionSqueezeSpotlightSize; }
|
||||
void setVisionSqueezeSpotlightSize(float value);
|
||||
float getVisionSqueezeTurningXFactor() const { return _visionSqueezeTurningXFactor; }
|
||||
void setVisionSqueezeTurningXFactor(float value);
|
||||
float getVisionSqueezeTurningYFactor() const { return _visionSqueezeTurningYFactor; }
|
||||
void setVisionSqueezeTurningYFactor(float value);
|
||||
|
||||
void updateVisionSqueeze(const glm::mat4& sensorToWorldMatrix, float deltaTime);
|
||||
|
||||
// state variable accessors used by Application.cpp...
|
||||
bool getSqueezeVision() const { return _squeezeVision; }
|
||||
void setSqueezeVision(bool value) { _squeezeVision = value; }
|
||||
bool getSqueezeVisionTurning() const { return _squeezeVisionTurning; }
|
||||
void setSqueezeVisionTurning(bool value) { _squeezeVisionTurning = value; }
|
||||
|
||||
private:
|
||||
Setting::Handle<bool> _visionSqueezeEnabledSetting {"visionSqueezeEnabled", false};
|
||||
Setting::Handle<float> _visionSqueezeRatioXSetting {"visionSqueezeRatioX", 0.0f};
|
||||
Setting::Handle<float> _visionSqueezeRatioYSetting {"visionSqueezeRatioY", 0.0f};
|
||||
Setting::Handle<float> _visionSqueezeUnSqueezeDelaySetting {"visionSqueezeUnSqueezeDelay",
|
||||
DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY};
|
||||
Setting::Handle<float> _visionSqueezeUnSqueezeSpeedSetting {"visionSqueezeUnSqueezeSpeed",
|
||||
DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED};
|
||||
Setting::Handle<float> _visionSqueezeTransitionSetting {"visionSqueezeTransition", DEFAULT_VISION_SQUEEZE_TRANSITION};
|
||||
Setting::Handle<float> _visionSqueezePerEyeSetting {"visionSqueezePerEye", DEFAULT_VISION_SQUEEZE_PER_EYE};
|
||||
Setting::Handle<float> _visionSqueezeGroundPlaneYSetting {"visionSqueezeGroundPlaneY",
|
||||
DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y};
|
||||
Setting::Handle<float> _visionSqueezeSpotlightSizeSetting {"visionSqueezeSpotlightSize",
|
||||
DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE};
|
||||
Setting::Handle<float> _visionSqueezeTurningXFactorSetting {"visionSqueezeTurningXFactor",
|
||||
DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR};
|
||||
Setting::Handle<float> _visionSqueezeTurningYFactorSetting {"visionSqueezeTurningYFactor",
|
||||
DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR};
|
||||
|
||||
|
||||
// these are readable and writable from the scripting interface (on a different thread), so make them atomic
|
||||
std::atomic<bool> _visionSqueezeEnabled { false };
|
||||
std::atomic<float> _visionSqueezeRatioX { 0.0f };
|
||||
std::atomic<float> _visionSqueezeRatioY { 0.0f };
|
||||
std::atomic<float> _visionSqueezeUnSqueezeDelay { DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY }; // seconds
|
||||
std::atomic<float> _visionSqueezeUnSqueezeSpeed { DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED };
|
||||
std::atomic<float> _visionSqueezeTransition { DEFAULT_VISION_SQUEEZE_TRANSITION };
|
||||
std::atomic<int> _visionSqueezePerEye { DEFAULT_VISION_SQUEEZE_PER_EYE };
|
||||
std::atomic<float> _visionSqueezeGroundPlaneY { DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y };
|
||||
std::atomic<float> _visionSqueezeSpotlightSize { DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE };
|
||||
std::atomic<float> _visionSqueezeTurningXFactor { DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR };
|
||||
std::atomic<float> _visionSqueezeTurningYFactor { DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR };
|
||||
|
||||
bool _squeezeVision { false };
|
||||
bool _squeezeVisionTurning { false };
|
||||
|
||||
float _visionSqueezeLockout { 0.0 };
|
||||
glm::vec3 _prevTranslation;
|
||||
glm::quat _prevRotation;
|
||||
};
|
||||
|
||||
#endif // hifi_VisionSqueeze_h
|
|
@ -574,6 +574,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar
|
|||
|
||||
avatar->die();
|
||||
queuePhysicsChange(avatar);
|
||||
avatar->removeOrb();
|
||||
|
||||
// remove this avatar's entities from the tree now, if we wait (as we did previously) for this Avatar's destructor
|
||||
// it might not fire until after we create a new instance for the same remote avatar, which creates a race
|
||||
|
|
|
@ -6144,4 +6144,3 @@ void MyAvatar::sendPacket(const QUuid& entityID) const {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ void OtherAvatar::createOrb() {
|
|||
properties.setType(EntityTypes::Sphere);
|
||||
properties.setAlpha(1.0f);
|
||||
properties.setColor(getLoadingOrbColor(_loadingStatus));
|
||||
properties.setName("Loading Avatar " + getID().toString());
|
||||
properties.setPrimitiveMode(PrimitiveMode::LINES);
|
||||
properties.getPulse().setMin(0.5f);
|
||||
properties.getPulse().setMax(1.0f);
|
||||
|
@ -201,6 +202,7 @@ void OtherAvatar::computeShapeLOD() {
|
|||
break;
|
||||
case workload::Region::UNKNOWN:
|
||||
case workload::Region::INVALID:
|
||||
case workload::Region::R4:
|
||||
case workload::Region::R3:
|
||||
default:
|
||||
newLOD = BodyLOD::Sphere;
|
||||
|
|
|
@ -259,7 +259,7 @@ void GraphicsEngine::render_performFrame() {
|
|||
batch.enableSkybox(true);
|
||||
batch.enableStereo(isStereo);
|
||||
batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() });
|
||||
_splashScreen->render(batch, viewFrustum);
|
||||
_splashScreen->render(batch, viewFrustum, renderArgs._renderMethod == RenderArgs::RenderMethod::FORWARD);
|
||||
});
|
||||
} else {
|
||||
{
|
||||
|
|
|
@ -114,7 +114,11 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
|
|||
if (renderer) {
|
||||
renderer->processDatagram(*message, sendingNode);
|
||||
if (_safeLanding && _safeLanding->isTracking()) {
|
||||
_safeLanding->addToSequence(renderer->getLastOctreeMessageSequence());
|
||||
OCTREE_PACKET_SEQUENCE thisSequence = renderer->getLastOctreeMessageSequence();
|
||||
_safeLanding->addToSequence(thisSequence);
|
||||
if (_safeLandingSequenceStart == SafeLanding::INVALID_SEQUENCE) {
|
||||
_safeLandingSequenceStart = thisSequence;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,8 +128,8 @@ void OctreePacketProcessor::processPacket(QSharedPointer<ReceivedMessage> messag
|
|||
// Read sequence #
|
||||
OCTREE_PACKET_SEQUENCE completionNumber;
|
||||
message->readPrimitive(&completionNumber);
|
||||
if (_safeLanding) {
|
||||
_safeLanding->finishSequence(0, completionNumber);
|
||||
if (_safeLanding && _safeLanding->isTracking()) {
|
||||
_safeLanding->finishSequence(_safeLandingSequenceStart, completionNumber);
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -153,6 +157,13 @@ void OctreePacketProcessor::stopSafeLanding() {
|
|||
}
|
||||
}
|
||||
|
||||
void OctreePacketProcessor::resetSafeLanding() {
|
||||
if (_safeLanding) {
|
||||
_safeLanding->reset();
|
||||
}
|
||||
_safeLandingSequenceStart = SafeLanding::INVALID_SEQUENCE;
|
||||
}
|
||||
|
||||
bool OctreePacketProcessor::safeLandingIsActive() const {
|
||||
return _safeLanding && _safeLanding->isTracking();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ public:
|
|||
void startSafeLanding();
|
||||
void updateSafeLanding();
|
||||
void stopSafeLanding();
|
||||
void resetSafeLanding();
|
||||
bool safeLandingIsActive() const;
|
||||
bool safeLandingIsComplete() const;
|
||||
|
||||
|
@ -43,6 +44,7 @@ private slots:
|
|||
void handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||
|
||||
private:
|
||||
OCTREE_PACKET_SEQUENCE _safeLandingSequenceStart { SafeLanding::INVALID_SEQUENCE };
|
||||
std::unique_ptr<SafeLanding> _safeLanding;
|
||||
};
|
||||
#endif // hifi_OctreePacketProcessor_h
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "InterfaceLogging.h"
|
||||
#include "Application.h"
|
||||
|
||||
const int SafeLanding::SEQUENCE_MODULO = std::numeric_limits<OCTREE_PACKET_SEQUENCE>::max() + 1;
|
||||
|
||||
CalculateEntityLoadingPriority SafeLanding::entityLoadingOperatorElevateCollidables = [](const EntityItem& entityItem) {
|
||||
const int COLLIDABLE_ENTITY_PRIORITY = 10.0f;
|
||||
|
@ -25,8 +24,8 @@ CalculateEntityLoadingPriority SafeLanding::entityLoadingOperatorElevateCollidab
|
|||
};
|
||||
|
||||
namespace {
|
||||
template<typename T> bool lessThanWraparound(int a, int b) {
|
||||
constexpr int MAX_T_VALUE = std::numeric_limits<T>::max();
|
||||
template<typename T> bool lessThanWraparound(int32_t a, int32_t b) {
|
||||
constexpr int32_t MAX_T_VALUE = std::numeric_limits<T>::max();
|
||||
if (b <= a) {
|
||||
b += MAX_T_VALUE;
|
||||
}
|
||||
|
@ -34,7 +33,7 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
bool SafeLanding::SequenceLessThan::operator()(const int& a, const int& b) const {
|
||||
bool SafeLanding::SequenceLessThan::operator()(const OCTREE_PACKET_SEQUENCE& a, const OCTREE_PACKET_SEQUENCE& b) const {
|
||||
return lessThanWraparound<OCTREE_PACKET_SEQUENCE>(a, b);
|
||||
}
|
||||
|
||||
|
@ -46,8 +45,8 @@ void SafeLanding::startTracking(QSharedPointer<EntityTreeRenderer> entityTreeRen
|
|||
_entityTreeRenderer = entityTreeRenderer;
|
||||
_trackedEntities.clear();
|
||||
_maxTrackedEntityCount = 0;
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_sequenceStart = SafeLanding::INVALID_SEQUENCE;
|
||||
_sequenceEnd = SafeLanding::INVALID_SEQUENCE;
|
||||
_sequenceNumbers.clear();
|
||||
_trackingEntities = true;
|
||||
_startTime = usecTimestampNow();
|
||||
|
@ -72,7 +71,7 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
|
|||
if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) {
|
||||
_trackedEntities.emplace(entityID, entity);
|
||||
|
||||
int trackedEntityCount = (int)_trackedEntities.size();
|
||||
int32_t trackedEntityCount = (int32_t)_trackedEntities.size();
|
||||
if (trackedEntityCount > _maxTrackedEntityCount) {
|
||||
_maxTrackedEntityCount = trackedEntityCount;
|
||||
_trackedEntityStabilityCount = 0;
|
||||
|
@ -87,15 +86,15 @@ void SafeLanding::deleteTrackedEntity(const EntityItemID& entityID) {
|
|||
_trackedEntities.erase(entityID);
|
||||
}
|
||||
|
||||
void SafeLanding::finishSequence(int first, int last) {
|
||||
void SafeLanding::finishSequence(OCTREE_PACKET_SEQUENCE first, OCTREE_PACKET_SEQUENCE last) {
|
||||
Locker lock(_lock);
|
||||
if (_trackingEntities) {
|
||||
_initialStart = first;
|
||||
_initialEnd = last;
|
||||
_sequenceStart = first;
|
||||
_sequenceEnd = last;
|
||||
}
|
||||
}
|
||||
|
||||
void SafeLanding::addToSequence(int sequenceNumber) {
|
||||
void SafeLanding::addToSequence(OCTREE_PACKET_SEQUENCE sequenceNumber) {
|
||||
Locker lock(_lock);
|
||||
_sequenceNumbers.insert(sequenceNumber);
|
||||
}
|
||||
|
@ -135,14 +134,13 @@ void SafeLanding::updateTracking() {
|
|||
|
||||
if (_trackedEntities.empty()) {
|
||||
// no more tracked entities --> check sequenceNumbers
|
||||
if (_initialStart != INVALID_SEQUENCE) {
|
||||
if (_sequenceStart != SafeLanding::INVALID_SEQUENCE) {
|
||||
bool shouldStop = false;
|
||||
{
|
||||
Locker lock(_lock);
|
||||
int sequenceSize = _initialStart <= _initialEnd ? _initialEnd - _initialStart:
|
||||
_initialEnd + SEQUENCE_MODULO - _initialStart;
|
||||
auto startIter = _sequenceNumbers.find(_initialStart);
|
||||
auto endIter = _sequenceNumbers.find(_initialEnd - 1);
|
||||
auto sequenceSize = _sequenceEnd - _sequenceStart; // this works even in rollover case
|
||||
auto startIter = _sequenceNumbers.find(_sequenceStart);
|
||||
auto endIter = _sequenceNumbers.find(_sequenceEnd - 1);
|
||||
|
||||
bool missingSequenceNumbers = qApp->isMissingSequenceNumbers();
|
||||
shouldStop = (sequenceSize == 0 ||
|
||||
|
@ -159,31 +157,41 @@ void SafeLanding::updateTracking() {
|
|||
|
||||
void SafeLanding::stopTracking() {
|
||||
Locker lock(_lock);
|
||||
_trackingEntities = false;
|
||||
if (_entityTreeRenderer) {
|
||||
auto entityTree = _entityTreeRenderer->getTree();
|
||||
disconnect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
|
||||
disconnect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
|
||||
_entityTreeRenderer.reset();
|
||||
if (_trackingEntities) {
|
||||
_trackingEntities = false;
|
||||
if (_entityTreeRenderer) {
|
||||
auto entityTree = _entityTreeRenderer->getTree();
|
||||
disconnect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
|
||||
disconnect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
|
||||
_entityTreeRenderer.reset();
|
||||
}
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(_prevEntityLoadingPriorityOperator);
|
||||
}
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(_prevEntityLoadingPriorityOperator);
|
||||
}
|
||||
|
||||
void SafeLanding::reset() {
|
||||
_trackingEntities = false;
|
||||
_trackedEntities.clear();
|
||||
_maxTrackedEntityCount = 0;
|
||||
_sequenceStart = SafeLanding::INVALID_SEQUENCE;
|
||||
_sequenceEnd = SafeLanding::INVALID_SEQUENCE;
|
||||
}
|
||||
|
||||
bool SafeLanding::trackingIsComplete() const {
|
||||
return !_trackingEntities && (_initialStart != INVALID_SEQUENCE);
|
||||
return !_trackingEntities && (_sequenceStart != SafeLanding::INVALID_SEQUENCE);
|
||||
}
|
||||
|
||||
float SafeLanding::loadingProgressPercentage() {
|
||||
Locker lock(_lock);
|
||||
static const int MINIMUM_TRACKED_ENTITY_STABILITY_COUNT = 15;
|
||||
|
||||
float entityReadyPercentage = 0.0f;
|
||||
if (_maxTrackedEntityCount > 0) {
|
||||
entityReadyPercentage = ((_maxTrackedEntityCount - _trackedEntities.size()) / (float)_maxTrackedEntityCount);
|
||||
}
|
||||
|
||||
constexpr int32_t MINIMUM_TRACKED_ENTITY_STABILITY_COUNT = 15;
|
||||
if (_trackedEntityStabilityCount < MINIMUM_TRACKED_ENTITY_STABILITY_COUNT) {
|
||||
entityReadyPercentage *= 0.20f;
|
||||
}
|
||||
|
@ -203,8 +211,22 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) {
|
|||
if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) {
|
||||
auto space = _entityTreeRenderer->getWorkloadSpace();
|
||||
uint8_t region = space ? space->getRegion(entity->getSpaceIndex()) : (uint8_t)workload::Region::INVALID;
|
||||
bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical();
|
||||
return (!shouldBePhysical || entity->isInPhysicsSimulation() || modelEntity->computeShapeFailedToLoad());
|
||||
|
||||
// Note: the meanings of the workload regions are:
|
||||
// R1 = in physics simulation and willing to own simulation
|
||||
// R2 = in physics simulation but does NOT want to own simulation
|
||||
// R3 = not in physics simulation but kinematically animated when velocities are non-zero
|
||||
// R4 = sorted by workload and found to be outside R3
|
||||
// UNKNOWN = known to workload but not yet sorted
|
||||
// INVALID = not known to workload
|
||||
// So any entity sorted into R3 or R4 is definitelyNotPhysical
|
||||
|
||||
bool definitelyNotPhysical = region == workload::Region::R3 ||
|
||||
region == workload::Region::R4 ||
|
||||
!entity->shouldBePhysical() ||
|
||||
modelEntity->unableToLoadCollisionShape();
|
||||
bool definitelyPhysical = entity->isInPhysicsSimulation();
|
||||
return definitelyNotPhysical || definitelyPhysical;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,20 +234,24 @@ bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) {
|
|||
}
|
||||
|
||||
void SafeLanding::debugDumpSequenceIDs() const {
|
||||
int p = -1;
|
||||
qCDebug(interfaceapp) << "Sequence set size:" << _sequenceNumbers.size();
|
||||
for (auto s: _sequenceNumbers) {
|
||||
if (p == -1) {
|
||||
p = s;
|
||||
qCDebug(interfaceapp) << "First:" << s;
|
||||
} else {
|
||||
|
||||
auto itr = _sequenceNumbers.begin();
|
||||
OCTREE_PACKET_SEQUENCE p = SafeLanding::INVALID_SEQUENCE;
|
||||
if (itr != _sequenceNumbers.end()) {
|
||||
p = (*itr);
|
||||
qCDebug(interfaceapp) << "First:" << (int32_t)p;
|
||||
++itr;
|
||||
while (itr != _sequenceNumbers.end()) {
|
||||
OCTREE_PACKET_SEQUENCE s = *itr;
|
||||
if (s != p + 1) {
|
||||
qCDebug(interfaceapp) << "Gap from" << p << "to" << s << "(exclusive)";
|
||||
qCDebug(interfaceapp) << "Gap from" << (int32_t)p << "to" << (int32_t)s << "(exclusive)";
|
||||
p = s;
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
if (p != SafeLanding::INVALID_SEQUENCE) {
|
||||
qCDebug(interfaceapp) << "Last:" << p;
|
||||
}
|
||||
}
|
||||
if (p != -1) {
|
||||
qCDebug(interfaceapp) << "Last:" << p;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedPointer>
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "EntityItem.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
|
||||
|
@ -27,14 +29,18 @@ class EntityItemID;
|
|||
|
||||
class SafeLanding : public QObject {
|
||||
public:
|
||||
static constexpr OCTREE_PACKET_SEQUENCE MAX_SEQUENCE = std::numeric_limits<OCTREE_PACKET_SEQUENCE>::max();
|
||||
static constexpr OCTREE_PACKET_SEQUENCE INVALID_SEQUENCE = MAX_SEQUENCE; // not technically invalid, but close enough
|
||||
|
||||
void startTracking(QSharedPointer<EntityTreeRenderer> entityTreeRenderer);
|
||||
void updateTracking();
|
||||
void stopTracking();
|
||||
void reset();
|
||||
bool isTracking() const { return _trackingEntities; }
|
||||
bool trackingIsComplete() const;
|
||||
|
||||
void finishSequence(int first, int last); // 'last' exclusive.
|
||||
void addToSequence(int sequenceNumber);
|
||||
void finishSequence(OCTREE_PACKET_SEQUENCE first, OCTREE_PACKET_SEQUENCE last); // 'last' exclusive.
|
||||
void addToSequence(OCTREE_PACKET_SEQUENCE sequenceNumber);
|
||||
float loadingProgressPercentage();
|
||||
|
||||
private slots:
|
||||
|
@ -52,24 +58,22 @@ private:
|
|||
using EntityMap = std::map<EntityItemID, EntityItemPointer>;
|
||||
EntityMap _trackedEntities;
|
||||
|
||||
static constexpr int INVALID_SEQUENCE = -1;
|
||||
int _initialStart { INVALID_SEQUENCE };
|
||||
int _initialEnd { INVALID_SEQUENCE };
|
||||
int _maxTrackedEntityCount { 0 };
|
||||
int _trackedEntityStabilityCount { 0 };
|
||||
OCTREE_PACKET_SEQUENCE _sequenceStart { INVALID_SEQUENCE };
|
||||
OCTREE_PACKET_SEQUENCE _sequenceEnd { INVALID_SEQUENCE };
|
||||
int32_t _maxTrackedEntityCount { 0 };
|
||||
int32_t _trackedEntityStabilityCount { 0 };
|
||||
|
||||
quint64 _startTime { 0 };
|
||||
|
||||
struct SequenceLessThan {
|
||||
bool operator()(const int& a, const int& b) const;
|
||||
bool operator()(const OCTREE_PACKET_SEQUENCE& a, const OCTREE_PACKET_SEQUENCE& b) const;
|
||||
};
|
||||
|
||||
std::set<int, SequenceLessThan> _sequenceNumbers;
|
||||
using SequenceSet = std::set<OCTREE_PACKET_SEQUENCE, SequenceLessThan>;
|
||||
SequenceSet _sequenceNumbers;
|
||||
|
||||
static CalculateEntityLoadingPriority entityLoadingOperatorElevateCollidables;
|
||||
CalculateEntityLoadingPriority _prevEntityLoadingPriorityOperator { nullptr };
|
||||
|
||||
static const int SEQUENCE_MODULO;
|
||||
};
|
||||
|
||||
#endif // hifi_SafeLanding_h
|
||||
|
|
|
@ -405,7 +405,8 @@ gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabo
|
|||
using namespace shader::render_utils::program;
|
||||
|
||||
static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
|
||||
std::make_tuple(false, false, parabola), std::make_tuple(false, true, forward_parabola), std::make_tuple(true, false, parabola_translucent)/*, std::make_tuple(true, true, forward_parabola_translucent)*/
|
||||
std::make_tuple(false, false, parabola), std::make_tuple(false, true, parabola_forward),
|
||||
std::make_tuple(true, false, parabola_translucent), std::make_tuple(true, true, parabola_forward) // The forward opaque/translucent pipelines are the same for now
|
||||
};
|
||||
|
||||
for (auto& key : keys) {
|
||||
|
@ -423,9 +424,6 @@ gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabo
|
|||
|
||||
_parabolaPipelines[{std::get<0>(key), std::get<1>(key)}] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state);
|
||||
}
|
||||
|
||||
// The forward opaque/translucent pipelines are the same for now
|
||||
_parabolaPipelines[{ true, true }] = _parabolaPipelines[{ false, true}];
|
||||
}
|
||||
return _parabolaPipelines[{ _parabolaData.color.a < 1.0f, forward }];
|
||||
}
|
||||
|
|
|
@ -111,10 +111,11 @@ void DesktopScriptingInterface::show(const QString& path, const QString& title)
|
|||
InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& sourceUrl, const QVariantMap& properties) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
InteractiveWindowPointer interactiveWindow = nullptr;
|
||||
BLOCKING_INVOKE_METHOD(this, "createWindow",
|
||||
BLOCKING_INVOKE_METHOD(this, "createWindowOnThread",
|
||||
Q_RETURN_ARG(InteractiveWindowPointer, interactiveWindow),
|
||||
Q_ARG(QString, sourceUrl),
|
||||
Q_ARG(QVariantMap, properties));
|
||||
Q_ARG(QVariantMap, properties),
|
||||
Q_ARG(QThread*, QThread::currentThread()));
|
||||
return interactiveWindow;
|
||||
}
|
||||
|
||||
|
@ -129,3 +130,16 @@ InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString&
|
|||
|
||||
return new InteractiveWindow(sourceUrl, properties);
|
||||
}
|
||||
|
||||
InteractiveWindowPointer DesktopScriptingInterface::createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread) {
|
||||
// The offscreen surface already validates against non-local QML sources, but we also need to ensure that
|
||||
// if we create top level QML, like dock widgets or other types of QQuickView containing desktop windows
|
||||
// that the source URL is permitted
|
||||
const auto& urlValidator = OffscreenQmlSurface::getUrlValidator();
|
||||
if (!urlValidator(sourceUrl)) {
|
||||
return nullptr;
|
||||
}
|
||||
InteractiveWindowPointer window = new InteractiveWindow(sourceUrl, properties);
|
||||
window->moveToThread(targetThread);
|
||||
return window;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,8 @@ private:
|
|||
static int flagAlwaysOnTop() { return AlwaysOnTop; }
|
||||
static int flagCloseButtonHides() { return CloseButtonHides; }
|
||||
|
||||
Q_INVOKABLE InteractiveWindowPointer createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread);
|
||||
|
||||
static QVariantMap getDockArea();
|
||||
|
||||
Q_INVOKABLE static QVariantMap getPresentationMode();
|
||||
|
|
|
@ -236,3 +236,83 @@ QVariant HMDScriptingInterface::getPlayAreaRect() {
|
|||
QVector<glm::vec3> HMDScriptingInterface::getSensorPositions() {
|
||||
return qApp->getActiveDisplayPlugin()->getSensorPositions();
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeRatioX() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeRatioX();
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeRatioY() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeRatioY();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeRatioX(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeRatioX(value);
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeRatioY(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeRatioY(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeUnSqueezeDelay() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeUnSqueezeDelay();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeUnSqueezeDelay(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeUnSqueezeDelay(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeUnSqueezeSpeed() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeUnSqueezeSpeed();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeUnSqueezeSpeed(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeUnSqueezeSpeed(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeTransition() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeTransition();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeTransition(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeTransition(value);
|
||||
}
|
||||
|
||||
int HMDScriptingInterface::getVisionSqueezePerEye() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezePerEye();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezePerEye(int value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezePerEye(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeGroundPlaneY() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeGroundPlaneY();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeGroundPlaneY(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeGroundPlaneY(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeSpotlightSize() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeSpotlightSize();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeSpotlightSize(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeSpotlightSize(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeTurningXFactor() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeTurningXFactor();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeTurningXFactor(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeTurningXFactor(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeTurningYFactor() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeTurningYFactor();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeTurningYFactor(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeTurningYFactor(value);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,17 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
|
|||
Q_PROPERTY(QVariant playArea READ getPlayAreaRect);
|
||||
Q_PROPERTY(QVector<glm::vec3> sensorPositions READ getSensorPositions);
|
||||
|
||||
Q_PROPERTY(float visionSqueezeRatioX READ getVisionSqueezeRatioX WRITE setVisionSqueezeRatioX);
|
||||
Q_PROPERTY(float visionSqueezeRatioY READ getVisionSqueezeRatioY WRITE setVisionSqueezeRatioY);
|
||||
Q_PROPERTY(float visionSqueezeUnSqueezeDelay READ getVisionSqueezeUnSqueezeDelay WRITE setVisionSqueezeUnSqueezeDelay);
|
||||
Q_PROPERTY(float visionSqueezeUnSqueezeSpeed READ getVisionSqueezeUnSqueezeSpeed WRITE setVisionSqueezeUnSqueezeSpeed);
|
||||
Q_PROPERTY(float visionSqueezeTransition READ getVisionSqueezeTransition WRITE setVisionSqueezeTransition);
|
||||
Q_PROPERTY(int visionSqueezePerEye READ getVisionSqueezePerEye WRITE setVisionSqueezePerEye);
|
||||
Q_PROPERTY(float visionSqueezeGroundPlaneY READ getVisionSqueezeGroundPlaneY WRITE setVisionSqueezeGroundPlaneY);
|
||||
Q_PROPERTY(float visionSqueezeSpotlightSize READ getVisionSqueezeSpotlightSize WRITE setVisionSqueezeSpotlightSize);
|
||||
Q_PROPERTY(float visionSqueezeTurningXFactor READ getVisionSqueezeTurningXFactor WRITE setVisionSqueezeTurningXFactor);
|
||||
Q_PROPERTY(float visionSqueezeTurningYFactor READ getVisionSqueezeTurningYFactor WRITE setVisionSqueezeTurningYFactor);
|
||||
|
||||
public:
|
||||
|
||||
/**jsdoc
|
||||
|
@ -339,6 +350,27 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE void openTablet(bool contextualMode = false);
|
||||
|
||||
float getVisionSqueezeRatioX() const;
|
||||
float getVisionSqueezeRatioY() const;
|
||||
void setVisionSqueezeRatioX(float value);
|
||||
void setVisionSqueezeRatioY(float value);
|
||||
float getVisionSqueezeUnSqueezeDelay() const;
|
||||
void setVisionSqueezeUnSqueezeDelay(float value);
|
||||
float getVisionSqueezeUnSqueezeSpeed() const;
|
||||
void setVisionSqueezeUnSqueezeSpeed(float value);
|
||||
float getVisionSqueezeTransition() const;
|
||||
void setVisionSqueezeTransition(float value);
|
||||
int getVisionSqueezePerEye() const;
|
||||
void setVisionSqueezePerEye(int value);
|
||||
float getVisionSqueezeGroundPlaneY() const;
|
||||
void setVisionSqueezeGroundPlaneY(float value);
|
||||
float getVisionSqueezeSpotlightSize() const;
|
||||
void setVisionSqueezeSpotlightSize(float value);
|
||||
float getVisionSqueezeTurningXFactor() const;
|
||||
void setVisionSqueezeTurningXFactor(float value);
|
||||
float getVisionSqueezeTurningYFactor() const;
|
||||
void setVisionSqueezeTurningYFactor(float value);
|
||||
|
||||
signals:
|
||||
/**jsdoc
|
||||
* Triggered when a request to show or hide models of the HMD hand controllers is made using
|
||||
|
|
|
@ -221,4 +221,6 @@ QStringList PlatformInfoScriptingInterface::getPlatformTierNames() {
|
|||
return platformTierNames;
|
||||
}
|
||||
|
||||
|
||||
bool PlatformInfoScriptingInterface::isRenderMethodDeferredCapable() {
|
||||
return platform::Profiler::isRenderMethodDeferredCapable();
|
||||
}
|
||||
|
|
|
@ -245,7 +245,12 @@ public slots:
|
|||
*/
|
||||
QStringList getPlatformTierNames();
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* Gets whether the current hardware can render using the Deferred method.
|
||||
* @function PlatformInfo.isRenderMethodDeferredCapable
|
||||
* @returns {bool} <code>true</code> if the current hardware can render using the Deferred method; <code>false</code> otherwise.
|
||||
*/
|
||||
bool isRenderMethodDeferredCapable();
|
||||
};
|
||||
|
||||
#endif // hifi_PlatformInfoScriptingInterface_h
|
||||
|
|
|
@ -94,7 +94,7 @@ void AvatarInputs::setShowBubbleTools(bool showBubbleTools) {
|
|||
return;
|
||||
|
||||
_showBubbleTools = showBubbleTools;
|
||||
showBubbleToolsSetting.set(_showAudioTools);
|
||||
showBubbleToolsSetting.set(_showBubbleTools);
|
||||
emit showBubbleToolsChanged(_showBubbleTools);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,28 @@ static const QStringList KNOWN_SCHEMES = QStringList() << "http" << "https" << "
|
|||
|
||||
static const int DEFAULT_HEIGHT = 60;
|
||||
|
||||
QmlWindowProxy::QmlWindowProxy(QObject* qmlObject, QObject* parent) : QmlWrapper(qmlObject, parent) {
|
||||
_qmlWindow = qmlObject;
|
||||
}
|
||||
|
||||
void QmlWindowProxy::parentNativeWindowToMainWindow() {
|
||||
#ifdef Q_OS_WIN
|
||||
if (!_qmlWindow) {
|
||||
return;
|
||||
}
|
||||
const auto nativeWindowProperty = _qmlWindow->property("nativeWindow");
|
||||
if (nativeWindowProperty.isNull() || !nativeWindowProperty.isValid()) {
|
||||
return;
|
||||
}
|
||||
const auto nativeWindow = qvariant_cast<QQuickWindow*>(nativeWindowProperty);
|
||||
SetWindowLongPtr((HWND)nativeWindow->winId(), GWLP_HWNDPARENT, (LONG)MainWindow::findMainWindow()->winId());
|
||||
#endif
|
||||
}
|
||||
|
||||
static void qmlWindowProxyDeleter(QmlWindowProxy* qmlWindowProxy) {
|
||||
qmlWindowProxy->deleteLater();
|
||||
}
|
||||
|
||||
static void dockWidgetDeleter(DockWidget* dockWidget) {
|
||||
dockWidget->deleteLater();
|
||||
}
|
||||
|
@ -85,13 +107,13 @@ void InteractiveWindow::forwardKeyReleaseEvent(int key, int modifiers) {
|
|||
* @property {string} [title="InteractiveWindow] - The title of the window.
|
||||
* @property {Vec2} [position] - The initial position of the window, in pixels.
|
||||
* @property {Vec2} [size] - The initial size of the window, in pixels
|
||||
* @property {boolean} [visible=true] - <code>true</code> to make the window visible when created, <code>false</code> to make
|
||||
* @property {boolean} [visible=true] - <code>true</code> to make the window visible when created, <code>false</code> to make
|
||||
* it invisible.
|
||||
* @property {InteractiveWindow.PresentationMode} [presentationMode=Desktop.PresentationMode.VIRTUAL] -
|
||||
* <code>Desktop.PresentationMode.VIRTUAL</code> to display the window inside Interface, <code>.NATIVE</code> to display it
|
||||
* @property {InteractiveWindow.PresentationMode} [presentationMode=Desktop.PresentationMode.VIRTUAL] -
|
||||
* <code>Desktop.PresentationMode.VIRTUAL</code> to display the window inside Interface, <code>.NATIVE</code> to display it
|
||||
* as its own separate window.
|
||||
* @property {InteractiveWindow.PresentationWindowInfo} [presentationWindowInfo] - Controls how a <code>NATIVE</code> window is
|
||||
* displayed. If used, the window is docked to the specified edge of the Interface window, otherwise the window is
|
||||
* @property {InteractiveWindow.PresentationWindowInfo} [presentationWindowInfo] - Controls how a <code>NATIVE</code> window is
|
||||
* displayed. If used, the window is docked to the specified edge of the Interface window, otherwise the window is
|
||||
* displayed as its own separate window.
|
||||
* @property {InteractiveWindow.AdditionalFlags} [additionalFlags=0] - Window behavior flags in addition to "native window flags" (minimize/maximize/close),
|
||||
* set at window creation. Possible flag values are provided as {@link Desktop|Desktop.ALWAYS_ON_TOP} and {@link Desktop|Desktop.CLOSE_BUTTON_HIDES}.
|
||||
|
@ -124,7 +146,7 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
|
|||
auto mainWindow = qApp->getWindow();
|
||||
_dockWidget = std::shared_ptr<DockWidget>(new DockWidget(title, mainWindow), dockWidgetDeleter);
|
||||
auto quickView = _dockWidget->getQuickView();
|
||||
|
||||
|
||||
Application::setupQmlSurface(quickView->rootContext() , true);
|
||||
|
||||
//add any whitelisted callbacks
|
||||
|
@ -176,13 +198,12 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
|
|||
});
|
||||
|
||||
_dockWidget->setSource(QUrl(sourceUrl));
|
||||
|
||||
mainWindow->addDockWidget(dockArea, _dockWidget.get());
|
||||
} else {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
// Build the event bridge and wrapper on the main thread
|
||||
offscreenUi->loadInNewContext(CONTENT_WINDOW_QML, [&](QQmlContext* context, QObject* object) {
|
||||
_qmlWindow = object;
|
||||
_qmlWindowProxy = std::shared_ptr<QmlWindowProxy>(new QmlWindowProxy(object, nullptr), qmlWindowProxyDeleter);
|
||||
context->setContextProperty(EVENT_BRIDGE_PROPERTY, this);
|
||||
if (properties.contains(ADDITIONAL_FLAGS_PROPERTY)) {
|
||||
object->setProperty(ADDITIONAL_FLAGS_PROPERTY, properties[ADDITIONAL_FLAGS_PROPERTY].toUInt());
|
||||
|
@ -249,60 +270,48 @@ void InteractiveWindow::sendToQml(const QVariant& message) {
|
|||
QMetaObject::invokeMethod(rootItem, "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message));
|
||||
}
|
||||
} else {
|
||||
QMetaObject::invokeMethod(_qmlWindow, "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message));
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "fromScript", Qt::QueuedConnection, Q_ARG(QVariant, message));
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveWindow::emitScriptEvent(const QVariant& scriptMessage) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, scriptMessage));
|
||||
} else {
|
||||
emit scriptEventReceived(scriptMessage);
|
||||
}
|
||||
emit scriptEventReceived(scriptMessage);
|
||||
}
|
||||
|
||||
void InteractiveWindow::emitWebEvent(const QVariant& webMessage) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "emitWebEvent", Qt::QueuedConnection, Q_ARG(QVariant, webMessage));
|
||||
} else {
|
||||
emit webEventReceived(webMessage);
|
||||
}
|
||||
emit webEventReceived(webMessage);
|
||||
}
|
||||
|
||||
void InteractiveWindow::close() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "close");
|
||||
return;
|
||||
if (_qmlWindowProxy) {
|
||||
QObject* qmlWindow = _qmlWindowProxy->getQmlWindow();
|
||||
if (qmlWindow) {
|
||||
qmlWindow->deleteLater();
|
||||
}
|
||||
_qmlWindowProxy->deleteLater();
|
||||
}
|
||||
|
||||
if (_qmlWindow) {
|
||||
_qmlWindow->deleteLater();
|
||||
if (_dockWidget) {
|
||||
auto window = qApp->getWindow();
|
||||
if (QThread::currentThread() != window->thread()) {
|
||||
BLOCKING_INVOKE_METHOD(window, "removeDockWidget", Q_ARG(QDockWidget*, _dockWidget.get()));
|
||||
} else {
|
||||
window->removeDockWidget(_dockWidget.get());
|
||||
}
|
||||
}
|
||||
|
||||
qApp->getWindow()->removeDockWidget(_dockWidget.get());
|
||||
_dockWidget = nullptr;
|
||||
_qmlWindow = nullptr;
|
||||
_qmlWindowProxy = nullptr;
|
||||
}
|
||||
|
||||
void InteractiveWindow::show() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "show");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_qmlWindow) {
|
||||
QMetaObject::invokeMethod(_qmlWindow, "show", Qt::DirectConnection);
|
||||
if (_qmlWindowProxy) {
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "show");
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveWindow::raise() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "raise");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_qmlWindow) {
|
||||
QMetaObject::invokeMethod(_qmlWindow, "raiseWindow", Qt::DirectConnection);
|
||||
if (_qmlWindowProxy) {
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "raiseWindow");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,144 +326,84 @@ void InteractiveWindow::qmlToScript(const QVariant& message) {
|
|||
}
|
||||
|
||||
void InteractiveWindow::setVisible(bool visible) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setVisible", Q_ARG(bool, visible));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_qmlWindow.isNull()) {
|
||||
_qmlWindow->setProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY, visible);
|
||||
if (_qmlWindowProxy) {
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_VISIBLE_PROPERTY),
|
||||
Q_ARG(QVariant, visible));
|
||||
}
|
||||
}
|
||||
|
||||
bool InteractiveWindow::isVisible() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
bool result = false;
|
||||
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "isVisible", Q_RETURN_ARG(bool, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (_qmlWindow.isNull()) {
|
||||
if (!_qmlWindowProxy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _qmlWindow->property(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool();
|
||||
return _qmlWindowProxy->readProperty(INTERACTIVE_WINDOW_VISIBLE_PROPERTY).toBool();
|
||||
}
|
||||
|
||||
glm::vec2 InteractiveWindow::getPosition() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
glm::vec2 result;
|
||||
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getPosition", Q_RETURN_ARG(glm::vec2, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (_qmlWindow.isNull()) {
|
||||
if (!_qmlWindowProxy) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF());
|
||||
return toGlm(_qmlWindowProxy->readProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY).toPointF());
|
||||
}
|
||||
|
||||
void InteractiveWindow::setPosition(const glm::vec2& position) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setPosition", Q_ARG(const glm::vec2&, position));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_qmlWindow.isNull()) {
|
||||
_qmlWindow->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y));
|
||||
QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowPositionForMode", Qt::DirectConnection);
|
||||
if (_qmlWindowProxy) {
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_POSITION_PROPERTY),
|
||||
Q_ARG(QVariant, QPointF(position.x, position.y)));
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "updateInteractiveWindowPositionForMode");
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec2 InteractiveWindow::getSize() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
glm::vec2 result;
|
||||
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getSize", Q_RETURN_ARG(glm::vec2, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (_qmlWindow.isNull()) {
|
||||
if (!_qmlWindowProxy) {
|
||||
return {};
|
||||
}
|
||||
return toGlm(_qmlWindow->property(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize());
|
||||
|
||||
return toGlm(_qmlWindowProxy->readProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY).toSize());
|
||||
}
|
||||
|
||||
void InteractiveWindow::setSize(const glm::vec2& size) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setSize", Q_ARG(const glm::vec2&, size));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_qmlWindow.isNull()) {
|
||||
_qmlWindow->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y));
|
||||
QMetaObject::invokeMethod(_qmlWindow, "updateInteractiveWindowSizeForMode", Qt::DirectConnection);
|
||||
if (_qmlWindowProxy) {
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_SIZE_PROPERTY),
|
||||
Q_ARG(QVariant, QSize(size.x, size.y)));
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy->getQmlWindow(), "updateInteractiveWindowSizeForMode");
|
||||
}
|
||||
}
|
||||
|
||||
QString InteractiveWindow::getTitle() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QString result;
|
||||
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getTitle", Q_RETURN_ARG(QString, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (_qmlWindow.isNull()) {
|
||||
if (!_qmlWindowProxy) {
|
||||
return QString();
|
||||
}
|
||||
return _qmlWindow->property(TITLE_PROPERTY).toString();
|
||||
|
||||
return _qmlWindowProxy->readProperty(TITLE_PROPERTY).toString();
|
||||
}
|
||||
|
||||
void InteractiveWindow::setTitle(const QString& title) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setTitle", Q_ARG(const QString&, title));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_qmlWindow.isNull()) {
|
||||
_qmlWindow->setProperty(TITLE_PROPERTY, title);
|
||||
if (_qmlWindowProxy) {
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, TITLE_PROPERTY),
|
||||
Q_ARG(QVariant, title));
|
||||
}
|
||||
}
|
||||
|
||||
int InteractiveWindow::getPresentationMode() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
int result;
|
||||
BLOCKING_INVOKE_METHOD(const_cast<InteractiveWindow*>(this), "getPresentationMode",
|
||||
Q_RETURN_ARG(int, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (_qmlWindow.isNull()) {
|
||||
if (!_qmlWindowProxy) {
|
||||
return Virtual;
|
||||
}
|
||||
return _qmlWindow->property(PRESENTATION_MODE_PROPERTY).toInt();
|
||||
|
||||
return _qmlWindowProxy->readProperty(PRESENTATION_MODE_PROPERTY).toInt();
|
||||
}
|
||||
|
||||
void InteractiveWindow::parentNativeWindowToMainWindow() {
|
||||
#ifdef Q_OS_WIN
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "parentNativeWindowToMainWindow");
|
||||
return;
|
||||
if (_qmlWindowProxy) {
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "parentNativeWindowToMainWindow");
|
||||
}
|
||||
if (_qmlWindow.isNull()) {
|
||||
return;
|
||||
}
|
||||
const auto nativeWindowProperty = _qmlWindow->property("nativeWindow");
|
||||
if (nativeWindowProperty.isNull() || !nativeWindowProperty.isValid()) {
|
||||
return;
|
||||
}
|
||||
const auto nativeWindow = qvariant_cast<QQuickWindow*>(nativeWindowProperty);
|
||||
SetWindowLongPtr((HWND)nativeWindow->winId(), GWLP_HWNDPARENT, (LONG)MainWindow::findMainWindow()->winId());
|
||||
#endif
|
||||
}
|
||||
|
||||
void InteractiveWindow::setPresentationMode(int presentationMode) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setPresentationMode", Q_ARG(int, presentationMode));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_qmlWindow.isNull()) {
|
||||
_qmlWindow->setProperty(PRESENTATION_MODE_PROPERTY, presentationMode);
|
||||
if (_qmlWindowProxy) {
|
||||
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, PRESENTATION_MODE_PROPERTY),
|
||||
Q_ARG(QVariant, presentationMode));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,26 @@
|
|||
#include <QtCore/QPointer>
|
||||
#include <QtScript/QScriptValue>
|
||||
#include <QQmlEngine>
|
||||
#include <ui/QmlWrapper.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
class QmlWindowProxy : public QmlWrapper {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QmlWindowProxy(QObject* qmlObject, QObject* parent = nullptr);
|
||||
|
||||
Q_INVOKABLE void parentNativeWindowToMainWindow();
|
||||
|
||||
QObject* getQmlWindow() const { return _qmlWindow; }
|
||||
private:
|
||||
QObject* _qmlWindow;
|
||||
|
||||
};
|
||||
|
||||
|
||||
namespace InteractiveWindowEnums {
|
||||
Q_NAMESPACE
|
||||
|
||||
|
@ -291,7 +307,7 @@ protected slots:
|
|||
void forwardKeyReleaseEvent(int key, int modifiers);
|
||||
|
||||
private:
|
||||
QPointer<QObject> _qmlWindow;
|
||||
std::shared_ptr<QmlWindowProxy> _qmlWindowProxy;
|
||||
std::shared_ptr<DockWidget> _dockWidget { nullptr };
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <Preferences.h>
|
||||
#include <plugins/PluginUtils.h>
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
#include <display-plugins/hmd/HmdDisplayPlugin.h>
|
||||
#include "scripting/RenderScriptingInterface.h"
|
||||
#include "Application.h"
|
||||
#include "DialogsManager.h"
|
||||
|
@ -377,6 +378,33 @@ void setupPreferences() {
|
|||
preference->setDecimals(2);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->bool {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeEnabled();
|
||||
};
|
||||
auto setter = [](bool value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeEnabled(value);
|
||||
};
|
||||
auto preference = new CheckPreference(VR_MOVEMENT, "Enable HMD Comfort Mode", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
const float sliderPositions = 5.0f;
|
||||
auto getter = [sliderPositions]()->float {
|
||||
return roundf(sliderPositions * qApp->getVisionSqueeze().getVisionSqueezeRatioX());
|
||||
};
|
||||
auto setter = [sliderPositions](float value) {
|
||||
float ratio = value / sliderPositions;
|
||||
qApp->getVisionSqueeze().setVisionSqueezeRatioX(ratio);
|
||||
qApp->getVisionSqueeze().setVisionSqueezeRatioY(ratio);
|
||||
};
|
||||
auto preference = new SpinnerSliderPreference(VR_MOVEMENT, "Comfort Mode", getter, setter);
|
||||
preference->setMin(0.0f);
|
||||
preference->setMax(sliderPositions);
|
||||
preference->setStep(1.0f);
|
||||
preference->setDecimals(0);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [myAvatar]()->bool { return myAvatar->getShowPlayArea(); };
|
||||
auto setter = [myAvatar](bool value) { myAvatar->setShowPlayArea(value); };
|
||||
|
|
|
@ -442,7 +442,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
|
||||
NSString* contentPath = [[self getDownloadPathForContentAndScripts] stringByAppendingString:@"content"];
|
||||
NSString* displayName = [ self displayName];
|
||||
NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUI/"];
|
||||
NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUIBootstrapper.js"];
|
||||
NSString* domainUrl = [[Settings sharedSettings] getDomainUrl];
|
||||
NSString* userToken = [[Launcher sharedLauncher] getTokenString];
|
||||
NSString* homeBookmark = [[NSString stringWithFormat:@"hqhome="] stringByAppendingString:domainUrl];
|
||||
|
@ -453,7 +453,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
@"--tokens", userToken,
|
||||
@"--cache", contentPath,
|
||||
@"--displayName", displayName,
|
||||
@"--scripts", scriptsPath,
|
||||
@"--defaultScriptsOverride", scriptsPath,
|
||||
@"--setBookmark", homeBookmark,
|
||||
@"--no-updater",
|
||||
@"--no-launcher", nil];
|
||||
|
@ -461,7 +461,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
arguments = [NSArray arrayWithObjects:
|
||||
@"--url" , domainUrl,
|
||||
@"--cache", contentPath,
|
||||
@"--scripts", scriptsPath,
|
||||
@"--defaultScriptsOverride", scriptsPath,
|
||||
@"--setBookmark", homeBookmark,
|
||||
@"--no-updater",
|
||||
@"--no-launcher", nil];
|
||||
|
|
|
@ -672,7 +672,7 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
|
|||
theApp._manager.addToLog(_T("Start splash screen"));
|
||||
setDrawDialog(DrawStep::DrawLogo);
|
||||
}
|
||||
} else if (_splashStep > 100) {
|
||||
} else if (_splashStep > 100 && !theApp._manager.needsToWait()) {
|
||||
_showSplash = false;
|
||||
if (theApp._manager.shouldShutDown()) {
|
||||
if (_applicationWND != NULL) {
|
||||
|
|
|
@ -24,35 +24,7 @@ LauncherManager::~LauncherManager() {
|
|||
void LauncherManager::init() {
|
||||
initLog();
|
||||
addToLog(_T("Getting most recent build"));
|
||||
CString response;
|
||||
LauncherUtils::ResponseError error = getMostRecentBuild(_latestApplicationURL, _latestVersion, response);
|
||||
if (error == LauncherUtils::ResponseError::NoError) {
|
||||
addToLog(_T("Latest version: ") + _latestVersion);
|
||||
CString currentVersion;
|
||||
if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) {
|
||||
addToLog(_T("Installed version: ") + currentVersion);
|
||||
if (_latestVersion.Compare(currentVersion) == 0) {
|
||||
addToLog(_T("Already running most recent build. Launching interface.exe"));
|
||||
_shouldLaunch = TRUE;
|
||||
_shouldShutdown = TRUE;
|
||||
} else {
|
||||
addToLog(_T("New build found. Updating"));
|
||||
_shouldUpdate = TRUE;
|
||||
}
|
||||
} else if (_loggedIn) {
|
||||
addToLog(_T("Interface not found but logged in. Reinstalling"));
|
||||
_shouldUpdate = TRUE;
|
||||
} else {
|
||||
_shouldInstall = TRUE;
|
||||
}
|
||||
} else {
|
||||
_hasFailed = true;
|
||||
CString msg;
|
||||
msg.Format(_T("Getting most recent build has failed with error: %d"), error);
|
||||
addToLog(msg);
|
||||
msg.Format(_T("Response: %s"), response);
|
||||
addToLog(msg);
|
||||
}
|
||||
getMostRecentBuild(_latestApplicationURL, _latestVersion);
|
||||
}
|
||||
|
||||
BOOL LauncherManager::initLog() {
|
||||
|
@ -387,39 +359,71 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString
|
|||
return LauncherUtils::ResponseError::ParsingJSON;
|
||||
}
|
||||
|
||||
LauncherUtils::ResponseError LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut,
|
||||
CString& response) {
|
||||
void LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut) {
|
||||
CString contentTypeJson = L"content-type:application/json";
|
||||
LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher",
|
||||
L"thunder.highfidelity.com",
|
||||
L"/builds/api/tags/latest?format=json",
|
||||
contentTypeJson, CStringA(),
|
||||
response, false);
|
||||
if (error != LauncherUtils::ResponseError::NoError) {
|
||||
return error;
|
||||
}
|
||||
Json::Value json;
|
||||
if (LauncherUtils::parseJSON(response, json)) {
|
||||
int count = json["count"].isInt() ? json["count"].asInt() : 0;
|
||||
if (count > 0 && json["results"].isArray()) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (json["results"][i].isObject()) {
|
||||
Json::Value result = json["results"][i];
|
||||
if (result["latest_version"].isInt()) {
|
||||
std::string version = std::to_string(result["latest_version"].asInt());
|
||||
versionOut = CString(version.c_str());
|
||||
}
|
||||
if (result["installers"].isObject() &&
|
||||
result["installers"]["windows"].isObject() &&
|
||||
result["installers"]["windows"]["zip_url"].isString()) {
|
||||
urlOut = result["installers"]["windows"]["zip_url"].asCString();
|
||||
return LauncherUtils::ResponseError::NoError;
|
||||
std::function<void(CString, int)> httpCallback = [&](CString response, int err) {
|
||||
LauncherUtils::ResponseError error = LauncherUtils::ResponseError(err);
|
||||
if (error == LauncherUtils::ResponseError::NoError) {
|
||||
Json::Value json;
|
||||
error = LauncherUtils::ResponseError::ParsingJSON;
|
||||
if (LauncherUtils::parseJSON(response, json)) {
|
||||
int count = json["count"].isInt() ? json["count"].asInt() : 0;
|
||||
if (count > 0 && json["results"].isArray()) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (json["results"][i].isObject()) {
|
||||
Json::Value result = json["results"][i];
|
||||
if (result["latest_version"].isInt()) {
|
||||
std::string version = std::to_string(result["latest_version"].asInt());
|
||||
versionOut = CString(version.c_str());
|
||||
}
|
||||
if (result["installers"].isObject() &&
|
||||
result["installers"]["windows"].isObject() &&
|
||||
result["installers"]["windows"]["zip_url"].isString()) {
|
||||
urlOut = result["installers"]["windows"]["zip_url"].asCString();
|
||||
error = LauncherUtils::ResponseError::NoError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onMostRecentBuildReceived(response, error);
|
||||
}
|
||||
};
|
||||
LauncherUtils::httpCallOnThread(L"HQ Launcher",
|
||||
L"thunder.highfidelity.com",
|
||||
L"/builds/api/tags/latest?format=json",
|
||||
contentTypeJson, CStringA(), false, httpCallback);
|
||||
}
|
||||
|
||||
void LauncherManager::onMostRecentBuildReceived(const CString& response, LauncherUtils::ResponseError error) {
|
||||
if (error == LauncherUtils::ResponseError::NoError) {
|
||||
addToLog(_T("Latest version: ") + _latestVersion);
|
||||
CString currentVersion;
|
||||
if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) {
|
||||
addToLog(_T("Installed version: ") + currentVersion);
|
||||
if (_latestVersion.Compare(currentVersion) == 0) {
|
||||
addToLog(_T("Already running most recent build. Launching interface.exe"));
|
||||
_shouldLaunch = TRUE;
|
||||
_shouldShutdown = TRUE;
|
||||
} else {
|
||||
addToLog(_T("New build found. Updating"));
|
||||
_shouldUpdate = TRUE;
|
||||
}
|
||||
} else if (_loggedIn) {
|
||||
addToLog(_T("Interface not found but logged in. Reinstalling"));
|
||||
_shouldUpdate = TRUE;
|
||||
} else {
|
||||
_shouldInstall = TRUE;
|
||||
}
|
||||
_shouldWait = FALSE;
|
||||
} else {
|
||||
_hasFailed = true;
|
||||
CString msg;
|
||||
msg.Format(_T("Getting most recent build has failed with error: %d"), error);
|
||||
addToLog(msg);
|
||||
msg.Format(_T("Response: %s"), response);
|
||||
addToLog(msg);
|
||||
}
|
||||
return LauncherUtils::ResponseError::ParsingJSON;
|
||||
}
|
||||
|
||||
LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString& username,
|
||||
|
@ -603,12 +607,10 @@ BOOL LauncherManager::downloadFile(ProcessType type, const CString& url, CString
|
|||
std::function<void(int, bool)> onDownloadFinished = [&](int type, bool error) {
|
||||
if (!error) {
|
||||
onFileDownloaded((ProcessType)type);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (type == ProcessType::DownloadApplication) {
|
||||
addToLog(_T("Error downloading content."));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
addToLog(_T("Error downloading application."));
|
||||
}
|
||||
_hasFailed = true;
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
BOOL isApplicationInstalled(CString& version, CString& domain,
|
||||
CString& content, bool& loggedIn);
|
||||
LauncherUtils::ResponseError getAccessTokenForCredentials(const CString& username, const CString& password);
|
||||
LauncherUtils::ResponseError getMostRecentBuild(CString& urlOut, CString& versionOut, CString& response);
|
||||
void getMostRecentBuild(CString& urlOut, CString& versionOut);
|
||||
LauncherUtils::ResponseError readOrganizationJSON(const CString& hash);
|
||||
LauncherUtils::ResponseError readConfigJSON(CString& version, CString& domain,
|
||||
CString& content, bool& loggedIn);
|
||||
|
@ -90,12 +90,13 @@ public:
|
|||
BOOL needsUpdate() { return _shouldUpdate; }
|
||||
BOOL needsUninstall() { return _shouldUninstall; }
|
||||
BOOL needsInstall() { return _shouldInstall; }
|
||||
BOOL needsToWait() { return _shouldWait; }
|
||||
void setDisplayName(const CString& displayName) { _displayName = displayName; }
|
||||
bool isLoggedIn() { return _loggedIn; }
|
||||
bool hasFailed() { return _hasFailed; }
|
||||
void setFailed(bool hasFailed) { _hasFailed = hasFailed; }
|
||||
const CString& getLatestInterfaceURL() const { return _latestApplicationURL; }
|
||||
void uninstall() { _shouldUninstall = true; };
|
||||
void uninstall() { _shouldUninstall = true; _shouldWait = false; };
|
||||
|
||||
BOOL downloadFile(ProcessType type, const CString& url, CString& localPath);
|
||||
BOOL downloadContent();
|
||||
|
@ -110,6 +111,7 @@ public:
|
|||
|
||||
private:
|
||||
ProcessType _currentProcess { ProcessType::DownloadApplication };
|
||||
void onMostRecentBuildReceived(const CString& response, LauncherUtils::ResponseError error);
|
||||
CString _latestApplicationURL;
|
||||
CString _latestVersion;
|
||||
CString _contentURL;
|
||||
|
@ -126,6 +128,7 @@ private:
|
|||
BOOL _shouldInstall { FALSE };
|
||||
BOOL _shouldShutdown { FALSE };
|
||||
BOOL _shouldLaunch { FALSE };
|
||||
BOOL _shouldWait { TRUE };
|
||||
float _progress { 0.0f };
|
||||
CStdioFile _logFile;
|
||||
};
|
||||
|
|
|
@ -470,9 +470,9 @@ BOOL LauncherUtils::hMac256(const CString& cmessage, const char* keystr, CString
|
|||
|
||||
DWORD WINAPI LauncherUtils::unzipThread(LPVOID lpParameter) {
|
||||
UnzipThreadData& data = *((UnzipThreadData*)lpParameter);
|
||||
uint64_t size = LauncherUtils::extractZip(data._zipFile, data._path, std::vector<std::string>(), data.progressCallback);
|
||||
uint64_t size = LauncherUtils::extractZip(data._zipFile, data._path, std::vector<std::string>(), data._progressCallback);
|
||||
int mb_size = (int)(size * 0.001f);
|
||||
data.callback(data._type, mb_size);
|
||||
data._callback(data._type, mb_size);
|
||||
delete &data;
|
||||
return 0;
|
||||
}
|
||||
|
@ -480,17 +480,26 @@ DWORD WINAPI LauncherUtils::unzipThread(LPVOID lpParameter) {
|
|||
DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter) {
|
||||
DownloadThreadData& data = *((DownloadThreadData*)lpParameter);
|
||||
ProgressCallback progressCallback;
|
||||
progressCallback.setProgressCallback(data.progressCallback);
|
||||
progressCallback.setProgressCallback(data._progressCallback);
|
||||
auto hr = URLDownloadToFile(0, data._url, data._file, 0,
|
||||
static_cast<LPBINDSTATUSCALLBACK>(&progressCallback));
|
||||
data.callback(data._type, hr != S_OK);
|
||||
data._callback(data._type, hr != S_OK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WINAPI LauncherUtils::deleteDirectoryThread(LPVOID lpParameter) {
|
||||
DeleteThreadData& data = *((DeleteThreadData*)lpParameter);
|
||||
BOOL success = LauncherUtils::deleteFileOrDirectory(data._dirPath);
|
||||
data.callback(!success);
|
||||
data._callback(!success);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WINAPI LauncherUtils::httpThread(LPVOID lpParameter) {
|
||||
HttpThreadData& data = *((HttpThreadData*)lpParameter);
|
||||
CString response;
|
||||
auto error = LauncherUtils::makeHTTPCall(data._callerName, data._mainUrl, data._dirUrl,
|
||||
data._contentType, data._postData, response, data._isPost);
|
||||
data._callback(response, error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -543,6 +552,26 @@ BOOL LauncherUtils::deleteDirectoryOnThread(const CString& dirPath, std::functio
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LauncherUtils::httpCallOnThread(const CString& callerName, const CString& mainUrl, const CString& dirUrl,
|
||||
const CString& contentType, CStringA& postData, bool isPost,
|
||||
std::function<void(CString, int)> callback) {
|
||||
DWORD myThreadID;
|
||||
HttpThreadData* httpThreadData = new HttpThreadData();
|
||||
httpThreadData->_callerName = callerName;
|
||||
httpThreadData->_mainUrl = mainUrl;
|
||||
httpThreadData->_dirUrl = dirUrl;
|
||||
httpThreadData->_contentType = contentType;
|
||||
httpThreadData->_postData = postData;
|
||||
httpThreadData->_isPost = isPost;
|
||||
httpThreadData->setCallback(callback);
|
||||
HANDLE myHandle = CreateThread(0, 0, httpThread, httpThreadData, 0, &myThreadID);
|
||||
if (myHandle) {
|
||||
CloseHandle(myHandle);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HWND LauncherUtils::executeOnForeground(const CString& path, const CString& params) {
|
||||
SHELLEXECUTEINFO info;
|
||||
info.cbSize = sizeof(SHELLEXECUTEINFO);
|
||||
|
|
|
@ -55,15 +55,15 @@ public:
|
|||
ULONG ulStatusCode, LPCWSTR szStatusText) {
|
||||
float progress = (float)ulProgress / ulProgressMax;
|
||||
if (!isnan(progress)) {
|
||||
onProgressCallback(progress);
|
||||
_onProgressCallback(progress);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
void setProgressCallback(std::function<void(float)> fn) {
|
||||
onProgressCallback = std::bind(fn, std::placeholders::_1);
|
||||
_onProgressCallback = std::bind(fn, std::placeholders::_1);
|
||||
}
|
||||
private:
|
||||
std::function<void(float)> onProgressCallback;
|
||||
std::function<void(float)> _onProgressCallback;
|
||||
};
|
||||
|
||||
enum ResponseError {
|
||||
|
@ -82,14 +82,14 @@ public:
|
|||
int _type;
|
||||
CString _url;
|
||||
CString _file;
|
||||
std::function<void(int, bool)> callback;
|
||||
std::function<void(float)> progressCallback;
|
||||
std::function<void(int, bool)> _callback;
|
||||
std::function<void(float)> _progressCallback;
|
||||
// function(type, errorType)
|
||||
void setCallback(std::function<void(int, bool)> fn) {
|
||||
callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
|
||||
_callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
void setProgressCallback(std::function<void(float)> fn) {
|
||||
progressCallback = std::bind(fn, std::placeholders::_1);
|
||||
_progressCallback = std::bind(fn, std::placeholders::_1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -98,23 +98,36 @@ public:
|
|||
std::string _zipFile;
|
||||
std::string _path;
|
||||
// function(type, size)
|
||||
std::function<void(int, int)> callback;
|
||||
std::function<void(float)> progressCallback;
|
||||
std::function<void(int, int)> _callback;
|
||||
std::function<void(float)> _progressCallback;
|
||||
void setCallback(std::function<void(int, int)> fn) {
|
||||
callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
|
||||
_callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
void setProgressCallback(std::function<void(float)> fn) {
|
||||
progressCallback = std::bind(fn, std::placeholders::_1);
|
||||
_progressCallback = std::bind(fn, std::placeholders::_1);
|
||||
}
|
||||
};
|
||||
|
||||
struct DeleteThreadData {
|
||||
CString _dirPath;
|
||||
std::function<void(bool)> callback;
|
||||
std::function<void(float)> progressCallback;
|
||||
void setCallback(std::function<void(bool)> fn) { callback = std::bind(fn, std::placeholders::_1); }
|
||||
std::function<void(bool)> _callback;
|
||||
std::function<void(float)> _progressCallback;
|
||||
void setCallback(std::function<void(bool)> fn) { _callback = std::bind(fn, std::placeholders::_1); }
|
||||
void setProgressCallback(std::function<void(float)> fn) {
|
||||
progressCallback = std::bind(fn, std::placeholders::_1);
|
||||
_progressCallback = std::bind(fn, std::placeholders::_1);
|
||||
}
|
||||
};
|
||||
|
||||
struct HttpThreadData {
|
||||
CString _callerName;
|
||||
CString _mainUrl;
|
||||
CString _dirUrl;
|
||||
CString _contentType;
|
||||
CStringA _postData;
|
||||
bool _isPost { false };
|
||||
std::function<void(CString, int)> _callback;
|
||||
void setCallback(std::function<void(CString, int)> fn) {
|
||||
_callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -150,6 +163,9 @@ public:
|
|||
std::function<void(int, bool)> callback,
|
||||
std::function<void(float)> progressCallback);
|
||||
static BOOL deleteDirectoryOnThread(const CString& dirPath, std::function<void(bool)> callback);
|
||||
static BOOL httpCallOnThread(const CString& callerName, const CString& mainUrl, const CString& dirUrl,
|
||||
const CString& contentType, CStringA& postData, bool isPost,
|
||||
std::function<void(CString, int)> callback);
|
||||
|
||||
static CString urlEncodeString(const CString& url);
|
||||
static HWND executeOnForeground(const CString& path, const CString& params);
|
||||
|
@ -159,4 +175,5 @@ private:
|
|||
static DWORD WINAPI unzipThread(LPVOID lpParameter);
|
||||
static DWORD WINAPI downloadThread(LPVOID lpParameter);
|
||||
static DWORD WINAPI deleteDirectoryThread(LPVOID lpParameter);
|
||||
};
|
||||
static DWORD WINAPI httpThread(LPVOID lpParameter);
|
||||
};
|
||||
|
|
|
@ -431,7 +431,6 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const
|
|||
constrained = constraint->apply(tipRelativeRotation);
|
||||
if (constrained) {
|
||||
tipOrientation = tipParentOrientation * tipRelativeRotation;
|
||||
tipRelativeRotation = tipRelativeRotation;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,5 +47,9 @@ void AbstractHMDScriptingInterface::setIPDScale(float IPDScale) {
|
|||
}
|
||||
|
||||
bool AbstractHMDScriptingInterface::isHMDMode() const {
|
||||
return PluginContainer::getInstance().getActiveDisplayPlugin()->isHmd();
|
||||
}
|
||||
auto displayPlugin = PluginContainer::getInstance().getActiveDisplayPlugin();
|
||||
if (displayPlugin) {
|
||||
return displayPlugin->isHmd();
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawTextureWithVisionSqueeze.frag
|
||||
//
|
||||
// Draw texture 0 fetched at texcoord.xy
|
||||
//
|
||||
// Created by Seth Alves on 2019-2-15
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include display-plugins/VisionSqueeze.slh@>
|
||||
|
||||
struct DrawTextureWithVisionSqueezeParams {
|
||||
float _visionSqueezeX;
|
||||
float _visionSqueezeY;
|
||||
float _spareA;
|
||||
float _spareB;
|
||||
mat4 _leftProjection;
|
||||
mat4 _rightProjection;
|
||||
mat4 _hmdSensorMatrix;
|
||||
float _visionSqueezeTransition;
|
||||
int _visionSqueezePerEye;
|
||||
float _visionSqueezeGroundPlaneY;
|
||||
float _visionSqueezeSpotlightSize;
|
||||
};
|
||||
|
||||
|
||||
LAYOUT(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
// binding=1 must match drawTextureWithSqueezeParamsSlot in OpenGLDisplayPlugin.h
|
||||
LAYOUT(binding=1) uniform drawTextureWithSqueezeMappingParamsBuffer {
|
||||
DrawTextureWithVisionSqueezeParams params;
|
||||
};
|
||||
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
|
||||
float getVisionSqueezeX() {
|
||||
return params._visionSqueezeX;
|
||||
}
|
||||
float getVisionSqueezeY() {
|
||||
return params._visionSqueezeY;
|
||||
}
|
||||
float getVisionSqueezeTransitionRatio() {
|
||||
return params._visionSqueezeTransition;
|
||||
}
|
||||
int getVisionSqueezePerEye() {
|
||||
return params._visionSqueezePerEye;
|
||||
}
|
||||
float getVisionSqueezeGroundPlaneY() {
|
||||
return params._visionSqueezeGroundPlaneY;
|
||||
}
|
||||
float getVisionSqueezeSpotlightSize() {
|
||||
return params._visionSqueezeSpotlightSize;
|
||||
}
|
||||
mat4 getProjectionMatrix(float eye) {
|
||||
if (eye == 0.0) {
|
||||
return params._leftProjection;
|
||||
} else {
|
||||
return params._rightProjection;
|
||||
}
|
||||
}
|
||||
mat4 getHMDSensorMatrix() {
|
||||
return params._hmdSensorMatrix;
|
||||
}
|
||||
|
||||
|
||||
void main(void) {
|
||||
|
||||
float side = float(varTexCoord0.x > 0.5);
|
||||
mat4 leftProjectionMatrix = getProjectionMatrix(0.0);
|
||||
vec4 fovTan = extractFovTan(leftProjectionMatrix);
|
||||
vec2 focalPointNDC = extractFocalPoint(fovTan);
|
||||
focalPointNDC.x -= 2.0 * focalPointNDC.x * (1.0 - side);
|
||||
vec2 focalPointUV = 0.5 * (focalPointNDC + vec2(1.0));
|
||||
|
||||
// block edges of vision to avoid sickness
|
||||
vec2 visionSqueezeRatios = vec2(getVisionSqueezeX(), getVisionSqueezeY());
|
||||
bool perEye = getVisionSqueezePerEye() > 0;
|
||||
float frac = squeezeVision(perEye, varTexCoord0, visionSqueezeRatios, getVisionSqueezeTransitionRatio(), focalPointUV);
|
||||
|
||||
if (frac == 0.0) {
|
||||
// world only
|
||||
outFragColor = texture(colorMap, varTexCoord0);
|
||||
} else {
|
||||
// grid on the floor only or mixed
|
||||
mat4 hmdSensorMatrix = getHMDSensorMatrix();
|
||||
mat4 projectionMatrix = getProjectionMatrix(side);
|
||||
mat4 projectionInverse = inverse(projectionMatrix);
|
||||
float groundPlaneY = getVisionSqueezeGroundPlaneY();
|
||||
float spotLightSize = getVisionSqueezeSpotlightSize();
|
||||
vec4 gridColor = vec4(gridFloor(varTexCoord0, hmdSensorMatrix, projectionInverse, groundPlaneY, spotLightSize), 1.0);
|
||||
|
||||
vec4 preSqueezeColor = texture(colorMap, varTexCoord0);
|
||||
// mix between grid and world
|
||||
outFragColor = mix(preSqueezeColor, gridColor, frac);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
VERTEX gpu::vertex::DrawUnitQuadTexcoord
|
|
@ -392,6 +392,9 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
|
||||
_drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState);
|
||||
|
||||
_drawTextureSqueezePipeline =
|
||||
gpu::Pipeline::create(gpu::Shader::createProgram(shader::display_plugins::program::DrawTextureWithVisionSqueeze), scissorState);
|
||||
|
||||
_linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureLinearToSRGB), scissorState);
|
||||
|
||||
_SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureSRGBToLinear), scissorState);
|
||||
|
@ -407,6 +410,7 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
void OpenGLDisplayPlugin::uncustomizeContext() {
|
||||
|
||||
_drawTexturePipeline.reset();
|
||||
_drawTextureSqueezePipeline.reset();
|
||||
_linearToSRGBPipeline.reset();
|
||||
_SRGBToLinearPipeline.reset();
|
||||
_cursorPipeline.reset();
|
||||
|
@ -629,6 +633,10 @@ void OpenGLDisplayPlugin::compositePointer() {
|
|||
});
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::setupCompositeScenePipeline(gpu::Batch& batch) {
|
||||
batch.setPipeline(_drawTexturePipeline);
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::compositeScene() {
|
||||
render([&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
|
@ -637,8 +645,8 @@ void OpenGLDisplayPlugin::compositeScene() {
|
|||
batch.setStateScissorRect(ivec4(uvec2(), _compositeFramebuffer->getSize()));
|
||||
batch.resetViewTransform();
|
||||
batch.setProjectionTransform(mat4());
|
||||
batch.setPipeline(_drawTexturePipeline);
|
||||
batch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0));
|
||||
setupCompositeScenePipeline(batch);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
});
|
||||
}
|
||||
|
@ -958,4 +966,3 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne
|
|||
gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() {
|
||||
return _drawTexturePipeline;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ protected:
|
|||
|
||||
virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; }
|
||||
virtual void compositeLayers();
|
||||
virtual void setupCompositeScenePipeline(gpu::Batch& batch);
|
||||
virtual void compositeScene();
|
||||
virtual void compositePointer();
|
||||
virtual void compositeExtra(){};
|
||||
|
@ -155,6 +156,7 @@ protected:
|
|||
gpu::PipelinePointer _mirrorHUDPipeline;
|
||||
gpu::ShaderPointer _mirrorHUDPS;
|
||||
gpu::PipelinePointer _drawTexturePipeline;
|
||||
gpu::PipelinePointer _drawTextureSqueezePipeline;
|
||||
gpu::PipelinePointer _linearToSRGBPipeline;
|
||||
gpu::PipelinePointer _SRGBToLinearPipeline;
|
||||
gpu::PipelinePointer _cursorPipeline;
|
||||
|
|
106
libraries/display-plugins/src/display-plugins/VisionSqueeze.slh
Normal file
106
libraries/display-plugins/src/display-plugins/VisionSqueeze.slh
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Created by Seth Alves on 2019-2-13.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@if not VISION_SQUEEZE_SLH@>
|
||||
<@def VISION_SQUEEZE_SLH@>
|
||||
|
||||
|
||||
float ellipse(vec2 coord, vec2 centerUV, vec2 semiAxis) {
|
||||
return pow(coord.x - centerUV.x, 2.0) / semiAxis.x + pow(coord.y - centerUV.y, 2.0) / semiAxis.y;
|
||||
}
|
||||
|
||||
vec4 extractFovTan(mat4 m) {
|
||||
mat4 mt = transpose(m);
|
||||
vec4 v;
|
||||
vec4 result;
|
||||
|
||||
// x -- Left
|
||||
v = mt * vec4(1.0, 0.0, 0.0, 1.0);
|
||||
result.x = -(v.z / v.x);
|
||||
// y -- Right
|
||||
v = mt * vec4(-1.0, 0.0, 0.0, 1.0);
|
||||
result.y = (v.z / v.x);
|
||||
// z -- Down
|
||||
v = mt * vec4(0.0, 1.0, 0.0, 1.0);
|
||||
result.z = -(v.z / v.y);
|
||||
// w -- Up
|
||||
v = mt * vec4(0.0, -1.0, 0.0, 1.0);
|
||||
result.w = v.z / v.y;
|
||||
return result;
|
||||
}
|
||||
|
||||
// takes left-side projection matrix, returns NDC for right eye. to get left, invert sign on x coord of result.
|
||||
vec2 extractFocalPoint(vec4 fovTan) {
|
||||
float fovwidth = fovTan.x + fovTan.y;
|
||||
float fovheight = fovTan.z + fovTan.w;
|
||||
vec2 focalPoint = vec2(fovTan.y / fovwidth, (fovTan.z / fovheight) - 0.5f);
|
||||
return focalPoint;
|
||||
}
|
||||
|
||||
float squeezeVision(bool perEye, vec2 varTexCoord0, vec2 visionSqueezeRatios, float transitionRatio, vec2 focalPointUV) {
|
||||
if (visionSqueezeRatios.x == 0.0 && visionSqueezeRatios.y == 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
vec2 centerUV;
|
||||
vec2 semiAxis;
|
||||
if (perEye) {
|
||||
// tubes in front of each eye
|
||||
centerUV = focalPointUV;
|
||||
semiAxis = vec2(0.25) - visionSqueezeRatios * 0.25;
|
||||
} else {
|
||||
// one tube in front of face
|
||||
centerUV = vec2(0.5, focalPointUV.y);
|
||||
semiAxis = vec2(0.5) - visionSqueezeRatios * 0.5;
|
||||
}
|
||||
float ellipseValue = ellipse(varTexCoord0, centerUV, semiAxis);
|
||||
float frac = clamp((ellipseValue - 1.0) / clamp(transitionRatio, 0.01, 0.7), 0.0, 1.0);
|
||||
|
||||
return frac;
|
||||
}
|
||||
|
||||
vec3 gridFloor(vec2 varTexCoord0, mat4 hmdSensorMatrix, mat4 projectionInverse, float groundPlaneY, float spotLightSize) {
|
||||
vec4 ndc = vec4(varTexCoord0.x * 4.0 - 1.0 - 2.0 * float(varTexCoord0.x > 0.5), varTexCoord0.y * 2.0 - 1.0, -1.0, 1.0);
|
||||
|
||||
vec4 fragmentEyeCoords = hmdSensorMatrix * projectionInverse * ndc;
|
||||
vec4 near4 = hmdSensorMatrix * vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
vec3 near = (near4 / near4.w).xyz;
|
||||
vec3 far = fragmentEyeCoords.xyz / fragmentEyeCoords.w;
|
||||
|
||||
// intersect a line from near to far with the plane y = groundPlaneY
|
||||
float t = -(near.y - groundPlaneY) / (far.y - near.y);
|
||||
vec2 R = (near + t * (far - near)).xz;
|
||||
|
||||
float lineThickness = 1.5 / length(R);
|
||||
vec4 gridColor = vec4(0.35);
|
||||
vec4 baseColor = vec4(0.1);
|
||||
vec4 skyColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec2 wrapped = fract(R) - 0.5f;
|
||||
vec2 range = abs(wrapped);
|
||||
vec2 speeds = fwidth(R);
|
||||
vec2 pixelRange = range/speeds;
|
||||
float lineWeight = clamp(min(pixelRange.x, pixelRange.y) - lineThickness, 0.0, 1.0);
|
||||
|
||||
float horizonFuzz = 0.02;
|
||||
if (t < 0.0) {
|
||||
return mix(gridColor, skyColor, clamp(0.0, 1.0, -t)).xyz;
|
||||
} else if (t < horizonFuzz) {
|
||||
lineWeight = lineWeight * max(0.0, t);
|
||||
}
|
||||
|
||||
vec4 c = mix(gridColor, baseColor, lineWeight);
|
||||
|
||||
// fade out grid to avoid shimmer
|
||||
float fadeVal = 0.7;
|
||||
return mix(c, baseColor * fadeVal + gridColor * (1.0 - fadeVal),
|
||||
0.1 * clamp((length(R) - spotLightSize), 0.0, 1.0)).xyz;
|
||||
}
|
||||
|
||||
<@endif@>
|
|
@ -1,4 +1,4 @@
|
|||
//
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2016/02/15
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -113,6 +113,11 @@ void HmdDisplayPlugin::internalDeactivate() {
|
|||
}
|
||||
|
||||
void HmdDisplayPlugin::customizeContext() {
|
||||
|
||||
VisionSqueezeParameters parameters;
|
||||
_visionSqueezeParametersBuffer =
|
||||
gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(VisionSqueezeParameters), (const gpu::Byte*) ¶meters));
|
||||
|
||||
Parent::customizeContext();
|
||||
_hudRenderer.build();
|
||||
}
|
||||
|
@ -478,3 +483,48 @@ HmdDisplayPlugin::~HmdDisplayPlugin() {
|
|||
float HmdDisplayPlugin::stutterRate() const {
|
||||
return _stutterRate.rate();
|
||||
}
|
||||
|
||||
float adjustVisionSqueezeRatioForDevice(float visionSqueezeRatio, float visionSqueezeDeviceLow, float visionSqueezeDeviceHigh) {
|
||||
if (visionSqueezeRatio <= 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float deviceRange = visionSqueezeDeviceHigh - visionSqueezeDeviceLow;
|
||||
const float SQUEEZE_ADJUSTMENT = 0.75f; // magic number picked through experimentation
|
||||
return deviceRange * (SQUEEZE_ADJUSTMENT * visionSqueezeRatio) + visionSqueezeDeviceLow;
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY,
|
||||
float visionSqueezeTransition,
|
||||
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
||||
float visionSqueezeSpotlightSize) {
|
||||
|
||||
visionSqueezeX = adjustVisionSqueezeRatioForDevice(visionSqueezeX, _visionSqueezeDeviceLowX, _visionSqueezeDeviceHighX);
|
||||
visionSqueezeY = adjustVisionSqueezeRatioForDevice(visionSqueezeY, _visionSqueezeDeviceLowY, _visionSqueezeDeviceHighY);
|
||||
|
||||
auto& params = _visionSqueezeParametersBuffer.get<VisionSqueezeParameters>();
|
||||
if (params._visionSqueezeX != visionSqueezeX) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeX = visionSqueezeX;
|
||||
}
|
||||
if (params._visionSqueezeY != visionSqueezeY) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeY = visionSqueezeY;
|
||||
}
|
||||
if (params._visionSqueezeTransition != visionSqueezeTransition) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeTransition = visionSqueezeTransition;
|
||||
}
|
||||
if (params._visionSqueezePerEye != visionSqueezePerEye) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezePerEye = visionSqueezePerEye;
|
||||
}
|
||||
if (params._visionSqueezeGroundPlaneY != visionSqueezeGroundPlaneY) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeGroundPlaneY = visionSqueezeGroundPlaneY;
|
||||
}
|
||||
if (params._visionSqueezeSpotlightSize != visionSqueezeSpotlightSize) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeSpotlightSize = visionSqueezeSpotlightSize;
|
||||
}
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::setupCompositeScenePipeline(gpu::Batch& batch) {
|
||||
batch.setPipeline(_drawTextureSqueezePipeline);
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._hmdSensorMatrix = _currentPresentFrameInfo.presentPose;
|
||||
batch.setUniformBuffer(drawTextureWithVisionSqueezeParamsSlot, _visionSqueezeParametersBuffer);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,9 @@ public:
|
|||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator() override;
|
||||
virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::PAINT; }
|
||||
void updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
|
||||
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
||||
float visionSqueezeSpotlightSize);
|
||||
|
||||
signals:
|
||||
void hmdMountedChanged();
|
||||
|
@ -91,6 +94,33 @@ protected:
|
|||
RateCounter<> _stutterRate;
|
||||
|
||||
bool _disablePreview { true };
|
||||
|
||||
class VisionSqueezeParameters {
|
||||
public:
|
||||
float _visionSqueezeX { 0.0f };
|
||||
float _visionSqueezeY { 0.0f };
|
||||
float _spareA { 0.0f };
|
||||
float _spareB { 0.0f };
|
||||
glm::mat4 _leftProjection;
|
||||
glm::mat4 _rightProjection;
|
||||
glm::mat4 _hmdSensorMatrix;
|
||||
float _visionSqueezeTransition { 0.15f };
|
||||
int _visionSqueezePerEye { 0 };
|
||||
float _visionSqueezeGroundPlaneY { 0.0f };
|
||||
float _visionSqueezeSpotlightSize { 0.0f };
|
||||
|
||||
VisionSqueezeParameters() {}
|
||||
};
|
||||
typedef gpu::BufferView UniformBufferView;
|
||||
gpu::BufferView _visionSqueezeParametersBuffer;
|
||||
|
||||
virtual void setupCompositeScenePipeline(gpu::Batch& batch) override;
|
||||
|
||||
float _visionSqueezeDeviceLowX { 0.0f };
|
||||
float _visionSqueezeDeviceHighX { 1.0f };
|
||||
float _visionSqueezeDeviceLowY { 0.0f };
|
||||
float _visionSqueezeDeviceHighY { 1.0f };
|
||||
|
||||
private:
|
||||
ivec4 getViewportForSourceSize(const uvec2& size) const;
|
||||
float getLeftCenterPixel() const;
|
||||
|
@ -112,7 +142,7 @@ private:
|
|||
struct Uniforms {
|
||||
float alpha { 1.0f };
|
||||
} uniforms;
|
||||
|
||||
|
||||
struct Vertex {
|
||||
vec3 pos;
|
||||
vec2 uv;
|
||||
|
@ -126,3 +156,5 @@ private:
|
|||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> render();
|
||||
} _hudRenderer;
|
||||
};
|
||||
|
||||
const int drawTextureWithVisionSqueezeParamsSlot = 1; // must match binding in DrawTextureWithVisionSqueeze.slf
|
||||
|
|
|
@ -122,7 +122,7 @@ void GridEntityRenderer::doRender(RenderArgs* args) {
|
|||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
});
|
||||
|
||||
if (!_visible) {
|
||||
if (!_visible || color.a == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -282,27 +282,26 @@ bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3
|
|||
}
|
||||
|
||||
void RenderableModelEntityItem::fetchCollisionGeometryResource() {
|
||||
_compoundShapeResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(getCollisionShapeURL());
|
||||
_collisionGeometryResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(getCollisionShapeURL());
|
||||
}
|
||||
|
||||
bool RenderableModelEntityItem::computeShapeFailedToLoad() {
|
||||
if (!_compoundShapeResource) {
|
||||
bool RenderableModelEntityItem::unableToLoadCollisionShape() {
|
||||
if (!_collisionGeometryResource) {
|
||||
fetchCollisionGeometryResource();
|
||||
}
|
||||
|
||||
return (_compoundShapeResource && _compoundShapeResource->isFailed());
|
||||
return (_collisionGeometryResource && _collisionGeometryResource->isFailed());
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::setShapeType(ShapeType type) {
|
||||
ModelEntityItem::setShapeType(type);
|
||||
auto shapeType = getShapeType();
|
||||
if (shapeType == SHAPE_TYPE_COMPOUND || shapeType == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
if (!_compoundShapeResource && !getCollisionShapeURL().isEmpty()) {
|
||||
if (!_collisionGeometryResource && !getCollisionShapeURL().isEmpty()) {
|
||||
fetchCollisionGeometryResource();
|
||||
}
|
||||
} else if (_compoundShapeResource && !getCompoundShapeURL().isEmpty()) {
|
||||
} else if (_collisionGeometryResource && !getCompoundShapeURL().isEmpty()) {
|
||||
// the compoundURL has been set but the shapeType does not agree
|
||||
_compoundShapeResource.reset();
|
||||
_collisionGeometryResource.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,11 +332,11 @@ bool RenderableModelEntityItem::isReadyToComputeShape() const {
|
|||
}
|
||||
|
||||
if (model->isLoaded()) {
|
||||
if (!shapeURL.isEmpty() && !_compoundShapeResource) {
|
||||
if (!shapeURL.isEmpty() && !_collisionGeometryResource) {
|
||||
const_cast<RenderableModelEntityItem*>(this)->fetchCollisionGeometryResource();
|
||||
}
|
||||
|
||||
if (_compoundShapeResource && _compoundShapeResource->isLoaded()) {
|
||||
if (_collisionGeometryResource && _collisionGeometryResource->isLoaded()) {
|
||||
// we have both URLs AND both geometries AND they are both fully loaded.
|
||||
if (_needsInitialSimulation) {
|
||||
// the _model's offset will be wrong until _needsInitialSimulation is false
|
||||
|
@ -368,7 +367,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
}
|
||||
|
||||
if (type == SHAPE_TYPE_COMPOUND) {
|
||||
if (!_compoundShapeResource || !_compoundShapeResource->isLoaded()) {
|
||||
if (!_collisionGeometryResource || !_collisionGeometryResource->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -376,8 +375,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
|
||||
// should never fall in here when collision model not fully loaded
|
||||
// TODO: assert that all geometries exist and are loaded
|
||||
//assert(_model && _model->isLoaded() && _compoundShapeResource && _compoundShapeResource->isLoaded());
|
||||
const HFMModel& collisionGeometry = _compoundShapeResource->getHFMModel();
|
||||
//assert(_model && _model->isLoaded() && _collisionGeometryResource && _collisionGeometryResource->isLoaded());
|
||||
const HFMModel& collisionGeometry = _collisionGeometryResource->getHFMModel();
|
||||
|
||||
ShapeInfo::PointCollection& pointCollection = shapeInfo.getPointCollection();
|
||||
pointCollection.clear();
|
||||
|
@ -499,7 +498,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
|
||||
std::vector<std::shared_ptr<const graphics::Mesh>> meshes;
|
||||
if (type == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
auto& hfmMeshes = _compoundShapeResource->getHFMModel().meshes;
|
||||
auto& hfmMeshes = _collisionGeometryResource->getHFMModel().meshes;
|
||||
meshes.reserve(hfmMeshes.size());
|
||||
for (auto& hfmMesh : hfmMeshes) {
|
||||
meshes.push_back(hfmMesh._mesh);
|
||||
|
@ -727,10 +726,10 @@ int RenderableModelEntityItem::avatarJointIndex(int modelJointIndex) {
|
|||
|
||||
bool RenderableModelEntityItem::contains(const glm::vec3& point) const {
|
||||
auto model = getModel();
|
||||
if (EntityItem::contains(point) && model && _compoundShapeResource && _compoundShapeResource->isLoaded()) {
|
||||
if (EntityItem::contains(point) && model && _collisionGeometryResource && _collisionGeometryResource->isLoaded()) {
|
||||
glm::mat4 worldToHFMMatrix = model->getWorldToHFMMatrix();
|
||||
glm::vec3 hfmPoint = worldToHFMMatrix * glm::vec4(point, 1.0f);
|
||||
return _compoundShapeResource->getHFMModel().convexHullContains(hfmPoint);
|
||||
return _collisionGeometryResource->getHFMModel().convexHullContains(hfmPoint);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
|
||||
virtual bool isReadyToComputeShape() const override;
|
||||
virtual void computeShapeInfo(ShapeInfo& shapeInfo) override;
|
||||
bool computeShapeFailedToLoad();
|
||||
bool unableToLoadCollisionShape();
|
||||
|
||||
virtual bool contains(const glm::vec3& point) const override;
|
||||
void stopModelOverrideIfNoParent();
|
||||
|
@ -120,7 +120,7 @@ private:
|
|||
bool readyToAnimate() const;
|
||||
void fetchCollisionGeometryResource();
|
||||
|
||||
GeometryResource::Pointer _compoundShapeResource;
|
||||
GeometryResource::Pointer _collisionGeometryResource;
|
||||
std::vector<int> _jointMap;
|
||||
QVariantMap _originalTextures;
|
||||
bool _jointMapCompleted { false };
|
||||
|
|
|
@ -23,7 +23,7 @@ static uint8_t CUSTOM_PIPELINE_NUMBER = 0;
|
|||
static gpu::Stream::FormatPointer _vertexFormat;
|
||||
static std::weak_ptr<gpu::Pipeline> _texturedPipeline;
|
||||
|
||||
static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) {
|
||||
static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) {
|
||||
auto texturedPipeline = _texturedPipeline.lock();
|
||||
if (!texturedPipeline) {
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
|
|
|
@ -34,9 +34,7 @@
|
|||
|
||||
#include "EntityTreeRenderer.h"
|
||||
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
# include <FadeEffect.h>
|
||||
#endif
|
||||
#include <FadeEffect.h>
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -1553,52 +1551,49 @@ using namespace render;
|
|||
using namespace render::entities;
|
||||
|
||||
static uint8_t CUSTOM_PIPELINE_NUMBER;
|
||||
static gpu::PipelinePointer _pipelines[2];
|
||||
static gpu::PipelinePointer _wireframePipelines[2];
|
||||
static std::map<std::tuple<bool, bool, bool>, ShapePipelinePointer> _pipelines;
|
||||
static gpu::Stream::FormatPointer _vertexFormat;
|
||||
|
||||
ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) {
|
||||
if (!_pipelines[0]) {
|
||||
ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, RenderArgs* args) {
|
||||
// FIXME: custom pipelines like this don't handle shadows or renderLayers correctly
|
||||
|
||||
if (_pipelines.empty()) {
|
||||
using namespace shader::entities_renderer::program;
|
||||
int programsIds[2] = { polyvox, polyvox_fade };
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
|
||||
std::make_tuple(false, false, polyvox), std::make_tuple(true, false, polyvox_forward)
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
, std::make_tuple(false, true, polyvox_fade), std::make_tuple(true, true, polyvox_forward_fade)
|
||||
#else
|
||||
, std::make_tuple(false, true, polyvox), std::make_tuple(true, true, polyvox_forward)
|
||||
#endif
|
||||
};
|
||||
for (auto& key : keys) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
bool wireframe = i != 0;
|
||||
|
||||
auto wireframeState = std::make_shared<gpu::State>();
|
||||
wireframeState->setCullMode(gpu::State::CULL_BACK);
|
||||
wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
wireframeState->setFillMode(gpu::State::FILL_LINE);
|
||||
PrepareStencil::testMaskDrawShape(*wireframeState);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
|
||||
// Two sets of pipelines: normal and fading
|
||||
for (auto i = 0; i < 2; i++) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(programsIds[i]);
|
||||
_pipelines[i] = gpu::Pipeline::create(program, state);
|
||||
_wireframePipelines[i] = gpu::Pipeline::create(program, wireframeState);
|
||||
if (wireframe) {
|
||||
state->setFillMode(gpu::State::FILL_LINE);
|
||||
}
|
||||
|
||||
auto pipeline = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<2>(key)), state);
|
||||
if (std::get<1>(key)) {
|
||||
_pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared<render::ShapePipeline>(pipeline, nullptr, nullptr, nullptr);
|
||||
} else {
|
||||
const auto& fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
_pipelines[std::make_tuple(std::get<0>(key), std::get<1>(key), wireframe)] = std::make_shared<render::ShapePipeline>(pipeline, nullptr,
|
||||
fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
if (key.isFaded()) {
|
||||
const auto& fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
if (key.isWireframe()) {
|
||||
return std::make_shared<render::ShapePipeline>(_wireframePipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
|
||||
} else {
|
||||
return std::make_shared<render::ShapePipeline>(_pipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
if (key.isWireframe()) {
|
||||
return std::make_shared<render::ShapePipeline>(_wireframePipelines[0], nullptr, nullptr, nullptr);
|
||||
} else {
|
||||
return std::make_shared<render::ShapePipeline>(_pipelines[0], nullptr, nullptr, nullptr);
|
||||
}
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
}
|
||||
#endif
|
||||
return _pipelines[std::make_tuple(args->_renderMethod == Args::RenderMethod::FORWARD, key.isFaded(), key.isWireframe())];
|
||||
}
|
||||
|
||||
PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
||||
|
|
|
@ -30,14 +30,11 @@ using namespace render::entities;
|
|||
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
||||
static const float SPHERE_ENTITY_SCALE = 0.5f;
|
||||
|
||||
static_assert(shader::render_utils::program::simple != 0, "Validate simple program exists");
|
||||
static_assert(shader::render_utils::program::simple_transparent != 0, "Validate simple transparent program exists");
|
||||
|
||||
ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
||||
_procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple);
|
||||
_procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural);
|
||||
// FIXME: Setup proper uniform slots and use correct pipelines for forward rendering
|
||||
_procedural._opaqueFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple);
|
||||
_procedural._transparentFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_transparent);
|
||||
_procedural._opaqueFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_procedural);
|
||||
_procedural._transparentFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_procedural_translucent);
|
||||
|
||||
// TODO: move into Procedural.cpp
|
||||
PrepareStencil::testMaskDrawShape(*_procedural._opaqueState);
|
||||
|
|
|
@ -315,12 +315,19 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
|
|||
gpu::Batch& batch = *args->_batch;
|
||||
glm::vec4 color;
|
||||
Transform transform;
|
||||
bool forward;
|
||||
withReadLock([&] {
|
||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
color = glm::vec4(toGlm(_color), _alpha * fadeRatio);
|
||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
transform = _renderTransform;
|
||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD;
|
||||
});
|
||||
|
||||
if (color.a == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
batch.setResourceTexture(0, _texture);
|
||||
|
||||
transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition()));
|
||||
|
@ -328,7 +335,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
// Turn off jitter for these entities
|
||||
batch.pushProjectionJitter();
|
||||
DependencyManager::get<GeometryCache>()->bindWebBrowserProgram(batch, color.a < OPAQUE_ALPHA_THRESHOLD);
|
||||
DependencyManager::get<GeometryCache>()->bindWebBrowserProgram(batch, color.a < OPAQUE_ALPHA_THRESHOLD, forward);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, color, _geometryId);
|
||||
batch.popProjectionJitter();
|
||||
batch.setResourceTexture(0, nullptr);
|
||||
|
|
|
@ -317,6 +317,8 @@ void ZoneEntityRenderer::updateKeySunFromEntity(const TypedEntityPointer& entity
|
|||
sunLight->setIntensity(_keyLightProperties.getIntensity());
|
||||
sunLight->setDirection(_lastRotation * _keyLightProperties.getDirection());
|
||||
sunLight->setCastShadows(_keyLightProperties.getCastShadows());
|
||||
sunLight->setShadowBias(_keyLightProperties.getShadowBias());
|
||||
sunLight->setShadowsMaxDistance(_keyLightProperties.getShadowMaxDistance());
|
||||
}
|
||||
|
||||
void ZoneEntityRenderer::updateAmbientLightFromEntity(const TypedEntityPointer& entity) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
DEFINES forward
|
|
@ -1 +0,0 @@
|
|||
VERTEX paintStroke
|
|
@ -0,0 +1 @@
|
|||
DEFINES (shadow fade)/forward
|
|
@ -1,10 +1,8 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// <$_SCRIBE_FILENAME$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// paintStroke.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Eric Levin on 8/10/2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -12,29 +10,32 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
<@if not HIFI_USE_FORWARD@>
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
<@else@>
|
||||
layout(location=0) out vec4 _fragColor0;
|
||||
<@endif@>
|
||||
|
||||
<@include paintStroke.slh@>
|
||||
<$declarePolyLineBuffers()$>
|
||||
|
||||
LAYOUT(binding=0) uniform sampler2D _texture;
|
||||
|
||||
layout(location=0) in vec3 _normalWS;
|
||||
<@if not HIFI_USE_FORWARD@>
|
||||
layout(location=0) in vec3 _normalWS;
|
||||
<@endif@>
|
||||
layout(location=1) in vec2 _texCoord;
|
||||
layout(location=2) in vec4 _color;
|
||||
layout(location=3) in float _distanceFromCenter;
|
||||
|
||||
void main(void) {
|
||||
vec4 texel = texture(_texture, _texCoord);
|
||||
float frontCondition = 2.0 * float(gl_FrontFacing) - 1.0;
|
||||
vec3 color = _color.rgb * texel.rgb;
|
||||
float alpha = texel.a * _color.a;
|
||||
texel *= _color;
|
||||
texel.a *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y);
|
||||
|
||||
alpha *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y);
|
||||
|
||||
packDeferredFragmentTranslucent(
|
||||
_normalWS * frontCondition,
|
||||
alpha,
|
||||
color,
|
||||
DEFAULT_ROUGHNESS);
|
||||
<@if not HIFI_USE_FORWARD@>
|
||||
packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS);
|
||||
<@else@>
|
||||
_fragColor0 = texel;
|
||||
<@endif@>
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// <$_SCRIBE_FILENAME$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// paintStroke.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Eric Levin on 7/20/15.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -20,7 +18,9 @@
|
|||
<@include paintStroke.slh@>
|
||||
<$declarePolyLineBuffers()$>
|
||||
|
||||
layout(location=0) out vec3 _normalWS;
|
||||
<@if not HIFI_USE_FORWARD@>
|
||||
layout(location=0) out vec3 _normalWS;
|
||||
<@endif@>
|
||||
layout(location=1) out vec2 _texCoord;
|
||||
layout(location=2) out vec4 _color;
|
||||
layout(location=3) out float _distanceFromCenter;
|
||||
|
@ -50,11 +50,15 @@ void main(void) {
|
|||
vec3 binormalEye = normalize(cross(normalEye, tangentEye));
|
||||
posEye.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormalEye;
|
||||
<$transformEyeToClipPos(cam, posEye, gl_Position)$>
|
||||
<@if not HIFI_USE_FORWARD@>
|
||||
<$transformEyeToWorldDir(cam, normalEye, _normalWS)$>
|
||||
<@endif@>
|
||||
} else {
|
||||
vec3 normal = vertex.normal.xyz;
|
||||
position.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormal;
|
||||
<$transformModelToClipPos(cam, obj, position, gl_Position)$>
|
||||
<@if not HIFI_USE_FORWARD@>
|
||||
<$transformModelToWorldDir(cam, obj, normal, _normalWS)$>
|
||||
<@endif@>
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// paintStroke.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Eric Levin on 8/10/2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include paintStroke.slh@>
|
||||
<$declarePolyLineBuffers()$>
|
||||
|
||||
LAYOUT(binding=0) uniform sampler2D _texture;
|
||||
|
||||
layout(location=0) in vec3 _normalWS;
|
||||
layout(location=1) in vec2 _texCoord;
|
||||
layout(location=2) in vec4 _color;
|
||||
layout(location=3) in float _distanceFromCenter;
|
||||
layout(location=0) out vec4 _fragColor0;
|
||||
|
||||
void main(void) {
|
||||
vec4 texel = texture(_texture, _texCoord);
|
||||
int frontCondition = 1 - 2 * int(gl_FrontFacing);
|
||||
vec3 color = _color.rgb * texel.rgb;
|
||||
float alpha = texel.a * _color.a;
|
||||
|
||||
alpha *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y);
|
||||
|
||||
_fragColor0 = vec4(color, alpha);
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// <$_SCRIBE_FILENAME$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// polyvox.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Seth Alves on 2015-8-3
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
|
@ -11,51 +10,111 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include graphics/Material.slh@>
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
<@include entities-renderer/ShaderConstants.h@>
|
||||
<@if HIFI_USE_FADE@>
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normal;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _position;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _worldPosition;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS;
|
||||
<@endif@>
|
||||
|
||||
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap;
|
||||
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap;
|
||||
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap;
|
||||
<@if not HIFI_USE_SHADOW@>
|
||||
<@include graphics/Material.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
<@include entities-renderer/ShaderConstants.h@>
|
||||
|
||||
struct PolyvoxParams {
|
||||
vec4 voxelVolumeSize;
|
||||
};
|
||||
<@if not HIFI_USE_FORWARD@>
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
<@else@>
|
||||
<@include DefaultMaterials.slh@>
|
||||
|
||||
LAYOUT(binding=0) uniform polyvoxParamsBuffer {
|
||||
PolyvoxParams params;
|
||||
};
|
||||
<@include GlobalLight.slh@>
|
||||
<$declareEvalSkyboxGlobalColor(_SCRIBE_NULL, HIFI_USE_FORWARD)$>
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardCameraTransform()$>
|
||||
<@endif@>
|
||||
|
||||
<@if HIFI_USE_FORWARD@>
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES;
|
||||
<@endif@>
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec3 _positionMS;
|
||||
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
|
||||
|
||||
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap;
|
||||
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap;
|
||||
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap;
|
||||
|
||||
struct PolyvoxParams {
|
||||
vec4 voxelVolumeSize;
|
||||
};
|
||||
|
||||
LAYOUT(binding=0) uniform polyvoxParamsBuffer {
|
||||
PolyvoxParams params;
|
||||
};
|
||||
<@endif@>
|
||||
|
||||
<@if HIFI_USE_SHADOW or HIFI_USE_FORWARD@>
|
||||
layout(location=0) out vec4 _fragColor0;
|
||||
<@endif@>
|
||||
|
||||
void main(void) {
|
||||
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
|
||||
worldNormal = normalize(worldNormal);
|
||||
<@if HIFI_USE_FADE@>
|
||||
<@if not HIFI_USE_SHADOW@>
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _positionWS.xyz, fadeEmissive);
|
||||
<@else@>
|
||||
FadeObjectParams fadeParams;
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFadeClip(fadeParams, _positionWS.xyz);
|
||||
<@endif@>
|
||||
<@endif@>
|
||||
|
||||
float inPositionX = (_worldPosition.x - 0.5) / params.voxelVolumeSize.x;
|
||||
float inPositionY = (_worldPosition.y - 0.5) / params.voxelVolumeSize.y;
|
||||
float inPositionZ = (_worldPosition.z - 0.5) / params.voxelVolumeSize.z;
|
||||
<@if not HIFI_USE_SHADOW@>
|
||||
float inPositionX = (_positionMS.x - 0.5) / params.voxelVolumeSize.x;
|
||||
float inPositionY = (_positionMS.y - 0.5) / params.voxelVolumeSize.y;
|
||||
float inPositionZ = (_positionMS.z - 0.5) / params.voxelVolumeSize.z;
|
||||
|
||||
vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY));
|
||||
vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ));
|
||||
vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY));
|
||||
|
||||
vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z);
|
||||
vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y);
|
||||
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
|
||||
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
|
||||
vec3 normalMS = normalize(cross(dFdy(_positionMS.xyz), dFdx(_positionMS.xyz)));
|
||||
vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(normalMS.z);
|
||||
vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(normalMS.y);
|
||||
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(normalMS.x);
|
||||
vec3 diffuse = vec3(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled);
|
||||
|
||||
packDeferredFragment(
|
||||
_normal,
|
||||
1.0,
|
||||
vec3(diffuse),
|
||||
DEFAULT_ROUGHNESS,
|
||||
DEFAULT_METALLIC,
|
||||
DEFAULT_EMISSIVE,
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
<@if not HIFI_USE_FORWARD@>
|
||||
packDeferredFragment(
|
||||
normalize(_normalWS),
|
||||
1.0,
|
||||
diffuse,
|
||||
DEFAULT_ROUGHNESS,
|
||||
DEFAULT_METALLIC,
|
||||
DEFAULT_EMISSIVE
|
||||
<@if HIFI_USE_FADE@>
|
||||
+ fadeEmissive
|
||||
<@endif@>
|
||||
,
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
<@else@>
|
||||
TransformCamera cam = getTransformCamera();
|
||||
_fragColor0 = vec4(evalSkyboxGlobalColor(
|
||||
cam._viewInverse,
|
||||
1.0,
|
||||
DEFAULT_OCCLUSION,
|
||||
_positionES.xyz,
|
||||
normalize(_normalWS),
|
||||
diffuse,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_METALLIC,
|
||||
DEFAULT_ROUGHNESS),
|
||||
1.0);
|
||||
<@endif@>
|
||||
<@else@>
|
||||
_fragColor0 = vec4(1.0);
|
||||
<@endif@>
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// <$_SCRIBE_FILENAME$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// polyvox.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -11,20 +10,39 @@
|
|||
//
|
||||
|
||||
<@include gpu/Inputs.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _position;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _worldPosition;
|
||||
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normal;
|
||||
<@if HIFI_USE_FADE@>
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS;
|
||||
<@endif@>
|
||||
<@if not HIFI_USE_SHADOW@>
|
||||
<@if HIFI_USE_FORWARD@>
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES;
|
||||
<@endif@>
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec3 _positionMS;
|
||||
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS;
|
||||
<@endif@>
|
||||
|
||||
void main(void) {
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
|
||||
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
_worldPosition = inPosition;
|
||||
|
||||
<@if HIFI_USE_SHADOW@>
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<@else@>
|
||||
<@if not HIFI_USE_FORWARD@>
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<@else@>
|
||||
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$>
|
||||
<@endif@>
|
||||
|
||||
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$>
|
||||
_positionMS = inPosition.xyz;
|
||||
<@endif@>
|
||||
<@if HIFI_USE_FADE@>
|
||||
<$transformModelToWorldPos(obj, inPosition, _positionWS)$>
|
||||
<@endif@>
|
||||
}
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// polyvox_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 2017-06-08
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include graphics/Material.slh@>
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
<@include entities-renderer/ShaderConstants.h@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
|
||||
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normal;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _position;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _worldPosition;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _worldFadePosition;
|
||||
|
||||
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap;
|
||||
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap;
|
||||
LAYOUT(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap;
|
||||
|
||||
struct PolyvoxParams {
|
||||
vec4 voxelVolumeSize;
|
||||
};
|
||||
|
||||
LAYOUT(binding=0) uniform polyvoxParamsBuffer {
|
||||
PolyvoxParams params;
|
||||
};
|
||||
|
||||
// Declare after all samplers to prevent sampler location mix up with voxel shading (sampler locations are hardcoded in RenderablePolyVoxEntityItem)
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
void main(void) {
|
||||
vec3 emissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldFadePosition.xyz, emissive);
|
||||
|
||||
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
|
||||
worldNormal = normalize(worldNormal);
|
||||
|
||||
float inPositionX = (_worldPosition.x - 0.5) / params.voxelVolumeSize.x;
|
||||
float inPositionY = (_worldPosition.y - 0.5) / params.voxelVolumeSize.y;
|
||||
float inPositionZ = (_worldPosition.z - 0.5) / params.voxelVolumeSize.z;
|
||||
|
||||
vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY));
|
||||
vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ));
|
||||
vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY));
|
||||
|
||||
vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z);
|
||||
vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y);
|
||||
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
|
||||
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
|
||||
|
||||
packDeferredFragment(
|
||||
_normal,
|
||||
1.0,
|
||||
vec3(diffuse),
|
||||
DEFAULT_ROUGHNESS,
|
||||
DEFAULT_METALLIC,
|
||||
DEFAULT_EMISSIVE+emissive,
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// polyvox_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Seth Alves on 2015-8-3
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include gpu/Inputs.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _position;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _worldPosition;
|
||||
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normal;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _worldFadePosition;
|
||||
|
||||
void main(void) {
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
|
||||
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _worldFadePosition)$>
|
||||
_worldPosition = inPosition;
|
||||
}
|
|
@ -2753,6 +2753,8 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
|
|||
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLight, keylight, Direction, direction);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_KEYLIGHT_CAST_SHADOW, KeyLight, keyLight, CastShadows, castShadows);
|
||||
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_BIAS, KeyLight, keyLight, ShadowBias, shadowBias, 0.0f, 1.0f);
|
||||
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, KeyLight, keyLight, ShadowMaxDistance, shadowMaxDistance, 1.0f, 250.0f);
|
||||
}
|
||||
{ // Ambient light
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_INTENSITY, AmbientLight, ambientLight, Intensity, intensity);
|
||||
|
|
|
@ -159,6 +159,8 @@ enum EntityPropertyList {
|
|||
PROP_DERIVED_29,
|
||||
PROP_DERIVED_30,
|
||||
PROP_DERIVED_31,
|
||||
PROP_DERIVED_32,
|
||||
PROP_DERIVED_33,
|
||||
|
||||
PROP_AFTER_LAST_ITEM,
|
||||
|
||||
|
@ -249,39 +251,41 @@ enum EntityPropertyList {
|
|||
PROP_KEYLIGHT_INTENSITY = PROP_DERIVED_1,
|
||||
PROP_KEYLIGHT_DIRECTION = PROP_DERIVED_2,
|
||||
PROP_KEYLIGHT_CAST_SHADOW = PROP_DERIVED_3,
|
||||
PROP_KEYLIGHT_SHADOW_BIAS = PROP_DERIVED_4,
|
||||
PROP_KEYLIGHT_SHADOW_MAX_DISTANCE = PROP_DERIVED_5,
|
||||
// Ambient light
|
||||
PROP_AMBIENT_LIGHT_INTENSITY = PROP_DERIVED_4,
|
||||
PROP_AMBIENT_LIGHT_URL = PROP_DERIVED_5,
|
||||
PROP_AMBIENT_LIGHT_INTENSITY = PROP_DERIVED_6,
|
||||
PROP_AMBIENT_LIGHT_URL = PROP_DERIVED_7,
|
||||
// Skybox
|
||||
PROP_SKYBOX_COLOR = PROP_DERIVED_6,
|
||||
PROP_SKYBOX_URL = PROP_DERIVED_7,
|
||||
PROP_SKYBOX_COLOR = PROP_DERIVED_8,
|
||||
PROP_SKYBOX_URL = PROP_DERIVED_9,
|
||||
// Haze
|
||||
PROP_HAZE_RANGE = PROP_DERIVED_8,
|
||||
PROP_HAZE_COLOR = PROP_DERIVED_9,
|
||||
PROP_HAZE_GLARE_COLOR = PROP_DERIVED_10,
|
||||
PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_11,
|
||||
PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_12,
|
||||
PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_13,
|
||||
PROP_HAZE_CEILING = PROP_DERIVED_14,
|
||||
PROP_HAZE_BASE_REF = PROP_DERIVED_15,
|
||||
PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_16,
|
||||
PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_17,
|
||||
PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_18,
|
||||
PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_19,
|
||||
PROP_HAZE_RANGE = PROP_DERIVED_10,
|
||||
PROP_HAZE_COLOR = PROP_DERIVED_11,
|
||||
PROP_HAZE_GLARE_COLOR = PROP_DERIVED_12,
|
||||
PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_13,
|
||||
PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_14,
|
||||
PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_15,
|
||||
PROP_HAZE_CEILING = PROP_DERIVED_16,
|
||||
PROP_HAZE_BASE_REF = PROP_DERIVED_17,
|
||||
PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_18,
|
||||
PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_19,
|
||||
PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_20,
|
||||
PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_21,
|
||||
// Bloom
|
||||
PROP_BLOOM_INTENSITY = PROP_DERIVED_20,
|
||||
PROP_BLOOM_THRESHOLD = PROP_DERIVED_21,
|
||||
PROP_BLOOM_SIZE = PROP_DERIVED_22,
|
||||
PROP_FLYING_ALLOWED = PROP_DERIVED_23,
|
||||
PROP_GHOSTING_ALLOWED = PROP_DERIVED_24,
|
||||
PROP_FILTER_URL = PROP_DERIVED_25,
|
||||
PROP_KEY_LIGHT_MODE = PROP_DERIVED_26,
|
||||
PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_27,
|
||||
PROP_SKYBOX_MODE = PROP_DERIVED_28,
|
||||
PROP_HAZE_MODE = PROP_DERIVED_29,
|
||||
PROP_BLOOM_MODE = PROP_DERIVED_30,
|
||||
PROP_BLOOM_INTENSITY = PROP_DERIVED_22,
|
||||
PROP_BLOOM_THRESHOLD = PROP_DERIVED_23,
|
||||
PROP_BLOOM_SIZE = PROP_DERIVED_24,
|
||||
PROP_FLYING_ALLOWED = PROP_DERIVED_25,
|
||||
PROP_GHOSTING_ALLOWED = PROP_DERIVED_26,
|
||||
PROP_FILTER_URL = PROP_DERIVED_27,
|
||||
PROP_KEY_LIGHT_MODE = PROP_DERIVED_28,
|
||||
PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_29,
|
||||
PROP_SKYBOX_MODE = PROP_DERIVED_30,
|
||||
PROP_HAZE_MODE = PROP_DERIVED_31,
|
||||
PROP_BLOOM_MODE = PROP_DERIVED_32,
|
||||
// Avatar priority
|
||||
PROP_AVATAR_PRIORITY = PROP_DERIVED_31,
|
||||
PROP_AVATAR_PRIORITY = PROP_DERIVED_33,
|
||||
|
||||
// Polyvox
|
||||
PROP_VOXEL_VOLUME_SIZE = PROP_DERIVED_0,
|
||||
|
|
|
@ -22,6 +22,8 @@ const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_INTENSITY = 1.0f;
|
|||
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY = 0.5f;
|
||||
const glm::vec3 KeyLightPropertyGroup::DEFAULT_KEYLIGHT_DIRECTION = { 0.0f, -1.0f, 0.0f };
|
||||
const bool KeyLightPropertyGroup::DEFAULT_KEYLIGHT_CAST_SHADOWS { false };
|
||||
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_SHADOW_BIAS { 0.5f };
|
||||
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE { 40.0f };
|
||||
|
||||
void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties,
|
||||
QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||
|
@ -30,6 +32,8 @@ void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desired
|
|||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_DIRECTION, KeyLight, keyLight, Direction, direction);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_CAST_SHADOW, KeyLight, keyLight, CastShadows, castShadows);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_SHADOW_BIAS, KeyLight, keyLight, ShadowBias, shadowBias);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, KeyLight, keyLight, ShadowMaxDistance, shadowMaxDistance);
|
||||
}
|
||||
|
||||
void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
||||
|
@ -37,6 +41,8 @@ void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, intensity, float, setIntensity);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, direction, vec3, setDirection);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, castShadows, bool, setCastShadows);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, shadowBias, float, setShadowBias);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, shadowMaxDistance, float, setShadowMaxDistance);
|
||||
|
||||
// legacy property support
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightColor, u8vec3Color, setColor, getColor);
|
||||
|
@ -50,14 +56,18 @@ void KeyLightPropertyGroup::merge(const KeyLightPropertyGroup& other) {
|
|||
COPY_PROPERTY_IF_CHANGED(intensity);
|
||||
COPY_PROPERTY_IF_CHANGED(direction);
|
||||
COPY_PROPERTY_IF_CHANGED(castShadows);
|
||||
COPY_PROPERTY_IF_CHANGED(shadowBias);
|
||||
COPY_PROPERTY_IF_CHANGED(shadowMaxDistance);
|
||||
}
|
||||
|
||||
void KeyLightPropertyGroup::debugDump() const {
|
||||
qCDebug(entities) << " KeyLightPropertyGroup: ---------------------------------------------";
|
||||
qCDebug(entities) << " color:" << getColor(); // << "," << getColor()[1] << "," << getColor()[2];
|
||||
qCDebug(entities) << " intensity:" << getIntensity();
|
||||
qCDebug(entities) << " direction:" << getDirection();
|
||||
qCDebug(entities) << " castShadows:" << getCastShadows();
|
||||
qCDebug(entities) << " color:" << getColor();
|
||||
qCDebug(entities) << " intensity:" << getIntensity();
|
||||
qCDebug(entities) << " direction:" << getDirection();
|
||||
qCDebug(entities) << " castShadows:" << getCastShadows();
|
||||
qCDebug(entities) << " shadowBias:" << getShadowBias();
|
||||
qCDebug(entities) << " shadowMaxDistance:" << getShadowMaxDistance();
|
||||
}
|
||||
|
||||
void KeyLightPropertyGroup::listChangedProperties(QList<QString>& out) {
|
||||
|
@ -73,6 +83,12 @@ void KeyLightPropertyGroup::listChangedProperties(QList<QString>& out) {
|
|||
if (castShadowsChanged()) {
|
||||
out << "keyLight-castShadows";
|
||||
}
|
||||
if (shadowBiasChanged()) {
|
||||
out << "keyLight-shadowBias";
|
||||
}
|
||||
if (shadowMaxDistanceChanged()) {
|
||||
out << "keyLight-shadowMaxDistance";
|
||||
}
|
||||
}
|
||||
|
||||
bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
|
||||
|
@ -88,6 +104,8 @@ bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
|
|||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, getCastShadows());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, getShadowBias());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, getShadowMaxDistance());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -103,11 +121,15 @@ bool KeyLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFl
|
|||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, bool, setCastShadows);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, float, setShadowBias);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, float, setShadowMaxDistance);
|
||||
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_COLOR, Color);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_INTENSITY, Intensity);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_DIRECTION, Direction);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_CAST_SHADOW, CastShadows);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_SHADOW_BIAS, ShadowBias);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, ShadowMaxDistance);
|
||||
|
||||
processedBytes += bytesRead;
|
||||
|
||||
|
@ -121,6 +143,8 @@ void KeyLightPropertyGroup::markAllChanged() {
|
|||
_intensityChanged = true;
|
||||
_directionChanged = true;
|
||||
_castShadowsChanged = true;
|
||||
_shadowBiasChanged = true;
|
||||
_shadowMaxDistanceChanged = true;
|
||||
}
|
||||
|
||||
EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const {
|
||||
|
@ -130,6 +154,8 @@ EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_INTENSITY, intensity);
|
||||
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, direction);
|
||||
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_CAST_SHADOW, castShadows);
|
||||
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_SHADOW_BIAS, shadowBias);
|
||||
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, shadowMaxDistance);
|
||||
|
||||
return changedProperties;
|
||||
}
|
||||
|
@ -139,6 +165,8 @@ void KeyLightPropertyGroup::getProperties(EntityItemProperties& properties) cons
|
|||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Intensity, getIntensity);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Direction, getDirection);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, CastShadows, getCastShadows);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, ShadowBias, getShadowBias);
|
||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, ShadowMaxDistance, getShadowMaxDistance);
|
||||
}
|
||||
|
||||
bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties) {
|
||||
|
@ -148,6 +176,8 @@ bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties
|
|||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Intensity, intensity, setIntensity);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Direction, direction, setDirection);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, CastShadows, castShadows, setCastShadows);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, ShadowBias, shadowBias, setShadowBias);
|
||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, ShadowMaxDistance, shadowMaxDistance, setShadowMaxDistance);
|
||||
|
||||
return somethingChanged;
|
||||
}
|
||||
|
@ -159,6 +189,8 @@ EntityPropertyFlags KeyLightPropertyGroup::getEntityProperties(EncodeBitstreamPa
|
|||
requestedProperties += PROP_KEYLIGHT_INTENSITY;
|
||||
requestedProperties += PROP_KEYLIGHT_DIRECTION;
|
||||
requestedProperties += PROP_KEYLIGHT_CAST_SHADOW;
|
||||
requestedProperties += PROP_KEYLIGHT_SHADOW_BIAS;
|
||||
requestedProperties += PROP_KEYLIGHT_SHADOW_MAX_DISTANCE;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
@ -177,6 +209,8 @@ void KeyLightPropertyGroup::appendSubclassData(OctreePacketData* packetData, Enc
|
|||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, getCastShadows());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, getShadowBias());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, getShadowMaxDistance());
|
||||
}
|
||||
|
||||
int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
|
@ -191,6 +225,8 @@ int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char*
|
|||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, bool, setCastShadows);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, float, setShadowBias);
|
||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, float, setShadowMaxDistance);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,10 @@ class ReadBitstreamToTreeParams;
|
|||
* are cast by avatars, plus {@link Entities.EntityProperties-Model|Model} and
|
||||
* {@link Entities.EntityProperties-Shape|Shape} entities that have their
|
||||
* <code>{@link Entities.EntityProperties|canCastShadow}</code> property set to <code>true</code>.
|
||||
* @property {number} shadowBias=0.5 - The bias of the shadows cast by the light. Use this to fine-tune your shadows to your scene
|
||||
* to prevent shadow acne and peter panning. In the range <code>0.0</code> – <code>1.0</code>.
|
||||
* @property {number} shadowMaxDistance=40.0 - The max distance from your view at which shadows will be computed. Higher values will
|
||||
* cover more of your scene, but with less precision. In the range <code>1.0</code> – <code>250.0</code>.
|
||||
*/
|
||||
class KeyLightPropertyGroup : public PropertyGroup {
|
||||
public:
|
||||
|
@ -90,11 +94,15 @@ public:
|
|||
static const float DEFAULT_KEYLIGHT_AMBIENT_INTENSITY;
|
||||
static const glm::vec3 DEFAULT_KEYLIGHT_DIRECTION;
|
||||
static const bool DEFAULT_KEYLIGHT_CAST_SHADOWS;
|
||||
static const float DEFAULT_KEYLIGHT_SHADOW_BIAS;
|
||||
static const float DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE;
|
||||
|
||||
DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, Color, color, glm::u8vec3, DEFAULT_KEYLIGHT_COLOR);
|
||||
DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, Intensity, intensity, float, DEFAULT_KEYLIGHT_INTENSITY);
|
||||
DEFINE_PROPERTY_REF(PROP_KEYLIGHT_DIRECTION, Direction, direction, glm::vec3, DEFAULT_KEYLIGHT_DIRECTION);
|
||||
DEFINE_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, CastShadows, castShadows, bool, DEFAULT_KEYLIGHT_CAST_SHADOWS);
|
||||
DEFINE_PROPERTY(PROP_KEYLIGHT_SHADOW_BIAS, ShadowBias, shadowBias, float, DEFAULT_KEYLIGHT_SHADOW_BIAS);
|
||||
DEFINE_PROPERTY(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, ShadowMaxDistance, shadowMaxDistance, float, DEFAULT_KEYLIGHT_SHADOW_MAX_DISTANCE);
|
||||
};
|
||||
|
||||
#endif // hifi_KeyLightPropertyGroup_h
|
||||
|
|
|
@ -26,13 +26,19 @@ size_t evalGLFormatSwapchainPixelSize(const QSurfaceFormat& format) {
|
|||
return pixelSize;
|
||||
}
|
||||
|
||||
static bool FORCE_DISABLE_OPENGL_45 = false;
|
||||
|
||||
void gl::setDisableGl45(bool disable) {
|
||||
FORCE_DISABLE_OPENGL_45 = disable;
|
||||
}
|
||||
|
||||
bool gl::disableGl45() {
|
||||
#if defined(USE_GLES)
|
||||
return false;
|
||||
#else
|
||||
static const QString DEBUG_FLAG("HIFI_DISABLE_OPENGL_45");
|
||||
static bool disableOpenGL45 = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||
return disableOpenGL45;
|
||||
return FORCE_DISABLE_OPENGL_45 || disableOpenGL45;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -202,6 +208,15 @@ uint16_t gl::getAvailableVersion() {
|
|||
return;
|
||||
}
|
||||
gl::initModuleGl();
|
||||
|
||||
std::string glvendor{ (const char*)glGetString(GL_VENDOR) };
|
||||
std::transform(glvendor.begin(), glvendor.end(), glvendor.begin(), ::tolower);
|
||||
|
||||
// Intel has *notoriously* buggy DSA implementations, especially around cubemaps
|
||||
if (std::string::npos != glvendor.find("intel")) {
|
||||
gl::setDisableGl45(true);
|
||||
}
|
||||
|
||||
wglMakeCurrent(0, 0);
|
||||
hGLRC.reset();
|
||||
if (!wglChoosePixelFormatARB || !wglCreateContextAttribsARB) {
|
||||
|
|
|
@ -55,6 +55,7 @@ namespace gl {
|
|||
bool checkGLErrorDebug(const char* name);
|
||||
|
||||
bool disableGl45();
|
||||
void setDisableGl45(bool disable);
|
||||
|
||||
uint16_t getTargetVersion();
|
||||
|
||||
|
|
|
@ -220,7 +220,7 @@ double Context::getFrameTimerBatchAverage() const {
|
|||
const Backend::TransformCamera& Backend::TransformCamera::recomputeDerived(const Transform& xformView) const {
|
||||
_projectionInverse = glm::inverse(_projection);
|
||||
|
||||
// Get the viewEyeToWorld matrix form the transformView as passed to the gpu::Batch
|
||||
// Get the viewEyeToWorld matrix from the transformView as passed to the gpu::Batch
|
||||
// this is the "_viewInverse" fed to the shader
|
||||
// Genetrate the "_view" matrix as well from the xform
|
||||
xformView.getMatrix(_viewInverse);
|
||||
|
|
|
@ -98,7 +98,7 @@ void Haze::setHazeGlareColor(const glm::vec3 hazeGlareColor) {
|
|||
void Haze::setHazeActive(const bool isHazeActive) {
|
||||
auto& params = _hazeParametersBuffer.get<Parameters>();
|
||||
|
||||
if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE )&& !isHazeActive) {
|
||||
if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) && !isHazeActive) {
|
||||
_hazeParametersBuffer.edit<Parameters>().hazeMode &= ~HAZE_MODE_IS_ACTIVE;
|
||||
} else if (((params.hazeMode & HAZE_MODE_IS_ACTIVE) != HAZE_MODE_IS_ACTIVE) && isHazeActive) {
|
||||
_hazeParametersBuffer.edit<Parameters>().hazeMode |= HAZE_MODE_IS_ACTIVE;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<@if not HAZE_SLH@>
|
||||
<@def HAZE_SLH@>
|
||||
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
<@include graphics/ShaderConstants.h@>
|
||||
|
||||
const int HAZE_MODE_IS_ACTIVE = 1 << 0;
|
||||
const int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;
|
||||
|
@ -38,8 +38,7 @@ struct HazeParams {
|
|||
float hazeKeyLightAltitudeFactor;
|
||||
};
|
||||
|
||||
// See ShapePipeline::Slot::BUFFER in ShapePipeline.h
|
||||
LAYOUT_STD140(binding=RENDER_UTILS_BUFFER_HAZE_PARAMS) uniform hazeBuffer {
|
||||
LAYOUT_STD140(binding=GRAPHICS_BUFFER_HAZE_PARAMS) uniform hazeBuffer {
|
||||
HazeParams hazeParams;
|
||||
};
|
||||
|
|
@ -81,20 +81,12 @@ float Light::getShadowsMaxDistance() const {
|
|||
return _shadowsMaxDistance;
|
||||
}
|
||||
|
||||
void Light::setShadowsBiasScale(const float scale) {
|
||||
_shadowsBiasScale = std::max(0.0f, scale);
|
||||
void Light::setShadowBias(float bias) {
|
||||
_shadowBias = bias;
|
||||
}
|
||||
|
||||
float Light::getShadowsBiasScale() const {
|
||||
return _shadowsBiasScale;
|
||||
}
|
||||
|
||||
void Light::setBiasInput(float bias) {
|
||||
_biasInput = bias;
|
||||
}
|
||||
|
||||
float Light::getBiasInput() const {
|
||||
return _biasInput;
|
||||
float Light::getShadowBias() const {
|
||||
return _shadowBias;
|
||||
}
|
||||
|
||||
void Light::setColor(const Color& color) {
|
||||
|
|
|
@ -109,11 +109,8 @@ public:
|
|||
void setShadowsMaxDistance(const float maxDistance);
|
||||
float getShadowsMaxDistance() const;
|
||||
|
||||
void setShadowsBiasScale(const float scale);
|
||||
float getShadowsBiasScale() const;
|
||||
|
||||
void setBiasInput(float bias);
|
||||
float getBiasInput() const;
|
||||
void setShadowBias(float bias);
|
||||
float getShadowBias() const;
|
||||
|
||||
void setOrientation(const Quat& orientation);
|
||||
const glm::quat& getOrientation() const { return _transform.getRotation(); }
|
||||
|
@ -201,9 +198,8 @@ protected:
|
|||
Type _type { SUN };
|
||||
float _spotCos { -1.0f }; // stored here to be able to reset the spot angle when turning the type spot on/off
|
||||
|
||||
float _shadowsMaxDistance{ 40.0f };
|
||||
float _shadowsBiasScale{ 1.0f };
|
||||
float _biasInput{ 0.5f }; // 0.23f will roughly give the default constant and slope values
|
||||
float _shadowsMaxDistance { 40.0f };
|
||||
float _shadowBias { 0.5f };
|
||||
bool _castShadows{ false };
|
||||
|
||||
void updateLightRadius();
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#define GRAPHICS_TEXTURE_SKYBOX 11
|
||||
#define GRAPHICS_BUFFER_SKYBOX_PARAMS 5
|
||||
|
||||
#define GRAPHICS_BUFFER_HAZE_PARAMS 7
|
||||
|
||||
// <!
|
||||
|
||||
namespace graphics { namespace slot {
|
||||
|
@ -43,7 +45,8 @@ enum Buffer {
|
|||
Light = GRAPHICS_BUFFER_LIGHT,
|
||||
KeyLight = GRAPHICS_BUFFER_KEY_LIGHT,
|
||||
AmbientLight = GRAPHICS_BUFFER_AMBIENT_LIGHT,
|
||||
SkyboxParams = GRAPHICS_BUFFER_SKYBOX_PARAMS
|
||||
SkyboxParams = GRAPHICS_BUFFER_SKYBOX_PARAMS,
|
||||
HazeParams = GRAPHICS_BUFFER_HAZE_PARAMS
|
||||
};
|
||||
} // namespace buffer
|
||||
|
||||
|
|
|
@ -73,29 +73,29 @@ void Skybox::prepare(gpu::Batch& batch) const {
|
|||
}
|
||||
}
|
||||
|
||||
void Skybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const {
|
||||
void Skybox::render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const {
|
||||
updateSchemaBuffer();
|
||||
Skybox::render(batch, frustum, (*this));
|
||||
Skybox::render(batch, frustum, (*this), forward);
|
||||
}
|
||||
|
||||
void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) {
|
||||
// Create the static shared elements used to render the skybox
|
||||
static gpu::BufferPointer theConstants;
|
||||
static gpu::PipelinePointer thePipeline;
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
{
|
||||
auto skyShader = gpu::Shader::createProgram(shader::graphics::program::skybox);
|
||||
auto skyState = std::make_shared<gpu::State>();
|
||||
static std::map<bool, gpu::PipelinePointer> _pipelines;
|
||||
|
||||
void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox, bool forward) {
|
||||
if (_pipelines.empty()) {
|
||||
static const std::vector<std::tuple<bool, uint32_t>> keys = {
|
||||
std::make_tuple(false, shader::graphics::program::skybox),
|
||||
std::make_tuple(true, shader::graphics::program::skybox_forward)
|
||||
};
|
||||
for (auto& key : keys) {
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
// Must match PrepareStencil::STENCIL_BACKGROUND
|
||||
const int8_t STENCIL_BACKGROUND = 0;
|
||||
skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_BACKGROUND, 0xFF, gpu::EQUAL,
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_BACKGROUND, 0xFF, gpu::EQUAL,
|
||||
gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
|
||||
thePipeline = gpu::Pipeline::create(skyShader, skyState);
|
||||
_pipelines[std::get<0>(key)] = gpu::Pipeline::create(gpu::Shader::createProgram(std::get<1>(key)), state);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Render
|
||||
glm::mat4 projMat;
|
||||
|
@ -111,7 +111,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
batch.setViewTransform(viewTransform);
|
||||
batch.setModelTransform(Transform()); // only for Mac
|
||||
|
||||
batch.setPipeline(thePipeline);
|
||||
batch.setPipeline(_pipelines[forward]);
|
||||
skybox.prepare(batch);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
|
|
|
@ -44,9 +44,9 @@ public:
|
|||
virtual void clear();
|
||||
|
||||
void prepare(gpu::Batch& batch) const;
|
||||
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const;
|
||||
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const;
|
||||
|
||||
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox);
|
||||
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox, bool forward);
|
||||
|
||||
const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; }
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// <$_SCRIBE_FILENAME$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// skybox.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Sam Gateau on 5/5/2015.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
|
@ -12,6 +11,16 @@
|
|||
//
|
||||
<@include graphics/ShaderConstants.h@>
|
||||
|
||||
<@if HIFI_USE_FORWARD@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardCameraTransform()$>
|
||||
|
||||
<@include graphics/Light.slh@>
|
||||
<$declareLightBuffer()$>
|
||||
|
||||
<@include graphics/Haze.slh@>
|
||||
<@endif@>
|
||||
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_SKYBOX) uniform samplerCube cubeMap;
|
||||
|
||||
struct Skybox {
|
||||
|
@ -32,8 +41,28 @@ void main(void) {
|
|||
// mix(skyboxColor, skyboxTexel, skybox.color.a)
|
||||
// and the blend factor should be user controlled
|
||||
|
||||
vec3 skyboxTexel = texture(cubeMap, normalize(_normal)).rgb;
|
||||
vec3 normal = normalize(_normal);
|
||||
vec3 skyboxTexel = texture(cubeMap, normal).rgb;
|
||||
vec3 skyboxColor = skybox.color.rgb;
|
||||
_fragColor = vec4(mix(vec3(1.0), skyboxTexel, float(skybox.color.a > 0.0)) *
|
||||
mix(vec3(1.0), skyboxColor, float(skybox.color.a < 1.0)), 1.0);
|
||||
|
||||
<@if HIFI_USE_FORWARD@>
|
||||
// FIXME: either move this elsewhere or give it access to isHazeEnabled() (which is in render-utils/LightingModel.slh)
|
||||
if (/*(isHazeEnabled() > 0.0) && */(hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
|
||||
TransformCamera cam = getTransformCamera();
|
||||
vec4 eyePositionWS = cam._viewInverse[3];
|
||||
// We choose an arbitrary large number > BLEND_DISTANCE in Haze.slh
|
||||
const float SKYBOX_DISTANCE = 32000.0;
|
||||
vec4 fragPositionWS = eyePositionWS + SKYBOX_DISTANCE * vec4(normal, 0.0);
|
||||
vec4 fragPositionES = cam._view * fragPositionWS;
|
||||
|
||||
Light light = getKeyLight();
|
||||
vec3 lightDirectionWS = getLightDirection(light);
|
||||
|
||||
vec4 hazeColor = computeHazeColor(fragPositionES.xyz, fragPositionWS.xyz, eyePositionWS.xyz, lightDirectionWS);
|
||||
_fragColor.rgb = mix(_fragColor.rgb, hazeColor.rgb, hazeColor.a);
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
DEFINES forward:f
|
|
@ -1,8 +1,7 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// <$_SCRIBE_FILENAME$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// skybox.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Sam Gateau on 5/5/2015.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
|
@ -12,7 +11,6 @@
|
|||
//
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
layout(location=0) out vec3 _normal;
|
||||
|
|
|
@ -86,6 +86,7 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) :
|
|||
qRegisterMetaType<QHttpMultiPart*>("QHttpMultiPart*");
|
||||
|
||||
qRegisterMetaType<AccountManagerAuth::Type>();
|
||||
connect(this, &AccountManager::loginComplete, this, &AccountManager::uploadPublicKey);
|
||||
}
|
||||
|
||||
const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash";
|
||||
|
@ -838,18 +839,30 @@ void AccountManager::generateNewKeypair(bool isUserKeypair, const QUuid& domainI
|
|||
connect(keypairGenerator, &RSAKeypairGenerator::errorGeneratingKeypair, this,
|
||||
&AccountManager::handleKeypairGenerationError);
|
||||
|
||||
qCDebug(networking) << "Starting worker thread to generate 2048-bit RSA keypair.";
|
||||
static constexpr int RSA_THREAD_PRIORITY = 1;
|
||||
qCDebug(networking) << "Starting worker thread to generate 2048-bit RSA keypair, priority"
|
||||
<< RSA_THREAD_PRIORITY << "- QThreadPool::maxThreadCount =" << QThreadPool::globalInstance()->maxThreadCount();
|
||||
// Start on Qt's global thread pool.
|
||||
QThreadPool::globalInstance()->start(keypairGenerator);
|
||||
QThreadPool::globalInstance()->start(keypairGenerator, RSA_THREAD_PRIORITY);
|
||||
}
|
||||
}
|
||||
|
||||
void AccountManager::processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey) {
|
||||
|
||||
qCDebug(networking) << "Generated 2048-bit RSA keypair. Uploading public key now.";
|
||||
qCDebug(networking) << "Generated 2048-bit RSA keypair.";
|
||||
|
||||
// hold the private key to later set our metaverse API account info if upload succeeds
|
||||
_pendingPublicKey = publicKey;
|
||||
_pendingPrivateKey = privateKey;
|
||||
uploadPublicKey();
|
||||
}
|
||||
|
||||
void AccountManager::uploadPublicKey() {
|
||||
if (_pendingPrivateKey.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(networking) << "Attempting upload of public key";
|
||||
|
||||
// upload the public key so data-web has an up-to-date key
|
||||
const QString USER_PUBLIC_KEY_UPDATE_PATH = "api/v1/user/public_key";
|
||||
|
@ -871,7 +884,7 @@ void AccountManager::processGeneratedKeypair(QByteArray publicKey, QByteArray pr
|
|||
|
||||
publicKeyPart.setHeader(QNetworkRequest::ContentDispositionHeader,
|
||||
QVariant("form-data; name=\"public_key\"; filename=\"public_key\""));
|
||||
publicKeyPart.setBody(publicKey);
|
||||
publicKeyPart.setBody(_pendingPublicKey);
|
||||
requestMultiPart->append(publicKeyPart);
|
||||
|
||||
// Currently broken? We don't have the temporary domain key.
|
||||
|
@ -900,6 +913,7 @@ void AccountManager::publicKeyUploadSucceeded(QNetworkReply* reply) {
|
|||
|
||||
// public key upload complete - store the matching private key and persist the account to settings
|
||||
_accountInfo.setPrivateKey(_pendingPrivateKey);
|
||||
_pendingPublicKey.clear();
|
||||
_pendingPrivateKey.clear();
|
||||
persistAccountToFile();
|
||||
|
||||
|
@ -915,9 +929,6 @@ void AccountManager::publicKeyUploadFailed(QNetworkReply* reply) {
|
|||
|
||||
// we aren't waiting for a response any longer
|
||||
_isWaitingForKeypairResponse = false;
|
||||
|
||||
// clear our pending private key
|
||||
_pendingPrivateKey.clear();
|
||||
}
|
||||
|
||||
void AccountManager::handleKeypairGenerationError() {
|
||||
|
@ -961,3 +972,7 @@ void AccountManager::saveLoginStatus(bool isLoggedIn) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AccountManager::hasKeyPair() const {
|
||||
return _accountInfo.hasPrivateKey();
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ public:
|
|||
bool needsToRefreshToken();
|
||||
Q_INVOKABLE bool checkAndSignalForAccessToken();
|
||||
void setAccessTokenForCurrentAuthURL(const QString& accessToken);
|
||||
bool hasKeyPair() const;
|
||||
|
||||
void requestProfile();
|
||||
|
||||
|
@ -139,6 +140,7 @@ signals:
|
|||
private slots:
|
||||
void handleKeypairGenerationError();
|
||||
void processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey);
|
||||
void uploadPublicKey();
|
||||
void publicKeyUploadSucceeded(QNetworkReply* reply);
|
||||
void publicKeyUploadFailed(QNetworkReply* reply);
|
||||
void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid());
|
||||
|
@ -162,6 +164,7 @@ private:
|
|||
|
||||
bool _isWaitingForKeypairResponse { false };
|
||||
QByteArray _pendingPrivateKey;
|
||||
QByteArray _pendingPublicKey;
|
||||
|
||||
QUuid _sessionID { QUuid::createUuid() };
|
||||
|
||||
|
|
|
@ -842,7 +842,8 @@ bool Resource::handleFailedRequest(ResourceRequest::Result result) {
|
|||
// FALLTHRU
|
||||
default: {
|
||||
_attemptsRemaining = 0;
|
||||
qCDebug(networking) << "Error loading, attempt:" << _attempts << "attemptsRemaining:" << _attemptsRemaining;
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<ResourceRequest::Result>();
|
||||
qCDebug(networking) << "Error loading:" << metaEnum.valueToKey(result) << "resource:" << _url.toString();
|
||||
auto error = (result == ResourceRequest::Timeout) ? QNetworkReply::TimeoutError
|
||||
: QNetworkReply::UnknownNetworkError;
|
||||
emit failed(error);
|
||||
|
|
|
@ -272,6 +272,7 @@ enum class EntityVersion : PacketVersion {
|
|||
ParticleShapeTypeDeadlockFix,
|
||||
PrivateUserData,
|
||||
TextUnlit,
|
||||
ShadowBiasAndDistance,
|
||||
|
||||
// Add new versions above here
|
||||
NUM_PACKET_TYPE,
|
||||
|
|
|
@ -49,9 +49,9 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) {
|
|||
assert(entity);
|
||||
assert(!entity->isDead());
|
||||
uint8_t region = _space->getRegion(entity->getSpaceIndex());
|
||||
bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical();
|
||||
bool maybeShouldBePhysical = (region < workload::Region::R3 || region == workload::Region::UNKNOWN) && entity->shouldBePhysical();
|
||||
bool canBeKinematic = region <= workload::Region::R3;
|
||||
if (shouldBePhysical) {
|
||||
if (maybeShouldBePhysical) {
|
||||
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
|
||||
if (motionState) {
|
||||
motionState->setRegion(region);
|
||||
|
@ -330,6 +330,18 @@ void PhysicalEntitySimulation::buildMotionStatesForEntitiesThatNeedThem() {
|
|||
continue;
|
||||
}
|
||||
|
||||
uint8_t region = _space->getRegion(entity->getSpaceIndex());
|
||||
if (region == workload::Region::UNKNOWN) {
|
||||
// the workload hasn't categorized it yet --> skip for later
|
||||
++entityItr;
|
||||
continue;
|
||||
}
|
||||
if (region > workload::Region::R2) {
|
||||
// not in physical zone --> remove from list
|
||||
entityItr = _entitiesToAddToPhysics.erase(entityItr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entity->isReadyToComputeShape()) {
|
||||
ShapeRequest shapeRequest(entity);
|
||||
ShapeRequests::iterator requestItr = _shapeRequests.find(shapeRequest);
|
||||
|
|
|
@ -214,6 +214,9 @@ public:
|
|||
virtual StencilMaskMode getStencilMaskMode() const { return StencilMaskMode::NONE; }
|
||||
using StencilMaskMeshOperator = std::function<void(gpu::Batch&)>;
|
||||
virtual StencilMaskMeshOperator getStencilMaskMeshOperator() { return nullptr; }
|
||||
virtual void updateParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
|
||||
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
||||
float visionSqueezeSpotlightSize) {}
|
||||
|
||||
signals:
|
||||
void recommendedFramebufferSizeChanged(const QSize& size);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <shaders/Shaders.h>
|
||||
|
||||
ProceduralSkybox::ProceduralSkybox(uint64_t created) : graphics::Skybox(), _created(created) {
|
||||
// FIXME: support forward rendering for procedural skyboxes (needs haze calculation)
|
||||
_procedural._vertexSource = gpu::Shader::createVertex(shader::graphics::vertex::skybox)->getSource();
|
||||
_procedural._opaqueFragmentSource = shader::Source::get(shader::procedural::fragment::proceduralSkybox);
|
||||
// Adjust the pipeline state for background using the stencil test
|
||||
|
@ -40,15 +41,15 @@ void ProceduralSkybox::clear() {
|
|||
Skybox::clear();
|
||||
}
|
||||
|
||||
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const {
|
||||
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const {
|
||||
if (_procedural.isReady()) {
|
||||
ProceduralSkybox::render(batch, frustum, (*this));
|
||||
ProceduralSkybox::render(batch, frustum, (*this), forward);
|
||||
} else {
|
||||
Skybox::render(batch, frustum);
|
||||
Skybox::render(batch, frustum, forward);
|
||||
}
|
||||
}
|
||||
|
||||
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) {
|
||||
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox, bool forward) {
|
||||
glm::mat4 projMat;
|
||||
viewFrustum.evalProjectionMatrix(projMat);
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ public:
|
|||
bool empty() override;
|
||||
void clear() override;
|
||||
|
||||
void render(gpu::Batch& batch, const ViewFrustum& frustum) const override;
|
||||
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox);
|
||||
void render(gpu::Batch& batch, const ViewFrustum& frustum, bool forward) const override;
|
||||
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox, bool forward);
|
||||
|
||||
uint64_t getCreated() const { return _created; }
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <gpu/Context.h>
|
||||
|
||||
#include <graphics/ShaderConstants.h>
|
||||
|
||||
std::string BackgroundStage::_stageName { "BACKGROUND_STAGE"};
|
||||
const BackgroundStage::Index BackgroundStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
|
@ -71,6 +73,8 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext,
|
|||
}
|
||||
}
|
||||
|
||||
const auto& hazeFrame = inputs.get2();
|
||||
|
||||
if (skybox && !skybox->empty()) {
|
||||
PerformanceTimer perfTimer("skybox");
|
||||
auto args = renderContext->args;
|
||||
|
@ -91,7 +95,18 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext,
|
|||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
skybox->render(batch, args->getViewFrustum());
|
||||
// If we're using forward rendering, we need to calculate haze
|
||||
if (args->_renderMethod == render::Args::RenderMethod::FORWARD) {
|
||||
const auto& hazeStage = args->_scene->getStage<HazeStage>();
|
||||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front());
|
||||
if (hazePointer) {
|
||||
batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skybox->render(batch, args->getViewFrustum(), args->_renderMethod == render::Args::RenderMethod::FORWARD);
|
||||
});
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <unordered_map>
|
||||
#include <render/IndexedContainer.h>
|
||||
#include <render/Stage.h>
|
||||
#include "HazeStage.h"
|
||||
|
||||
#include "LightingModel.h"
|
||||
|
||||
|
@ -81,7 +82,7 @@ public:
|
|||
|
||||
class DrawBackgroundStage {
|
||||
public:
|
||||
using Inputs = render::VaryingSet2<LightingModelPointer, BackgroundStage::FramePointer>;
|
||||
using Inputs = render::VaryingSet3<LightingModelPointer, BackgroundStage::FramePointer, HazeStage::FramePointer>;
|
||||
using JobModel = render::Job::ModelI<DrawBackgroundStage, Inputs>;
|
||||
|
||||
DrawBackgroundStage() {}
|
||||
|
|
|
@ -432,7 +432,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front());
|
||||
if (hazePointer) {
|
||||
batch.setUniformBuffer(ru::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
|
||||
batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,7 +655,6 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) {
|
|||
if (!_defaultHaze) {
|
||||
auto hazeStage = renderContext->_scene->getStage<HazeStage>();
|
||||
if (hazeStage) {
|
||||
|
||||
auto haze = std::make_shared<graphics::Haze>();
|
||||
|
||||
_defaultHaze = haze;
|
||||
|
|
|
@ -78,7 +78,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
|
|||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(outputFramebufferSize, args->_viewport));
|
||||
|
||||
batch.setPipeline(_hazePipeline);
|
||||
batch.setUniformBuffer(ru::Buffer::HazeParams, haze->getHazeParametersBuffer());
|
||||
batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, haze->getHazeParametersBuffer());
|
||||
|
||||
batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, transformBuffer->getFrameTransformBuffer());
|
||||
batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer());
|
||||
|
|
|
@ -1,247 +0,0 @@
|
|||
<!
|
||||
// ForwardGlobalLight.slh
|
||||
// libraries/render-utils/src
|
||||
//
|
||||
// Created by Gabriel Calero & Cristian Duarte on 4/7/17.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
!>
|
||||
<@if not DEFERRED_GLOBAL_LIGHT_SLH@>
|
||||
<@def DEFERRED_GLOBAL_LIGHT_SLH@>
|
||||
|
||||
<@include graphics/Light.slh@>
|
||||
|
||||
<@include LightingModel.slh@>
|
||||
<$declareLightBuffer()$>
|
||||
<$declareLightAmbientBuffer()$>
|
||||
|
||||
<@include LightAmbient.slh@>
|
||||
<@include LightDirectional.slh@>
|
||||
|
||||
<@func prepareGlobalLight(positionES, normalWS)@>
|
||||
// prepareGlobalLight
|
||||
// Transform directions to worldspace
|
||||
vec3 fragNormalWS = vec3(<$normalWS$>);
|
||||
vec3 fragPositionWS = vec3(invViewMat * vec4(<$positionES$>, 1.0));
|
||||
vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;
|
||||
vec3 fragEyeDirWS = normalize(fragEyeVectorWS);
|
||||
|
||||
// Get light
|
||||
Light light = getKeyLight();
|
||||
LightAmbient lightAmbient = getLightAmbient();
|
||||
|
||||
vec3 lightDirection = getLightDirection(light);
|
||||
vec3 lightIrradiance = getLightIrradiance(light);
|
||||
|
||||
vec3 color = vec3(0.0);
|
||||
|
||||
<@endfunc@>
|
||||
|
||||
|
||||
<@func declareEvalAmbientGlobalColor()@>
|
||||
vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness) {
|
||||
<$prepareGlobalLight(position, normal)$>
|
||||
color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(lightAmbient);
|
||||
return color;
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func declareEvalAmbientSphereGlobalColor(supportScattering)@>
|
||||
|
||||
<$declareLightingAmbient(1, _SCRIBE_NULL, _SCRIBE_NULL, $supportScattering$)$>
|
||||
<$declareLightingDirectional($supportScattering$)$>
|
||||
|
||||
<@if supportScattering@>
|
||||
<$declareDeferredCurvature()$>
|
||||
<@endif@>
|
||||
|
||||
vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,
|
||||
vec3 albedo, vec3 fresnel, float metallic, float roughness
|
||||
<@if supportScattering@>
|
||||
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
|
||||
<@endif@> ) {
|
||||
|
||||
<$prepareGlobalLight(position, normal)$>
|
||||
|
||||
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
|
||||
|
||||
// Ambient
|
||||
vec3 ambientDiffuse;
|
||||
vec3 ambientSpecular;
|
||||
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance
|
||||
<@if supportScattering@>
|
||||
,scattering, midNormalCurvature, lowNormalCurvature
|
||||
<@endif@> );
|
||||
color += ambientDiffuse;
|
||||
color += ambientSpecular;
|
||||
|
||||
|
||||
// Directional
|
||||
vec3 directionalDiffuse;
|
||||
vec3 directionalSpecular;
|
||||
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation
|
||||
<@if supportScattering@>
|
||||
,scattering, midNormalCurvature, lowNormalCurvature
|
||||
<@endif@> );
|
||||
color += directionalDiffuse;
|
||||
color += directionalSpecular;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
<@endfunc@>
|
||||
|
||||
|
||||
<@func declareEvalSkyboxGlobalColor(supportScattering)@>
|
||||
|
||||
<$declareLightingAmbient(_SCRIBE_NULL, 1, _SCRIBE_NULL, $supportScattering$)$>
|
||||
<$declareLightingDirectional($supportScattering$)$>
|
||||
|
||||
<@if supportScattering@>
|
||||
<$declareDeferredCurvature()$>
|
||||
<@endif@>
|
||||
|
||||
vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,
|
||||
vec3 albedo, vec3 fresnel, float metallic, float roughness
|
||||
<@if supportScattering@>
|
||||
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
|
||||
<@endif@>
|
||||
) {
|
||||
<$prepareGlobalLight(position, normal)$>
|
||||
|
||||
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
|
||||
|
||||
// Ambient
|
||||
vec3 ambientDiffuse;
|
||||
vec3 ambientSpecular;
|
||||
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance
|
||||
<@if supportScattering@>
|
||||
,scattering, midNormalCurvature, lowNormalCurvature
|
||||
<@endif@>
|
||||
);
|
||||
color += ambientDiffuse;
|
||||
color += ambientSpecular;
|
||||
|
||||
vec3 directionalDiffuse;
|
||||
vec3 directionalSpecular;
|
||||
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation
|
||||
<@if supportScattering@>
|
||||
,scattering, midNormalCurvature, lowNormalCurvature
|
||||
<@endif@>
|
||||
);
|
||||
color += directionalDiffuse;
|
||||
color += directionalSpecular;
|
||||
|
||||
// FIXME - temporarily removed until we support it for forward...
|
||||
// Attenuate the light if haze effect selected
|
||||
// if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {
|
||||
// color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS);
|
||||
// }
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
<@endfunc@>
|
||||
|
||||
<@func declareEvalLightmappedColor()@>
|
||||
vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {
|
||||
Light light = getKeyLight();
|
||||
LightAmbient ambient = getLightAmbient();
|
||||
|
||||
// Catch normals perpendicular to the projection plane, hence the magic number for the threshold
|
||||
// It should be just 0, but we have inaccuracy so we overshoot
|
||||
const float PERPENDICULAR_THRESHOLD = -0.005;
|
||||
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace
|
||||
float diffuseDot = dot(fragNormal, -getLightDirection(light));
|
||||
float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot);
|
||||
|
||||
// Reevaluate the shadow attenuation for light facing fragments
|
||||
float lightAttenuation = (1.0 - facingLight) + facingLight * shadowAttenuation;
|
||||
|
||||
// Diffuse light is the lightmap dimmed by shadow
|
||||
vec3 diffuseLight = lightAttenuation * lightmap;
|
||||
|
||||
// Ambient light is the lightmap when in shadow
|
||||
vec3 ambientLight = (1.0 - lightAttenuation) * lightmap * getLightAmbientIntensity(ambient);
|
||||
|
||||
return isLightmapEnabled() * obscurance * albedo * (diffuseLight + ambientLight);
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
|
||||
|
||||
<@include Haze.slh@>
|
||||
|
||||
<@func declareEvalGlobalLightingAlphaBlended()@>
|
||||
|
||||
<$declareLightingAmbient(1, 1, 1)$>
|
||||
<$declareLightingDirectional()$>
|
||||
|
||||
vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) {
|
||||
<$prepareGlobalLight(position, normal)$>
|
||||
|
||||
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
|
||||
|
||||
color += emissive * isEmissiveEnabled();
|
||||
|
||||
// Ambient
|
||||
vec3 ambientDiffuse;
|
||||
vec3 ambientSpecular;
|
||||
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);
|
||||
color += ambientDiffuse;
|
||||
|
||||
// Directional
|
||||
vec3 directionalDiffuse;
|
||||
vec3 directionalSpecular;
|
||||
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
|
||||
color += directionalDiffuse;
|
||||
color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
vec3 evalGlobalLightingAlphaBlendedWithHaze(
|
||||
mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,
|
||||
vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity)
|
||||
{
|
||||
<$prepareGlobalLight(position, normal)$>
|
||||
|
||||
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
|
||||
|
||||
color += emissive * isEmissiveEnabled();
|
||||
|
||||
// Ambient
|
||||
vec3 ambientDiffuse;
|
||||
vec3 ambientSpecular;
|
||||
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);
|
||||
color += ambientDiffuse;
|
||||
|
||||
// Directional
|
||||
vec3 directionalDiffuse;
|
||||
vec3 directionalSpecular;
|
||||
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
|
||||
color += directionalDiffuse;
|
||||
color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity);
|
||||
|
||||
// Haze
|
||||
// FIXME - temporarily removed until we support it for forward...
|
||||
/* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
|
||||
vec4 hazeColor = computeHazeColor(
|
||||
positionES, // fragment position in eye coordinates
|
||||
fragPositionWS, // fragment position in world coordinates
|
||||
invViewMat[3].xyz, // eye position in world coordinates
|
||||
lightDirection // keylight direction vector
|
||||
);
|
||||
|
||||
color = mix(color.rgb, hazeColor.rgb, hazeColor.a);
|
||||
}*/
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
<@endfunc@>
|
||||
|
||||
|
||||
<@endif@>
|
|
@ -113,6 +113,7 @@ static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, no
|
|||
static const uint SHAPE_TEXCOORD0_OFFSET = offsetof(GeometryCache::ShapeVertex, uv);
|
||||
static const uint SHAPE_TANGENT_OFFSET = offsetof(GeometryCache::ShapeVertex, tangent);
|
||||
|
||||
std::map<std::pair<bool, bool>, gpu::PipelinePointer> GeometryCache::_webPipelines;
|
||||
std::map<std::pair<bool, bool>, gpu::PipelinePointer> GeometryCache::_gridPipelines;
|
||||
|
||||
void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector<glm::vec3> &outPointList) {
|
||||
|
@ -2018,7 +2019,7 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo
|
|||
const float DEPTH_BIAS = 0.001f;
|
||||
|
||||
static const std::vector<std::tuple<bool, bool, uint32_t>> keys = {
|
||||
std::make_tuple(false, false, grid), std::make_tuple(false, true, forward_grid), std::make_tuple(true, false, grid_translucent), std::make_tuple(true, true, forward_grid_translucent)
|
||||
std::make_tuple(false, false, grid), std::make_tuple(false, true, grid_forward), std::make_tuple(true, false, grid_translucent), std::make_tuple(true, true, grid_translucent_forward)
|
||||
};
|
||||
|
||||
for (auto& key : keys) {
|
||||
|
@ -2109,34 +2110,35 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) {
|
|||
return a.getRaw() == b.getRaw();
|
||||
}
|
||||
|
||||
static void buildWebShader(int programId, bool blendEnable,
|
||||
gpu::ShaderPointer& shaderPointerOut, gpu::PipelinePointer& pipelinePointerOut) {
|
||||
shaderPointerOut = gpu::Shader::createProgram(programId);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(blendEnable,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
PrepareStencil::testMaskDrawShapeNoAA(*state);
|
||||
|
||||
pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state);
|
||||
void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward) {
|
||||
batch.setPipeline(getWebBrowserProgram(transparent, forward));
|
||||
}
|
||||
|
||||
void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent) {
|
||||
batch.setPipeline(getWebBrowserProgram(transparent));
|
||||
}
|
||||
gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent, bool forward) {
|
||||
if (_webPipelines.empty()) {
|
||||
using namespace shader::render_utils::program;
|
||||
const int NUM_WEB_PIPELINES = 4;
|
||||
for (int i = 0; i < NUM_WEB_PIPELINES; ++i) {
|
||||
bool transparent = i & 1;
|
||||
bool forward = i & 2;
|
||||
|
||||
gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent) {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]() {
|
||||
// FIXME: need a forward pipeline for this
|
||||
buildWebShader(shader::render_utils::program::simple_opaque_web_browser, false, _simpleOpaqueWebBrowserShader, _simpleOpaqueWebBrowserPipeline);
|
||||
buildWebShader(shader::render_utils::program::simple_transparent_web_browser, true, _simpleTransparentWebBrowserShader, _simpleTransparentWebBrowserPipeline);
|
||||
});
|
||||
// For any non-opaque or non-deferred pipeline, we use web_browser_forward
|
||||
auto pipeline = (transparent || forward) ? web_browser_forward : web_browser;
|
||||
|
||||
return transparent ? _simpleTransparentWebBrowserPipeline : _simpleOpaqueWebBrowserPipeline;
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
// FIXME: do we need a testMaskDrawNoAA?
|
||||
PrepareStencil::testMaskDrawShapeNoAA(*state);
|
||||
state->setBlendFunction(transparent,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
|
||||
_webPipelines[{ transparent, forward }] = gpu::Pipeline::create(gpu::Shader::createProgram(pipeline), state);
|
||||
}
|
||||
}
|
||||
|
||||
return _webPipelines[{ transparent, forward }];
|
||||
}
|
||||
|
||||
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool isAntiAliased, bool forward) {
|
||||
|
@ -2164,24 +2166,24 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
|
|||
std::call_once(once, [&]() {
|
||||
using namespace shader::render_utils::program;
|
||||
|
||||
_forwardSimpleShader = gpu::Shader::createProgram(forward_simple_textured);
|
||||
_forwardTransparentShader = gpu::Shader::createProgram(forward_simple_textured_transparent);
|
||||
_forwardUnlitShader = gpu::Shader::createProgram(forward_simple_textured_unlit);
|
||||
_forwardSimpleShader = gpu::Shader::createProgram(simple_forward);
|
||||
_forwardTransparentShader = gpu::Shader::createProgram(simple_translucent_forward);
|
||||
_forwardUnlitShader = gpu::Shader::createProgram(simple_unlit_forward);
|
||||
|
||||
_simpleShader = gpu::Shader::createProgram(simple_textured);
|
||||
_transparentShader = gpu::Shader::createProgram(simple_transparent_textured);
|
||||
_unlitShader = gpu::Shader::createProgram(simple_textured_unlit);
|
||||
_simpleShader = gpu::Shader::createProgram(simple);
|
||||
_transparentShader = gpu::Shader::createProgram(simple_translucent);
|
||||
_unlitShader = gpu::Shader::createProgram(simple_unlit);
|
||||
});
|
||||
} else {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]() {
|
||||
using namespace shader::render_utils::program;
|
||||
// FIXME: these aren't right...
|
||||
_forwardSimpleFadeShader = gpu::Shader::createProgram(forward_simple_textured);
|
||||
_forwardUnlitFadeShader = gpu::Shader::createProgram(forward_simple_textured_unlit);
|
||||
// Fading is currently disabled during forward rendering
|
||||
_forwardSimpleFadeShader = gpu::Shader::createProgram(simple_forward);
|
||||
_forwardUnlitFadeShader = gpu::Shader::createProgram(simple_unlit_forward);
|
||||
|
||||
_simpleFadeShader = gpu::Shader::createProgram(simple_textured_fade);
|
||||
_unlitFadeShader = gpu::Shader::createProgram(simple_textured_unlit_fade);
|
||||
_simpleFadeShader = gpu::Shader::createProgram(simple_fade);
|
||||
_unlitFadeShader = gpu::Shader::createProgram(simple_unlit_fade);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue