Merge branch 'master' of github.com:highfidelity/hifi into head-controller

This commit is contained in:
Seth Alves 2017-06-07 10:09:46 -07:00
commit b1c7c251ac
100 changed files with 1124 additions and 1039 deletions

View file

@ -1,5 +1,7 @@
This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit. This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit.
## Building High Fidelity
### Step 1. Installing Visual Studio 2013 ### Step 1. Installing Visual Studio 2013
If you don't already have the Community or Professional edition of Visual Studio 2013, download and install [Visual Studio Community 2013](https://www.visualstudio.com/en-us/news/releasenotes/vs2013-community-vs). You do not need to install any of the optional components when going through the installer. If you don't already have the Community or Professional edition of Visual Studio 2013, download and install [Visual Studio Community 2013](https://www.visualstudio.com/en-us/news/releasenotes/vs2013-community-vs). You do not need to install any of the optional components when going through the installer.
@ -18,8 +20,8 @@ Keep the default components checked when going through the installer.
### Step 4. Setting Qt Environment Variable ### Step 4. Setting Qt Environment Variable
Go to "Control Panel > System > Advanced System Settings > Environment Variables > New..." (or search “Environment Variables” in Start Search). Go to `Control Panel > System > Advanced System Settings > Environment Variables > New...` (or search “Environment Variables” in Start Search).
* Set "Variable name": QT_CMAKE_PREFIX_PATH * Set "Variable name": `QT_CMAKE_PREFIX_PATH`
* Set "Variable value": `%QT_DIR%\5.6\msvc2013_64\lib\cmake` * Set "Variable value": `%QT_DIR%\5.6\msvc2013_64\lib\cmake`
### Step 5. Installing OpenSSL ### Step 5. Installing OpenSSL
@ -29,34 +31,36 @@ Download and install the [Win64 OpenSSL v1.0.2L Installer](https://slproweb.com/
### Step 6. Running CMake to Generate Build Files ### Step 6. Running CMake to Generate Build Files
Run Command Prompt from Start and run the following commands: Run Command Prompt from Start and run the following commands:
cd "%HIFI_DIR%" ````
mkdir build cd "%HIFI_DIR%"
cd build mkdir build
cmake .. -G "Visual Studio 12 Win64" cd build
cmake .. -G "Visual Studio 12 Win64"
````
Where %HIFI_DIR% is the directory for the highfidelity repository. Where `%HIFI_DIR%` is the directory for the highfidelity repository.
### Step 7. Making a Build ### Step 7. Making a Build
Open '%HIFI_DIR%\build\hifi.sln' using Visual Studio. Open `%HIFI_DIR%\build\hifi.sln` using Visual Studio.
Change the Solution Configuration (next to the green play button) from "Debug" to "Release" for best performance. Change the Solution Configuration (next to the green play button) from "Debug" to "Release" for best performance.
Run Build > Build Solution. Run `Build > Build Solution`.
### Step 8. Testing Interface ### Step 8. Testing Interface
Create another environment variable (see Step #4) Create another environment variable (see Step #4)
* Set "Variable name": _NO_DEBUG_HEAP * Set "Variable name": `_NO_DEBUG_HEAP`
* Set "Variable value": 1 * Set "Variable value": `1`
In Visual Studio, right+click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run Debug > Start Debugging. In Visual Studio, right+click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run `Debug > Start Debugging`.
Now, you should have a full build of High Fidelity and be able to run the Interface using Visual Studio. Please check our [Docs](https://wiki.highfidelity.com/wiki/Main_Page) for more information regarding the programming workflow. Now, you should have a full build of High Fidelity and be able to run the Interface using Visual Studio. Please check our [Docs](https://wiki.highfidelity.com/wiki/Main_Page) for more information regarding the programming workflow.
Note: You can also run Interface by launching it from command line or File Explorer from %HIFI_DIR%\build\interface\Release\interface.exe Note: You can also run Interface by launching it from command line or File Explorer from `%HIFI_DIR%\build\interface\Release\interface.exe`
### Troubleshooting ## Troubleshooting
For any problems after Step #6, first try this: For any problems after Step #6, first try this:
* Delete your locally cloned copy of the highfidelity repository * Delete your locally cloned copy of the highfidelity repository
@ -66,16 +70,16 @@ For any problems after Step #6, first try this:
#### CMake gives you the same error message repeatedly after the build fails #### CMake gives you the same error message repeatedly after the build fails
Remove `CMakeCache.txt` found in the '%HIFI_DIR%\build' directory Remove `CMakeCache.txt` found in the `%HIFI_DIR%\build` directory.
#### nmake cannot be found #### nmake cannot be found
Make sure nmake.exe is located at the following path: Make sure nmake.exe is located at the following path:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin
If not, add the directory where nmake is located to the PATH environment variable. If not, add the directory where nmake is located to the PATH environment variable.
#### Qt is throwing an error #### Qt is throwing an error
Make sure you have the correct version (5.6.2) installed and 'QT_CMAKE_PREFIX_PATH' environment variable is set correctly. Make sure you have the correct version (5.6.2) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly.

View file

@ -8,8 +8,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
if (WIN32) if (WIN32)
ExternalProject_Add( ExternalProject_Add(
${EXTERNAL_NAME} ${EXTERNAL_NAME}
URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.zip URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.hifi.zip
URL_MD5 3ea6eeadbcc69071acf9c49ba565760e URL_MD5 10da01cf601f88f6dc12a6bc13c89136
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND "" BUILD_COMMAND ""
INSTALL_COMMAND "" INSTALL_COMMAND ""
@ -29,8 +29,8 @@ else ()
ExternalProject_Add( ExternalProject_Add(
${EXTERNAL_NAME} ${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.zip URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.hifi.zip
URL_MD5 81b8fa6a9ee3f986088eb6e2215d6a57 URL_MD5 5794b950f8b265a9a41b2839b3bf7ebb
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=1 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=1 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
LOG_DOWNLOAD 1 LOG_DOWNLOAD 1
LOG_CONFIGURE 1 LOG_CONFIGURE 1

View file

@ -2,7 +2,6 @@ import QtQuick 2.5
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtWebChannel 1.0 import QtWebChannel 1.0
import QtWebEngine 1.2 import QtWebEngine 1.2
import FileTypeProfile 1.0
import "controls-uit" import "controls-uit"
import "styles" as HifiStyles import "styles" as HifiStyles
@ -209,6 +208,7 @@ ScrollingWindow {
WebView { WebView {
id: webview id: webview
url: "https://highfidelity.com/" url: "https://highfidelity.com/"
profile: FileTypeProfile;
property alias eventBridgeWrapper: eventBridgeWrapper property alias eventBridgeWrapper: eventBridgeWrapper
@ -218,10 +218,6 @@ ScrollingWindow {
property var eventBridge; property var eventBridge;
} }
profile: FileTypeProfile {
id: webviewProfile
storageName: "qmlWebEngine"
}
webChannel.registeredObjects: [eventBridgeWrapper] webChannel.registeredObjects: [eventBridgeWrapper]

View file

@ -8,7 +8,6 @@ import "controls-uit" as HifiControls
import "styles" as HifiStyles import "styles" as HifiStyles
import "styles-uit" import "styles-uit"
import "windows" import "windows"
import HFTabletWebEngineProfile 1.0
Item { Item {
id: root id: root
@ -47,10 +46,7 @@ Item {
width: parent.width width: parent.width
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
profile: HFTabletWebEngineProfile { profile: HFTabletWebEngineProfile;
id: webviewTabletProfile
storageName: "qmlTabletWebEngine"
}
property string userScriptUrl: "" property string userScriptUrl: ""

View file

@ -10,13 +10,10 @@
import QtQuick 2.5 import QtQuick 2.5
import QtWebEngine 1.2 import QtWebEngine 1.2
import HFWebEngineProfile 1.0
WebEngineView { WebEngineView {
id: root id: root
// profile: desktop.browserProfile
Component.onCompleted: { Component.onCompleted: {
console.log("Connecting JS messaging to Hifi Logging") console.log("Connecting JS messaging to Hifi Logging")
// Ensure the JS from the web-engine makes it to our logging // Ensure the JS from the web-engine makes it to our logging

View file

@ -2,7 +2,6 @@ import QtQuick 2.5
import QtWebEngine 1.1 import QtWebEngine 1.1
import QtWebChannel 1.0 import QtWebChannel 1.0
import "../controls-uit" as HiFiControls import "../controls-uit" as HiFiControls
import HFTabletWebEngineProfile 1.0
Item { Item {
property alias url: root.url property alias url: root.url
@ -39,10 +38,7 @@ Item {
width: parent.width width: parent.width
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
profile: HFTabletWebEngineProfile { profile: HFTabletWebEngineProfile;
id: webviewProfile
storageName: "qmlTabletWebEngine"
}
property string userScriptUrl: "" property string userScriptUrl: ""

View file

@ -2,7 +2,6 @@ import QtQuick 2.5
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import QtWebEngine 1.2 import QtWebEngine 1.2
import QtWebChannel 1.0 import QtWebChannel 1.0
import HFTabletWebEngineProfile 1.0
import "../controls-uit" as HiFiControls import "../controls-uit" as HiFiControls
import "../styles" as HifiStyles import "../styles" as HifiStyles
import "../styles-uit" import "../styles-uit"
@ -150,10 +149,7 @@ Item {
width: parent.width width: parent.width
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height - web.headerHeight : parent.height - web.headerHeight height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height - web.headerHeight : parent.height - web.headerHeight
anchors.top: buttons.bottom anchors.top: buttons.bottom
profile: HFTabletWebEngineProfile { profile: HFTabletWebEngineProfile;
id: webviewTabletProfile
storageName: "qmlTabletWebEngine"
}
property string userScriptUrl: "" property string userScriptUrl: ""

View file

@ -10,13 +10,9 @@
import QtQuick 2.5 import QtQuick 2.5
import "." import "."
import FileTypeProfile 1.0
WebView { WebView {
viewProfile: FileTypeProfile { viewProfile: FileTypeProfile;
id: webviewProfile
storageName: "qmlWebEngine"
}
urlTag: "noDownload=true"; urlTag: "noDownload=true";
} }

View file

@ -2,7 +2,6 @@ import QtQuick 2.5
import QtWebEngine 1.1 import QtWebEngine 1.1
import QtWebChannel 1.0 import QtWebChannel 1.0
import "../controls-uit" as HiFiControls import "../controls-uit" as HiFiControls
import HFWebEngineProfile 1.0
Item { Item {
property alias url: root.url property alias url: root.url
@ -39,10 +38,7 @@ Item {
width: parent.width width: parent.width
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
profile: HFWebEngineProfile { profile: HFWebEngineProfile;
id: webviewProfile
storageName: "qmlWebEngine"
}
property string userScriptUrl: "" property string userScriptUrl: ""

View file

@ -2,7 +2,6 @@ import QtQuick 2.5
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import QtWebEngine 1.1; import QtWebEngine 1.1;
import Qt.labs.settings 1.0 import Qt.labs.settings 1.0
import HFWebEngineProfile 1.0
import "../desktop" as OriginalDesktop import "../desktop" as OriginalDesktop
import ".." import ".."
@ -27,11 +26,6 @@ OriginalDesktop.Desktop {
property alias toolWindow: toolWindow property alias toolWindow: toolWindow
ToolWindow { id: toolWindow } ToolWindow { id: toolWindow }
property var browserProfile: HFWebEngineProfile {
id: webviewProfile
storageName: "qmlWebEngine"
}
Action { Action {
text: "Open Browser" text: "Open Browser"
shortcut: "Ctrl+B" shortcut: "Ctrl+B"

View file

@ -5,7 +5,6 @@ import QtWebChannel 1.0
import QtQuick.Controls.Styles 1.4 import QtQuick.Controls.Styles 1.4
import "../../controls" import "../../controls"
import "../toolbars" import "../toolbars"
import HFWebEngineProfile 1.0
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
import "../../controls-uit" as HifiControls import "../../controls-uit" as HifiControls
import "../../styles-uit" import "../../styles-uit"

View file

@ -4,7 +4,6 @@ import QtQuick.Controls 1.4
import QtQml 2.2 import QtQml 2.2
import QtWebChannel 1.0 import QtWebChannel 1.0
import QtWebEngine 1.1 import QtWebEngine 1.1
import HFWebEngineProfile 1.0
import "." import "."

View file

@ -1,7 +1,6 @@
import QtQuick 2.0 import QtQuick 2.0
import Hifi 1.0 import Hifi 1.0
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import HFTabletWebEngineProfile 1.0
import "../../dialogs" import "../../dialogs"
import "../../controls" import "../../controls"

View file

@ -72,6 +72,7 @@
#include <ErrorDialog.h> #include <ErrorDialog.h>
#include <FileScriptingInterface.h> #include <FileScriptingInterface.h>
#include <Finally.h> #include <Finally.h>
#include <FingerprintUtils.h>
#include <FramebufferCache.h> #include <FramebufferCache.h>
#include <gpu/Batch.h> #include <gpu/Batch.h>
#include <gpu/Context.h> #include <gpu/Context.h>
@ -114,6 +115,7 @@
#include <RenderDeferredTask.h> #include <RenderDeferredTask.h>
#include <RenderForwardTask.h> #include <RenderForwardTask.h>
#include <ResourceCache.h> #include <ResourceCache.h>
#include <ResourceRequest.h>
#include <SandboxUtils.h> #include <SandboxUtils.h>
#include <SceneScriptingInterface.h> #include <SceneScriptingInterface.h>
#include <ScriptEngines.h> #include <ScriptEngines.h>
@ -148,9 +150,6 @@
#include "LODManager.h" #include "LODManager.h"
#include "ModelPackager.h" #include "ModelPackager.h"
#include "networking/CloseEventSender.h" #include "networking/CloseEventSender.h"
#include "networking/HFWebEngineProfile.h"
#include "networking/HFTabletWebEngineProfile.h"
#include "networking/FileTypeProfile.h"
#include "scripting/TestScriptingInterface.h" #include "scripting/TestScriptingInterface.h"
#include "scripting/AccountScriptingInterface.h" #include "scripting/AccountScriptingInterface.h"
#include "scripting/AssetMappingsScriptingInterface.h" #include "scripting/AssetMappingsScriptingInterface.h"
@ -248,6 +247,8 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda
Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS); Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com"; static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com";
static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds
static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensions { const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensions {
{ SVO_EXTENSION, &Application::importSVOFromURL }, { SVO_EXTENSION, &Application::importSVOFromURL },
@ -951,6 +952,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3; properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3;
} }
// add firstRun flag from settings to launch event
Setting::Handle<bool> firstRun { Settings::firstRun, true };
properties["first_run"] = firstRun.get();
// add the user's machine ID to the launch event
properties["machine_fingerprint"] = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint());
UserActivityLogger::getInstance().logAction("launch", properties); UserActivityLogger::getInstance().logAction("launch", properties);
// Tell our entity edit sender about our known jurisdictions // Tell our entity edit sender about our known jurisdictions
@ -1310,6 +1318,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond(); properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond();
properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond(); properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond();
properties["atp_in_kbps"] = bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer);
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer); SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer);
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
@ -1323,8 +1333,61 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1; properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1;
auto loadingRequests = ResourceCache::getLoadingRequests(); auto loadingRequests = ResourceCache::getLoadingRequests();
QJsonArray loadingRequestsStats;
for (const auto& request : loadingRequests) {
QJsonObject requestStats;
requestStats["filename"] = request->getURL().fileName();
requestStats["received"] = request->getBytesReceived();
requestStats["total"] = request->getBytesTotal();
requestStats["attempts"] = (int)request->getDownloadAttempts();
loadingRequestsStats.append(requestStats);
}
properties["active_downloads"] = loadingRequests.size(); properties["active_downloads"] = loadingRequests.size();
properties["pending_downloads"] = ResourceCache::getPendingRequestCount(); properties["pending_downloads"] = ResourceCache::getPendingRequestCount();
properties["active_downloads_details"] = loadingRequestsStats;
auto statTracker = DependencyManager::get<StatTracker>();
properties["processing_resources"] = statTracker->getStat("Processing").toInt();
properties["pending_processing_resources"] = statTracker->getStat("PendingProcessing").toInt();
QJsonObject startedRequests;
startedRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_STARTED).toInt();
startedRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_STARTED).toInt();
startedRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_STARTED).toInt();
startedRequests["total"] = startedRequests["atp"].toInt() + startedRequests["http"].toInt()
+ startedRequests["file"].toInt();
properties["started_requests"] = startedRequests;
QJsonObject successfulRequests;
successfulRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_SUCCESS).toInt();
successfulRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_SUCCESS).toInt();
successfulRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_SUCCESS).toInt();
successfulRequests["total"] = successfulRequests["atp"].toInt() + successfulRequests["http"].toInt()
+ successfulRequests["file"].toInt();
properties["successful_requests"] = successfulRequests;
QJsonObject failedRequests;
failedRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_FAILED).toInt();
failedRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt();
failedRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_FAILED).toInt();
failedRequests["total"] = failedRequests["atp"].toInt() + failedRequests["http"].toInt()
+ failedRequests["file"].toInt();
properties["failed_requests"] = failedRequests;
QJsonObject cacheRequests;
cacheRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_CACHE).toInt();
cacheRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_CACHE).toInt();
cacheRequests["total"] = cacheRequests["atp"].toInt() + cacheRequests["http"].toInt();
properties["cache_requests"] = cacheRequests;
QJsonObject atpMappingRequests;
atpMappingRequests["started"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_STARTED).toInt();
atpMappingRequests["failed"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_FAILED).toInt();
atpMappingRequests["successful"] = statTracker->getStat(STAT_ATP_MAPPING_REQUEST_SUCCESS).toInt();
properties["atp_mapping_requests"] = atpMappingRequests;
properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false; properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false;
@ -1340,9 +1403,43 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
properties["deleted_entity_cnt"] = entityActivityTracking.deletedEntityCount; properties["deleted_entity_cnt"] = entityActivityTracking.deletedEntityCount;
properties["edited_entity_cnt"] = entityActivityTracking.editedEntityCount; properties["edited_entity_cnt"] = entityActivityTracking.editedEntityCount;
NodeToOctreeSceneStats* octreeServerSceneStats = getOcteeSceneStats();
unsigned long totalServerOctreeElements = 0;
for (NodeToOctreeSceneStatsIterator i = octreeServerSceneStats->begin(); i != octreeServerSceneStats->end(); i++) {
totalServerOctreeElements += i->second.getTotalElements();
}
properties["local_octree_elements"] = (qint64) OctreeElement::getInternalNodeCount();
properties["server_octree_elements"] = (qint64) totalServerOctreeElements;
properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["active_display_plugin"] = getActiveDisplayPlugin()->getName();
properties["using_hmd"] = isHMDMode(); properties["using_hmd"] = isHMDMode();
_autoSwitchDisplayModeSupportedHMDPlugin = nullptr;
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
if (displayPlugin->isHmd() &&
displayPlugin->getSupportsAutoSwitch()) {
_autoSwitchDisplayModeSupportedHMDPlugin = displayPlugin;
_autoSwitchDisplayModeSupportedHMDPluginName =
_autoSwitchDisplayModeSupportedHMDPlugin->getName();
_previousHMDWornStatus =
_autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible();
break;
}
}
if (_autoSwitchDisplayModeSupportedHMDPlugin) {
if (getActiveDisplayPlugin() != _autoSwitchDisplayModeSupportedHMDPlugin &&
!_autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) {
startHMDStandBySession();
}
// Poll periodically to check whether the user has worn HMD or not. Switch Display mode accordingly.
// If the user wears HMD then switch to VR mode. If the user removes HMD then switch to Desktop mode.
QTimer* autoSwitchDisplayModeTimer = new QTimer(this);
connect(autoSwitchDisplayModeTimer, SIGNAL(timeout()), this, SLOT(switchDisplayMode()));
autoSwitchDisplayModeTimer->start(INTERVAL_TO_CHECK_HMD_WORN_STATUS);
}
auto glInfo = getGLContextData(); auto glInfo = getGLContextData();
properties["gl_info"] = glInfo; properties["gl_info"] = glInfo;
properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemSize()); properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemSize());
@ -1365,6 +1462,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
lastLeftHandPose = leftHandPose; lastLeftHandPose = leftHandPose;
lastRightHandPose = rightHandPose; lastRightHandPose = rightHandPose;
properties["local_socket_changes"] = DependencyManager::get<StatTracker>()->getStat(LOCAL_SOCKET_CHANGE_STAT).toInt();
UserActivityLogger::getInstance().logAction("stats", properties); UserActivityLogger::getInstance().logAction("stats", properties);
}); });
sendStatsTimer->start(); sendStatsTimer->start();
@ -1574,7 +1673,10 @@ void Application::aboutToQuit() {
} }
getActiveDisplayPlugin()->deactivate(); getActiveDisplayPlugin()->deactivate();
if (_autoSwitchDisplayModeSupportedHMDPlugin
&& _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) {
_autoSwitchDisplayModeSupportedHMDPlugin->endSession();
}
// use the CloseEventSender via a QThread to send an event that says the user asked for the app to close // use the CloseEventSender via a QThread to send an event that says the user asked for the app to close
auto closeEventSender = DependencyManager::get<CloseEventSender>(); auto closeEventSender = DependencyManager::get<CloseEventSender>();
QThread* closureEventThread = new QThread(this); QThread* closureEventThread = new QThread(this);
@ -1852,14 +1954,10 @@ void Application::initializeUi() {
UpdateDialog::registerType(); UpdateDialog::registerType();
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference"); qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
qmlRegisterType<HFWebEngineProfile>("HFWebEngineProfile", 1, 0, "HFWebEngineProfile");
qmlRegisterType<HFTabletWebEngineProfile>("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile");
qmlRegisterType<FileTypeProfile>("FileTypeProfile", 1, 0, "FileTypeProfile");
auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->create(_glWidget->qglContext()); offscreenUi->create(_glWidget->qglContext());
auto rootContext = offscreenUi->getRootContext(); auto surfaceContext = offscreenUi->getSurfaceContext();
offscreenUi->setProxyWindow(_window->windowHandle()); offscreenUi->setProxyWindow(_window->windowHandle());
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
@ -1871,7 +1969,7 @@ void Application::initializeUi() {
// do better detection in the offscreen UI of what has focus // do better detection in the offscreen UI of what has focus
offscreenUi->setNavigationFocused(false); offscreenUi->setNavigationFocused(false);
auto engine = rootContext->engine(); auto engine = surfaceContext->engine();
connect(engine, &QQmlEngine::quit, [] { connect(engine, &QQmlEngine::quit, [] {
qApp->quit(); qApp->quit();
}); });
@ -1880,79 +1978,78 @@ void Application::initializeUi() {
// For some reason there is already an "Application" object in the QML context, // For some reason there is already an "Application" object in the QML context,
// though I can't find it. Hence, "ApplicationInterface" // though I can't find it. Hence, "ApplicationInterface"
rootContext->setContextProperty("ApplicationInterface", this); surfaceContext->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data());
rootContext->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data()); surfaceContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
rootContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data()); surfaceContext->setContextProperty("AudioScope", DependencyManager::get<AudioScope>().data());
rootContext->setContextProperty("AudioScope", DependencyManager::get<AudioScope>().data());
rootContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data()); surfaceContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
rootContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data()); surfaceContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
_fileDownload = new FileScriptingInterface(engine); _fileDownload = new FileScriptingInterface(engine);
rootContext->setContextProperty("File", _fileDownload); surfaceContext->setContextProperty("File", _fileDownload);
connect(_fileDownload, &FileScriptingInterface::unzipResult, this, &Application::handleUnzip); connect(_fileDownload, &FileScriptingInterface::unzipResult, this, &Application::handleUnzip);
rootContext->setContextProperty("MyAvatar", getMyAvatar().get()); surfaceContext->setContextProperty("MyAvatar", getMyAvatar().get());
rootContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data()); surfaceContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data());
rootContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data()); surfaceContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());
rootContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data()); surfaceContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
rootContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data()); surfaceContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
rootContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface); surfaceContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);
rootContext->setContextProperty("Rates", new RatesScriptingInterface(this)); surfaceContext->setContextProperty("Rates", new RatesScriptingInterface(this));
rootContext->setContextProperty("pathToFonts", "../../");
rootContext->setContextProperty("TREE_SCALE", TREE_SCALE); surfaceContext->setContextProperty("TREE_SCALE", TREE_SCALE);
rootContext->setContextProperty("Quat", new Quat()); // FIXME Quat and Vec3 won't work with QJSEngine used by QML
rootContext->setContextProperty("Vec3", new Vec3()); surfaceContext->setContextProperty("Quat", new Quat());
rootContext->setContextProperty("Uuid", new ScriptUUID()); surfaceContext->setContextProperty("Vec3", new Vec3());
rootContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data()); surfaceContext->setContextProperty("Uuid", new ScriptUUID());
surfaceContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
rootContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data()); surfaceContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
rootContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data()); surfaceContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
rootContext->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data()); surfaceContext->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
rootContext->setContextProperty("Camera", &_myCamera); surfaceContext->setContextProperty("Camera", &_myCamera);
#if defined(Q_OS_MAC) || defined(Q_OS_WIN) #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
rootContext->setContextProperty("SpeechRecognizer", DependencyManager::get<SpeechRecognizer>().data()); surfaceContext->setContextProperty("SpeechRecognizer", DependencyManager::get<SpeechRecognizer>().data());
#endif #endif
rootContext->setContextProperty("Overlays", &_overlays); surfaceContext->setContextProperty("Overlays", &_overlays);
rootContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data()); surfaceContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
rootContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance()); surfaceContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
rootContext->setContextProperty("Stats", Stats::getInstance()); surfaceContext->setContextProperty("Stats", Stats::getInstance());
rootContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance()); surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
rootContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data()); surfaceContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
rootContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance()); surfaceContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance());
rootContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data()); surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
rootContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data()); surfaceContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
// Caches // Caches
rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data()); surfaceContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
rootContext->setContextProperty("TextureCache", DependencyManager::get<TextureCache>().data()); surfaceContext->setContextProperty("TextureCache", DependencyManager::get<TextureCache>().data());
rootContext->setContextProperty("ModelCache", DependencyManager::get<ModelCache>().data()); surfaceContext->setContextProperty("ModelCache", DependencyManager::get<ModelCache>().data());
rootContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data()); surfaceContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
rootContext->setContextProperty("Account", AccountScriptingInterface::getInstance()); surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
rootContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data()); surfaceContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
rootContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface); surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
rootContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
rootContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data()); surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
rootContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data()); surfaceContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data());
rootContext->setContextProperty("UndoStack", &_undoStackScriptingInterface); surfaceContext->setContextProperty("UndoStack", &_undoStackScriptingInterface);
rootContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data()); surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
rootContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data()); surfaceContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data());
rootContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data()); surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
rootContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data()); surfaceContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
rootContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get());
rootContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
rootContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data()); surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
rootContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get())); surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
} }
@ -2211,6 +2308,9 @@ void Application::paintGL() {
}); });
renderArgs._context->setStereoProjections(eyeProjections); renderArgs._context->setStereoProjections(eyeProjections);
renderArgs._context->setStereoViews(eyeOffsets); renderArgs._context->setStereoViews(eyeOffsets);
// Configure the type of display / stereo
renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR);
} }
renderArgs._blitFramebuffer = finalFramebuffer; renderArgs._blitFramebuffer = finalFramebuffer;
displaySide(&renderArgs, _myCamera); displaySide(&renderArgs, _myCamera);
@ -6787,6 +6887,35 @@ void Application::updateDisplayMode() {
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
} }
void Application::switchDisplayMode() {
if (!_autoSwitchDisplayModeSupportedHMDPlugin) {
return;
}
bool currentHMDWornStatus = _autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible();
if (currentHMDWornStatus != _previousHMDWornStatus) {
// Switch to respective mode as soon as currentHMDWornStatus changes
if (currentHMDWornStatus) {
qCDebug(interfaceapp) << "Switching from Desktop to HMD mode";
endHMDSession();
setActiveDisplayPlugin(_autoSwitchDisplayModeSupportedHMDPluginName);
} else {
qCDebug(interfaceapp) << "Switching from HMD to desktop mode";
setActiveDisplayPlugin(DESKTOP_DISPLAY_PLUGIN_NAME);
startHMDStandBySession();
}
emit activeDisplayPluginChanged();
}
_previousHMDWornStatus = currentHMDWornStatus;
}
void Application::startHMDStandBySession() {
_autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession();
}
void Application::endHMDSession() {
_autoSwitchDisplayModeSupportedHMDPlugin->endSession();
}
mat4 Application::getEyeProjection(int eye) const { mat4 Application::getEyeProjection(int eye) const {
QMutexLocker viewLocker(&_viewMutex); QMutexLocker viewLocker(&_viewMutex);
if (isHMDMode()) { if (isHMDMode()) {

View file

@ -442,7 +442,7 @@ private slots:
void addAssetToWorldErrorTimeout(); void addAssetToWorldErrorTimeout();
void handleSandboxStatus(QNetworkReply* reply); void handleSandboxStatus(QNetworkReply* reply);
void switchDisplayMode();
private: private:
static void initDisplay(); static void initDisplay();
void init(); void init();
@ -680,7 +680,11 @@ private:
FileScriptingInterface* _fileDownload; FileScriptingInterface* _fileDownload;
AudioInjector* _snapshotSoundInjector { nullptr }; AudioInjector* _snapshotSoundInjector { nullptr };
SharedSoundPointer _snapshotSound; SharedSoundPointer _snapshotSound;
DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin;
QString _autoSwitchDisplayModeSupportedHMDPluginName;
bool _previousHMDWornStatus;
void startHMDStandBySession();
void endHMDSession();
}; };
#endif // hifi_Application_h #endif // hifi_Application_h

View file

@ -51,6 +51,16 @@ Text3DOverlay::~Text3DOverlay() {
} }
} }
const QString Text3DOverlay::getText() const {
QMutexLocker lock(&_mutex);
return _text;
}
void Text3DOverlay::setText(const QString& text) {
QMutexLocker lock(&_mutex);
_text = text;
}
xColor Text3DOverlay::getBackgroundColor() { xColor Text3DOverlay::getBackgroundColor() {
if (_colorPulse == 0.0f) { if (_colorPulse == 0.0f) {
return _backgroundColor; return _backgroundColor;
@ -125,7 +135,7 @@ void Text3DOverlay::render(RenderArgs* args) {
// FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline // FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline
// for a gpu performance increase. Currently, // for a gpu performance increase. Currently,
// Text renderer sets its own pipeline, // Text renderer sets its own pipeline,
_textRenderer->draw(batch, 0, 0, _text, textColor, glm::vec2(-1.0f), getDrawInFront()); _textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), getDrawInFront());
// so before we continue, we must reset the pipeline // so before we continue, we must reset the pipeline
batch.setPipeline(args->_pipeline->pipeline); batch.setPipeline(args->_pipeline->pipeline);
args->_pipeline->prepare(batch); args->_pipeline->prepare(batch);
@ -188,7 +198,7 @@ void Text3DOverlay::setProperties(const QVariantMap& properties) {
QVariant Text3DOverlay::getProperty(const QString& property) { QVariant Text3DOverlay::getProperty(const QString& property) {
if (property == "text") { if (property == "text") {
return _text; return getText();
} }
if (property == "textAlpha") { if (property == "textAlpha") {
return _textAlpha; return _textAlpha;
@ -231,7 +241,7 @@ QSizeF Text3DOverlay::textSize(const QString& text) const {
return QSizeF(extents.x, extents.y) * pointToWorldScale; return QSizeF(extents.x, extents.y) * pointToWorldScale;
} }
bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance, bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance,
BoxFace &face, glm::vec3& surfaceNormal) { BoxFace &face, glm::vec3& surfaceNormal) {
Transform transform = getTransform(); Transform transform = getTransform();
applyTransformTo(transform, true); applyTransformTo(transform, true);

View file

@ -12,14 +12,14 @@
#define hifi_Text3DOverlay_h #define hifi_Text3DOverlay_h
#include <QString> #include <QString>
#include <QtCore/QMutex>
#include "Billboard3DOverlay.h" #include "Billboard3DOverlay.h"
class TextRenderer3D; class TextRenderer3D;
class Text3DOverlay : public Billboard3DOverlay { class Text3DOverlay : public Billboard3DOverlay {
Q_OBJECT Q_OBJECT
public: public:
static QString const TYPE; static QString const TYPE;
virtual QString getType() const override { return TYPE; } virtual QString getType() const override { return TYPE; }
@ -34,7 +34,7 @@ public:
virtual const render::ShapeKey getShapeKey() override; virtual const render::ShapeKey getShapeKey() override;
// getters // getters
const QString& getText() const { return _text; } const QString getText() const;
float getLineHeight() const { return _lineHeight; } float getLineHeight() const { return _lineHeight; }
float getLeftMargin() const { return _leftMargin; } float getLeftMargin() const { return _leftMargin; }
float getTopMargin() const { return _topMargin; } float getTopMargin() const { return _topMargin; }
@ -45,7 +45,7 @@ public:
float getBackgroundAlpha() { return getAlpha(); } float getBackgroundAlpha() { return getAlpha(); }
// setters // setters
void setText(const QString& text) { _text = text; } void setText(const QString& text);
void setTextAlpha(float alpha) { _textAlpha = alpha; } void setTextAlpha(float alpha) { _textAlpha = alpha; }
void setLineHeight(float value) { _lineHeight = value; } void setLineHeight(float value) { _lineHeight = value; }
void setLeftMargin(float margin) { _leftMargin = margin; } void setLeftMargin(float margin) { _leftMargin = margin; }
@ -58,15 +58,16 @@ public:
QSizeF textSize(const QString& test) const; // Meters QSizeF textSize(const QString& test) const; // Meters
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal) override; BoxFace& face, glm::vec3& surfaceNormal) override;
virtual Text3DOverlay* createClone() const override; virtual Text3DOverlay* createClone() const override;
private: private:
TextRenderer3D* _textRenderer = nullptr; TextRenderer3D* _textRenderer = nullptr;
QString _text; QString _text;
mutable QMutex _mutex; // used to make get/setText threadsafe, mutable so can be used in const functions
xColor _backgroundColor = xColor { 0, 0, 0 }; xColor _backgroundColor = xColor { 0, 0, 0 };
float _textAlpha { 1.0f }; float _textAlpha { 1.0f };
float _lineHeight { 1.0f }; float _lineHeight { 1.0f };

View file

@ -135,7 +135,7 @@ Web3DOverlay::~Web3DOverlay() {
void Web3DOverlay::update(float deltatime) { void Web3DOverlay::update(float deltatime) {
if (_webSurface) { if (_webSurface) {
// update globalPosition // update globalPosition
_webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
} }
} }
@ -163,57 +163,56 @@ void Web3DOverlay::loadSourceURL() {
_webSurface->resume(); _webSurface->resume();
_webSurface->getRootItem()->setProperty("url", _url); _webSurface->getRootItem()->setProperty("url", _url);
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
_webSurface->getRootContext()->setContextProperty("ApplicationInterface", qApp);
} else { } else {
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath())); _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath()));
_webSurface->load(_url, [&](QQmlContext* context, QObject* obj) {}); _webSurface->load(_url, [&](QQmlContext* context, QObject* obj) {});
_webSurface->resume(); _webSurface->resume();
_webSurface->getRootContext()->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
_webSurface->getRootContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
_webSurface->getRootContext()->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
_webSurface->getRootContext()->setContextProperty("Preferences", DependencyManager::get<Preferences>().data()); _webSurface->getSurfaceContext()->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
_webSurface->getRootContext()->setContextProperty("Vec3", new Vec3()); _webSurface->getSurfaceContext()->setContextProperty("Vec3", new Vec3());
_webSurface->getRootContext()->setContextProperty("Quat", new Quat()); _webSurface->getSurfaceContext()->setContextProperty("Quat", new Quat());
_webSurface->getRootContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get()); _webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
_webSurface->getRootContext()->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
_webSurface->getRootContext()->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data()); _webSurface->getSurfaceContext()->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") { if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto flags = tabletScriptingInterface->getFlags(); auto flags = tabletScriptingInterface->getFlags();
_webSurface->getRootContext()->setContextProperty("offscreenFlags", flags); _webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags);
_webSurface->getRootContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data()); _webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
_webSurface->getRootContext()->setContextProperty("Account", AccountScriptingInterface::getInstance()); _webSurface->getSurfaceContext()->setContextProperty("Account", AccountScriptingInterface::getInstance());
_webSurface->getRootContext()->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data()); _webSurface->getSurfaceContext()->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
_webSurface->getRootContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
_webSurface->getRootContext()->setContextProperty("fileDialogHelper", new FileDialogHelper()); _webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper());
_webSurface->getRootContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get()); _webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
_webSurface->getRootContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data()); _webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
_webSurface->getRootContext()->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
_webSurface->getRootContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
_webSurface->getRootContext()->setContextProperty("LODManager", DependencyManager::get<LODManager>().data()); _webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
_webSurface->getRootContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data()); _webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
_webSurface->getRootContext()->setContextProperty("DCModel", DependencyManager::get<DomainConnectionModel>().data()); _webSurface->getSurfaceContext()->setContextProperty("DCModel", DependencyManager::get<DomainConnectionModel>().data());
_webSurface->getRootContext()->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance()); _webSurface->getSurfaceContext()->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance());
_webSurface->getRootContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); _webSurface->getSurfaceContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
_webSurface->getRootContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); _webSurface->getSurfaceContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
_webSurface->getRootContext()->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data()); _webSurface->getSurfaceContext()->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
_webSurface->getRootContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance()); _webSurface->getSurfaceContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
_webSurface->getRootContext()->setContextProperty("pathToFonts", "../../"); _webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../");
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem(), _webSurface.data()); tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem(), _webSurface.data());
// mark the TabletProxy object as cpp ownership. // mark the TabletProxy object as cpp ownership.
QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
_webSurface->getRootContext()->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); _webSurface->getSurfaceContext()->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
// Override min fps for tablet UI, for silky smooth scrolling // Override min fps for tablet UI, for silky smooth scrolling
setMaxFPS(90); setMaxFPS(90);
} }
} }
_webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
} }
void Web3DOverlay::setMaxFPS(uint8_t maxFPS) { void Web3DOverlay::setMaxFPS(uint8_t maxFPS) {

View file

@ -1135,9 +1135,9 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm
} }
glm::vec3 headUp = headQuat * Vectors::UNIT_Y; glm::vec3 headUp = headQuat * Vectors::UNIT_Y;
glm::vec3 z, y, x; glm::vec3 z, y, zCrossY;
generateBasisVectors(lookAtVector, headUp, z, y, x); generateBasisVectors(lookAtVector, headUp, z, y, zCrossY);
glm::mat3 m(glm::cross(y, z), y, z); glm::mat3 m(-zCrossY, y, z);
glm::quat desiredQuat = glm::normalize(glm::quat_cast(m)); glm::quat desiredQuat = glm::normalize(glm::quat_cast(m));
glm::quat deltaQuat = desiredQuat * glm::inverse(headQuat); glm::quat deltaQuat = desiredQuat * glm::inverse(headQuat);

