mirror of
https://github.com/overte-org/overte.git
synced 2025-06-25 22:09:43 +02:00
Merge branch 'android' into android_new
This commit is contained in:
commit
3e7872637d
20 changed files with 261 additions and 85 deletions
BIN
interface/resources/images/preview-privacy.png
Normal file
BIN
interface/resources/images/preview-privacy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
|
@ -214,6 +214,7 @@
|
||||||
#include "commerce/QmlCommerce.h"
|
#include "commerce/QmlCommerce.h"
|
||||||
|
|
||||||
#include "webbrowser/WebBrowserSuggestionsEngine.h"
|
#include "webbrowser/WebBrowserSuggestionsEngine.h"
|
||||||
|
#include <DesktopPreviewProvider.h>
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
#include <VersionHelpers.h>
|
#include <VersionHelpers.h>
|
||||||
|
@ -631,6 +632,24 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, cacheDir);
|
qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, cacheDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME fix the OSX installer to install the resources.rcc binary instead of resource files and remove
|
||||||
|
// this conditional exclusion
|
||||||
|
#if !defined(Q_OS_OSX)
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_ANDROID)
|
||||||
|
const QString resourcesBinaryFile = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/resources.rcc";
|
||||||
|
#else
|
||||||
|
const QString resourcesBinaryFile = QCoreApplication::applicationDirPath() + "/resources.rcc";
|
||||||
|
#endif
|
||||||
|
if (!QFile::exists(resourcesBinaryFile)) {
|
||||||
|
throw std::runtime_error("Unable to find primary resources");
|
||||||
|
}
|
||||||
|
if (!QResource::registerResource(resourcesBinaryFile)) {
|
||||||
|
throw std::runtime_error("Unable to load primary resources");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Setting::init();
|
Setting::init();
|
||||||
|
|
||||||
// Tell the plugin manager about our statically linked plugins
|
// Tell the plugin manager about our statically linked plugins
|
||||||
|
@ -670,6 +689,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
DependencyManager::set<PickScriptingInterface>();
|
DependencyManager::set<PickScriptingInterface>();
|
||||||
DependencyManager::set<Cursor::Manager>();
|
DependencyManager::set<Cursor::Manager>();
|
||||||
DependencyManager::set<VirtualPad::Manager>();
|
DependencyManager::set<VirtualPad::Manager>();
|
||||||
|
DependencyManager::set<DesktopPreviewProvider>();
|
||||||
DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp));
|
DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp));
|
||||||
DependencyManager::set<StatTracker>();
|
DependencyManager::set<StatTracker>();
|
||||||
DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT);
|
DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT);
|
||||||
|
@ -817,24 +837,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
// FIXME fix the OSX installer to install the resources.rcc binary instead of resource files and remove
|
|
||||||
// this conditional exclusion
|
|
||||||
#if !defined(Q_OS_OSX)
|
|
||||||
{
|
|
||||||
#if defined(Q_OS_ANDROID)
|
|
||||||
const QString resourcesBinaryFile = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/resources.rcc";
|
|
||||||
#else
|
|
||||||
const QString resourcesBinaryFile = applicationDirPath() + "/resources.rcc";
|
|
||||||
#endif
|
|
||||||
if (!QFile::exists(resourcesBinaryFile)) {
|
|
||||||
throw std::runtime_error("Unable to find primary resources");
|
|
||||||
}
|
|
||||||
if (!QResource::registerResource(resourcesBinaryFile)) {
|
|
||||||
throw std::runtime_error("Unable to load primary resources");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto steamClient = PluginManager::getInstance()->getSteamClientPlugin();
|
auto steamClient = PluginManager::getInstance()->getSteamClientPlugin();
|
||||||
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
|
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
|
||||||
setProperty(hifi::properties::CRASHED, _previousSessionCrashed);
|
setProperty(hifi::properties::CRASHED, _previousSessionCrashed);
|
||||||
|
@ -5853,6 +5855,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
||||||
scriptEngine->registerFunction("OverlayWindow", QmlWindowClass::constructor);
|
scriptEngine->registerFunction("OverlayWindow", QmlWindowClass::constructor);
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance());
|
scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance());
|
||||||
|
scriptEngine->registerGlobalObject("DesktopPreviewProvider", DependencyManager::get<DesktopPreviewProvider>().data());
|
||||||
scriptEngine->registerGlobalObject("Stats", Stats::getInstance());
|
scriptEngine->registerGlobalObject("Stats", Stats::getInstance());
|
||||||
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
|
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
|
||||||
scriptEngine->registerGlobalObject("Snapshot", DependencyManager::get<Snapshot>().data());
|
scriptEngine->registerGlobalObject("Snapshot", DependencyManager::get<Snapshot>().data());
|
||||||
|
|
|
@ -277,7 +277,8 @@ void WindowScriptingInterface::browseAsync(const QString& title, const QString&
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
setPreviousBrowseLocation(QFileInfo(result).absolutePath());
|
setPreviousBrowseLocation(QFileInfo(result).absolutePath());
|
||||||
}
|
}
|
||||||
emit openFileChanged(result);
|
emit browseChanged(result);
|
||||||
|
emit openFileChanged(result); // Deprecated signal; to be removed in due course.
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -197,18 +197,19 @@ public slots:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Prompt the user to choose a file. Displays a non-modal dialog that navigates the directory tree. A
|
* Prompt the user to choose a file. Displays a non-modal dialog that navigates the directory tree. A
|
||||||
* {@link Window.openFileChanged|openFileChanged} signal is emitted when a file is chosen; no signal is emitted if the user
|
* {@link Window.browseChanged|browseChanged} signal is emitted when a file is chosen; no signal is emitted if the user
|
||||||
* cancels the dialog.
|
* cancels the dialog.
|
||||||
|
* @deprecated A deprecated {@link Window.openFileChanged|openFileChanged} signal is also emitted when a file is chosen.
|
||||||
* @function Window.browseAsync
|
* @function Window.browseAsync
|
||||||
* @param {string} title="" - The title to display at the top of the dialog.
|
* @param {string} title="" - The title to display at the top of the dialog.
|
||||||
* @param {string} directory="" - The initial directory to start browsing at.
|
* @param {string} directory="" - The initial directory to start browsing at.
|
||||||
* @param {string} nameFilter="" - The types of files to display. Examples: <code>"*.json"</code> and
|
* @param {string} nameFilter="" - The types of files to display. Examples: <code>"*.json"</code> and
|
||||||
* <code>"Images (*.png *.jpg *.svg)"</code>. All files are displayed if a filter isn't specified.
|
* <code>"Images (*.png *.jpg *.svg)"</code>. All files are displayed if a filter isn't specified.
|
||||||
* @example <caption>Ask the user to choose an image file without waiting for the answer.</caption>
|
* @example <caption>Ask the user to choose an image file without waiting for the answer.</caption>
|
||||||
* function onOpenFileChanged(filename) {
|
* function onBrowseChanged(filename) {
|
||||||
* print("File: " + filename);
|
* print("File: " + filename);
|
||||||
* }
|
* }
|
||||||
* Window.openFileChanged.connect(onOpenFileChanged);
|
* Window.browseChanged.connect(onBrowseChanged);
|
||||||
*
|
*
|
||||||
* Window.browseAsync("Select Image File", Paths.resources, "Images (*.png *.jpg *.svg)");
|
* Window.browseAsync("Select Image File", Paths.resources, "Images (*.png *.jpg *.svg)");
|
||||||
* print("Script continues without waiting");
|
* print("Script continues without waiting");
|
||||||
|
@ -659,9 +660,18 @@ signals:
|
||||||
*/
|
*/
|
||||||
void saveFileChanged(QString filename);
|
void saveFileChanged(QString filename);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Triggered when the user chooses a file in a {@link Window.browseAsync|browseAsync} dialog.
|
||||||
|
* @function Window.browseChanged
|
||||||
|
* @param {string} filename - The path and name of the file the user chose in the dialog.
|
||||||
|
* @returns {Signal}
|
||||||
|
*/
|
||||||
|
void browseChanged(QString filename);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Triggered when the user chooses a file in a {@link Window.browseAsync|browseAsync} dialog.
|
* Triggered when the user chooses a file in a {@link Window.browseAsync|browseAsync} dialog.
|
||||||
* @function Window.openFileChanged
|
* @function Window.openFileChanged
|
||||||
|
* @deprecated This signal is being replaced with {@link Window.browseChanged|browseChanged} and will be removed.
|
||||||
* @param {string} filename - The path and name of the file the user chose in the dialog.
|
* @param {string} filename - The path and name of the file the user chose in the dialog.
|
||||||
* @returns {Signal}
|
* @returns {Signal}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "../Logging.h"
|
#include "../Logging.h"
|
||||||
#include "../CompositorHelper.h"
|
#include "../CompositorHelper.h"
|
||||||
|
|
||||||
|
#include "DesktopPreviewProvider.h"
|
||||||
#include "render-utils/hmd_ui_vert.h"
|
#include "render-utils/hmd_ui_vert.h"
|
||||||
#include "render-utils/hmd_ui_frag.h"
|
#include "render-utils/hmd_ui_frag.h"
|
||||||
|
|
||||||
|
@ -254,16 +255,8 @@ void HmdDisplayPlugin::internalPresent() {
|
||||||
swapBuffers();
|
swapBuffers();
|
||||||
|
|
||||||
} else if (_clearPreviewFlag) {
|
} else if (_clearPreviewFlag) {
|
||||||
QImage image;
|
|
||||||
if (_vsyncEnabled) {
|
|
||||||
image = QImage(PathUtils::resourcesPath() + "images/preview.png");
|
|
||||||
} else {
|
|
||||||
image = QImage(PathUtils::resourcesPath() + "images/preview-disabled.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
image = image.mirrored();
|
QImage image = DesktopPreviewProvider::getInstance()->getPreviewDisabledImage(_vsyncEnabled);
|
||||||
image = image.convertToFormat(QImage::Format_RGBA8888);
|
|
||||||
if (!_previewTexture) {
|
|
||||||
_previewTexture = gpu::Texture::createStrict(
|
_previewTexture = gpu::Texture::createStrict(
|
||||||
gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA),
|
gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA),
|
||||||
image.width(), image.height(),
|
image.width(), image.height(),
|
||||||
|
@ -274,7 +267,6 @@ void HmdDisplayPlugin::internalPresent() {
|
||||||
_previewTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
_previewTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||||
_previewTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
_previewTexture->assignStoredMip(0, image.byteCount(), image.constBits());
|
||||||
_previewTexture->setAutoGenerateMips(true);
|
_previewTexture->setAutoGenerateMips(true);
|
||||||
}
|
|
||||||
|
|
||||||
auto viewport = getViewportForSourceSize(uvec2(_previewTexture->getDimensions()));
|
auto viewport = getViewportForSourceSize(uvec2(_previewTexture->getDimensions()));
|
||||||
|
|
||||||
|
|
|
@ -1394,8 +1394,14 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
// That is where _currentFrame and _lastAnimated were updated.
|
// That is where _currentFrame and _lastAnimated were updated.
|
||||||
if (_animating) {
|
if (_animating) {
|
||||||
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
||||||
|
|
||||||
if (!jointsMapped()) {
|
if (!jointsMapped()) {
|
||||||
mapJoints(entity, model->getJointNames());
|
mapJoints(entity, model->getJointNames());
|
||||||
|
//else the joint have been mapped before but we have a new animation to load
|
||||||
|
} else if (_animation && (_animation->getURL().toString() != entity->getAnimationURL())) {
|
||||||
|
_animation = DependencyManager::get<AnimationCache>()->getAnimation(entity->getAnimationURL());
|
||||||
|
_jointMappingCompleted = false;
|
||||||
|
mapJoints(entity, model->getJointNames());
|
||||||
}
|
}
|
||||||
if (!(entity->getAnimationFirstFrame() < 0) && !(entity->getAnimationFirstFrame() > entity->getAnimationLastFrame())) {
|
if (!(entity->getAnimationFirstFrame() < 0) && !(entity->getAnimationFirstFrame() > entity->getAnimationLastFrame())) {
|
||||||
animate(entity);
|
animate(entity);
|
||||||
|
|
|
@ -368,6 +368,7 @@ public:
|
||||||
void* getPhysicsInfo() const { return _physicsInfo; }
|
void* getPhysicsInfo() const { return _physicsInfo; }
|
||||||
|
|
||||||
void setPhysicsInfo(void* data) { _physicsInfo = data; }
|
void setPhysicsInfo(void* data) { _physicsInfo = data; }
|
||||||
|
|
||||||
EntityTreeElementPointer getElement() const { return _element; }
|
EntityTreeElementPointer getElement() const { return _element; }
|
||||||
EntityTreePointer getTree() const;
|
EntityTreePointer getTree() const;
|
||||||
virtual SpatialParentTree* getParentTree() const override;
|
virtual SpatialParentTree* getParentTree() const override;
|
||||||
|
|
|
@ -256,25 +256,32 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
||||||
assert(_entity);
|
assert(_entity);
|
||||||
assert(entityTreeIsLocked());
|
assert(entityTreeIsLocked());
|
||||||
measureBodyAcceleration();
|
measureBodyAcceleration();
|
||||||
bool positionSuccess;
|
|
||||||
_entity->setWorldPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset(), positionSuccess, false);
|
// If transform or velocities are flagged as dirty it means a network or scripted change
|
||||||
if (!positionSuccess) {
|
// occured between the beginning and end of the stepSimulation() and we DON'T want to apply
|
||||||
static QString repeatedMessage =
|
// these physics simulation results.
|
||||||
LogHandler::getInstance().addRepeatedMessageRegex("EntityMotionState::setWorldTransform "
|
uint32_t flags = _entity->getDirtyFlags() & (Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES);
|
||||||
"setPosition failed.*");
|
if (!flags) {
|
||||||
qCDebug(physics) << "EntityMotionState::setWorldTransform setPosition failed" << _entity->getID();
|
// flags are clear
|
||||||
}
|
_entity->setWorldTransform(bulletToGLM(worldTrans.getOrigin()), bulletToGLM(worldTrans.getRotation()));
|
||||||
bool orientationSuccess;
|
_entity->setWorldVelocity(getBodyLinearVelocity());
|
||||||
_entity->setWorldOrientation(bulletToGLM(worldTrans.getRotation()), orientationSuccess, false);
|
_entity->setWorldAngularVelocity(getBodyAngularVelocity());
|
||||||
if (!orientationSuccess) {
|
|
||||||
static QString repeatedMessage =
|
|
||||||
LogHandler::getInstance().addRepeatedMessageRegex("EntityMotionState::setWorldTransform "
|
|
||||||
"setOrientation failed.*");
|
|
||||||
qCDebug(physics) << "EntityMotionState::setWorldTransform setOrientation failed" << _entity->getID();
|
|
||||||
}
|
|
||||||
_entity->setVelocity(getBodyLinearVelocity());
|
|
||||||
_entity->setAngularVelocity(getBodyAngularVelocity());
|
|
||||||
_entity->setLastSimulated(usecTimestampNow());
|
_entity->setLastSimulated(usecTimestampNow());
|
||||||
|
} else {
|
||||||
|
// only set properties NOT flagged
|
||||||
|
if (!(flags & Simulation::DIRTY_TRANSFORM)) {
|
||||||
|
_entity->setWorldTransform(bulletToGLM(worldTrans.getOrigin()), bulletToGLM(worldTrans.getRotation()));
|
||||||
|
}
|
||||||
|
if (!(flags & Simulation::DIRTY_LINEAR_VELOCITY)) {
|
||||||
|
_entity->setWorldVelocity(getBodyLinearVelocity());
|
||||||
|
}
|
||||||
|
if (!(flags & Simulation::DIRTY_ANGULAR_VELOCITY)) {
|
||||||
|
_entity->setWorldAngularVelocity(getBodyAngularVelocity());
|
||||||
|
}
|
||||||
|
if (flags != (Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES)) {
|
||||||
|
_entity->setLastSimulated(usecTimestampNow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_entity->getSimulatorID().isNull()) {
|
if (_entity->getSimulatorID().isNull()) {
|
||||||
_loopsWithoutOwner++;
|
_loopsWithoutOwner++;
|
||||||
|
@ -530,9 +537,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
||||||
|
|
||||||
if (!_body->isActive()) {
|
if (!_body->isActive()) {
|
||||||
// make sure all derivatives are zero
|
// make sure all derivatives are zero
|
||||||
_entity->setVelocity(Vectors::ZERO);
|
zeroCleanObjectVelocities();
|
||||||
_entity->setAngularVelocity(Vectors::ZERO);
|
|
||||||
_entity->setAcceleration(Vectors::ZERO);
|
|
||||||
_numInactiveUpdates++;
|
_numInactiveUpdates++;
|
||||||
} else {
|
} else {
|
||||||
glm::vec3 gravity = _entity->getGravity();
|
glm::vec3 gravity = _entity->getGravity();
|
||||||
|
@ -559,9 +564,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
||||||
if (movingSlowly) {
|
if (movingSlowly) {
|
||||||
// velocities might not be zero, but we'll fake them as such, which will hopefully help convince
|
// velocities might not be zero, but we'll fake them as such, which will hopefully help convince
|
||||||
// other simulating observers to deactivate their own copies
|
// other simulating observers to deactivate their own copies
|
||||||
glm::vec3 zero(0.0f);
|
zeroCleanObjectVelocities();
|
||||||
_entity->setVelocity(zero);
|
|
||||||
_entity->setAngularVelocity(zero);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_numInactiveUpdates = 0;
|
_numInactiveUpdates = 0;
|
||||||
|
@ -818,3 +821,22 @@ bool EntityMotionState::shouldBeLocallyOwned() const {
|
||||||
void EntityMotionState::upgradeOutgoingPriority(uint8_t priority) {
|
void EntityMotionState::upgradeOutgoingPriority(uint8_t priority) {
|
||||||
_outgoingPriority = glm::max<uint8_t>(_outgoingPriority, priority);
|
_outgoingPriority = glm::max<uint8_t>(_outgoingPriority, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityMotionState::zeroCleanObjectVelocities() const {
|
||||||
|
// If transform or velocities are flagged as dirty it means a network or scripted change
|
||||||
|
// occured between the beginning and end of the stepSimulation() and we DON'T want to apply
|
||||||
|
// these physics simulation results.
|
||||||
|
uint32_t flags = _entity->getDirtyFlags() & (Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES);
|
||||||
|
if (!flags) {
|
||||||
|
_entity->setWorldVelocity(glm::vec3(0.0f));
|
||||||
|
_entity->setWorldAngularVelocity(glm::vec3(0.0f));
|
||||||
|
} else {
|
||||||
|
if (!(flags & Simulation::DIRTY_LINEAR_VELOCITY)) {
|
||||||
|
_entity->setWorldVelocity(glm::vec3(0.0f));
|
||||||
|
}
|
||||||
|
if (!(flags & Simulation::DIRTY_ANGULAR_VELOCITY)) {
|
||||||
|
_entity->setWorldAngularVelocity(glm::vec3(0.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_entity->setAcceleration(glm::vec3(0.0f));
|
||||||
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
// changes _outgoingPriority only if priority is larger
|
// changes _outgoingPriority only if priority is larger
|
||||||
void upgradeOutgoingPriority(uint8_t priority);
|
void upgradeOutgoingPriority(uint8_t priority);
|
||||||
|
void zeroCleanObjectVelocities() const;
|
||||||
|
|
||||||
#ifdef WANT_DEBUG_ENTITY_TREE_LOCKS
|
#ifdef WANT_DEBUG_ENTITY_TREE_LOCKS
|
||||||
bool entityTreeIsLocked() const;
|
bool entityTreeIsLocked() const;
|
||||||
|
|
|
@ -186,7 +186,7 @@ float specularDistribution(SurfaceData surface) {
|
||||||
// Add geometric factors G1(n,l) and G1(n,v)
|
// Add geometric factors G1(n,l) and G1(n,v)
|
||||||
float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);
|
float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl);
|
||||||
denom *= surface.smithInvG1NdotV * smithInvG1NdotL;
|
denom *= surface.smithInvG1NdotV * smithInvG1NdotL;
|
||||||
// Don't divide by PI as it will be done later
|
// Don't divide by PI as this is part of the light normalization factor
|
||||||
float power = surface.roughness4 / denom;
|
float power = surface.roughness4 / denom;
|
||||||
return power;
|
return power;
|
||||||
}
|
}
|
||||||
|
@ -202,12 +202,11 @@ vec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) {
|
||||||
vec3 specular = fresnelColor * power * angleAttenuation;
|
vec3 specular = fresnelColor * power * angleAttenuation;
|
||||||
float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);
|
float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x);
|
||||||
|
|
||||||
diffuse /= 3.1415926;
|
// We don't divided by PI, as the "normalized" equations state we should, because we decide, as Naty Hoffman, that
|
||||||
// Diffuse is divided by PI but specular isn't because an infinitesimal volume light source
|
// we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit
|
||||||
// has a multiplier of PI, says Naty Hoffman.
|
// by a white light of intensity 1. But this is an arbitrary normalization of what light intensity "means".
|
||||||
// (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf
|
// (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf
|
||||||
// page 23 paragraph "Punctual light sources")
|
// page 23 paragraph "Punctual light sources")
|
||||||
|
|
||||||
return vec4(specular, diffuse);
|
return vec4(specular, diffuse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,9 +221,9 @@ vec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) {
|
||||||
vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;
|
vec3 specular = vec3(fresnelScalar) * power * angleAttenuation;
|
||||||
float diffuse = angleAttenuation * (1.0 - fresnelScalar);
|
float diffuse = angleAttenuation * (1.0 - fresnelScalar);
|
||||||
|
|
||||||
diffuse /= 3.1415926;
|
// We don't divided by PI, as the "normalized" equations state we should, because we decide, as Naty Hoffman, that
|
||||||
// Diffuse is divided by PI but specular isn't because an infinitesimal volume light source
|
// we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit
|
||||||
// has a multiplier of PI, says Naty Hoffman.
|
// by a white light of intensity 1. But this is an arbitrary normalization of what light intensity "means".
|
||||||
// (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf
|
// (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf
|
||||||
// page 23 paragraph "Punctual light sources")
|
// page 23 paragraph "Punctual light sources")
|
||||||
return vec4(specular, diffuse);
|
return vec4(specular, diffuse);
|
||||||
|
@ -239,8 +238,9 @@ vec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) {
|
||||||
float power = specularDistribution(surface);
|
float power = specularDistribution(surface);
|
||||||
vec3 specular = fresnelColor * power * angleAttenuation;
|
vec3 specular = fresnelColor * power * angleAttenuation;
|
||||||
|
|
||||||
// Specular isn't divided by PI because an infinitesimal volume light source
|
// We don't divided by PI, as the "normalized" equations state we should, because we decide, as Naty Hoffman, that
|
||||||
// has a multiplier of PI, says Naty Hoffman.
|
// we wish to have a similar color as raw albedo on a perfectly diffuse surface perpendicularly lit
|
||||||
|
// by a white light of intensity 1. But this is an arbitrary normalization of what light intensity "means".
|
||||||
// (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf
|
// (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf
|
||||||
// page 23 paragraph "Punctual light sources")
|
// page 23 paragraph "Punctual light sources")
|
||||||
return vec4(specular, 0.f);
|
return vec4(specular, 0.f);
|
||||||
|
|
|
@ -253,6 +253,7 @@ glm::vec2 getFacingDir2D(const glm::mat4& m);
|
||||||
|
|
||||||
inline bool isNaN(const glm::vec3& value) { return isNaN(value.x) || isNaN(value.y) || isNaN(value.z); }
|
inline bool isNaN(const glm::vec3& value) { return isNaN(value.x) || isNaN(value.y) || isNaN(value.z); }
|
||||||
inline bool isNaN(const glm::quat& value) { return isNaN(value.w) || isNaN(value.x) || isNaN(value.y) || isNaN(value.z); }
|
inline bool isNaN(const glm::quat& value) { return isNaN(value.w) || isNaN(value.x) || isNaN(value.y) || isNaN(value.z); }
|
||||||
|
inline bool isNaN(const glm::mat3& value) { return isNaN(value * glm::vec3(1.0f)); }
|
||||||
|
|
||||||
glm::mat4 orthoInverse(const glm::mat4& m);
|
glm::mat4 orthoInverse(const glm::mat4& m);
|
||||||
|
|
||||||
|
|
|
@ -464,6 +464,36 @@ glm::vec3 SpatiallyNestable::localToWorldDimensions(const glm::vec3& dimensions,
|
||||||
return dimensions;
|
return dimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpatiallyNestable::setWorldTransform(const glm::vec3& position, const glm::quat& orientation) {
|
||||||
|
// guard against introducing NaN into the transform
|
||||||
|
if (isNaN(orientation) || isNaN(position)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
bool success = true;
|
||||||
|
Transform parentTransform = getParentTransform(success);
|
||||||
|
_transformLock.withWriteLock([&] {
|
||||||
|
Transform myWorldTransform;
|
||||||
|
Transform::mult(myWorldTransform, parentTransform, _transform);
|
||||||
|
if (myWorldTransform.getRotation() != orientation) {
|
||||||
|
changed = true;
|
||||||
|
myWorldTransform.setRotation(orientation);
|
||||||
|
}
|
||||||
|
if (myWorldTransform.getTranslation() != position) {
|
||||||
|
changed = true;
|
||||||
|
myWorldTransform.setTranslation(position);
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
Transform::inverseMult(_transform, parentTransform, myWorldTransform);
|
||||||
|
_translationChanged = usecTimestampNow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (success && changed) {
|
||||||
|
locationChanged(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 SpatiallyNestable::getWorldPosition(bool& success) const {
|
glm::vec3 SpatiallyNestable::getWorldPosition(bool& success) const {
|
||||||
return getTransform(success).getTranslation();
|
return getTransform(success).getTranslation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ public:
|
||||||
|
|
||||||
virtual Transform getParentTransform(bool& success, int depth = 0) const;
|
virtual Transform getParentTransform(bool& success, int depth = 0) const;
|
||||||
|
|
||||||
|
void setWorldTransform(const glm::vec3& position, const glm::quat& orientation);
|
||||||
virtual glm::vec3 getWorldPosition(bool& success) const;
|
virtual glm::vec3 getWorldPosition(bool& success) const;
|
||||||
virtual glm::vec3 getWorldPosition() const;
|
virtual glm::vec3 getWorldPosition() const;
|
||||||
virtual void setWorldPosition(const glm::vec3& position, bool& success, bool tellPhysics = true);
|
virtual void setWorldPosition(const glm::vec3& position, bool& success, bool tellPhysics = true);
|
||||||
|
|
46
libraries/ui/src/DesktopPreviewProvider.cpp
Normal file
46
libraries/ui/src/DesktopPreviewProvider.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include "DesktopPreviewProvider.h"
|
||||||
|
#include <PathUtils.h>
|
||||||
|
#include <QMetaEnum>
|
||||||
|
#include <QtPlugin>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
DesktopPreviewProvider::DesktopPreviewProvider() {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const char* DesktopPreviewProvider::imagePaths[];
|
||||||
|
|
||||||
|
QSharedPointer<DesktopPreviewProvider> DesktopPreviewProvider::getInstance() {
|
||||||
|
static QSharedPointer<DesktopPreviewProvider> instance = DependencyManager::get<DesktopPreviewProvider>();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage DesktopPreviewProvider::getPreviewDisabledImage(bool vsyncEnabled) const {
|
||||||
|
|
||||||
|
auto imageIndex = vsyncEnabled ? VSYNC : m_previewDisabledReason;
|
||||||
|
assert(imageIndex >= 0 && imageIndex <= VSYNC);
|
||||||
|
|
||||||
|
return !m_previewDisabled[imageIndex].isNull() ? m_previewDisabled[imageIndex] : loadPreviewImage(m_previewDisabled[imageIndex], PathUtils::resourcesPath() + imagePaths[imageIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesktopPreviewProvider::setPreviewDisabledReason(PreviewDisabledReasons reason) {
|
||||||
|
if (reason == VSYNC) {
|
||||||
|
qDebug() << "Preview disabled reason can't be forced to " << QMetaEnum::fromType<DesktopPreviewProvider::PreviewDisabledReasons>().valueToKey(reason);
|
||||||
|
return; // Not settable via this interface, as VSYNC is controlled by HMD plugin..
|
||||||
|
}
|
||||||
|
|
||||||
|
m_previewDisabledReason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesktopPreviewProvider::setPreviewDisabledReason(const QString& reasonString) {
|
||||||
|
PreviewDisabledReasons reason = USER;
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
reason = (PreviewDisabledReasons) QMetaEnum::fromType<DesktopPreviewProvider::PreviewDisabledReasons>().keyToValue(reasonString.toLatin1().data(), &ok);
|
||||||
|
if (ok) {
|
||||||
|
setPreviewDisabledReason(reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage& DesktopPreviewProvider::loadPreviewImage(QImage& image, const QString& path) const {
|
||||||
|
return image = QImage(path).mirrored().convertToFormat(QImage::Format_RGBA8888);
|
||||||
|
}
|
47
libraries/ui/src/DesktopPreviewProvider.h
Normal file
47
libraries/ui/src/DesktopPreviewProvider.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// Created by Alexander Ivash on 2018/01/08
|
||||||
|
// Copyright 2018 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 <DependencyManager.h>
|
||||||
|
#include <QImage>
|
||||||
|
|
||||||
|
class DesktopPreviewProvider : public QObject, public Dependency {
|
||||||
|
SINGLETON_DEPENDENCY
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
DesktopPreviewProvider();
|
||||||
|
DesktopPreviewProvider(const DesktopPreviewProvider& other) = delete;
|
||||||
|
|
||||||
|
constexpr static const char* imagePaths[] = {
|
||||||
|
"images/preview-disabled.png", // USER
|
||||||
|
"images/preview-privacy.png", // SECURE_SCREEN
|
||||||
|
"images/preview.png", // VSYNC
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum PreviewDisabledReasons {
|
||||||
|
USER = 0,
|
||||||
|
SECURE_SCREEN,
|
||||||
|
VSYNC // Not settable via this interface, as VSYNC is controlled by HMD plugin..
|
||||||
|
};
|
||||||
|
Q_ENUM(PreviewDisabledReasons)
|
||||||
|
|
||||||
|
static QSharedPointer<DesktopPreviewProvider> getInstance();
|
||||||
|
|
||||||
|
QImage getPreviewDisabledImage(bool vsyncEnabled) const;
|
||||||
|
void setPreviewDisabledReason(PreviewDisabledReasons reason);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setPreviewDisabledReason(const QString& reason);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QImage& loadPreviewImage(QImage& image, const QString& path) const;
|
||||||
|
|
||||||
|
PreviewDisabledReasons m_previewDisabledReason = { USER };
|
||||||
|
|
||||||
|
mutable QImage m_previewDisabled[3];
|
||||||
|
};
|
|
@ -562,9 +562,11 @@
|
||||||
break;
|
break;
|
||||||
case 'disableHmdPreview':
|
case 'disableHmdPreview':
|
||||||
isHmdPreviewDisabled = Menu.isOptionChecked("Disable Preview");
|
isHmdPreviewDisabled = Menu.isOptionChecked("Disable Preview");
|
||||||
|
DesktopPreviewProvider.setPreviewDisabledReason("SECURE_SCREEN");
|
||||||
Menu.setIsOptionChecked("Disable Preview", true);
|
Menu.setIsOptionChecked("Disable Preview", true);
|
||||||
break;
|
break;
|
||||||
case 'maybeEnableHmdPreview':
|
case 'maybeEnableHmdPreview':
|
||||||
|
DesktopPreviewProvider.setPreviewDisabledReason("USER");
|
||||||
Menu.setIsOptionChecked("Disable Preview", isHmdPreviewDisabled);
|
Menu.setIsOptionChecked("Disable Preview", isHmdPreviewDisabled);
|
||||||
break;
|
break;
|
||||||
case 'passphraseReset':
|
case 'passphraseReset':
|
||||||
|
@ -635,7 +637,11 @@
|
||||||
// -Called when the TabletScriptingInterface::screenChanged() signal is emitted. The "type" argument can be either the string
|
// -Called when the TabletScriptingInterface::screenChanged() signal is emitted. The "type" argument can be either the string
|
||||||
// value of "Home", "Web", "Menu", "QML", or "Closed". The "url" argument is only valid for Web and QML.
|
// value of "Home", "Web", "Menu", "QML", or "Closed". The "url" argument is only valid for Web and QML.
|
||||||
function onTabletScreenChanged(type, url) {
|
function onTabletScreenChanged(type, url) {
|
||||||
onWalletScreen = (type === "QML" && url === WALLET_QML_SOURCE);
|
var onWalletScreenNow = (type === "QML" && url === WALLET_QML_SOURCE);
|
||||||
|
if (!onWalletScreenNow && onWalletScreen) {
|
||||||
|
DesktopPreviewProvider.setPreviewDisabledReason("USER");
|
||||||
|
}
|
||||||
|
onWalletScreen = onWalletScreenNow;
|
||||||
wireEventBridge(onWalletScreen);
|
wireEventBridge(onWalletScreen);
|
||||||
// Change button to active when window is first openend, false otherwise.
|
// Change button to active when window is first openend, false otherwise.
|
||||||
if (button) {
|
if (button) {
|
||||||
|
|
|
@ -370,6 +370,7 @@ Script.include("/~/system/libraries/Xform.js");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.isReady = function (controllerData) {
|
this.isReady = function (controllerData) {
|
||||||
|
if (HMD.active) {
|
||||||
if (this.notPointingAtEntity(controllerData)) {
|
if (this.notPointingAtEntity(controllerData)) {
|
||||||
return makeRunningValues(false, [], []);
|
return makeRunningValues(false, [], []);
|
||||||
}
|
}
|
||||||
|
@ -384,6 +385,8 @@ Script.include("/~/system/libraries/Xform.js");
|
||||||
this.destroyContextOverlay();
|
this.destroyContextOverlay();
|
||||||
return makeRunningValues(false, [], []);
|
return makeRunningValues(false, [], []);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return makeRunningValues(false, [], []);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.run = function (controllerData) {
|
this.run = function (controllerData) {
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
|
|
||||||
this.isReady = function (controllerData) {
|
this.isReady = function (controllerData) {
|
||||||
var otherModuleRunning = this.getOtherModule().running;
|
var otherModuleRunning = this.getOtherModule().running;
|
||||||
if (!otherModuleRunning) {
|
if (!otherModuleRunning && HMD.active) {
|
||||||
if (this.processLaser(controllerData)) {
|
if (this.processLaser(controllerData)) {
|
||||||
this.running = true;
|
this.running = true;
|
||||||
return ControllerDispatcherUtils.makeRunningValues(true, [], []);
|
return ControllerDispatcherUtils.makeRunningValues(true, [], []);
|
||||||
|
|
|
@ -448,7 +448,7 @@ var toolBar = (function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
addButton("importEntitiesButton", "assets-01.svg", function() {
|
addButton("importEntitiesButton", "assets-01.svg", function() {
|
||||||
Window.openFileChanged.connect(onFileOpenChanged);
|
Window.browseChanged.connect(onFileOpenChanged);
|
||||||
Window.browseAsync("Select Model to Import", "", "*.json");
|
Window.browseAsync("Select Model to Import", "", "*.json");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1497,7 +1497,7 @@ function onFileOpenChanged(filename) {
|
||||||
// disconnect the event, otherwise the requests will stack up
|
// disconnect the event, otherwise the requests will stack up
|
||||||
try {
|
try {
|
||||||
// Not all calls to onFileOpenChanged() connect an event.
|
// Not all calls to onFileOpenChanged() connect an event.
|
||||||
Window.openFileChanged.disconnect(onFileOpenChanged);
|
Window.browseChanged.disconnect(onFileOpenChanged);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Ignore.
|
// Ignore.
|
||||||
}
|
}
|
||||||
|
@ -1549,7 +1549,7 @@ function handeMenuEvent(menuItem) {
|
||||||
}
|
}
|
||||||
} else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") {
|
} else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") {
|
||||||
if (menuItem === "Import Entities") {
|
if (menuItem === "Import Entities") {
|
||||||
Window.openFileChanged.connect(onFileOpenChanged);
|
Window.browseChanged.connect(onFileOpenChanged);
|
||||||
Window.browseAsync("Select Model to Import", "", "*.json");
|
Window.browseAsync("Select Model to Import", "", "*.json");
|
||||||
} else {
|
} else {
|
||||||
Window.promptTextChanged.connect(onPromptTextChanged);
|
Window.promptTextChanged.connect(onPromptTextChanged);
|
||||||
|
|
|
@ -539,9 +539,15 @@
|
||||||
return startingUp;
|
return startingUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDomainConnectionRefused(reason) {
|
function onDomainConnectionRefused(reason, reasonCode) {
|
||||||
|
// the "login error" reason means that the DS couldn't decrypt the username signature
|
||||||
|
// since this eventually resolves itself for good actors we don't need to show a notification for it
|
||||||
|
var LOGIN_ERROR_REASON_CODE = 2;
|
||||||
|
|
||||||
|
if (reasonCode != LOGIN_ERROR_REASON_CODE) {
|
||||||
createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED);
|
createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onEditError(msg) {
|
function onEditError(msg) {
|
||||||
createNotification(wordWrap(msg), NotificationType.EDIT_ERROR);
|
createNotification(wordWrap(msg), NotificationType.EDIT_ERROR);
|
||||||
|
|
Loading…
Reference in a new issue