View file

@ -339,6 +339,18 @@ void OpenGLDisplayPlugin::deactivate() {
Parent::deactivate(); Parent::deactivate();
} }
bool OpenGLDisplayPlugin::startStandBySession() {
if (!activateStandBySession()) {
return false;
}
return Parent::startStandBySession();
}
void OpenGLDisplayPlugin::endSession() {
deactivateSession();
Parent::endSession();
}
void OpenGLDisplayPlugin::customizeContext() { void OpenGLDisplayPlugin::customizeContext() {
auto presentThread = DependencyManager::get<PresentThread>(); auto presentThread = DependencyManager::get<PresentThread>();
Q_ASSERT(thread() == presentThread->thread()); Q_ASSERT(thread() == presentThread->thread());

View file

@ -42,6 +42,8 @@ public:
// between the main thread and the presentation thread // between the main thread and the presentation thread
bool activate() override final; bool activate() override final;
void deactivate() override final; void deactivate() override final;
bool startStandBySession() override final;
void endSession() override final;
bool eventFilter(QObject* receiver, QEvent* event) override; bool eventFilter(QObject* receiver, QEvent* event) override;
bool isDisplayVisible() const override { return true; } bool isDisplayVisible() const override { return true; }
@ -99,6 +101,10 @@ protected:
// Returns true on successful activation // Returns true on successful activation
virtual bool internalActivate() { return true; } virtual bool internalActivate() { return true; }
virtual void internalDeactivate() {} virtual void internalDeactivate() {}
// Returns true on successful activation of standby session
virtual bool activateStandBySession() { return true; }
virtual void deactivateSession() {}
// Plugin specific functionality to send the composed scene to the output window or device // Plugin specific functionality to send the composed scene to the output window or device
virtual void internalPresent(); virtual void internalPresent();

View file

@ -13,6 +13,7 @@
#include <DependencyManager.h> #include <DependencyManager.h>
#include <PerfStat.h> #include <PerfStat.h>
#include <GeometryCache.h> #include <GeometryCache.h>
#include <StencilMaskPass.h>
#include <AbstractViewStateInterface.h> #include <AbstractViewStateInterface.h>
#include "EntitiesRendererLogging.h" #include "EntitiesRendererLogging.h"
@ -292,6 +293,7 @@ void RenderableParticleEffectEntityItem::createPipelines() {
state->setDepthTest(true, false, gpu::LESS_EQUAL); state->setDepthTest(true, false, gpu::LESS_EQUAL);
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
PrepareStencil::testMask(*state);
auto vertShader = gpu::Shader::createVertex(std::string(untextured_particle_vert)); auto vertShader = gpu::Shader::createVertex(std::string(untextured_particle_vert));
auto fragShader = gpu::Shader::createPixel(std::string(untextured_particle_frag)); auto fragShader = gpu::Shader::createPixel(std::string(untextured_particle_frag));
@ -305,6 +307,7 @@ void RenderableParticleEffectEntityItem::createPipelines() {
state->setDepthTest(true, false, gpu::LESS_EQUAL); state->setDepthTest(true, false, gpu::LESS_EQUAL);
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
PrepareStencil::testMask(*state);
auto vertShader = gpu::Shader::createVertex(std::string(textured_particle_vert)); auto vertShader = gpu::Shader::createVertex(std::string(textured_particle_vert));
auto fragShader = gpu::Shader::createPixel(std::string(textured_particle_frag)); auto fragShader = gpu::Shader::createPixel(std::string(textured_particle_frag));

View file

@ -12,6 +12,7 @@
#include <glm/gtx/quaternion.hpp> #include <glm/gtx/quaternion.hpp>
#include <GeometryCache.h> #include <GeometryCache.h>
#include <StencilMaskPass.h>
#include <TextureCache.h> #include <TextureCache.h>
#include <PathUtils.h> #include <PathUtils.h>
#include <PerfStat.h> #include <PerfStat.h>
@ -69,6 +70,7 @@ void RenderablePolyLineEntityItem::createPipeline() {
gpu::StatePointer state = gpu::StatePointer(new gpu::State()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setDepthTest(true, true, gpu::LESS_EQUAL);
PrepareStencil::testMask(*state);
state->setBlendFunction(true, state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, 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); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);

View file

@ -46,6 +46,9 @@
#endif #endif
#include "model/Geometry.h" #include "model/Geometry.h"
#include "StencilMaskPass.h"
#include "EntityTreeRenderer.h" #include "EntityTreeRenderer.h"
#include "polyvox_vert.h" #include "polyvox_vert.h"
#include "polyvox_frag.h" #include "polyvox_frag.h"
@ -743,6 +746,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
auto state = std::make_shared<gpu::State>(); auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_BACK); state->setCullMode(gpu::State::CULL_BACK);
state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setDepthTest(true, true, gpu::LESS_EQUAL);
PrepareStencil::testMaskDrawShape(*state);
_pipeline = gpu::Pipeline::create(program, state); _pipeline = gpu::Pipeline::create(program, state);
@ -750,6 +754,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
wireframeState->setCullMode(gpu::State::CULL_BACK); wireframeState->setCullMode(gpu::State::CULL_BACK);
wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL); wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL);
wireframeState->setFillMode(gpu::State::FILL_LINE); wireframeState->setFillMode(gpu::State::FILL_LINE);
PrepareStencil::testMaskDrawShape(*wireframeState);
_wireframePipeline = gpu::Pipeline::create(program, wireframeState); _wireframePipeline = gpu::Pipeline::create(program, wireframeState);
} }

View file

@ -13,6 +13,7 @@
#include <gpu/Batch.h> #include <gpu/Batch.h>
#include <DependencyManager.h> #include <DependencyManager.h>
#include <StencilMaskPass.h>
#include <GeometryCache.h> #include <GeometryCache.h>
#include <PerfStat.h> #include <PerfStat.h>
@ -93,6 +94,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) {
_procedural->_fragmentSource = simple_frag; _procedural->_fragmentSource = simple_frag;
_procedural->_opaqueState->setCullMode(gpu::State::CULL_NONE); _procedural->_opaqueState->setCullMode(gpu::State::CULL_NONE);
_procedural->_opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL); _procedural->_opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL);
PrepareStencil::testMaskDrawShape(*_procedural->_opaqueState);
_procedural->_opaqueState->setBlendFunction(false, _procedural->_opaqueState->setBlendFunction(false,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, 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); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);

View file

@ -127,7 +127,7 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer<EntityTreeRenderer>
_webSurface->resume(); _webSurface->resume();
_webSurface->getRootItem()->setProperty("url", _sourceUrl); _webSurface->getRootItem()->setProperty("url", _sourceUrl);
_webSurface->getRootContext()->setContextProperty("desktop", QVariant()); _webSurface->getSurfaceContext()->setContextProperty("desktop", QVariant());
// FIXME - Keyboard HMD only: Possibly add "HMDinfo" object to context for WebView.qml. // FIXME - Keyboard HMD only: Possibly add "HMDinfo" object to context for WebView.qml.
// forward web events to EntityScriptingInterface // forward web events to EntityScriptingInterface
@ -271,7 +271,7 @@ void RenderableWebEntityItem::loadSourceURL() {
}); });
_webSurface->getRootItem()->setProperty("url", _sourceUrl); _webSurface->getRootItem()->setProperty("url", _sourceUrl);
_webSurface->getRootContext()->setContextProperty("desktop", QVariant()); _webSurface->getSurfaceContext()->setContextProperty("desktop", QVariant());
} else { } else {
_contentType = qmlContent; _contentType = qmlContent;
@ -284,7 +284,7 @@ void RenderableWebEntityItem::loadSourceURL() {
_webSurface->getRootItem(), _webSurface.data()); _webSurface->getRootItem(), _webSurface.data());
} }
} }
_webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
} }
@ -420,7 +420,7 @@ void RenderableWebEntityItem::update(const quint64& now) {
if (_webSurface) { if (_webSurface) {
// update globalPosition // update globalPosition
_webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
} }
auto interval = now - _lastRenderTime; auto interval = now - _lastRenderTime;

View file

@ -1,6 +1,6 @@
set(TARGET_NAME gl) set(TARGET_NAME gl)
setup_hifi_library(OpenGL Qml Quick) setup_hifi_library(OpenGL Qml Quick)
link_hifi_libraries(shared) link_hifi_libraries(shared networking)
target_opengl() target_opengl()

View file

@ -33,6 +33,9 @@
#include <NetworkAccessManager.h> #include <NetworkAccessManager.h>
#include <GLMHelpers.h> #include <GLMHelpers.h>
#include <shared/GlobalAppProperties.h> #include <shared/GlobalAppProperties.h>
#include <FileTypeProfile.h>
#include <HFWebEngineProfile.h>
#include <HFTabletWebEngineProfile.h>
#include "OffscreenGLCanvas.h" #include "OffscreenGLCanvas.h"
#include "GLHelpers.h" #include "GLHelpers.h"
@ -41,6 +44,7 @@
Q_LOGGING_CATEGORY(trace_render_qml, "trace.render.qml") Q_LOGGING_CATEGORY(trace_render_qml, "trace.render.qml")
Q_LOGGING_CATEGORY(trace_render_qml_gl, "trace.render.qml.gl") Q_LOGGING_CATEGORY(trace_render_qml_gl, "trace.render.qml.gl")
Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus")
struct TextureSet { struct TextureSet {
// The number of surfaces with this size // The number of surfaces with this size
@ -254,8 +258,72 @@ QNetworkAccessManager* QmlNetworkAccessManagerFactory::create(QObject* parent) {
return new QmlNetworkAccessManager(parent); return new QmlNetworkAccessManager(parent);
} }
Q_DECLARE_LOGGING_CATEGORY(offscreenFocus) static QQmlEngine* globalEngine { nullptr };
Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus") static size_t globalEngineRefCount { 0 };
QString getEventBridgeJavascript() {
// FIXME: Refactor with similar code in RenderableWebEntityItem
QString javaScriptToInject;
QFile webChannelFile(":qtwebchannel/qwebchannel.js");
QFile createGlobalEventBridgeFile(PathUtils::resourcesPath() + "/html/createGlobalEventBridge.js");
if (webChannelFile.open(QFile::ReadOnly | QFile::Text) &&
createGlobalEventBridgeFile.open(QFile::ReadOnly | QFile::Text)) {
QString webChannelStr = QTextStream(&webChannelFile).readAll();
QString createGlobalEventBridgeStr = QTextStream(&createGlobalEventBridgeFile).readAll();
javaScriptToInject = webChannelStr + createGlobalEventBridgeStr;
} else {
qCWarning(glLogging) << "Unable to find qwebchannel.js or createGlobalEventBridge.js";
}
return javaScriptToInject;
}
QQmlEngine* acquireEngine(QQuickWindow* window) {
Q_ASSERT(QThread::currentThread() == qApp->thread());
if (!globalEngine) {
Q_ASSERT(0 == globalEngineRefCount);
globalEngine = new QQmlEngine();
globalEngine->setNetworkAccessManagerFactory(new QmlNetworkAccessManagerFactory);
auto importList = globalEngine->importPathList();
importList.insert(importList.begin(), PathUtils::resourcesPath());
globalEngine->setImportPathList(importList);
for (const auto& path : importList) {
qDebug() << path;
}
if (!globalEngine->incubationController()) {
globalEngine->setIncubationController(window->incubationController());
}
auto rootContext = globalEngine->rootContext();
rootContext->setContextProperty("GL", ::getGLContextData());
rootContext->setContextProperty("urlHandler", new UrlHandler());
rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath()));
rootContext->setContextProperty("pathToFonts", "../../");
rootContext->setContextProperty("ApplicationInterface", qApp);
auto javaScriptToInject = getEventBridgeJavascript();
if (!javaScriptToInject.isEmpty()) {
rootContext->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject));
}
rootContext->setContextProperty("FileTypeProfile", new FileTypeProfile(rootContext));
rootContext->setContextProperty("HFWebEngineProfile", new HFWebEngineProfile(rootContext));
rootContext->setContextProperty("HFTabletWebEngineProfile", new HFTabletWebEngineProfile(rootContext));
}
++globalEngineRefCount;
return globalEngine;
}
void releaseEngine() {
Q_ASSERT(QThread::currentThread() == qApp->thread());
Q_ASSERT(0 != globalEngineRefCount);
if (0 == --globalEngineRefCount) {
globalEngine->deleteLater();
globalEngine = nullptr;
}
}
void OffscreenQmlSurface::cleanup() { void OffscreenQmlSurface::cleanup() {
_canvas->makeCurrent(); _canvas->makeCurrent();
@ -294,6 +362,7 @@ void OffscreenQmlSurface::render() {
GLuint texture = offscreenTextures.getNextTexture(_size); GLuint texture = offscreenTextures.getNextTexture(_size);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_renderControl->render(); _renderControl->render();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, texture);
@ -362,8 +431,8 @@ OffscreenQmlSurface::~OffscreenQmlSurface() {
_canvas->deleteLater(); _canvas->deleteLater();
_rootItem->deleteLater(); _rootItem->deleteLater();
_qmlComponent->deleteLater(); _qmlComponent->deleteLater();
_qmlEngine->deleteLater();
_quickWindow->deleteLater(); _quickWindow->deleteLater();
releaseEngine();
} }
void OffscreenQmlSurface::onAboutToQuit() { void OffscreenQmlSurface::onAboutToQuit() {
@ -375,6 +444,8 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
qCDebug(glLogging) << "Building QML surface"; qCDebug(glLogging) << "Building QML surface";
_renderControl = new QMyQuickRenderControl(); _renderControl = new QMyQuickRenderControl();
connect(_renderControl, &QQuickRenderControl::renderRequested, this, [this] { _render = true; });
connect(_renderControl, &QQuickRenderControl::sceneChanged, this, [this] { _render = _polish = true; });
QQuickWindow::setDefaultAlphaBuffer(true); QQuickWindow::setDefaultAlphaBuffer(true);
@ -385,7 +456,7 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
// so we wait until after its ctor to move object/context to this thread. // so we wait until after its ctor to move object/context to this thread.
_quickWindow = new QQuickWindow(_renderControl); _quickWindow = new QQuickWindow(_renderControl);
_quickWindow->setColor(QColor(255, 255, 255, 0)); _quickWindow->setColor(QColor(255, 255, 255, 0));
_quickWindow->setFlags(_quickWindow->flags() | static_cast<Qt::WindowFlags>(Qt::WA_TranslucentBackground)); _quickWindow->setClearBeforeRendering(false);
_renderControl->_renderWindow = _proxyWindow; _renderControl->_renderWindow = _proxyWindow;
@ -398,32 +469,20 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
connect(_quickWindow, &QQuickWindow::focusObjectChanged, this, &OffscreenQmlSurface::onFocusObjectChanged); connect(_quickWindow, &QQuickWindow::focusObjectChanged, this, &OffscreenQmlSurface::onFocusObjectChanged);
// Create a QML engine. // Create a QML engine.
_qmlEngine = new QQmlEngine; auto qmlEngine = acquireEngine(_quickWindow);
_qmlContext = new QQmlContext(qmlEngine->rootContext());
_qmlEngine->setNetworkAccessManagerFactory(new QmlNetworkAccessManagerFactory); _qmlContext->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
_qmlContext->setContextProperty("globalEventBridge", this);
_qmlContext->setContextProperty("webEntity", this);
auto importList = _qmlEngine->importPathList(); _qmlComponent = new QQmlComponent(qmlEngine);
importList.insert(importList.begin(), PathUtils::resourcesPath());
_qmlEngine->setImportPathList(importList);
if (!_qmlEngine->incubationController()) {
_qmlEngine->setIncubationController(_quickWindow->incubationController());
}
// FIXME
_glData = ::getGLContextData(); // Initialize JSON structure so that it can be filled in later and then used in QML.
_qmlEngine->rootContext()->setContextProperty("GL", _glData);
_qmlEngine->rootContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
_qmlComponent = new QQmlComponent(_qmlEngine);
connect(_renderControl, &QQuickRenderControl::renderRequested, this, [this] { _render = true; });
connect(_renderControl, &QQuickRenderControl::sceneChanged, this, [this] { _render = _polish = true; });
if (!_canvas->makeCurrent()) { if (!_canvas->makeCurrent()) {
qWarning("Failed to make context current for QML Renderer"); qWarning("Failed to make context current for QML Renderer");
return; return;
} }
_glData = ::getGLContextData();
_renderControl->initialize(_canvas->getContext()); _renderControl->initialize(_canvas->getContext());
// When Quick says there is a need to render, we will not render immediately. Instead, // When Quick says there is a need to render, we will not render immediately. Instead,
@ -433,11 +492,6 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
_updateTimer.setTimerType(Qt::PreciseTimer); _updateTimer.setTimerType(Qt::PreciseTimer);
_updateTimer.setInterval(MIN_TIMER_MS); // 5ms, Qt::PreciseTimer required _updateTimer.setInterval(MIN_TIMER_MS); // 5ms, Qt::PreciseTimer required
_updateTimer.start(); _updateTimer.start();
auto rootContext = getRootContext();
rootContext->setContextProperty("urlHandler", new UrlHandler());
rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath()));
rootContext->setContextProperty("pathToFonts", "../../");
} }
static uvec2 clampSize(const uvec2& size, uint32_t maxDimension) { static uvec2 clampSize(const uvec2& size, uint32_t maxDimension) {
@ -460,7 +514,7 @@ void OffscreenQmlSurface::resize(const QSize& newSize_, bool forceResize) {
return; return;
} }
_qmlEngine->rootContext()->setContextProperty("surfaceSize", newSize); _qmlContext->setContextProperty("surfaceSize", newSize);
if (_rootItem) { if (_rootItem) {
_rootItem->setSize(newSize); _rootItem->setSize(newSize);
@ -520,14 +574,19 @@ QQuickItem* OffscreenQmlSurface::getRootItem() {
} }
void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) { void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) {
_qmlEngine->setBaseUrl(baseUrl); _qmlContext->setBaseUrl(baseUrl);
} }
QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) { QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
// Synchronous loading may take a while; restart the deadlock timer // Synchronous loading may take a while; restart the deadlock timer
QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection); QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection);
_qmlComponent->loadUrl(qmlSource, QQmlComponent::PreferSynchronous); if ((qmlSource.isRelative() && !qmlSource.isEmpty()) || qmlSource.scheme() == QLatin1String("file")) {
_qmlComponent->loadUrl(_qmlContext->resolvedUrl(qmlSource), QQmlComponent::PreferSynchronous);
} else {
_qmlComponent->loadUrl(qmlSource, QQmlComponent::PreferSynchronous);
}
if (_qmlComponent->isLoading()) { if (_qmlComponent->isLoading()) {
connect(_qmlComponent, &QQmlComponent::statusChanged, this, connect(_qmlComponent, &QQmlComponent::statusChanged, this,
@ -541,10 +600,22 @@ QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQm
} }
void OffscreenQmlSurface::clearCache() { void OffscreenQmlSurface::clearCache() {
getRootContext()->engine()->clearComponentCache(); _qmlContext->engine()->clearComponentCache();
} }
QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QObject*)> f) { QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QObject*)> f) {
#if 0
if (!_rootItem) {
QQmlComponent component(_qmlContext->engine());
component.setData(R"QML(
import QtQuick 2.0
import QtWebChannel 1.0
Item { Component.onCompleted: globalEventBridge.WebChannel.id = "globalEventBridge"; }
)QML", QUrl());
QObject *helper = component.create(_qmlContext);
qDebug() << "Created helper";
}
#endif
disconnect(_qmlComponent, &QQmlComponent::statusChanged, this, 0); disconnect(_qmlComponent, &QQmlComponent::statusChanged, this, 0);
if (_qmlComponent->isError()) { if (_qmlComponent->isError()) {
QList<QQmlError> errorList = _qmlComponent->errors(); QList<QQmlError> errorList = _qmlComponent->errors();
@ -554,21 +625,8 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QOb
return nullptr; return nullptr;
} }
// FIXME: Refactor with similar code in RenderableWebEntityItem
QString javaScriptToInject;
QFile webChannelFile(":qtwebchannel/qwebchannel.js");
QFile createGlobalEventBridgeFile(PathUtils::resourcesPath() + "/html/createGlobalEventBridge.js");
if (webChannelFile.open(QFile::ReadOnly | QFile::Text) &&
createGlobalEventBridgeFile.open(QFile::ReadOnly | QFile::Text)) {
QString webChannelStr = QTextStream(&webChannelFile).readAll();
QString createGlobalEventBridgeStr = QTextStream(&createGlobalEventBridgeFile).readAll();
javaScriptToInject = webChannelStr + createGlobalEventBridgeStr;
} else {
qCWarning(glLogging) << "Unable to find qwebchannel.js or createGlobalEventBridge.js";
}
QQmlContext* newContext = new QQmlContext(_qmlEngine, qApp); QObject* newObject = _qmlComponent->beginCreate(_qmlContext);
QObject* newObject = _qmlComponent->beginCreate(newContext);
if (_qmlComponent->isError()) { if (_qmlComponent->isError()) {
QList<QQmlError> errorList = _qmlComponent->errors(); QList<QQmlError> errorList = _qmlComponent->errors();
foreach(const QQmlError& error, errorList) foreach(const QQmlError& error, errorList)
@ -579,12 +637,10 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QOb
return nullptr; return nullptr;
} }
_qmlEngine->setObjectOwnership(this, QQmlEngine::CppOwnership); _qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership);
newObject->setProperty("eventBridge", QVariant::fromValue(this)); newObject->setProperty("eventBridge", QVariant::fromValue(this));
newContext->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject)); f(_qmlContext, newObject);
f(newContext, newObject);
_qmlComponent->completeCreate(); _qmlComponent->completeCreate();
@ -735,7 +791,7 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even
mouseEvent->screenPos(), mouseEvent->button(), mouseEvent->screenPos(), mouseEvent->button(),
mouseEvent->buttons(), mouseEvent->modifiers()); mouseEvent->buttons(), mouseEvent->modifiers());
if (event->type() == QEvent::MouseMove) { if (event->type() == QEvent::MouseMove) {
_qmlEngine->rootContext()->setContextProperty("lastMousePosition", transformedPos); _qmlContext->setContextProperty("lastMousePosition", transformedPos);
} }
mappedEvent.ignore(); mappedEvent.ignore();
if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) { if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) {
@ -762,9 +818,6 @@ void OffscreenQmlSurface::resume() {
if (getRootItem()) { if (getRootItem()) {
getRootItem()->setProperty("eventBridge", QVariant::fromValue(this)); getRootItem()->setProperty("eventBridge", QVariant::fromValue(this));
} }
if (getRootContext()) {
getRootContext()->setContextProperty("webEntity", this);
}
} }
bool OffscreenQmlSurface::isPaused() const { bool OffscreenQmlSurface::isPaused() const {
@ -790,8 +843,8 @@ QSize OffscreenQmlSurface::size() const {
return _quickWindow->geometry().size(); return _quickWindow->geometry().size();
} }
QQmlContext* OffscreenQmlSurface::getRootContext() { QQmlContext* OffscreenQmlSurface::getSurfaceContext() {
return _qmlEngine->rootContext(); return _qmlContext;
} }
Q_DECLARE_METATYPE(std::function<void()>); Q_DECLARE_METATYPE(std::function<void()>);

View file

@ -73,7 +73,7 @@ public:
QQuickItem* getRootItem(); QQuickItem* getRootItem();
QQuickWindow* getWindow(); QQuickWindow* getWindow();
QObject* getEventHandler(); QObject* getEventHandler();
QQmlContext* getRootContext(); QQmlContext* getSurfaceContext();
QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget); QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget);
bool eventFilter(QObject* originalDestination, QEvent* event) override; bool eventFilter(QObject* originalDestination, QEvent* event) override;
@ -133,11 +133,10 @@ private slots:
private: private:
QQuickWindow* _quickWindow { nullptr }; QQuickWindow* _quickWindow { nullptr };
QMyQuickRenderControl* _renderControl{ nullptr }; QMyQuickRenderControl* _renderControl{ nullptr };
QQmlEngine* _qmlEngine { nullptr }; QQmlContext* _qmlContext { nullptr };
QQmlComponent* _qmlComponent { nullptr }; QQmlComponent* _qmlComponent { nullptr };
QQuickItem* _rootItem { nullptr }; QQuickItem* _rootItem { nullptr };
OffscreenGLCanvas* _canvas { nullptr }; OffscreenGLCanvas* _canvas { nullptr };
QJsonObject _glData;
QTimer _updateTimer; QTimer _updateTimer;
uint32_t _fbo { 0 }; uint32_t _fbo { 0 };

View file

@ -49,7 +49,6 @@ QSharedPointer<OffscreenQmlSurface> OffscreenQmlSurfaceCache::buildSurface(const
surface->create(currentContext); surface->create(currentContext);
surface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); surface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
surface->load(rootSource); surface->load(rootSource);
surface->getRootContext()->setContextProperty("ApplicationInterface", qApp);
surface->resize(QSize(100, 100)); surface->resize(QSize(100, 100));
currentContext->makeCurrent(currentSurface); currentContext->makeCurrent(currentSurface);
return surface; return surface;

View file

@ -0,0 +1,28 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// Draw and transform the fed vertex position with the standard MVP stack
// Output the clip position
//
// Created by Sam Gateau on 5/30/2017
// 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 gpu/Transform.slh@>
<$declareStandardTransform()$>
layout(location = 0) in vec4 inPosition;
out vec3 varWorldPos;
void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
}

View file

@ -2,25 +2,18 @@
<$VERSION_HEADER$> <$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$> // Generated on <$_SCRIBE_DATE$>
// //
// hit_effect.vert // Draw the fed vertex position, pass straight as clip pos
// vertex shader // Output the clip position
// //
// Created by Eric Levin on 7/20/15. // Created by Sam Gateau on 5/30/2017
// Copyright 2015 High Fidelity, Inc. // Copyright 2017 High Fidelity, Inc.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
<@include gpu/Inputs.slh@> layout(location = 0) in vec4 inPosition;
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
out vec2 varQuadPosition;
void main(void) { void main(void) {
varQuadPosition = inPosition.xy;
gl_Position = inPosition; gl_Position = inPosition;
} }

View file

@ -2,15 +2,17 @@
<$VERSION_HEADER$> <$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$> // Generated on <$_SCRIBE_DATE$>
// //
// drawOpaqueStencil.frag // Draw white
// fragment shader
// //
// Created by Sam Gateau on 9/29/15. // Created by Sam Gateau on 5/30/2017
// Copyright 2015 High Fidelity, Inc. // Copyright 2017 High Fidelity, Inc.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
out vec4 outFragColor;
void main(void) { void main(void) {
outFragColor = vec4(1.0);
} }

View file

@ -16,6 +16,12 @@
#include "DrawTransformUnitQuad_vert.h" #include "DrawTransformUnitQuad_vert.h"
#include "DrawTexcoordRectTransformUnitQuad_vert.h" #include "DrawTexcoordRectTransformUnitQuad_vert.h"
#include "DrawViewportQuadTransformTexcoord_vert.h" #include "DrawViewportQuadTransformTexcoord_vert.h"
#include "DrawVertexPosition_vert.h"
#include "DrawTransformVertexPosition_vert.h"
const char DrawNada_frag[] = "void main(void) {}"; // DrawNada is really simple...
#include "DrawWhite_frag.h"
#include "DrawTexture_frag.h" #include "DrawTexture_frag.h"
#include "DrawTextureOpaque_frag.h" #include "DrawTextureOpaque_frag.h"
#include "DrawColoredTexture_frag.h" #include "DrawColoredTexture_frag.h"
@ -26,6 +32,10 @@ ShaderPointer StandardShaderLib::_drawUnitQuadTexcoordVS;
ShaderPointer StandardShaderLib::_drawTransformUnitQuadVS; ShaderPointer StandardShaderLib::_drawTransformUnitQuadVS;
ShaderPointer StandardShaderLib::_drawTexcoordRectTransformUnitQuadVS; ShaderPointer StandardShaderLib::_drawTexcoordRectTransformUnitQuadVS;
ShaderPointer StandardShaderLib::_drawViewportQuadTransformTexcoordVS; ShaderPointer StandardShaderLib::_drawViewportQuadTransformTexcoordVS;
ShaderPointer StandardShaderLib::_drawVertexPositionVS;
ShaderPointer StandardShaderLib::_drawTransformVertexPositionVS;
ShaderPointer StandardShaderLib::_drawNadaPS;
ShaderPointer StandardShaderLib::_drawWhitePS;
ShaderPointer StandardShaderLib::_drawTexturePS; ShaderPointer StandardShaderLib::_drawTexturePS;
ShaderPointer StandardShaderLib::_drawTextureOpaquePS; ShaderPointer StandardShaderLib::_drawTextureOpaquePS;
ShaderPointer StandardShaderLib::_drawColoredTexturePS; ShaderPointer StandardShaderLib::_drawColoredTexturePS;
@ -85,6 +95,34 @@ ShaderPointer StandardShaderLib::getDrawViewportQuadTransformTexcoordVS() {
return _drawViewportQuadTransformTexcoordVS; return _drawViewportQuadTransformTexcoordVS;
} }
ShaderPointer StandardShaderLib::getDrawVertexPositionVS() {
if (!_drawVertexPositionVS) {
_drawVertexPositionVS = gpu::Shader::createVertex(std::string(DrawVertexPosition_vert));
}
return _drawVertexPositionVS;
}
ShaderPointer StandardShaderLib::getDrawTransformVertexPositionVS() {
if (!_drawTransformVertexPositionVS) {
_drawTransformVertexPositionVS = gpu::Shader::createVertex(std::string(DrawTransformVertexPosition_vert));
}
return _drawTransformVertexPositionVS;
}
ShaderPointer StandardShaderLib::getDrawNadaPS() {
if (!_drawNadaPS) {
_drawNadaPS = gpu::Shader::createPixel(std::string(DrawNada_frag));
}
return _drawNadaPS;
}
ShaderPointer StandardShaderLib::getDrawWhitePS() {
if (!_drawWhitePS) {
_drawWhitePS = gpu::Shader::createPixel(std::string(DrawWhite_frag));
}
return _drawWhitePS;
}
ShaderPointer StandardShaderLib::getDrawTexturePS() { ShaderPointer StandardShaderLib::getDrawTexturePS() {
if (!_drawTexturePS) { if (!_drawTexturePS) {
_drawTexturePS = gpu::Shader::createPixel(std::string(DrawTexture_frag)); _drawTexturePS = gpu::Shader::createPixel(std::string(DrawTexture_frag));
@ -99,8 +137,6 @@ ShaderPointer StandardShaderLib::getDrawTextureOpaquePS() {
return _drawTextureOpaquePS; return _drawTextureOpaquePS;
} }
ShaderPointer StandardShaderLib::getDrawColoredTexturePS() { ShaderPointer StandardShaderLib::getDrawColoredTexturePS() {
if (!_drawColoredTexturePS) { if (!_drawColoredTexturePS) {
_drawColoredTexturePS = gpu::Shader::createPixel(std::string(DrawColoredTexture_frag)); _drawColoredTexturePS = gpu::Shader::createPixel(std::string(DrawColoredTexture_frag));

View file

@ -37,6 +37,15 @@ public:
// Shader draws the unit quad in the full viewport clipPos = ([(-1,-1),(1,1)]) and transform the texcoord = [(0,0),(1,1)] by the model transform. // Shader draws the unit quad in the full viewport clipPos = ([(-1,-1),(1,1)]) and transform the texcoord = [(0,0),(1,1)] by the model transform.
static ShaderPointer getDrawViewportQuadTransformTexcoordVS(); static ShaderPointer getDrawViewportQuadTransformTexcoordVS();
// Shader draw the fed vertex position and transform it by the full model transform stack (Model, View, Proj).
// simply output the world pos and the clip pos to the next stage
static ShaderPointer getDrawVertexPositionVS();
static ShaderPointer getDrawTransformVertexPositionVS();
// PShader does nothing, no really nothing, but still needed for defining a program triggering rasterization
static ShaderPointer getDrawNadaPS();
static ShaderPointer getDrawWhitePS();
static ShaderPointer getDrawTexturePS(); static ShaderPointer getDrawTexturePS();
static ShaderPointer getDrawTextureOpaquePS(); static ShaderPointer getDrawTextureOpaquePS();
static ShaderPointer getDrawColoredTexturePS(); static ShaderPointer getDrawColoredTexturePS();
@ -51,6 +60,12 @@ protected:
static ShaderPointer _drawTransformUnitQuadVS; static ShaderPointer _drawTransformUnitQuadVS;
static ShaderPointer _drawTexcoordRectTransformUnitQuadVS; static ShaderPointer _drawTexcoordRectTransformUnitQuadVS;
static ShaderPointer _drawViewportQuadTransformTexcoordVS; static ShaderPointer _drawViewportQuadTransformTexcoordVS;
static ShaderPointer _drawVertexPositionVS;
static ShaderPointer _drawTransformVertexPositionVS;
static ShaderPointer _drawNadaPS;
static ShaderPointer _drawWhitePS;
static ShaderPointer _drawTexturePS; static ShaderPointer _drawTexturePS;
static ShaderPointer _drawTextureOpaquePS; static ShaderPointer _drawTextureOpaquePS;
static ShaderPointer _drawColoredTexturePS; static ShaderPointer _drawColoredTexturePS;

View file

@ -241,6 +241,42 @@ void Mesh::forEach(std::function<void(glm::vec3)> vertexFunc,
} }
} }
MeshPointer Mesh::createIndexedTriangles_P3F(uint32_t numVertices, uint32_t numIndices, const glm::vec3* vertices, const uint32_t* indices) {
MeshPointer mesh;
if (numVertices == 0) { return mesh; }
if (numIndices < 3) { return mesh; }
mesh = std::make_shared<Mesh>();
// Vertex buffer
mesh->setVertexBuffer(gpu::BufferView(new gpu::Buffer(numVertices * sizeof(glm::vec3), (gpu::Byte*) vertices), gpu::Element::VEC3F_XYZ));
// trim down the indices to shorts if possible
if (numIndices < std::numeric_limits<uint16_t>::max()) {
Indices16 shortIndicesVector;
int16_t* shortIndices = nullptr;
if (indices) {
shortIndicesVector.resize(numIndices);
for (uint32_t i = 0; i < numIndices; i++) {
shortIndicesVector[i] = indices[i];
}
shortIndices = shortIndicesVector.data();
}
mesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(numIndices * sizeof(uint16_t), (gpu::Byte*) shortIndices), gpu::Element::INDEX_UINT16));
} else {
mesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(numIndices * sizeof(uint32_t), (gpu::Byte*) indices), gpu::Element::INDEX_INT32));
}
std::vector<model::Mesh::Part> parts;
parts.push_back(model::Mesh::Part(0, numIndices, 0, model::Mesh::TRIANGLES));
mesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part), (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL));
return mesh;
}
Geometry::Geometry() { Geometry::Geometry() {
} }
@ -256,3 +292,5 @@ Geometry::~Geometry() {
void Geometry::setMesh(const MeshPointer& mesh) { void Geometry::setMesh(const MeshPointer& mesh) {
_mesh = mesh; _mesh = mesh;
} }

View file

@ -65,6 +65,9 @@ public:
const gpu::BufferStream& getVertexStream() const { return _vertexStream; } const gpu::BufferStream& getVertexStream() const { return _vertexStream; }
// Index Buffer // Index Buffer
using Indices16 = std::vector<int16_t>;
using Indices32 = std::vector<int32_t>;
void setIndexBuffer(const BufferView& buffer); void setIndexBuffer(const BufferView& buffer);
const BufferView& getIndexBuffer() const { return _indexBuffer; } const BufferView& getIndexBuffer() const { return _indexBuffer; }
size_t getNumIndices() const { return _indexBuffer.getNumElements(); } size_t getNumIndices() const { return _indexBuffer.getNumElements(); }
@ -127,6 +130,9 @@ public:
std::function<void(glm::vec3)> normalFunc, std::function<void(glm::vec3)> normalFunc,
std::function<void(uint32_t)> indexFunc); std::function<void(uint32_t)> indexFunc);
static MeshPointer createIndexedTriangles_P3F(uint32_t numVertices, uint32_t numTriangles, const glm::vec3* vertices = nullptr, const uint32_t* indices = nullptr);
protected: protected:
gpu::Stream::FormatPointer _vertexFormat; gpu::Stream::FormatPointer _vertexFormat;

View file

@ -97,7 +97,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
} }
auto skyState = std::make_shared<gpu::State>(); auto skyState = std::make_shared<gpu::State>();
skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(1, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
thePipeline = gpu::Pipeline::create(skyShader, skyState); thePipeline = gpu::Pipeline::create(skyShader, skyState);
} }

View file

@ -1,5 +1,5 @@
set(TARGET_NAME networking) set(TARGET_NAME networking)
setup_hifi_library(Network) setup_hifi_library(Network WebEngine)
link_hifi_libraries(shared) link_hifi_libraries(shared)
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes") target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes")

View file

@ -15,11 +15,13 @@
#include <QtCore/QThread> #include <QtCore/QThread>
#include <StatTracker.h>
#include <Trace.h>
#include "AssetClient.h" #include "AssetClient.h"
#include "NetworkLogging.h" #include "NetworkLogging.h"
#include "NodeList.h" #include "NodeList.h"
#include "ResourceCache.h" #include "ResourceCache.h"
#include <Trace.h>
static int requestID = 0; static int requestID = 0;
@ -62,9 +64,12 @@ void AssetRequest::start() {
_data = loadFromCache(getUrl()); _data = loadFromCache(getUrl());
if (!_data.isNull()) { if (!_data.isNull()) {
_error = NoError; _error = NoError;
_loadedFromCache = true;
_state = Finished; _state = Finished;
emit finished(this); emit finished(this);
return; return;
} }

View file

@ -52,6 +52,8 @@ public:
QUrl getUrl() const { return ::getATPUrl(_hash); } QUrl getUrl() const { return ::getATPUrl(_hash); }
QString getHash() const { return _hash; } QString getHash() const { return _hash; }
bool loadedFromCache() const { return _loadedFromCache; }
signals: signals:
void finished(AssetRequest* thisRequest); void finished(AssetRequest* thisRequest);
void progress(qint64 totalReceived, qint64 total); void progress(qint64 totalReceived, qint64 total);
@ -66,6 +68,7 @@ private:
int _numPendingRequests { 0 }; int _numPendingRequests { 0 };
MessageID _assetRequestID { INVALID_MESSAGE_ID }; MessageID _assetRequestID { INVALID_MESSAGE_ID };
const ByteRange _byteRange; const ByteRange _byteRange;
bool _loadedFromCache { false };
}; };
#endif #endif

View file

@ -13,12 +13,14 @@
#include <QtCore/QLoggingCategory> #include <QtCore/QLoggingCategory>
#include <Trace.h>
#include <Profile.h>
#include <StatTracker.h>
#include "AssetClient.h" #include "AssetClient.h"
#include "AssetUtils.h" #include "AssetUtils.h"
#include "MappingRequest.h" #include "MappingRequest.h"
#include "NetworkLogging.h" #include "NetworkLogging.h"
#include <Trace.h>
#include <Profile.h>
static const int DOWNLOAD_PROGRESS_LOG_INTERVAL_SECONDS = 5; static const int DOWNLOAD_PROGRESS_LOG_INTERVAL_SECONDS = 5;
@ -48,6 +50,8 @@ bool AssetResourceRequest::urlIsAssetHash(const QUrl& url) {
} }
void AssetResourceRequest::doSend() { void AssetResourceRequest::doSend() {
DependencyManager::get<StatTracker>()->incrementStat(STAT_ATP_REQUEST_STARTED);
// We'll either have a hash or an ATP path to a file (that maps to a hash) // We'll either have a hash or an ATP path to a file (that maps to a hash)
if (urlIsAssetHash(_url)) { if (urlIsAssetHash(_url)) {
// We've detected that this is a hash - simply use AssetClient to request that asset // We've detected that this is a hash - simply use AssetClient to request that asset
@ -65,11 +69,16 @@ void AssetResourceRequest::doSend() {
} }
void AssetResourceRequest::requestMappingForPath(const AssetPath& path) { void AssetResourceRequest::requestMappingForPath(const AssetPath& path) {
auto statTracker = DependencyManager::get<StatTracker>();
statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_STARTED);
auto assetClient = DependencyManager::get<AssetClient>(); auto assetClient = DependencyManager::get<AssetClient>();
_assetMappingRequest = assetClient->createGetMappingRequest(path); _assetMappingRequest = assetClient->createGetMappingRequest(path);
// make sure we'll hear about the result of the get mapping request // make sure we'll hear about the result of the get mapping request
connect(_assetMappingRequest, &GetMappingRequest::finished, this, [this, path](GetMappingRequest* request){ connect(_assetMappingRequest, &GetMappingRequest::finished, this, [this, path](GetMappingRequest* request){
auto statTracker = DependencyManager::get<StatTracker>();
Q_ASSERT(_state == InProgress); Q_ASSERT(_state == InProgress);
Q_ASSERT(request == _assetMappingRequest); Q_ASSERT(request == _assetMappingRequest);
@ -80,6 +89,8 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) {
requestHash(request->getHash()); requestHash(request->getHash());
statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_SUCCESS);
break; break;
default: { default: {
switch (request->getError()) { switch (request->getError()) {
@ -100,6 +111,9 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) {
_state = Finished; _state = Finished;
emit finished(); emit finished();
statTracker->incrementStat(STAT_ATP_MAPPING_REQUEST_FAILED);
statTracker->incrementStat(STAT_ATP_REQUEST_FAILED);
break; break;
} }
} }
@ -140,10 +154,26 @@ void AssetResourceRequest::requestHash(const AssetHash& hash) {
_result = Error; _result = Error;
break; break;
} }
auto statTracker = DependencyManager::get<StatTracker>();
if (_assetRequest->loadedFromCache()) {
_loadedFromCache = true;
}
_state = Finished; _state = Finished;
emit finished(); emit finished();
if (_result == Success) {
statTracker->incrementStat(STAT_ATP_REQUEST_SUCCESS);
if (loadedFromCache()) {
statTracker->incrementStat(STAT_ATP_REQUEST_CACHE);
}
} else {
statTracker->incrementStat(STAT_ATP_REQUEST_FAILED);
}
_assetRequest->deleteLater(); _assetRequest->deleteLater();
_assetRequest = nullptr; _assetRequest = nullptr;
}); });

View file

@ -15,7 +15,12 @@
#include <QFile> #include <QFile>
#include <StatTracker.h>
void FileResourceRequest::doSend() { void FileResourceRequest::doSend() {
auto statTracker = DependencyManager::get<StatTracker>();
statTracker->incrementStat(STAT_FILE_REQUEST_STARTED);
QString filename = _url.toLocalFile(); QString filename = _url.toLocalFile();
// sometimes on windows, we see the toLocalFile() return null, // sometimes on windows, we see the toLocalFile() return null,
@ -60,4 +65,10 @@ void FileResourceRequest::doSend() {
_state = Finished; _state = Finished;
emit finished(); emit finished();
if (_result == ResourceRequest::Success) {
statTracker->incrementStat(STAT_FILE_REQUEST_SUCCESS);
} else {
statTracker->incrementStat(STAT_FILE_REQUEST_FAILED);
}
} }

View file

@ -19,6 +19,7 @@ HFTabletWebEngineProfile::HFTabletWebEngineProfile(QObject* parent) : QQuickWebE
static const QString WEB_ENGINE_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; static const QString WEB_ENGINE_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36";
setHttpUserAgent(WEB_ENGINE_USER_AGENT); setHttpUserAgent(WEB_ENGINE_USER_AGENT);
setStorageName(QML_WEB_ENGINE_NAME);
auto requestInterceptor = new HFTabletWebEngineRequestInterceptor(this); auto requestInterceptor = new HFTabletWebEngineRequestInterceptor(this);
setRequestInterceptor(requestInterceptor); setRequestInterceptor(requestInterceptor);

View file

@ -11,7 +11,7 @@
#include "HFTabletWebEngineRequestInterceptor.h" #include "HFTabletWebEngineRequestInterceptor.h"
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <AccountManager.h> #include "AccountManager.h"
bool isTabletAuthableHighFidelityURL(const QUrl& url) { bool isTabletAuthableHighFidelityURL(const QUrl& url) {
static const QStringList HF_HOSTS = { static const QStringList HF_HOSTS = {

View file

@ -20,6 +20,7 @@ HFWebEngineProfile::HFWebEngineProfile(QObject* parent) :
{ {
static const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (HighFidelityInterface)"; static const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (HighFidelityInterface)";
setHttpUserAgent(WEB_ENGINE_USER_AGENT); setHttpUserAgent(WEB_ENGINE_USER_AGENT);
setStorageName(QML_WEB_ENGINE_STORAGE_NAME);
// we use the HFWebEngineRequestInterceptor to make sure that web requests are authenticated for the interface user // we use the HFWebEngineRequestInterceptor to make sure that web requests are authenticated for the interface user
auto requestInterceptor = new HFWebEngineRequestInterceptor(this); auto requestInterceptor = new HFWebEngineRequestInterceptor(this);

View file

@ -13,7 +13,7 @@
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <AccountManager.h> #include "AccountManager.h"
#include "RequestFilters.h" #include "RequestFilters.h"
void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {

View file

@ -17,6 +17,7 @@
#include <QMetaEnum> #include <QMetaEnum>
#include <SharedUtil.h> #include <SharedUtil.h>
#include <StatTracker.h>
#include "NetworkAccessManager.h" #include "NetworkAccessManager.h"
#include "NetworkLogging.h" #include "NetworkLogging.h"
@ -49,6 +50,8 @@ void HTTPResourceRequest::cleanupTimer() {
} }
void HTTPResourceRequest::doSend() { void HTTPResourceRequest::doSend() {
DependencyManager::get<StatTracker>()->incrementStat(STAT_HTTP_REQUEST_STARTED);
QNetworkRequest networkRequest(_url); QNetworkRequest networkRequest(_url);
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
@ -178,6 +181,17 @@ void HTTPResourceRequest::onRequestFinished() {
_state = Finished; _state = Finished;
emit finished(); emit finished();
auto statTracker = DependencyManager::get<StatTracker>();
if (_result == Success) {
statTracker->incrementStat(STAT_HTTP_REQUEST_SUCCESS);
if (loadedFromCache()) {
statTracker->incrementStat(STAT_HTTP_REQUEST_CACHE);
}
} else {
statTracker->incrementStat(STAT_HTTP_REQUEST_FAILED);
}
} }
void HTTPResourceRequest::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { void HTTPResourceRequest::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
@ -202,4 +216,6 @@ void HTTPResourceRequest::onTimeout() {
_result = Timeout; _result = Timeout;
_state = Finished; _state = Finished;
emit finished(); emit finished();
DependencyManager::get<StatTracker>()->incrementStat(STAT_HTTP_REQUEST_FAILED);
} }

View file

@ -29,6 +29,7 @@
#include <NumericalConstants.h> #include <NumericalConstants.h>
#include <SettingHandle.h> #include <SettingHandle.h>
#include <SharedUtil.h> #include <SharedUtil.h>
#include <StatTracker.h>
#include <UUID.h> #include <UUID.h>
#include "AccountManager.h" #include "AccountManager.h"
@ -37,7 +38,6 @@
#include "HifiSockAddr.h" #include "HifiSockAddr.h"
#include "NetworkLogging.h" #include "NetworkLogging.h"
#include "udt/Packet.h" #include "udt/Packet.h"
#include <Trace.h>
static Setting::Handle<quint16> LIMITED_NODELIST_LOCAL_PORT("LimitedNodeList.LocalPort", 0); static Setting::Handle<quint16> LIMITED_NODELIST_LOCAL_PORT("LimitedNodeList.LocalPort", 0);
@ -1044,10 +1044,10 @@ void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) {
qCInfo(networking) << "Local socket is" << sockAddr; qCInfo(networking) << "Local socket is" << sockAddr;
} else { } else {
qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr; qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr;
DependencyManager::get<StatTracker>()->incrementStat(LOCAL_SOCKET_CHANGE_STAT);
} }
_localSockAddr = sockAddr; _localSockAddr = sockAddr;
emit localSockAddrChanged(_localSockAddr); emit localSockAddrChanged(_localSockAddr);
} }
} }

View file

@ -66,6 +66,8 @@ const QHostAddress DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME = QHostAddress::Lo
const QString USERNAME_UUID_REPLACEMENT_STATS_KEY = "$username"; const QString USERNAME_UUID_REPLACEMENT_STATS_KEY = "$username";
const QString LOCAL_SOCKET_CHANGE_STAT = "LocalSocketChanges";
using namespace tbb; using namespace tbb;
typedef std::pair<QUuid, SharedNodePointer> UUIDNodePair; typedef std::pair<QUuid, SharedNodePointer> UUIDNodePair;
typedef concurrent_unordered_map<QUuid, SharedNodePointer, UUIDHasher> NodeHash; typedef concurrent_unordered_map<QUuid, SharedNodePointer, UUIDHasher> NodeHash;

View file

@ -14,7 +14,7 @@
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <AccountManager.h> #include "AccountManager.h"
namespace { namespace {

View file

@ -19,6 +19,21 @@
#include "ByteRange.h" #include "ByteRange.h"
const QString STAT_ATP_REQUEST_STARTED = "StartedATPRequest";
const QString STAT_HTTP_REQUEST_STARTED = "StartedHTTPRequest";
const QString STAT_FILE_REQUEST_STARTED = "StartedFileRequest";
const QString STAT_ATP_REQUEST_SUCCESS = "SuccessfulATPRequest";
const QString STAT_HTTP_REQUEST_SUCCESS = "SuccessfulHTTPRequest";
const QString STAT_FILE_REQUEST_SUCCESS = "SuccessfulFileRequest";
const QString STAT_ATP_REQUEST_FAILED = "FailedATPRequest";
const QString STAT_HTTP_REQUEST_FAILED = "FailedHTTPRequest";
const QString STAT_FILE_REQUEST_FAILED = "FailedFileRequest";
const QString STAT_ATP_REQUEST_CACHE = "CacheATPRequest";
const QString STAT_HTTP_REQUEST_CACHE = "CacheHTTPRequest";
const QString STAT_ATP_MAPPING_REQUEST_STARTED = "StartedATPMappingRequest";
const QString STAT_ATP_MAPPING_REQUEST_FAILED = "FailedATPMappingRequest";
const QString STAT_ATP_MAPPING_REQUEST_SUCCESS = "SuccessfulATPMappingRequest";
class ResourceRequest : public QObject { class ResourceRequest : public QObject {
Q_OBJECT Q_OBJECT
public: public:

View file

@ -200,6 +200,7 @@ public:
virtual float newFramePresentRate() const { return -1.0f; } virtual float newFramePresentRate() const { return -1.0f; }
// Rate at which rendered frames are being skipped // Rate at which rendered frames are being skipped
virtual float droppedFrameRate() const { return -1.0f; } virtual float droppedFrameRate() const { return -1.0f; }
virtual bool getSupportsAutoSwitch() { return false; }
// Hardware specific stats // Hardware specific stats
virtual QJsonObject getHardwareStats() const { return QJsonObject(); } virtual QJsonObject getHardwareStats() const { return QJsonObject(); }

View file

@ -53,6 +53,18 @@ public:
virtual bool isActive() { virtual bool isActive() {
return _active; return _active;
} }
virtual bool startStandBySession() {
_sessionStatus = true;
return _sessionStatus;
}
virtual void endSession() {
_sessionStatus = false;
}
virtual bool isSessionActive() {
return _sessionStatus;
}
/** /**
* Called by the application during it's idle phase. If the plugin needs to do * Called by the application during it's idle phase. If the plugin needs to do
@ -73,6 +85,7 @@ signals:
protected: protected:
bool _active { false }; bool _active { false };
bool _sessionStatus { false };
PluginContainer* _container { nullptr }; PluginContainer* _container { nullptr };
static const char* UNKNOWN_PLUGIN_ID; static const char* UNKNOWN_PLUGIN_ID;

View file

@ -23,7 +23,7 @@ ProceduralSkybox::ProceduralSkybox() : model::Skybox() {
_procedural._fragmentSource = skybox_frag; _procedural._fragmentSource = skybox_frag;
// Adjust the pipeline state for background using the stencil test // Adjust the pipeline state for background using the stencil test
_procedural.setDoesFade(false); _procedural.setDoesFade(false);
_procedural._opaqueState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); _procedural._opaqueState->setStencilTest(true, 0xFF, gpu::State::StencilTest(1, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
} }
bool ProceduralSkybox::empty() { bool ProceduralSkybox::empty() {

View file

@ -260,7 +260,7 @@ static void addLink(const AnimPose& rootPose, const AnimPose& pose, const AnimPo
// there is room, so lets draw a nice bone // there is room, so lets draw a nice bone
glm::vec3 uAxis, vAxis, wAxis; glm::vec3 uAxis, vAxis, wAxis;
generateBasisVectors(boneAxis0, glm::vec3(1, 0, 0), uAxis, vAxis, wAxis); generateBasisVectors(boneAxis0, glm::vec3(1.0f, 0.0f, 0.0f), uAxis, vAxis, wAxis);
glm::vec3 boneBaseCorners[NUM_BASE_CORNERS]; glm::vec3 boneBaseCorners[NUM_BASE_CORNERS];
boneBaseCorners[0] = pose0 * ((uAxis * radius) + (vAxis * radius) + (wAxis * radius)); boneBaseCorners[0] = pose0 * ((uAxis * radius) + (vAxis * radius) + (wAxis * radius));

View file

@ -17,6 +17,7 @@
#include <gpu/Context.h> #include <gpu/Context.h>
#include "AntialiasingEffect.h" #include "AntialiasingEffect.h"
#include "StencilMaskPass.h"
#include "TextureCache.h" #include "TextureCache.h"
#include "FramebufferCache.h" #include "FramebufferCache.h"
#include "DependencyManager.h" #include "DependencyManager.h"
@ -70,6 +71,8 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() {
gpu::StatePointer state = gpu::StatePointer(new gpu::State()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
PrepareStencil::testMask(*state);
state->setDepthTest(false, false, gpu::LESS_EQUAL); state->setDepthTest(false, false, gpu::LESS_EQUAL);
// Good to go add the brand new pipeline // Good to go add the brand new pipeline
@ -93,6 +96,7 @@ const gpu::PipelinePointer& Antialiasing::getBlendPipeline() {
gpu::StatePointer state = gpu::StatePointer(new gpu::State()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(false, false, gpu::LESS_EQUAL); state->setDepthTest(false, false, gpu::LESS_EQUAL);
PrepareStencil::testMask(*state);
// Good to go add the brand new pipeline // Good to go add the brand new pipeline
_blendPipeline = gpu::Pipeline::create(program, state); _blendPipeline = gpu::Pipeline::create(program, state);

View file

@ -18,6 +18,7 @@
#include <gpu/Batch.h> #include <gpu/Batch.h>
#include <gpu/Context.h> #include <gpu/Context.h>
#include "StencilMaskPass.h"
#include "AbstractViewStateInterface.h" #include "AbstractViewStateInterface.h"
#include "GeometryCache.h" #include "GeometryCache.h"
#include "TextureCache.h" #include "TextureCache.h"
@ -27,18 +28,15 @@
#include "deferred_light_point_vert.h" #include "deferred_light_point_vert.h"
#include "deferred_light_spot_vert.h" #include "deferred_light_spot_vert.h"
#include "directional_light_frag.h"
#include "directional_ambient_light_frag.h" #include "directional_ambient_light_frag.h"
#include "directional_skybox_light_frag.h" #include "directional_skybox_light_frag.h"
#include "directional_light_shadow_frag.h"
#include "directional_ambient_light_shadow_frag.h" #include "directional_ambient_light_shadow_frag.h"
#include "directional_skybox_light_shadow_frag.h" #include "directional_skybox_light_shadow_frag.h"
#include "local_lights_shading_frag.h" #include "local_lights_shading_frag.h"
#include "local_lights_drawOutline_frag.h" #include "local_lights_drawOutline_frag.h"
#include "point_light_frag.h"
#include "spot_light_frag.h"
using namespace render; using namespace render;
@ -82,48 +80,26 @@ enum DeferredShader_BufferSlot {
}; };
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations); static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations);
static void loadLightVolumeProgram(const char* vertSource, const char* fragSource, bool front, gpu::PipelinePointer& program, LightLocationsPtr& locations);
const char no_light_frag[] =
R"SCRIBE(
out vec4 _fragColor;
void main(void) {
_fragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
)SCRIBE"
;
void DeferredLightingEffect::init() { void DeferredLightingEffect::init() {
_directionalLightLocations = std::make_shared<LightLocations>();
_directionalAmbientSphereLightLocations = std::make_shared<LightLocations>(); _directionalAmbientSphereLightLocations = std::make_shared<LightLocations>();
_directionalSkyboxLightLocations = std::make_shared<LightLocations>(); _directionalSkyboxLightLocations = std::make_shared<LightLocations>();
_directionalLightShadowLocations = std::make_shared<LightLocations>();
_directionalAmbientSphereLightShadowLocations = std::make_shared<LightLocations>(); _directionalAmbientSphereLightShadowLocations = std::make_shared<LightLocations>();
_directionalSkyboxLightShadowLocations = std::make_shared<LightLocations>(); _directionalSkyboxLightShadowLocations = std::make_shared<LightLocations>();
_localLightLocations = std::make_shared<LightLocations>(); _localLightLocations = std::make_shared<LightLocations>();
_localLightOutlineLocations = std::make_shared<LightLocations>(); _localLightOutlineLocations = std::make_shared<LightLocations>();
_pointLightLocations = std::make_shared<LightLocations>();
_spotLightLocations = std::make_shared<LightLocations>();
loadLightProgram(deferred_light_vert, directional_light_frag, false, _directionalLight, _directionalLightLocations);
loadLightProgram(deferred_light_vert, directional_ambient_light_frag, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations); loadLightProgram(deferred_light_vert, directional_ambient_light_frag, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations);
loadLightProgram(deferred_light_vert, directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations); loadLightProgram(deferred_light_vert, directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations);
loadLightProgram(deferred_light_vert, directional_light_shadow_frag, false, _directionalLightShadow, _directionalLightShadowLocations);
loadLightProgram(deferred_light_vert, directional_ambient_light_shadow_frag, false, _directionalAmbientSphereLightShadow, _directionalAmbientSphereLightShadowLocations); loadLightProgram(deferred_light_vert, directional_ambient_light_shadow_frag, false, _directionalAmbientSphereLightShadow, _directionalAmbientSphereLightShadowLocations);
loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations); loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations);
loadLightProgram(deferred_light_vert, local_lights_shading_frag, true, _localLight, _localLightLocations); loadLightProgram(deferred_light_vert, local_lights_shading_frag, true, _localLight, _localLightLocations);
loadLightProgram(deferred_light_vert, local_lights_drawOutline_frag, true, _localLightOutline, _localLightOutlineLocations); loadLightProgram(deferred_light_vert, local_lights_drawOutline_frag, true, _localLightOutline, _localLightOutlineLocations);
loadLightVolumeProgram(deferred_light_point_vert, no_light_frag, false, _pointLightBack, _pointLightLocations);
loadLightVolumeProgram(deferred_light_point_vert, no_light_frag, true, _pointLightFront, _pointLightLocations);
loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, false, _spotLightBack, _spotLightLocations);
loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, true, _spotLightFront, _spotLightLocations);
// Light Stage and clusters // Light Stage and clusters
_lightStage = std::make_shared<LightStage>(); _lightStage = std::make_shared<LightStage>();
@ -160,11 +136,11 @@ void DeferredLightingEffect::init() {
lp->setAmbientIntensity(0.5f); lp->setAmbientIntensity(0.5f);
lp->setAmbientMap(_defaultSkyboxAmbientTexture); lp->setAmbientMap(_defaultSkyboxAmbientTexture);
auto irradianceSH = _defaultSkyboxAmbientTexture->getIrradiance(); auto irradianceSH = _defaultSkyboxAmbientTexture->getIrradiance();
if (irradianceSH) { if (irradianceSH) {
lp->setAmbientSphere((*irradianceSH)); lp->setAmbientSphere((*irradianceSH));
} }
} }
void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) { void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) {
@ -267,7 +243,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
state->setColorWriteMask(true, true, true, false); state->setColorWriteMask(true, true, true, false);
if (lightVolume) { if (lightVolume) {
state->setStencilTest(true, 0x00, gpu::State::StencilTest(1, 0xFF, gpu::LESS_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); PrepareStencil::testShape(*state);
state->setCullMode(gpu::State::CULL_BACK); state->setCullMode(gpu::State::CULL_BACK);
// state->setCullMode(gpu::State::CULL_FRONT); // state->setCullMode(gpu::State::CULL_FRONT);
@ -280,7 +256,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
} else { } else {
// Stencil test all the light passes for objects pixels only, not the background // Stencil test all the light passes for objects pixels only, not the background
state->setStencilTest(true, 0x00, gpu::State::StencilTest(0, 0x01, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); PrepareStencil::testShape(*state);
state->setCullMode(gpu::State::CULL_BACK); state->setCullMode(gpu::State::CULL_BACK);
// additive blending // additive blending
@ -290,39 +266,6 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo
} }
static void loadLightVolumeProgram(const char* vertSource, const char* fragSource, bool front, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) {
gpu::ShaderPointer program = makeLightProgram(vertSource, fragSource, locations);
auto state = std::make_shared<gpu::State>();
// Stencil test all the light passes for objects pixels only, not the background
if (front) {
state->setCullMode(gpu::State::CULL_BACK);
state->setDepthTest(true, false, gpu::LESS_EQUAL);
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_DECR, gpu::State::STENCIL_OP_KEEP));
// state->setDepthClampEnable(true);
// TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases
// additive blending
// state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
//state->setColorWriteMask(true, true, true, false);
state->setColorWriteMask(false, false, false, false);
} else {
state->setCullMode(gpu::State::CULL_FRONT);
state->setDepthTest(true, false, gpu::LESS_EQUAL);
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR, gpu::State::STENCIL_OP_KEEP));
// additive blending
// state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
// state->setColorWriteMask(true, true, true, false);
state->setColorWriteMask(false, false, false, false);
}
pipeline = gpu::Pipeline::create(program, state);
}
void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) { void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) {
/* auto globalLight = _allocatedLights.front(); /* auto globalLight = _allocatedLights.front();
globalLight->setDirection(light->getDirection()); globalLight->setDirection(light->getDirection());
@ -535,7 +478,7 @@ void PrepareDeferred::run(const RenderContextPointer& renderContext, const Input
gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_COLOR1 | gpu::Framebuffer::BUFFER_COLOR2 | gpu::Framebuffer::BUFFER_COLOR3 | gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_COLOR1 | gpu::Framebuffer::BUFFER_COLOR2 | gpu::Framebuffer::BUFFER_COLOR3 |
gpu::Framebuffer::BUFFER_DEPTH | gpu::Framebuffer::BUFFER_DEPTH |
gpu::Framebuffer::BUFFER_STENCIL, gpu::Framebuffer::BUFFER_STENCIL,
vec4(vec3(0), 0), 1.0, 0.0, true); vec4(vec3(0), 0), 1.0, 1, true);
// For the rest of the rendering, bind the lighting model // For the rest of the rendering, bind the lighting model
batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, lightingModel->getParametersBuffer()); batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, lightingModel->getParametersBuffer());
@ -619,8 +562,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow->map); batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow->map);
} }
auto& program = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadow : deferredLightingEffect->_directionalLight; auto& program = deferredLightingEffect->_directionalSkyboxLight;
LightLocationsPtr locations = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadowLocations : deferredLightingEffect->_directionalLightLocations; LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations;
const auto& keyLight = deferredLightingEffect->_allocatedLights[deferredLightingEffect->_globalLights.front()]; const auto& keyLight = deferredLightingEffect->_allocatedLights[deferredLightingEffect->_globalLights.front()];
// Setup the global directional pass pipeline // Setup the global directional pass pipeline

View file

@ -82,32 +82,21 @@ private:
gpu::PipelinePointer _directionalSkyboxLight; gpu::PipelinePointer _directionalSkyboxLight;
gpu::PipelinePointer _directionalAmbientSphereLight; gpu::PipelinePointer _directionalAmbientSphereLight;
gpu::PipelinePointer _directionalLight;
gpu::PipelinePointer _directionalSkyboxLightShadow; gpu::PipelinePointer _directionalSkyboxLightShadow;
gpu::PipelinePointer _directionalAmbientSphereLightShadow; gpu::PipelinePointer _directionalAmbientSphereLightShadow;
gpu::PipelinePointer _directionalLightShadow;
gpu::PipelinePointer _localLight; gpu::PipelinePointer _localLight;
gpu::PipelinePointer _localLightOutline; gpu::PipelinePointer _localLightOutline;
gpu::PipelinePointer _pointLightBack;
gpu::PipelinePointer _pointLightFront;
gpu::PipelinePointer _spotLightBack;
gpu::PipelinePointer _spotLightFront;
LightLocationsPtr _directionalSkyboxLightLocations; LightLocationsPtr _directionalSkyboxLightLocations;
LightLocationsPtr _directionalAmbientSphereLightLocations; LightLocationsPtr _directionalAmbientSphereLightLocations;
LightLocationsPtr _directionalLightLocations;
LightLocationsPtr _directionalSkyboxLightShadowLocations; LightLocationsPtr _directionalSkyboxLightShadowLocations;
LightLocationsPtr _directionalAmbientSphereLightShadowLocations; LightLocationsPtr _directionalAmbientSphereLightShadowLocations;
LightLocationsPtr _directionalLightShadowLocations;
LightLocationsPtr _localLightLocations; LightLocationsPtr _localLightLocations;
LightLocationsPtr _localLightOutlineLocations; LightLocationsPtr _localLightOutlineLocations;
LightLocationsPtr _pointLightLocations;
LightLocationsPtr _spotLightLocations;
using Lights = std::vector<model::LightPointer>; using Lights = std::vector<model::LightPointer>;

View file

@ -24,6 +24,7 @@
#include "TextureCache.h" #include "TextureCache.h"
#include "RenderUtilsLogging.h" #include "RenderUtilsLogging.h"
#include "StencilMaskPass.h"
#include "gpu/StandardShaderLib.h" #include "gpu/StandardShaderLib.h"
@ -1610,6 +1611,9 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const
state->setBlendFunction(true, state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, 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); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
PrepareStencil::testMask(*state);
gpu::Shader::BindingSet slotBindings; gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("lineData"), LINE_DATA_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("lineData"), LINE_DATA_SLOT));
gpu::Shader::makeProgram(*program, slotBindings); gpu::Shader::makeProgram(*program, slotBindings);
@ -1663,11 +1667,14 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {
// enable decal blend // enable decal blend
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
PrepareStencil::testMask(*state);
_standardDrawPipeline = gpu::Pipeline::create(program, state); _standardDrawPipeline = gpu::Pipeline::create(program, state);
auto stateNoBlend = std::make_shared<gpu::State>(); auto stateNoBlend = std::make_shared<gpu::State>();
PrepareStencil::testMaskDrawShape(*state);
auto noBlendPS = gpu::StandardShaderLib::getDrawTextureOpaquePS(); auto noBlendPS = gpu::StandardShaderLib::getDrawTextureOpaquePS();
auto programNoBlend = gpu::Shader::createProgram(vs, noBlendPS); auto programNoBlend = gpu::Shader::createProgram(vs, noBlendPS);
gpu::Shader::makeProgram((*programNoBlend)); gpu::Shader::makeProgram((*programNoBlend));
@ -1690,12 +1697,14 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo
auto stateLayered = std::make_shared<gpu::State>(); auto stateLayered = std::make_shared<gpu::State>();
stateLayered->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); stateLayered->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
PrepareStencil::testMask(*stateLayered);
_gridPipelineLayered = gpu::Pipeline::create(program, stateLayered); _gridPipelineLayered = gpu::Pipeline::create(program, stateLayered);
auto state = std::make_shared<gpu::State>(stateLayered->getValues()); auto state = std::make_shared<gpu::State>(stateLayered->getValues());
const float DEPTH_BIAS = 0.001f; const float DEPTH_BIAS = 0.001f;
state->setDepthBias(DEPTH_BIAS); state->setDepthBias(DEPTH_BIAS);
state->setDepthTest(true, false, gpu::LESS_EQUAL); state->setDepthTest(true, false, gpu::LESS_EQUAL);
PrepareStencil::testMaskDrawShape(*state);
_gridPipeline = gpu::Pipeline::create(program, state); _gridPipeline = gpu::Pipeline::create(program, state);
} }
@ -1773,6 +1782,11 @@ static void buildWebShader(const std::string& vertShaderText, const std::string&
state->setBlendFunction(blendEnable, state->setBlendFunction(blendEnable,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, 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); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
if (blendEnable) {
PrepareStencil::testMask(*state);
} else {
PrepareStencil::testMaskDrawShape(*state);
}
pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state); pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state);
} }
@ -1858,6 +1872,12 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, 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); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
if (config.isTransparent()) {
PrepareStencil::testMask(*state);
} else {
PrepareStencil::testMaskDrawShape(*state);
}
gpu::ShaderPointer program = (config.isUnlit()) ? _unlitShader : _simpleShader; gpu::ShaderPointer program = (config.isUnlit()) ? _unlitShader : _simpleShader;
gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state); gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state);
_simplePrograms.insert(config, pipeline); _simplePrograms.insert(config, pipeline);

View file

@ -1,94 +0,0 @@
//
// HitEffect.cpp
// interface/src/renderer
//
// Created by Andrzej Kapolka on 7/14/13.
// 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
//
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
#include <glm/gtc/random.hpp>
#include <DependencyManager.h>
#include <PathUtils.h>
#include <SharedUtil.h>
#include "AbstractViewStateInterface.h"
#include "HitEffect.h"
#include "TextureCache.h"
#include "DependencyManager.h"
#include "ViewFrustum.h"
#include "GeometryCache.h"
#include <gpu/Context.h>
#include "hit_effect_vert.h"
#include "hit_effect_frag.h"
HitEffect::HitEffect() {
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
}
HitEffect::~HitEffect() {
auto geometryCache = DependencyManager::get<GeometryCache>();
if (_geometryId && geometryCache) {
geometryCache->releaseID(_geometryId);
}
}
const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() {
if (!_hitEffectPipeline) {
auto vs = gpu::Shader::createVertex(std::string(hit_effect_vert));
auto ps = gpu::Shader::createPixel(std::string(hit_effect_frag));
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(false, false, gpu::LESS_EQUAL);
// Blend on transparent
state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
// Good to go add the brand new pipeline
_hitEffectPipeline = gpu::Pipeline::create(program, state);
}
return _hitEffectPipeline;
}
void HitEffect::run(const render::RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
glm::mat4 projMat;
Transform viewMat;
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
batch.setModelTransform(Transform());
batch.setPipeline(getHitEffectPipeline());
static const glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f);
static const glm::vec2 bottomLeft(-1.0f, -1.0f);
static const glm::vec2 topRight(1.0f, 1.0f);
DependencyManager::get<GeometryCache>()->renderQuad(batch, bottomLeft, topRight, color, _geometryId);
});
}

View file

@ -1,38 +0,0 @@
//
// hitEffect.h
// hifi
//
// Created by eric levin on 7/17/15.
//
//
#ifndef hifi_hitEffect_h
#define hifi_hitEffect_h
#include <render/DrawTask.h>
class HitEffectConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(bool enabled MEMBER enabled)
public:
HitEffectConfig() : render::Job::Config(false) {}
};
class HitEffect {
public:
using Config = HitEffectConfig;
using JobModel = render::Job::Model<HitEffect, Config>;
HitEffect();
~HitEffect();
void configure(const Config& config) {}
void run(const render::RenderContextPointer& renderContext);
const gpu::PipelinePointer& getHitEffectPipeline();
private:
int _geometryId { 0 };
gpu::PipelinePointer _hitEffectPipeline;
};
#endif

View file

@ -16,6 +16,8 @@
#include <gpu/StandardShaderLib.h> #include <gpu/StandardShaderLib.h>
#include "StencilMaskPass.h"
#include "lightClusters_drawGrid_vert.h" #include "lightClusters_drawGrid_vert.h"
#include "lightClusters_drawGrid_frag.h" #include "lightClusters_drawGrid_frag.h"

View file

@ -27,12 +27,12 @@
#include <render/BlurTask.h> #include <render/BlurTask.h>
#include "LightingModel.h" #include "LightingModel.h"
#include "StencilMaskPass.h"
#include "DebugDeferredBuffer.h" #include "DebugDeferredBuffer.h"
#include "DeferredFramebuffer.h" #include "DeferredFramebuffer.h"
#include "DeferredLightingEffect.h" #include "DeferredLightingEffect.h"
#include "SurfaceGeometryPass.h" #include "SurfaceGeometryPass.h"
#include "FramebufferCache.h" #include "FramebufferCache.h"
#include "HitEffect.h"
#include "TextureCache.h" #include "TextureCache.h"
#include "ZoneRenderer.h" #include "ZoneRenderer.h"
@ -43,8 +43,6 @@
#include <gpu/StandardShaderLib.h> #include <gpu/StandardShaderLib.h>
#include "drawOpaqueStencil_frag.h"
using namespace render; using namespace render;
extern void initOverlay3DPipelines(render::ShapePlumber& plumber); extern void initOverlay3DPipelines(render::ShapePlumber& plumber);
@ -85,13 +83,13 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
const auto deferredFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(0); const auto deferredFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(0);
const auto lightingFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(1); const auto lightingFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(1);
// draw a stencil mask in hidden regions of the framebuffer.
task.addJob<PrepareStencil>("PrepareStencil", primaryFramebuffer);
// Render opaque objects in DeferredBuffer // Render opaque objects in DeferredBuffer
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying();
task.addJob<DrawStateSortDeferred>("DrawOpaqueDeferred", opaqueInputs, shapePlumber); task.addJob<DrawStateSortDeferred>("DrawOpaqueDeferred", opaqueInputs, shapePlumber);
// Once opaque is all rendered create stencil background
task.addJob<DrawStencilDeferred>("DrawOpaqueStencil", deferredFramebuffer);
task.addJob<EndGPURangeTimer>("OpaqueRangeTimer", opaqueRangeTimer); task.addJob<EndGPURangeTimer>("OpaqueRangeTimer", opaqueRangeTimer);
@ -387,88 +385,6 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs&
} }
} }
gpu::PipelinePointer DrawStencilDeferred::getOpaquePipeline() {
if (!_opaquePipeline) {
const gpu::int8 STENCIL_OPAQUE = 1;
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
auto ps = gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag));
auto program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::makeProgram((*program));
auto state = std::make_shared<gpu::State>();
state->setDepthTest(true, false, gpu::LESS_EQUAL);
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP));
state->setColorWriteMask(0);
_opaquePipeline = gpu::Pipeline::create(program, state);
}
return _opaquePipeline;
}
void DrawStencilDeferred::run(const RenderContextPointer& renderContext, const DeferredFramebufferPointer& deferredFramebuffer) {
assert(renderContext->args);
assert(renderContext->args->hasViewFrustum());
// from the touched pixel generate the stencil buffer
RenderArgs* args = renderContext->args;
doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch;
auto deferredFboColorDepthStencil = deferredFramebuffer->getDeferredFramebufferDepthColor();
batch.enableStereo(false);
batch.setFramebuffer(deferredFboColorDepthStencil);
batch.setViewportTransform(args->_viewport);
batch.setStateScissorRect(args->_viewport);
batch.setPipeline(getOpaquePipeline());
batch.draw(gpu::TRIANGLE_STRIP, 4);
batch.setResourceTexture(0, nullptr);
});
args->_batch = nullptr;
}
void DrawBackgroundDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) {
assert(renderContext->args);
assert(renderContext->args->hasViewFrustum());
const auto& inItems = inputs.get0();
const auto& lightingModel = inputs.get1();
if (!lightingModel->isBackgroundEnabled()) {
return;
}
RenderArgs* args = renderContext->args;
doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch;
// _gpuTimer.begin(batch);
batch.enableSkybox(true);
batch.setViewportTransform(args->_viewport);
batch.setStateScissorRect(args->_viewport);
glm::mat4 projMat;
Transform viewMat;
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
renderItems(renderContext, inItems);
// _gpuTimer.end(batch);
});
args->_batch = nullptr;
// std::static_pointer_cast<Config>(renderContext->jobConfig)->gpuTime = _gpuTimer.getAverage();
}
void Blit::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) { void Blit::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) {
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_context); assert(renderContext->args->_context);
@ -538,3 +454,4 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer
} }
}); });
} }

View file

@ -120,35 +120,6 @@ protected:
bool _stateSort; bool _stateSort;
}; };
class DeferredFramebuffer;
class DrawStencilDeferred {
public:
using JobModel = render::Job::ModelI<DrawStencilDeferred, std::shared_ptr<DeferredFramebuffer>>;
void run(const render::RenderContextPointer& renderContext, const std::shared_ptr<DeferredFramebuffer>& deferredFramebuffer);
protected:
gpu::PipelinePointer _opaquePipeline;
gpu::PipelinePointer getOpaquePipeline();
};
using DrawBackgroundDeferredConfig = render::GPUJobConfig;
class DrawBackgroundDeferred {
public:
using Inputs = render::VaryingSet2 <render::ItemBounds, LightingModelPointer>;
using Config = DrawBackgroundDeferredConfig;
using JobModel = render::Job::ModelI<DrawBackgroundDeferred, Inputs, Config>;
void configure(const Config& config) {}
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
protected:
gpu::RangeTimerPointer _gpuTimer;
};
class DrawOverlay3DConfig : public render::Job::Config { class DrawOverlay3DConfig : public render::Job::Config {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged)

View file

@ -15,6 +15,7 @@
#include <gpu/Context.h> #include <gpu/Context.h>
#include <gpu/StandardShaderLib.h> #include <gpu/StandardShaderLib.h>
#include "StencilMaskPass.h"
#include "DeferredLightingEffect.h" #include "DeferredLightingEffect.h"
#include "TextureCache.h" #include "TextureCache.h"
#include "render/DrawTask.h" #include "render/DrawTask.h"
@ -330,6 +331,7 @@ void addPlumberPipeline(ShapePlumber& plumber,
bool isWireframed = (i & 4); bool isWireframed = (i & 4);
auto state = std::make_shared<gpu::State>(); auto state = std::make_shared<gpu::State>();
PrepareStencil::testMaskDrawShape(*state);
// Depth test depends on transparency // Depth test depends on transparency
state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);

View file

@ -0,0 +1,126 @@
//
// StencilMaskPass.cpp
// render-utils/src/
//
// Created by Sam Gateau on 5/31/17.
// Copyright 2016 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 "StencilMaskPass.h"
#include <RenderArgs.h>
#include <ViewFrustum.h>
#include <gpu/Context.h>
#include <gpu/StandardShaderLib.h>
#include "stencil_drawMask_frag.h"
using namespace render;
void PrepareStencil::configure(const Config& config) {
_maskMode = config.maskMode;
_forceDraw = config.forceDraw;
}
model::MeshPointer PrepareStencil::getMesh() {
if (!_mesh) {
std::vector<glm::vec3> vertices {
{ -1.0f, -1.0f, 0.0f }, { -1.0f, 0.0f, 0.0f },
{ -1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f },
{ 1.0f, 1.0f, 0.0f }, { 1.0f, 0.0f, 0.0f },
{ 1.0f, -1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f } };
std::vector<uint32_t> indices { 0, 7, 1, 1, 3, 2, 3, 5, 4, 5, 7, 6 };
_mesh = model::Mesh::createIndexedTriangles_P3F((uint32_t) vertices.size(), (uint32_t) indices.size(), vertices.data(), indices.data());
}
return _mesh;
}
gpu::PipelinePointer PrepareStencil::getMeshStencilPipeline() {
if (!_meshStencilPipeline) {
auto vs = gpu::StandardShaderLib::getDrawVertexPositionVS();
auto ps = gpu::StandardShaderLib::getDrawNadaPS();
auto program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::makeProgram((*program));
auto state = std::make_shared<gpu::State>();
drawMask(*state);
state->setColorWriteMask(0);
_meshStencilPipeline = gpu::Pipeline::create(program, state);
}
return _meshStencilPipeline;
}
gpu::PipelinePointer PrepareStencil::getPaintStencilPipeline() {
if (!_paintStencilPipeline) {
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
auto ps = gpu::Shader::createPixel(std::string(stencil_drawMask_frag));
auto program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::makeProgram((*program));
auto state = std::make_shared<gpu::State>();
drawMask(*state);
state->setColorWriteMask(0);
_paintStencilPipeline = gpu::Pipeline::create(program, state);
}
return _paintStencilPipeline;
}
void PrepareStencil::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) {
RenderArgs* args = renderContext->args;
// Only draw the stencil mask if in HMD mode or not forced.
if (!_forceDraw && (args->_displayMode != RenderArgs::STEREO_HMD)) {
return;
}
doInBatch(args->_context, [&](gpu::Batch& batch) {
batch.enableStereo(false);
batch.setViewportTransform(args->_viewport);
if (_maskMode < 0) {
batch.setPipeline(getMeshStencilPipeline());
auto mesh = getMesh();
batch.setIndexBuffer(mesh->getIndexBuffer());
batch.setInputFormat((mesh->getVertexFormat()));
batch.setInputStream(0, mesh->getVertexStream());
// Draw
auto part = mesh->getPartBuffer().get<model::Mesh::Part>(0);
batch.drawIndexed(gpu::TRIANGLES, part._numIndices, part._startIndex);
} else {
batch.setPipeline(getPaintStencilPipeline());
batch.draw(gpu::TRIANGLE_STRIP, 4);
}
});
}
void PrepareStencil::drawMask(gpu::State& state) {
state.setStencilTest(true, 0xFF, gpu::State::StencilTest(PrepareStencil::STENCIL_MASK, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE));
}
void PrepareStencil::testMask(gpu::State& state) {
state.setStencilTest(true, 0x00, gpu::State::StencilTest(PrepareStencil::STENCIL_MASK, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
}
void PrepareStencil::testBackground(gpu::State& state) {
state.setStencilTest(true, 0x00, gpu::State::StencilTest(PrepareStencil::STENCIL_BACKGROUND, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
}
void PrepareStencil::testMaskDrawShape(gpu::State& state) {
state.setStencilTest(true, 0xFF, gpu::State::StencilTest(PrepareStencil::STENCIL_MASK, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_ZERO));
}
void PrepareStencil::testShape(gpu::State& state) {
state.setStencilTest(true, 0x00, gpu::State::StencilTest(PrepareStencil::STENCIL_SHAPE, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
}

View file

@ -0,0 +1,71 @@
//
// StencilMaskPass.h
// render-utils/src/
//
// Created by Sam Gateau on 5/31/17.
// Copyright 20154 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
#ifndef hifi_StencilMaskPass_h
#define hifi_StencilMaskPass_h
#include <render/Engine.h>
#include <gpu/Pipeline.h>
#include <model/Geometry.h>
class PrepareStencilConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(int maskMode MEMBER maskMode NOTIFY dirty)
Q_PROPERTY(bool forceDraw MEMBER forceDraw NOTIFY dirty)
public:
PrepareStencilConfig(bool enabled = true) : JobConfig(enabled) {}
int maskMode { 0 };
bool forceDraw { false };
signals:
void dirty();
};
class PrepareStencil {
public:
using Config = PrepareStencilConfig;
using JobModel = render::Job::ModelI<PrepareStencil, gpu::FramebufferPointer, Config>;
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& dstFramebuffer);
static const gpu::int8 STENCIL_MASK = 2;
static const gpu::int8 STENCIL_BACKGROUND = 1;
static const gpu::int8 STENCIL_SHAPE = 0;
static void drawMask(gpu::State& state);
static void testMask(gpu::State& state);
static void testBackground(gpu::State& state);
static void testMaskDrawShape(gpu::State& state);
static void testShape(gpu::State& state);
private:
gpu::PipelinePointer _meshStencilPipeline;
gpu::PipelinePointer getMeshStencilPipeline();
gpu::PipelinePointer _paintStencilPipeline;
gpu::PipelinePointer getPaintStencilPipeline();
model::MeshPointer _mesh;
model::MeshPointer getMesh();
int _maskMode { 0 };
bool _forceDraw { false };
};
#endif // hifi_StencilMaskPass_h

View file

@ -14,7 +14,7 @@
#include <gpu/Context.h> #include <gpu/Context.h>
#include <gpu/StandardShaderLib.h> #include <gpu/StandardShaderLib.h>
#include "StencilMaskPass.h"
const int DepthLinearPass_FrameTransformSlot = 0; const int DepthLinearPass_FrameTransformSlot = 0;
const int DepthLinearPass_DepthMapSlot = 0; const int DepthLinearPass_DepthMapSlot = 0;
@ -224,7 +224,7 @@ const gpu::PipelinePointer& LinearDepthPass::getLinearDepthPipeline() {
gpu::StatePointer state = gpu::StatePointer(new gpu::State()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
// Stencil test the curvature pass for objects pixels only, not the background // Stencil test the curvature pass for objects pixels only, not the background
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); PrepareStencil::testShape(*state);
state->setColorWriteMask(true, false, false, false); state->setColorWriteMask(true, false, false, false);
@ -250,6 +250,7 @@ const gpu::PipelinePointer& LinearDepthPass::getDownsamplePipeline() {
gpu::StatePointer state = gpu::StatePointer(new gpu::State()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
PrepareStencil::testShape(*state);
state->setColorWriteMask(true, true, true, false); state->setColorWriteMask(true, true, true, false);
@ -554,7 +555,7 @@ const gpu::PipelinePointer& SurfaceGeometryPass::getCurvaturePipeline() {
#ifdef USE_STENCIL_TEST #ifdef USE_STENCIL_TEST
// Stencil test the curvature pass for objects pixels only, not the background // Stencil test the curvature pass for objects pixels only, not the background
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); PrepareStencil::testShape(*state);
#endif #endif
// Good to go add the brand new pipeline // Good to go add the brand new pipeline
_curvaturePipeline = gpu::Pipeline::create(program, state); _curvaturePipeline = gpu::Pipeline::create(program, state);

View file

@ -15,7 +15,7 @@
#include <gpu/StandardShaderLib.h> #include <gpu/StandardShaderLib.h>
#include <RenderArgs.h> #include <RenderArgs.h>
#include "StencilMaskPass.h"
#include "FramebufferCache.h" #include "FramebufferCache.h"
#include "toneMapping_frag.h" #include "toneMapping_frag.h"

View file

@ -17,6 +17,7 @@
#include <render/FilterTask.h> #include <render/FilterTask.h>
#include <render/DrawTask.h> #include <render/DrawTask.h>
#include "StencilMaskPass.h"
#include "DeferredLightingEffect.h" #include "DeferredLightingEffect.h"
#include "zone_drawKeyLight_frag.h" #include "zone_drawKeyLight_frag.h"
@ -74,6 +75,7 @@ const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() {
gpu::StatePointer state = gpu::StatePointer(new gpu::State()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
PrepareStencil::testMask(*state);
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
_keyLightPipeline = gpu::Pipeline::create(program, state); _keyLightPipeline = gpu::Pipeline::create(program, state);
} }
@ -95,6 +97,7 @@ const gpu::PipelinePointer& DebugZoneLighting::getAmbientPipeline() {
gpu::StatePointer state = gpu::StatePointer(new gpu::State()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
PrepareStencil::testMask(*state);
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
_ambientPipeline = gpu::Pipeline::create(program, state); _ambientPipeline = gpu::Pipeline::create(program, state);
} }
@ -115,6 +118,7 @@ const gpu::PipelinePointer& DebugZoneLighting::getBackgroundPipeline() {
gpu::StatePointer state = gpu::StatePointer(new gpu::State()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
PrepareStencil::testMask(*state);
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
_backgroundPipeline = gpu::Pipeline::create(program, state); _backgroundPipeline = gpu::Pipeline::create(program, state);
} }

View file

@ -1,47 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// directional_light.frag
// fragment shader
//
// Created by Andrzej Kapolka on 9/3/14.
// Copyright 2016 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 DeferredBufferRead.slh@>
<@include DeferredGlobalLight.slh@>
<$declareEvalLightmappedColor()$>
<$declareEvalAmbientGlobalColor()$>
in vec2 _texCoord0;
out vec4 _fragColor;
void main(void) {
DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);
float shadowAttenuation = 1.0;
if (frag.mode == FRAG_MODE_UNLIT) {
discard;
} else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {
discard;
} else {
vec3 color = evalAmbientGlobalColor(
getViewInverse(),
shadowAttenuation,
frag.obscurance,
frag.position.xyz,
frag.normal,
frag.albedo,
frag.fresnel,
frag.metallic,
frag.roughness);
_fragColor = vec4(color, 1.0);
}
}

View file

@ -1,49 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// directional_light_shadow.frag
// fragment shader
//
// Created by Zach Pomerantz on 1/18/2016.
// Copyright 2016 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 Shadow.slh@>
<@include DeferredBufferRead.slh@>
<@include DeferredGlobalLight.slh@>
<$declareEvalLightmappedColor()$>
<$declareEvalAmbientGlobalColor()$>
in vec2 _texCoord0;
out vec4 _fragColor;
void main(void) {
DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);
vec4 worldPos = getViewInverse() * vec4(frag.position.xyz, 1.0);
float shadowAttenuation = evalShadowAttenuation(worldPos);
if (frag.mode == FRAG_MODE_UNLIT) {
discard;
} else if (frag.mode == FRAG_MODE_LIGHTMAPPED) {
discard;
} else {
vec3 color = evalAmbientGlobalColor(
getViewInverse(),
shadowAttenuation,
frag.obscurance,
frag.position.xyz,
frag.normal,
frag.albedo,
frag.fresnel,
frag.metallic,
frag.roughness);
_fragColor = vec4(color, 1.0);
}
}

View file

@ -1,27 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// hit_effect.frag
// fragment shader
//
// Created by Eric Levin on 7/20
// 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 DeferredBufferWrite.slh@>
in vec2 varQuadPosition;
out vec4 outFragColor;
void main(void) {
vec2 center = vec2(0.0, 0.0);
float distFromCenter = distance( vec2(0.0, 0.0), varQuadPosition);
float alpha = mix(0.0, 0.5, pow(distFromCenter,5.));
outFragColor = vec4(1.0, 0.0, 0.0, alpha);
}

View file

@ -1,85 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// point_light.frag
// fragment shader
//
// Created by Sam Gateau on 9/18/15.
// Copyright 2014 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
//
<!
// Everything about deferred buffer
<@include DeferredBufferRead.slh@>
<$declareDeferredCurvature()$>
// Everything about light
<@include model/Light.slh@>
<$declareLightBuffer()$>
<@include LightingModel.slh@>
<@include LightPoint.slh@>
<$declareLightingPoint(supportScattering)$>
uniform vec4 texcoordFrameTransform;
in vec4 _texCoord0;!>
out vec4 _fragColor;
void main(void) {
_fragColor = vec4(1.0, 1.0, 1.0, 1.0);
<!
DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
// Grab the fragment data from the uv
vec2 texCoord = _texCoord0.st / _texCoord0.q;
texCoord *= texcoordFrameTransform.zw;
texCoord += texcoordFrameTransform.xy;
DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord);
if (frag.mode == FRAG_MODE_UNLIT) {
discard;
}
// Need the light now
Light light = getLight();
// Frag pos in world
mat4 invViewMat = getViewInverse();
vec4 fragPos = invViewMat * frag.position;
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
vec4 fragLightVecLen2;
if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {
discard;
}
// Frag to eye vec
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec3 diffuse;
vec3 specular;
vec4 midNormalCurvature;
vec4 lowNormalCurvature;
if (frag.mode == FRAG_MODE_SCATTERING) {
unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature);
}
evalLightingPoint(diffuse, specular, light,
fragLightVecLen2.xyz, fragEyeDir, frag.normal, frag.roughness,
frag.metallic, frag.fresnel, frag.albedo, 1.0,
frag.scattering, midNormalCurvature, lowNormalCurvature);
_fragColor.rgb += diffuse;
_fragColor.rgb += specular;
!>
}

View file

@ -1,115 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// spot_light.frag
// fragment shader
//
// Created by Sam Gateau on 9/18/15.
// Copyright 2014 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
//
// Everything about deferred buffer
<!<@include DeferredBufferRead.slh@>
<$declareDeferredCurvature()$>
// Everything about light
<@include model/Light.slh@>
<$declareLightBuffer(256)$>
uniform lightIndexBuffer {
int lightIndex[256];
};
<@include LightingModel.slh@>
<@include LightPoint.slh@>
<$declareLightingPoint(supportScattering)$>
<@include LightSpot.slh@>
<$declareLightingSpot(supportScattering)$>
//uniform vec4 texcoordFrameTransform;
!>
//in vec4 _texCoord0;
//flat in int instanceID;
out vec4 _fragColor;
void main(void) {
_fragColor = vec4(1.0, 1.0, 1.0, 1.0);
// DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
// Grab the fragment data from the uv
//vec2 texCoord = _texCoord0.st;/* / _texCoord0.q;
/*texCoord *= texcoordFrameTransform.zw;
texCoord += texcoordFrameTransform.xy;*/
/*
vec4 fragPosition = unpackDeferredPositionFromZeye(texCoord);
DeferredFragment frag = unpackDeferredFragmentNoPosition(texCoord);
if (frag.mode == FRAG_MODE_UNLIT) {
discard;
}
// frag.depthVal = depthValue;
frag.position = fragPosition;
vec4 midNormalCurvature;
vec4 lowNormalCurvature;
if (frag.mode == FRAG_MODE_SCATTERING) {
unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature);
}
// Frag pos in world
mat4 invViewMat = getViewInverse();
vec4 fragPos = invViewMat * fragPosition;
// Frag to eye vec
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
int numLights = lightIndex[0];
for (int i = 0; i < numLights; i++) {
// Need the light now
Light light = getLight(lightIndex[i + 1]);
bool isSpot = light_isSpot(light);
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
vec4 fragLightVecLen2;
vec4 fragLightDirLen;
float cosSpotAngle;
if (isSpot) {
if (!clipFragToLightVolumeSpot(light, fragPos.xyz, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) {
continue;
}
} else {
if (!clipFragToLightVolumePoint(light, fragPos.xyz, fragLightVecLen2)) {
continue;
}
}
vec3 diffuse;
vec3 specular;
if (isSpot) {
evalLightingSpot(diffuse, specular, light,
fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness,
frag.metallic, frag.fresnel, frag.albedo, 1.0,
frag.scattering, midNormalCurvature, lowNormalCurvature);
} else {
evalLightingPoint(diffuse, specular, light,
fragLightVecLen2.xyz, fragEyeDir, frag.normal, frag.roughness,
frag.metallic, frag.fresnel, frag.albedo, 1.0,
frag.scattering, midNormalCurvature, lowNormalCurvature);
}
_fragColor.rgb += diffuse;
_fragColor.rgb += specular;
}
*/
}

View file

@ -0,0 +1,23 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// stencil_drawMask.slf
// fragment shader
//
// Created by Sam Gateau on 5/31/17.
// 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
//
in vec2 varTexCoord0;
float aspectRatio = 0.95;
void main(void) {
vec2 pos = varTexCoord0 * 2.0 - vec2(1.0);
pos.x = aspectRatio * (pos.x * (pos.x > 0.0 ? 2.0 : -2.0) - 1.0);
if (1.0 - dot(pos.xy, pos.xy) > 0.0 ) discard;
}

View file

@ -49,7 +49,7 @@ const mat4 Matrices::Z_180 { createMatFromQuatAndPos(Quaternions::Z_180, Vectors
glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float proportion) { glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float proportion) {
float cosa = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w; float cosa = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
float ox = q2.x, oy = q2.y, oz = q2.z, ow = q2.w, s0, s1; float ox = q2.x, oy = q2.y, oz = q2.z, ow = q2.w, s0, s1;
// adjust signs if necessary // adjust signs if necessary
if (cosa < 0.0f) { if (cosa < 0.0f) {
cosa = -cosa; cosa = -cosa;
@ -58,19 +58,19 @@ glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float proportion) {
oz = -oz; oz = -oz;
ow = -ow; ow = -ow;
} }
// calculate coefficients; if the angle is too close to zero, we must fall back // calculate coefficients; if the angle is too close to zero, we must fall back
// to linear interpolation // to linear interpolation
if ((1.0f - cosa) > EPSILON) { if ((1.0f - cosa) > EPSILON) {
float angle = acosf(cosa), sina = sinf(angle); float angle = acosf(cosa), sina = sinf(angle);
s0 = sinf((1.0f - proportion) * angle) / sina; s0 = sinf((1.0f - proportion) * angle) / sina;
s1 = sinf(proportion * angle) / sina; s1 = sinf(proportion * angle) / sina;
} else { } else {
s0 = 1.0f - proportion; s0 = 1.0f - proportion;
s1 = proportion; s1 = proportion;
} }
return glm::normalize(glm::quat(s0 * q1.w + s1 * ow, s0 * q1.x + s1 * ox, s0 * q1.y + s1 * oy, s0 * q1.z + s1 * oz)); return glm::normalize(glm::quat(s0 * q1.w + s1 * ow, s0 * q1.x + s1 * ox, s0 * q1.y + s1 * oy, s0 * q1.z + s1 * oz));
} }
@ -105,10 +105,10 @@ int unpackFloatVec3FromSignedTwoByteFixed(const unsigned char* sourceBuffer, glm
int packFloatAngleToTwoByte(unsigned char* buffer, float degrees) { int packFloatAngleToTwoByte(unsigned char* buffer, float degrees) {
const float ANGLE_CONVERSION_RATIO = (std::numeric_limits<uint16_t>::max() / 360.0f); const float ANGLE_CONVERSION_RATIO = (std::numeric_limits<uint16_t>::max() / 360.0f);
uint16_t angleHolder = floorf((degrees + 180.0f) * ANGLE_CONVERSION_RATIO); uint16_t angleHolder = floorf((degrees + 180.0f) * ANGLE_CONVERSION_RATIO);
memcpy(buffer, &angleHolder, sizeof(uint16_t)); memcpy(buffer, &angleHolder, sizeof(uint16_t));
return sizeof(uint16_t); return sizeof(uint16_t);
} }
@ -125,7 +125,7 @@ int packOrientationQuatToBytes(unsigned char* buffer, const glm::quat& quatInput
quatParts[1] = floorf((quatNormalized.y + 1.0f) * QUAT_PART_CONVERSION_RATIO); quatParts[1] = floorf((quatNormalized.y + 1.0f) * QUAT_PART_CONVERSION_RATIO);
quatParts[2] = floorf((quatNormalized.z + 1.0f) * QUAT_PART_CONVERSION_RATIO); quatParts[2] = floorf((quatNormalized.z + 1.0f) * QUAT_PART_CONVERSION_RATIO);
quatParts[3] = floorf((quatNormalized.w + 1.0f) * QUAT_PART_CONVERSION_RATIO); quatParts[3] = floorf((quatNormalized.w + 1.0f) * QUAT_PART_CONVERSION_RATIO);
memcpy(buffer, &quatParts, sizeof(quatParts)); memcpy(buffer, &quatParts, sizeof(quatParts));
return sizeof(quatParts); return sizeof(quatParts);
} }
@ -133,12 +133,12 @@ int packOrientationQuatToBytes(unsigned char* buffer, const glm::quat& quatInput
int unpackOrientationQuatFromBytes(const unsigned char* buffer, glm::quat& quatOutput) { int unpackOrientationQuatFromBytes(const unsigned char* buffer, glm::quat& quatOutput) {
uint16_t quatParts[4]; uint16_t quatParts[4];
memcpy(&quatParts, buffer, sizeof(quatParts)); memcpy(&quatParts, buffer, sizeof(quatParts));
quatOutput.x = ((quatParts[0] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f; quatOutput.x = ((quatParts[0] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
quatOutput.y = ((quatParts[1] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f; quatOutput.y = ((quatParts[1] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
quatOutput.z = ((quatParts[2] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f; quatOutput.z = ((quatParts[2] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
quatOutput.w = ((quatParts[3] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f; quatOutput.w = ((quatParts[3] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
return sizeof(quatParts); return sizeof(quatParts);
} }
@ -235,7 +235,7 @@ glm::vec3 safeEulerAngles(const glm::quat& q) {
atan2f(q.y * q.z + q.x * q.w, 0.5f - (q.x * q.x + q.y * q.y)), atan2f(q.y * q.z + q.x * q.w, 0.5f - (q.x * q.x + q.y * q.y)),
asinf(sy), asinf(sy),
atan2f(q.x * q.y + q.z * q.w, 0.5f - (q.y * q.y + q.z * q.z))); atan2f(q.x * q.y + q.z * q.w, 0.5f - (q.y * q.y + q.z * q.z)));
} else { } else {
// not a unique solution; x + z = atan2(-m21, m11) // not a unique solution; x + z = atan2(-m21, m11)
eulers = glm::vec3( eulers = glm::vec3(
@ -250,7 +250,7 @@ glm::vec3 safeEulerAngles(const glm::quat& q) {
PI_OVER_TWO, PI_OVER_TWO,
-atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z))); -atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z)));
} }
// adjust so that z, rather than y, is in [-pi/2, pi/2] // adjust so that z, rather than y, is in [-pi/2, pi/2]
if (eulers.z < -PI_OVER_TWO) { if (eulers.z < -PI_OVER_TWO) {
if (eulers.x < 0.0f) { if (eulers.x < 0.0f) {
@ -265,7 +265,7 @@ glm::vec3 safeEulerAngles(const glm::quat& q) {
eulers.y -= PI; eulers.y -= PI;
} }
eulers.z += PI; eulers.z += PI;
} else if (eulers.z > PI_OVER_TWO) { } else if (eulers.z > PI_OVER_TWO) {
if (eulers.x < 0.0f) { if (eulers.x < 0.0f) {
eulers.x += PI; eulers.x += PI;
@ -320,7 +320,7 @@ glm::quat extractRotation(const glm::mat4& matrix, bool assumeOrthogonal) {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
// store the results of the previous iteration // store the results of the previous iteration
glm::mat3 previous = upper; glm::mat3 previous = upper;
// compute average of the matrix with its inverse transpose // compute average of the matrix with its inverse transpose
float sd00 = previous[1][1] * previous[2][2] - previous[2][1] * previous[1][2]; float sd00 = previous[1][1] * previous[2][2] - previous[2][1] * previous[1][2];
float sd10 = previous[0][1] * previous[2][2] - previous[2][1] * previous[0][2]; float sd10 = previous[0][1] * previous[2][2] - previous[2][1] * previous[0][2];
@ -334,15 +334,15 @@ glm::quat extractRotation(const glm::mat4& matrix, bool assumeOrthogonal) {
upper[0][0] = +sd00 * hrdet + previous[0][0] * 0.5f; upper[0][0] = +sd00 * hrdet + previous[0][0] * 0.5f;
upper[1][0] = -sd10 * hrdet + previous[1][0] * 0.5f; upper[1][0] = -sd10 * hrdet + previous[1][0] * 0.5f;
upper[2][0] = +sd20 * hrdet + previous[2][0] * 0.5f; upper[2][0] = +sd20 * hrdet + previous[2][0] * 0.5f;
upper[0][1] = -(previous[1][0] * previous[2][2] - previous[2][0] * previous[1][2]) * hrdet + previous[0][1] * 0.5f; upper[0][1] = -(previous[1][0] * previous[2][2] - previous[2][0] * previous[1][2]) * hrdet + previous[0][1] * 0.5f;
upper[1][1] = +(previous[0][0] * previous[2][2] - previous[2][0] * previous[0][2]) * hrdet + previous[1][1] * 0.5f; upper[1][1] = +(previous[0][0] * previous[2][2] - previous[2][0] * previous[0][2]) * hrdet + previous[1][1] * 0.5f;
upper[2][1] = -(previous[0][0] * previous[1][2] - previous[1][0] * previous[0][2]) * hrdet + previous[2][1] * 0.5f; upper[2][1] = -(previous[0][0] * previous[1][2] - previous[1][0] * previous[0][2]) * hrdet + previous[2][1] * 0.5f;
upper[0][2] = +(previous[1][0] * previous[2][1] - previous[2][0] * previous[1][1]) * hrdet + previous[0][2] * 0.5f; upper[0][2] = +(previous[1][0] * previous[2][1] - previous[2][0] * previous[1][1]) * hrdet + previous[0][2] * 0.5f;
upper[1][2] = -(previous[0][0] * previous[2][1] - previous[2][0] * previous[0][1]) * hrdet + previous[1][2] * 0.5f; upper[1][2] = -(previous[0][0] * previous[2][1] - previous[2][0] * previous[0][1]) * hrdet + previous[1][2] * 0.5f;
upper[2][2] = +(previous[0][0] * previous[1][1] - previous[1][0] * previous[0][1]) * hrdet + previous[2][2] * 0.5f; upper[2][2] = +(previous[0][0] * previous[1][1] - previous[1][0] * previous[0][1]) * hrdet + previous[2][2] * 0.5f;
// compute the difference; if it's small enough, we're done // compute the difference; if it's small enough, we're done
glm::mat3 diff = upper - previous; glm::mat3 diff = upper - previous;
if (diff[0][0] * diff[0][0] + diff[1][0] * diff[1][0] + diff[2][0] * diff[2][0] + diff[0][1] * diff[0][1] + if (diff[0][0] * diff[0][0] + diff[1][0] * diff[1][0] + diff[2][0] * diff[2][0] + diff[0][1] * diff[0][1] +
@ -352,7 +352,7 @@ glm::quat extractRotation(const glm::mat4& matrix, bool assumeOrthogonal) {
} }
} }
} }
// now that we have a nice orthogonal matrix, we can extract the rotation quaternion // now that we have a nice orthogonal matrix, we can extract the rotation quaternion
// using the method described in http://en.wikipedia.org/wiki/Rotation_matrix#Conversions // using the method described in http://en.wikipedia.org/wiki/Rotation_matrix#Conversions
float x2 = fabs(1.0f + upper[0][0] - upper[1][1] - upper[2][2]); float x2 = fabs(1.0f + upper[0][0] - upper[1][1] - upper[2][2]);
@ -473,7 +473,7 @@ glm::mat4 createMatFromScaleQuatAndPos(const glm::vec3& scale, const glm::quat&
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f)); glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f));
} }
// cancel out roll // cancel out roll
glm::quat cancelOutRoll(const glm::quat& q) { glm::quat cancelOutRoll(const glm::quat& q) {
glm::vec3 forward = q * Vectors::FRONT; glm::vec3 forward = q * Vectors::FRONT;
return glm::quat_cast(glm::inverse(glm::lookAt(Vectors::ZERO, forward, Vectors::UP))); return glm::quat_cast(glm::inverse(glm::lookAt(Vectors::ZERO, forward, Vectors::UP)));
@ -538,17 +538,16 @@ void generateBasisVectors(const glm::vec3& primaryAxis, const glm::vec3& seconda
uAxisOut = glm::normalize(primaryAxis); uAxisOut = glm::normalize(primaryAxis);
glm::vec3 normSecondary = glm::normalize(secondaryAxis); glm::vec3 normSecondary = glm::normalize(secondaryAxis);
// if secondaryAxis is parallel with the primaryAxis, pick another axis. // if normSecondary is parallel with the primaryAxis, pick another secondary.
const float EPSILON = 1.0e-4f; const float EPSILON = 1.0e-4f;
if (fabsf(fabsf(glm::dot(uAxisOut, secondaryAxis)) - 1.0f) > EPSILON) { if (fabsf(fabsf(glm::dot(uAxisOut, normSecondary)) - 1.0f) < EPSILON) {
// pick a better secondaryAxis. normSecondary = Vectors::UNIT_X;
normSecondary = glm::vec3(1.0f, 0.0f, 0.0f); if (fabsf(fabsf(glm::dot(uAxisOut, normSecondary)) - 1.0f) < EPSILON) {
if (fabsf(fabsf(glm::dot(uAxisOut, secondaryAxis)) - 1.0f) > EPSILON) { normSecondary = Vectors::UNIT_Y;
normSecondary = glm::vec3(0.0f, 1.0f, 0.0f);
} }
} }
wAxisOut = glm::normalize(glm::cross(uAxisOut, secondaryAxis)); wAxisOut = glm::normalize(glm::cross(uAxisOut, normSecondary));
vAxisOut = glm::cross(wAxisOut, uAxisOut); vAxisOut = glm::cross(wAxisOut, uAxisOut);
} }

View file

@ -76,7 +76,7 @@ public:
class RenderArgs { class RenderArgs {
public: public:
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, MIRROR_RENDER_MODE }; enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, MIRROR_RENDER_MODE };
enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT }; enum DisplayMode { MONO, STEREO_MONITOR, STEREO_HMD };
enum DebugFlags { enum DebugFlags {
RENDER_DEBUG_NONE = 0, RENDER_DEBUG_NONE = 0,
RENDER_DEBUG_HULLS = 1 RENDER_DEBUG_HULLS = 1
@ -87,7 +87,7 @@ public:
float sizeScale = 1.0f, float sizeScale = 1.0f,
int boundaryLevelAdjust = 0, int boundaryLevelAdjust = 0,
RenderMode renderMode = DEFAULT_RENDER_MODE, RenderMode renderMode = DEFAULT_RENDER_MODE,
RenderSide renderSide = MONO, DisplayMode displayMode = MONO,
DebugFlags debugFlags = RENDER_DEBUG_NONE, DebugFlags debugFlags = RENDER_DEBUG_NONE,
gpu::Batch* batch = nullptr) : gpu::Batch* batch = nullptr) :
_context(context), _context(context),
@ -95,7 +95,7 @@ public:
_sizeScale(sizeScale), _sizeScale(sizeScale),
_boundaryLevelAdjust(boundaryLevelAdjust), _boundaryLevelAdjust(boundaryLevelAdjust),
_renderMode(renderMode), _renderMode(renderMode),
_renderSide(renderSide), _displayMode(displayMode),
_debugFlags(debugFlags), _debugFlags(debugFlags),
_batch(batch) { _batch(batch) {
} }
@ -121,7 +121,7 @@ public:
float _sizeScale = 1.0f; float _sizeScale = 1.0f;
int _boundaryLevelAdjust = 0; int _boundaryLevelAdjust = 0;
RenderMode _renderMode = DEFAULT_RENDER_MODE; RenderMode _renderMode = DEFAULT_RENDER_MODE;
RenderSide _renderSide = MONO; DisplayMode _displayMode = MONO;
DebugFlags _debugFlags = RENDER_DEBUG_NONE; DebugFlags _debugFlags = RENDER_DEBUG_NONE;
gpu::Batch* _batch = nullptr; gpu::Batch* _batch = nullptr;

View file

@ -91,14 +91,14 @@ QObject* OffscreenUi::getFlags() {
void OffscreenUi::create(QOpenGLContext* context) { void OffscreenUi::create(QOpenGLContext* context) {
OffscreenQmlSurface::create(context); OffscreenQmlSurface::create(context);
auto rootContext = getRootContext(); auto myContext = getSurfaceContext();
rootContext->setContextProperty("OffscreenUi", this); myContext->setContextProperty("OffscreenUi", this);
rootContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags()); myContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags());
rootContext->setContextProperty("fileDialogHelper", new FileDialogHelper()); myContext->setContextProperty("fileDialogHelper", new FileDialogHelper());
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
TabletProxy* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); TabletProxy* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
rootContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); myContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
} }
void OffscreenUi::show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f) { void OffscreenUi::show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f) {
@ -547,14 +547,14 @@ void OffscreenUi::createDesktop(const QUrl& url) {
} }
#ifdef DEBUG #ifdef DEBUG
getRootContext()->setContextProperty("DebugQML", QVariant(true)); getSurfaceContext()->setContextProperty("DebugQML", QVariant(true));
#else #else
getRootContext()->setContextProperty("DebugQML", QVariant(false)); getSurfaceContext()->setContextProperty("DebugQML", QVariant(false));
#endif #endif
_desktop = dynamic_cast<QQuickItem*>(load(url)); _desktop = dynamic_cast<QQuickItem*>(load(url));
Q_ASSERT(_desktop); Q_ASSERT(_desktop);
getRootContext()->setContextProperty("desktop", _desktop); getSurfaceContext()->setContextProperty("desktop", _desktop);
_toolWindow = _desktop->findChild<QQuickItem*>("ToolWindow"); _toolWindow = _desktop->findChild<QQuickItem*>("ToolWindow");

View file

@ -115,7 +115,7 @@ private:
VrMenu::VrMenu(OffscreenUi* parent) : QObject(parent) { VrMenu::VrMenu(OffscreenUi* parent) : QObject(parent) {
_rootMenu = parent->getRootItem()->findChild<QObject*>("rootMenu"); _rootMenu = parent->getRootItem()->findChild<QObject*>("rootMenu");
parent->getRootContext()->setContextProperty("rootMenu", _rootMenu); parent->getSurfaceContext()->setContextProperty("rootMenu", _rootMenu);
} }
QObject* VrMenu::findMenuObject(const QString& menuOption) { QObject* VrMenu::findMenuObject(const QString& menuOption) {

View file

@ -123,10 +123,19 @@ bool OculusBaseDisplayPlugin::internalActivate() {
void OculusBaseDisplayPlugin::internalDeactivate() { void OculusBaseDisplayPlugin::internalDeactivate() {
Parent::internalDeactivate(); Parent::internalDeactivate();
}
bool OculusBaseDisplayPlugin::activateStandBySession() {
_session = acquireOculusSession();
if (!_session) {
return false;
}
return true;
}
void OculusBaseDisplayPlugin::deactivateSession() {
releaseOculusSession(); releaseOculusSession();
_session = nullptr; _session = nullptr;
} }
void OculusBaseDisplayPlugin::updatePresentPose() { void OculusBaseDisplayPlugin::updatePresentPose() {
//mat4 sensorResetMat; //mat4 sensorResetMat;
//_currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds(); //_currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();

View file

@ -26,6 +26,7 @@ public:
void resetSensors() override final; void resetSensors() override final;
bool beginFrameRender(uint32_t frameIndex) override; bool beginFrameRender(uint32_t frameIndex) override;
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; } float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
bool getSupportsAutoSwitch() override final { return true; }
protected: protected:
@ -33,6 +34,8 @@ protected:
void uncustomizeContext() override; void uncustomizeContext() override;
bool internalActivate() override; bool internalActivate() override;
void internalDeactivate() override; void internalDeactivate() override;
bool activateStandBySession() override;
void deactivateSession() override;
void updatePresentPose() override; void updatePresentPose() override;
protected: protected:

View file

@ -366,45 +366,25 @@ function Teleporter() {
} }
// related to repositioning the avatar after you teleport // related to repositioning the avatar after you teleport
var FOOT_JOINT_NAMES = ["RightToe_End", "RightToeBase", "RightFoot"];
var DEFAULT_ROOT_TO_FOOT_OFFSET = 0.5;
function getAvatarFootOffset() { function getAvatarFootOffset() {
var data = getJointData();
var upperLeg, lowerLeg, foot, toe, toeTop;
data.forEach(function(d) {
var jointName = d.joint; // find a valid foot jointIndex
if (jointName === "RightUpLeg") { var footJointIndex = -1;
upperLeg = d.translation.y; var i, l = FOOT_JOINT_NAMES.length;
} else if (jointName === "RightLeg") { for (i = 0; i < l; i++) {
lowerLeg = d.translation.y; footJointIndex = MyAvatar.getJointIndex(FOOT_JOINT_NAMES[i]);
} else if (jointName === "RightFoot") { if (footJointIndex != -1) {
foot = d.translation.y; break;
} else if (jointName === "RightToeBase") {
toe = d.translation.y;
} else if (jointName === "RightToe_End") {
toeTop = d.translation.y;
} }
}); }
if (footJointIndex != -1) {
var offset = upperLeg + lowerLeg + foot + toe + toeTop; // default vertical offset from foot to avatar root.
offset = offset / 100; return -MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(footJointIndex).y;
return offset; } else {
} return DEFAULT_ROOT_TO_FOOT_OFFSET * MyAvatar.scale;
}
function getJointData() {
var allJointData = [];
var jointNames = MyAvatar.jointNames;
jointNames.forEach(function(joint, index) {
var translation = MyAvatar.getJointTranslation(index);
var rotation = MyAvatar.getJointRotation(index);
allJointData.push({
joint: joint,
index: index,
translation: translation,
rotation: rotation
});
});
return allJointData;
} }
var leftPad = new ThumbPad('left'); var leftPad = new ThumbPad('left');

View file

@ -642,6 +642,8 @@ var toolBar = (function () {
enabled: active enabled: active
})); }));
isActive = active; isActive = active;
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
if (!isActive) { if (!isActive) {
entityListTool.setVisible(false); entityListTool.setVisible(false);
gridTool.setVisible(false); gridTool.setVisible(false);
@ -650,8 +652,8 @@ var toolBar = (function () {
selectionManager.clearSelections(); selectionManager.clearSelections();
cameraManager.disable(); cameraManager.disable();
selectionDisplay.triggerMapping.disable(); selectionDisplay.triggerMapping.disable();
tablet.landscape = false;
} else { } else {
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
tablet.loadQMLSource("Edit.qml"); tablet.loadQMLSource("Edit.qml");
UserActivityLogger.enabledEdit(); UserActivityLogger.enabledEdit();
entityListTool.setVisible(true); entityListTool.setVisible(true);
@ -659,6 +661,8 @@ var toolBar = (function () {
grid.setEnabled(true); grid.setEnabled(true);
propertiesTool.setVisible(true); propertiesTool.setVisible(true);
selectionDisplay.triggerMapping.enable(); selectionDisplay.triggerMapping.enable();
print("starting tablet in landscape mode")
tablet.landscape = true;
// Not sure what the following was meant to accomplish, but it currently causes // Not sure what the following was meant to accomplish, but it currently causes
// everybody else to think that Interface has lost focus overall. fogbugzid:558 // everybody else to think that Interface has lost focus overall. fogbugzid:558
// Window.setFocus(); // Window.setFocus();

View file

@ -22,7 +22,9 @@ var DEFAULT_WIDTH = 0.4375;
var DEFAULT_VERTICAL_FIELD_OF_VIEW = 45; // degrees var DEFAULT_VERTICAL_FIELD_OF_VIEW = 45; // degrees
var SENSOR_TO_ROOM_MATRIX = -2; var SENSOR_TO_ROOM_MATRIX = -2;
var CAMERA_MATRIX = -7; var CAMERA_MATRIX = -7;
var ROT_Y_180 = {x: 0, y: 1, z: 0, w: 0}; var ROT_Y_180 = {x: 0.0, y: 1.0, z: 0, w: 0};
var ROT_LANDSCAPE = {x: 1.0, y: 1.0, z: 0, w: 0};
var ROT_LANDSCAPE_WINDOW = {x: 0.0, y: 0.0, z: 0.0, w: 0};
var ROT_IDENT = {x: 0, y: 0, z: 0, w: 1}; var ROT_IDENT = {x: 0, y: 0, z: 0, w: 1};
var TABLET_TEXTURE_RESOLUTION = { x: 480, y: 706 }; var TABLET_TEXTURE_RESOLUTION = { x: 480, y: 706 };
var INCHES_TO_METERS = 1 / 39.3701; var INCHES_TO_METERS = 1 / 39.3701;
@ -243,29 +245,29 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
}; };
WebTablet.prototype.getDimensions = function() { WebTablet.prototype.getDimensions = function() {
if (this.landscape) { return { x: this.width, y: this.height, z: this.depth };
return { x: this.width * 2, y: this.height, z: this.depth };
} else {
return { x: this.width, y: this.height, z: this.depth };
}
}; };
WebTablet.prototype.getTabletTextureResolution = function() { WebTablet.prototype.getTabletTextureResolution = function() {
if (this.landscape) { if (this.landscape) {
return { x: TABLET_TEXTURE_RESOLUTION.x * 2, y: TABLET_TEXTURE_RESOLUTION.y }; return { x: TABLET_TEXTURE_RESOLUTION.y , y: TABLET_TEXTURE_RESOLUTION.x };
} else { } else {
return TABLET_TEXTURE_RESOLUTION; return TABLET_TEXTURE_RESOLUTION;
} }
}; };
WebTablet.prototype.setLandscape = function(newLandscapeValue) { WebTablet.prototype.setLandscape = function(newLandscapeValue) {
if (this.landscape == newLandscapeValue) { if (this.landscape === newLandscapeValue) {
return; return;
} }
this.landscape = newLandscapeValue; this.landscape = newLandscapeValue;
Overlays.editOverlay(this.tabletEntityID, { dimensions: this.getDimensions() }); Overlays.editOverlay(this.tabletEntityID,
{ rotation: this.landscape ? Quat.multiply(Camera.orientation, ROT_LANDSCAPE) :
Quat.multiply(Camera.orientation, ROT_Y_180) });
Overlays.editOverlay(this.webOverlayID, { Overlays.editOverlay(this.webOverlayID, {
resolution: this.getTabletTextureResolution() resolution: this.getTabletTextureResolution(),
rotation: Quat.multiply(Camera.orientation, ROT_LANDSCAPE_WINDOW)
}); });
}; };
@ -407,7 +409,7 @@ WebTablet.prototype.calculateWorldAttitudeRelativeToCamera = function (windowPos
return { return {
position: worldMousePosition, position: worldMousePosition,
rotation: Quat.multiply(Camera.orientation, ROT_Y_180) rotation: this.landscape ? Quat.multiply(Camera.orientation, ROT_LANDSCAPE) : Quat.multiply(Camera.orientation, ROT_Y_180)
}; };
}; };

View file

@ -191,16 +191,12 @@
gTablet.updateAudioBar(currentMicLevel); gTablet.updateAudioBar(currentMicLevel);
} }
if (validCheckTime - now > MSECS_PER_SEC/4) { if (now - validCheckTime > MSECS_PER_SEC) {
//each 250ms should be just fine validCheckTime = now;
updateTabletWidthFromSettings(); updateTabletWidthFromSettings();
if (UIWebTablet) { if (UIWebTablet) {
UIWebTablet.setLandscape(landscape); UIWebTablet.setLandscape(landscape);
} }
}
if (validCheckTime - now > MSECS_PER_SEC) {
validCheckTime = now;
if (tabletRezzed && UIWebTablet && !tabletIsValid()) { if (tabletRezzed && UIWebTablet && !tabletIsValid()) {
// when we switch domains, the tablet entity gets destroyed and recreated. this causes // when we switch domains, the tablet entity gets destroyed and recreated. this causes
// the overlay to be deleted, but not recreated. If the overlay is deleted for this or any // the overlay to be deleted, but not recreated. If the overlay is deleted for this or any

View file

@ -31,13 +31,9 @@
#include <render-utils/deferred_light_point_vert.h> #include <render-utils/deferred_light_point_vert.h>
#include <render-utils/deferred_light_spot_vert.h> #include <render-utils/deferred_light_spot_vert.h>
#include <render-utils/directional_light_frag.h>
#include <render-utils/directional_ambient_light_frag.h> #include <render-utils/directional_ambient_light_frag.h>
#include <render-utils/directional_skybox_light_frag.h> #include <render-utils/directional_skybox_light_frag.h>
#include <render-utils/point_light_frag.h>
#include <render-utils/spot_light_frag.h>
#include <render-utils/standardTransformPNTC_vert.h> #include <render-utils/standardTransformPNTC_vert.h>
#include <render-utils/standardDrawTexture_frag.h> #include <render-utils/standardDrawTexture_frag.h>
@ -66,9 +62,6 @@
#include <entities-renderer/textured_particle_frag.h> #include <entities-renderer/textured_particle_frag.h>
#include <entities-renderer/textured_particle_vert.h> #include <entities-renderer/textured_particle_vert.h>
#include <render-utils/hit_effect_vert.h>
#include <render-utils/hit_effect_frag.h>
#include <render-utils/overlay3D_vert.h> #include <render-utils/overlay3D_vert.h>
#include <render-utils/overlay3D_frag.h> #include <render-utils/overlay3D_frag.h>
@ -155,11 +148,8 @@ void QTestWindow::draw() {
testShaderBuild(simple_vert, simple_frag); testShaderBuild(simple_vert, simple_frag);
testShaderBuild(simple_vert, simple_textured_frag); testShaderBuild(simple_vert, simple_textured_frag);
testShaderBuild(simple_vert, simple_textured_unlit_frag); testShaderBuild(simple_vert, simple_textured_unlit_frag);
testShaderBuild(deferred_light_vert, directional_light_frag);
testShaderBuild(deferred_light_vert, directional_ambient_light_frag); testShaderBuild(deferred_light_vert, directional_ambient_light_frag);
testShaderBuild(deferred_light_vert, directional_skybox_light_frag); testShaderBuild(deferred_light_vert, directional_skybox_light_frag);
testShaderBuild(deferred_light_point_vert, point_light_frag);
testShaderBuild(deferred_light_spot_vert, spot_light_frag);
testShaderBuild(standardTransformPNTC_vert, standardDrawTexture_frag); testShaderBuild(standardTransformPNTC_vert, standardDrawTexture_frag);
testShaderBuild(standardTransformPNTC_vert, DrawTextureOpaque_frag); testShaderBuild(standardTransformPNTC_vert, DrawTextureOpaque_frag);
@ -190,7 +180,6 @@ void QTestWindow::draw() {
testShaderBuild(ambient_occlusion_vert, ambient_occlusion_frag); testShaderBuild(ambient_occlusion_vert, ambient_occlusion_frag);
testShaderBuild(ambient_occlusion_vert, occlusion_blend_frag); testShaderBuild(ambient_occlusion_vert, occlusion_blend_frag);
*/ */
testShaderBuild(hit_effect_vert, hit_effect_frag);
testShaderBuild(overlay3D_vert, overlay3D_frag); testShaderBuild(overlay3D_vert, overlay3D_frag);

View file

@ -140,3 +140,77 @@ void GLMHelpersTests::testSimd() {
} }
qDebug() << "Done "; qDebug() << "Done ";
} }
void GLMHelpersTests::testGenerateBasisVectors() {
{ // very simple case: primary along X, secondary is linear combination of X and Y
glm::vec3 u(1.0f, 0.0f, 0.0f);
glm::vec3 v(1.0f, 1.0f, 0.0f);
glm::vec3 w;
generateBasisVectors(u, v, u, v, w);
QCOMPARE_WITH_ABS_ERROR(u, Vectors::UNIT_X, EPSILON);
QCOMPARE_WITH_ABS_ERROR(v, Vectors::UNIT_Y, EPSILON);
QCOMPARE_WITH_ABS_ERROR(w, Vectors::UNIT_Z, EPSILON);
}
{ // point primary along Y instead of X
glm::vec3 u(0.0f, 1.0f, 0.0f);
glm::vec3 v(1.0f, 1.0f, 0.0f);
glm::vec3 w;
generateBasisVectors(u, v, u, v, w);
QCOMPARE_WITH_ABS_ERROR(u, Vectors::UNIT_Y, EPSILON);
QCOMPARE_WITH_ABS_ERROR(v, Vectors::UNIT_X, EPSILON);
QCOMPARE_WITH_ABS_ERROR(w, -Vectors::UNIT_Z, EPSILON);
}
{ // pass bad data (both vectors along Y). The helper will guess X for secondary.
glm::vec3 u(0.0f, 1.0f, 0.0f);
glm::vec3 v(0.0f, 1.0f, 0.0f);
glm::vec3 w;
generateBasisVectors(u, v, u, v, w);
QCOMPARE_WITH_ABS_ERROR(u, Vectors::UNIT_Y, EPSILON);
QCOMPARE_WITH_ABS_ERROR(v, Vectors::UNIT_X, EPSILON);
QCOMPARE_WITH_ABS_ERROR(w, -Vectors::UNIT_Z, EPSILON);
}
{ // pass bad data (both vectors along X). The helper will guess X for secondary, fail, then guess Y.
glm::vec3 u(1.0f, 0.0f, 0.0f);
glm::vec3 v(1.0f, 0.0f, 0.0f);
glm::vec3 w;
generateBasisVectors(u, v, u, v, w);
QCOMPARE_WITH_ABS_ERROR(u, Vectors::UNIT_X, EPSILON);
QCOMPARE_WITH_ABS_ERROR(v, Vectors::UNIT_Y, EPSILON);
QCOMPARE_WITH_ABS_ERROR(w, Vectors::UNIT_Z, EPSILON);
}
{ // general case for arbitrary rotation
float angle = 1.234f;
glm::vec3 axis = glm::normalize(glm::vec3(1.0f, 2.0f, 3.0f));
glm::quat rotation = glm::angleAxis(angle, axis);
// expected values
glm::vec3 x = rotation * Vectors::UNIT_X;
glm::vec3 y = rotation * Vectors::UNIT_Y;
glm::vec3 z = rotation * Vectors::UNIT_Z;
// primary is along x
// secondary is linear combination of x and y
// tertiary is unknown
glm::vec3 u = 1.23f * x;
glm::vec3 v = 2.34f * x + 3.45f * y;
glm::vec3 w;
generateBasisVectors(u, v, u, v, w);
QCOMPARE_WITH_ABS_ERROR(u, x, EPSILON);
QCOMPARE_WITH_ABS_ERROR(v, y, EPSILON);
QCOMPARE_WITH_ABS_ERROR(w, z, EPSILON);
}
}

View file

@ -21,6 +21,7 @@ private slots:
void testEulerDecomposition(); void testEulerDecomposition();
void testSixByteOrientationCompression(); void testSixByteOrientationCompression();
void testSimd(); void testSimd();
void testGenerateBasisVectors();
}; };
float getErrorDifference(const float& a, const float& b); float getErrorDifference(const float& a, const float& b);

View file

@ -8,6 +8,8 @@
#include "StorageTests.h" #include "StorageTests.h"
#include <memory>
QTEST_MAIN(StorageTests) QTEST_MAIN(StorageTests)
using namespace storage; using namespace storage;
@ -32,8 +34,8 @@ void StorageTests::testConversion() {
QFileInfo fileInfo(_testFile); QFileInfo fileInfo(_testFile);
QCOMPARE(fileInfo.exists(), false); QCOMPARE(fileInfo.exists(), false);
} }
StoragePointer storagePointer = std::make_unique<MemoryStorage>(_testData.size(), _testData.data()); StoragePointer storagePointer = std::unique_ptr<MemoryStorage>(new MemoryStorage(_testData.size(), _testData.data()));
QCOMPARE(storagePointer->size(), (quint64)_testData.size()); QCOMPARE(storagePointer->size(), _testData.size());
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0); QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0);
// Convert to a file // Convert to a file
storagePointer = storagePointer->toFileStorage(_testFile); storagePointer = storagePointer->toFileStorage(_testFile);
@ -42,12 +44,12 @@ void StorageTests::testConversion() {
QCOMPARE(fileInfo.exists(), true); QCOMPARE(fileInfo.exists(), true);
QCOMPARE(fileInfo.size(), (qint64)_testData.size()); QCOMPARE(fileInfo.size(), (qint64)_testData.size());
} }
QCOMPARE(storagePointer->size(), (quint64)_testData.size()); QCOMPARE(storagePointer->size(), _testData.size());
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0); QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0);
// Convert to memory // Convert to memory
storagePointer = storagePointer->toMemoryStorage(); storagePointer = storagePointer->toMemoryStorage();
QCOMPARE(storagePointer->size(), (quint64)_testData.size()); QCOMPARE(storagePointer->size(), _testData.size());
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0); QCOMPARE(memcmp(_testData.data(), storagePointer->data(), _testData.size()), 0);
{ {
// ensure the file is unaffected // ensure the file is unaffected
@ -58,13 +60,13 @@ void StorageTests::testConversion() {
// truncate the data as a new memory object // truncate the data as a new memory object
auto newSize = _testData.size() / 2; auto newSize = _testData.size() / 2;
storagePointer = std::make_unique<MemoryStorage>(newSize, storagePointer->data()); storagePointer = std::unique_ptr<Storage>(new MemoryStorage(newSize, storagePointer->data()));
QCOMPARE(storagePointer->size(), (quint64)newSize); QCOMPARE(storagePointer->size(), newSize);
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), newSize), 0); QCOMPARE(memcmp(_testData.data(), storagePointer->data(), newSize), 0);
// Convert back to file // Convert back to file
storagePointer = storagePointer->toFileStorage(_testFile); storagePointer = storagePointer->toFileStorage(_testFile);
QCOMPARE(storagePointer->size(), (quint64)newSize); QCOMPARE(storagePointer->size(), newSize);
QCOMPARE(memcmp(_testData.data(), storagePointer->data(), newSize), 0); QCOMPARE(memcmp(_testData.data(), storagePointer->data(), newSize), 0);
{ {
// ensure the file is truncated // ensure the file is truncated