From 4fbb0949786cfed4138610a32bf8b6db798756a4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 15:39:34 -0800 Subject: [PATCH 01/18] No reason to change that... --- interface/resources/shaders/model_normal_map.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/shaders/model_normal_map.frag b/interface/resources/shaders/model_normal_map.frag index af107e9d3c..f5a1047b2b 100644 --- a/interface/resources/shaders/model_normal_map.frag +++ b/interface/resources/shaders/model_normal_map.frag @@ -4,7 +4,7 @@ // model_normal_map.frag // fragment shader // -// Created by Andrzej Kapolka on 10/14/13. +// Created by Andrzej Kapolka on 10/29/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. From ce103acdf6c8b312d75d0234380c1eb4666ec832 Mon Sep 17 00:00:00 2001 From: dev Date: Mon, 24 Nov 2014 18:32:36 -0800 Subject: [PATCH 02/18] More debugging of the FBXReader in order to understand how to interpret the material fields --- interface/src/renderer/Model.cpp | 14 +++++++++++--- libraries/fbx/src/FBXReader.cpp | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index ddcdfe3a84..e6dc3ce74e 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2347,8 +2347,12 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod diffuseMap = (_dilatedTextures[i][j] = static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); } - GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ? - Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID()); + static bool showDiffuse = true; + if (showDiffuse && diffuseMap) { + GLBATCH(glBindTexture)(GL_TEXTURE_2D, diffuseMap->getID()); + } else { + GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID()); + } if (locations->texcoordMatrices >= 0) { glm::mat4 texcoordTransform[2]; @@ -2379,7 +2383,11 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (locations->emissiveTextureUnit >= 0) { assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader - GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f); + static float emissiveOffset = 0.1f; + static float emissiveScale = 1.0f; + //GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f); + GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 0cebacf51a..b54abedc33 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1597,9 +1597,28 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (property.properties.at(0) == "Opacity") { material.opacity = property.properties.at(index).value(); } +#if defined(DEBUG_FBXREADER) + else { + const std::string propname = property.properties.at(0).toString().toStdString(); + if (propname == "EmissiveFactor") { + } + } +#endif } } } +#if defined(DEBUG_FBXREADER) + else { + std::string propname = subobject.name.data(); + int unknown = 0; + if ( (propname == "Version") + ||(propname == "ShadingModel") + ||(propname == "Multilayer")) { + } else { + unknown++; + } + } +#endif } material.id = getID(object.properties); materials.insert(material.id, material); @@ -1687,7 +1706,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (type.contains("emissive")) { emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("ambient")) { + emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else { + std::string typenam = type.data(); counter++; } } From 77077f4e9c71ef66d34fdd30c70e833e8e042315 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 25 Nov 2014 18:17:28 -0800 Subject: [PATCH 03/18] hack a separate emissive information in the g-buffer --- .../resources/shaders/directional_light.frag | 45 ++++++++++++------- .../resources/shaders/model_lightmap.frag | 6 +-- interface/src/renderer/GeometryCache.cpp | 11 ++++- interface/src/renderer/Model.cpp | 8 ++-- libraries/fbx/src/FBXReader.cpp | 24 +++++----- libraries/fbx/src/FBXReader.h | 1 + 6 files changed, 58 insertions(+), 37 deletions(-) diff --git a/interface/resources/shaders/directional_light.frag b/interface/resources/shaders/directional_light.frag index da48149001..d4a6f5a28b 100644 --- a/interface/resources/shaders/directional_light.frag +++ b/interface/resources/shaders/directional_light.frag @@ -36,25 +36,36 @@ uniform vec2 depthTexCoordOffset; uniform vec2 depthTexCoordScale; void main(void) { + float depthVal = texture2D(depthMap, gl_TexCoord[0].st).r; + vec4 normalVal = texture2D(normalMap, gl_TexCoord[0].st); + vec4 diffuseVal = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 specularVal = texture2D(specularMap, gl_TexCoord[0].st); + // compute the view space position using the depth - float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0); + float z = near / (depthVal * depthScale - 1.0); vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 0.0); // get the normal from the map - vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0)); - - // compute the base color based on OpenGL lighting model - float diffuse = dot(normalizedNormal, gl_LightSource[0].position); - float facingLight = step(0.0, diffuse); - vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + - gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); - - // compute the specular multiplier (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(position)), - normalizedNormal)); - - // add specular contribution - vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st); - gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a); + vec4 normal = normalVal; + if (normalVal.a == 0.5) { + normal.a = 1.0; + normalVal.a = 0.0; + gl_FragColor = vec4(diffuseVal.rgb * specularColor.rgb, normal.a); + } else { + vec3 normalizedNormal = normalize(normal.xyz * 2.0 - vec3(1.0)); + + // compute the base color based on OpenGL lighting model + float diffuse = dot(normalizedNormal, gl_LightSource[0].position.xyz); + float facingLight = step(0.0, diffuse); + vec3 baseColor = diffuseVal.rgb * (gl_FrontLightModelProduct.sceneColor.rgb + + gl_FrontLightProduct[0].ambient.rgb + gl_FrontLightProduct[0].diffuse.rgb * (diffuse * facingLight)); + + // compute the specular multiplier (sans exponent) + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position.xyz - normalize(position.xyz)), + normalizedNormal)); + + // add specular contribution + vec4 specularColor = specularVal; + gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a); + } } diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag index b93f0abc6f..7c352b877e 100644 --- a/interface/resources/shaders/model_lightmap.frag +++ b/interface/resources/shaders/model_lightmap.frag @@ -31,7 +31,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); - gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5); + gl_FragData[2] = vec4((vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index c7d8b7fc8a..5ef90732ef 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -829,10 +829,17 @@ void GeometryReader::run() { return; } try { - QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, + std::string urlname = _url.path().toLower().toStdString(); + FBXGeometry fbxgeo; + if (_url.path().toLower().endsWith(".svo")) { + fbxgeo = readSVO(_reply->readAll()); + } else { + fbxgeo = readFBX(_reply->readAll(), _mapping); + } + QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo)); - _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping))); + // _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping))); } catch (const QString& error) { qDebug() << "Error reading " << _url << ": " << error; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index e6dc3ce74e..2e17cc2605 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2382,12 +2382,10 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } if (locations->emissiveTextureUnit >= 0) { - assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader - static float emissiveOffset = 0.1f; - static float emissiveScale = 1.0f; - //GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f); + // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + float emissiveOffset = part.emissiveParams.x; + float emissiveScale = part.emissiveParams.y; GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); - GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index b54abedc33..fd9190f597 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1216,6 +1216,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QHash bumpTextures; QHash specularTextures; QHash emissiveTextures; + QHash ambientTextures; QHash localRotations; QHash xComponents; QHash yComponents; @@ -1707,7 +1708,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("ambient")) { - emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else { std::string typenam = type.data(); counter++; @@ -1952,19 +1953,20 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } FBXTexture emissiveTexture; + glm::vec2 emissiveParams(0.f, 1.f); QString emissiveTextureID = emissiveTextures.value(childID); - if (!emissiveTextureID.isNull()) { - emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); - - // FBX files generated by 3DSMax have an intermediate texture parent, apparently - foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { - if (textureFilenames.contains(childTextureID)) { - emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); - } + QString ambientTextureID = ambientTextures.value(childID); + if (!emissiveTextureID.isNull() || !ambientTextureID.isNull()) { + + if (!emissiveTextureID.isNull()) { + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); + emissiveParams.y = 4.0f; + } else if (!ambientTextureID.isNull()) { + emissiveTexture = getTexture(ambientTextureID, textureNames, textureFilenames, textureContent, textureParams); } emissiveTexture.texcoordSet = matchTextureUVSetToAttributeChannel(emissiveTexture.texcoordSetName, extracted.texcoordSetMap); - + detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity()); } @@ -1992,6 +1994,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) if (!emissiveTexture.filename.isNull()) { part.emissiveTexture = emissiveTexture; } + part.emissiveParams = emissiveParams; + part.materialID = material.id; } } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 60e8ea2448..d92f787050 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -119,6 +119,7 @@ public: glm::vec3 diffuseColor; glm::vec3 specularColor; glm::vec3 emissiveColor; + glm::vec2 emissiveParams; float shininess; float opacity; From ff4d28abebb34dfda671506f5d70ea21025fc867 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 25 Nov 2014 18:27:49 -0800 Subject: [PATCH 04/18] hack a separate emissive information in the g-buffer --- interface/resources/shaders/directional_light.frag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/shaders/directional_light.frag b/interface/resources/shaders/directional_light.frag index d4a6f5a28b..906a33ea74 100644 --- a/interface/resources/shaders/directional_light.frag +++ b/interface/resources/shaders/directional_light.frag @@ -47,10 +47,10 @@ void main(void) { // get the normal from the map vec4 normal = normalVal; - if (normalVal.a == 0.5) { + if ((normalVal.a >= 0.45) && (normalVal.a <= 0.55)) { normal.a = 1.0; normalVal.a = 0.0; - gl_FragColor = vec4(diffuseVal.rgb * specularColor.rgb, normal.a); + gl_FragColor = vec4(diffuseVal.rgb * specularVal.rgb, 1.0); } else { vec3 normalizedNormal = normalize(normal.xyz * 2.0 - vec3(1.0)); From fe9fab68bfd6ea1c94d48a16bb5c29d09af4ff78 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 17:30:59 -0800 Subject: [PATCH 05/18] don't exit app in full screen or hdm mode --- interface/src/Application.cpp | 1 + interface/src/ui/HMDToolsDialog.cpp | 103 ++++++++++++++++++---------- interface/src/ui/HMDToolsDialog.h | 4 ++ 3 files changed, 70 insertions(+), 38 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 397f883b3e..6791ae3d62 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -438,6 +438,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : void Application::aboutToQuit() { _aboutToQuit = true; + setFullscreen(false); // if you exit while in full screen, you'll get bad behavior when you restart. } Application::~Application() { diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index a5e54fa546..f2be62a026 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -30,7 +30,8 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) , _previousScreen(NULL), _hmdScreen(NULL), - _previousDialogScreen(NULL) + _previousDialogScreen(NULL), + _inHDMMode(false) { this->setWindowTitle("HMD Tools"); @@ -65,14 +66,18 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); connect(mainWindow, &QWindow::screenChanged, this, &HMDToolsDialog::applicationWindowScreenChanged); - // watch for our dialog window moving screens. If it does we want to enforce our rules about what screens we're - // allowed on + // watch for our dialog window moving screens. If it does we want to enforce our rules about + // what screens we're allowed on QWindow* dialogWindow = windowHandle(); connect(dialogWindow, &QWindow::screenChanged, this, &HMDToolsDialog::dialogWindowScreenChanged); connect(dialogWindow, &QWindow::xChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); connect(dialogWindow, &QWindow::yChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); connect(dialogWindow, &QWindow::widthChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); connect(dialogWindow, &QWindow::heightChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); + + // when the application is about to quit, leave HDM mode + connect(Application::getInstance(), SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); + } HMDToolsDialog::~HMDToolsDialog() { @@ -159,37 +164,45 @@ QString HMDToolsDialog::getDebugDetails() const { } void HMDToolsDialog::enterModeClicked(bool checked) { - _debugDetails->setText(getDebugDetails()); + enterHDMMode(); +} - int hmdScreen = OculusManager::getHMDScreen(); - qDebug() << "enterModeClicked().... hmdScreen:" << hmdScreen; +void HMDToolsDialog::enterHDMMode() { + if (!_inHDMMode) { + _debugDetails->setText(getDebugDetails()); + + int hmdScreen = OculusManager::getHMDScreen(); + qDebug() << "enterModeClicked().... hmdScreen:" << hmdScreen; - if (hmdScreen >= 0) { - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - _hmdScreen = QGuiApplication::screens()[hmdScreen]; + if (hmdScreen >= 0) { + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + _hmdScreen = QGuiApplication::screens()[hmdScreen]; - _previousRect = Application::getInstance()->getWindow()->rect(); - _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), - mainWindow->mapToGlobal(_previousRect.bottomRight())); - _previousScreen = mainWindow->screen(); - QRect rect = QApplication::desktop()->screenGeometry(hmdScreen); - mainWindow->setScreen(_hmdScreen); - mainWindow->setGeometry(rect); + _previousRect = Application::getInstance()->getWindow()->rect(); + _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), + mainWindow->mapToGlobal(_previousRect.bottomRight())); + _previousScreen = mainWindow->screen(); + QRect rect = QApplication::desktop()->screenGeometry(hmdScreen); + mainWindow->setScreen(_hmdScreen); + mainWindow->setGeometry(rect); - _wasMoved = true; - } + _wasMoved = true; + } - // if we're on a single screen setup, then hide our tools window when entering HMD mode - if (QApplication::desktop()->screenCount() == 1) { - close(); - } + // if we're on a single screen setup, then hide our tools window when entering HMD mode + if (QApplication::desktop()->screenCount() == 1) { + close(); + } - Application::getInstance()->setFullscreen(true); - Application::getInstance()->setEnableVRMode(true); + Application::getInstance()->setFullscreen(true); + Application::getInstance()->setEnableVRMode(true); - const int SLIGHT_DELAY = 500; - QTimer::singleShot(SLIGHT_DELAY, this, SLOT(activateWindowAfterEnterMode())); + const int SLIGHT_DELAY = 500; + QTimer::singleShot(SLIGHT_DELAY, this, SLOT(activateWindowAfterEnterMode())); + + _inHDMMode = true; + } } void HMDToolsDialog::activateWindowAfterEnterMode() { @@ -199,23 +212,30 @@ void HMDToolsDialog::activateWindowAfterEnterMode() { centerCursorOnWidget(Application::getInstance()->getWindow()); } - void HMDToolsDialog::leaveModeClicked(bool checked) { - _debugDetails->setText(getDebugDetails()); + leaveHDMMode(); +} - Application::getInstance()->setFullscreen(false); - Application::getInstance()->setEnableVRMode(false); - Application::getInstance()->getWindow()->activateWindow(); - if (_wasMoved) { - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - mainWindow->setScreen(_previousScreen); - mainWindow->setGeometry(_previousRect); +void HMDToolsDialog::leaveHDMMode() { + if (_inHDMMode) { + _debugDetails->setText(getDebugDetails()); + + Application::getInstance()->setFullscreen(false); + Application::getInstance()->setEnableVRMode(false); + Application::getInstance()->getWindow()->activateWindow(); + + if (_wasMoved) { + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + mainWindow->setScreen(_previousScreen); + mainWindow->setGeometry(_previousRect); - const int SLIGHT_DELAY = 1500; - QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode())); + const int SLIGHT_DELAY = 1500; + QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode())); + } + _wasMoved = false; + _inHDMMode = false; } - _wasMoved = false; } void HMDToolsDialog::moveWindowAfterLeaveMode() { @@ -256,3 +276,10 @@ void HMDToolsDialog::hideEvent(QHideEvent* event) { } +void HMDToolsDialog::aboutToQuit() { + if (_inHDMMode) { + leaveHDMMode(); + } +} + + diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index 4fe0dd626f..d2068d9e82 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -35,6 +35,7 @@ public slots: void applicationWindowScreenChanged(QScreen* screen); void dialogWindowScreenChanged(QScreen* screen); void dialogWindowGeometryChanged(int arg); + void aboutToQuit(); protected: virtual void closeEvent(QCloseEvent*); // Emits a 'closed' signal when this dialog is closed. @@ -43,6 +44,8 @@ protected: private: void centerCursorOnWidget(QWidget* widget); + void enterHDMMode(); + void leaveHDMMode(); bool _wasMoved; QRect _previousRect; @@ -52,6 +55,7 @@ private: QRect _previousDialogRect; QScreen* _previousDialogScreen; + bool _inHDMMode; }; #endif // hifi_HMDToolsDialog_h From 85ca03199ebafcd8f26091d8c87eb8c107d0413b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 17:53:41 -0800 Subject: [PATCH 06/18] remove Entities developer menu items from C++ menu, make them available through script --- examples/developerMenuItems.js | 37 ++++++++++++++++++++++++++++++++++ interface/src/Menu.cpp | 16 --------------- 2 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 examples/developerMenuItems.js diff --git a/examples/developerMenuItems.js b/examples/developerMenuItems.js new file mode 100644 index 0000000000..221975c9c8 --- /dev/null +++ b/examples/developerMenuItems.js @@ -0,0 +1,37 @@ +// +// developerMenuItems.js +// examples +// +// Created by Brad Hefta-Gaub on 2/24/14 +// Copyright 2013 High Fidelity, Inc. +// +// Adds a bunch of developer and debugging menu items +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +function setupMenus() { + if (!Menu.menuExists("Developer")) { + Menu.addMenu("Developer"); + } + if (!Menu.menuExists("Developer > Entities")) { + Menu.addMenu("Developer > Entities"); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Bounds", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Bounds", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Children", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt to Reduce Material Switches", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt Render Entities as Scene", isCheckable: true, isChecked: false }); + Menu.addMenu("Developer > Entities > Culling"); + Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Out Of View Mesh Parts", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Too Small Mesh Parts", isCheckable: true, isChecked: false }); + } +} + +function scriptEnding() { + Menu.removeMenu("Developer > Entities"); +} +setupMenus(); +Script.scriptEnding.connect(scriptEnding); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 2c7b4a9efd..6cfb3db35a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -445,23 +445,7 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderBoundingCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false); - - QMenu* entitiesDebugMenu = developerMenu->addMenu("Entities"); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelBounds, 0, false); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelElementProxy, 0, false); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelElementChildProxies, 0, false); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisableLightEntities, 0, false); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DontReduceMaterialSwitches, 0, false); - addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DontRenderEntitiesAsScene, 0, false); - - QMenu* entityCullingMenu = entitiesDebugMenu->addMenu("Culling"); - addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontCullOutOfViewMeshParts, 0, false); - addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontCullTooSmallMeshParts, 0, false); - - - - QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxels"); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); From 184acaedefa7e5ff8b7aecb520529ec8f982dc7e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 19:43:01 -0800 Subject: [PATCH 07/18] switch to single button for mode switching --- interface/src/ui/HMDToolsDialog.cpp | 31 ++++++++++++++--------------- interface/src/ui/HMDToolsDialog.h | 4 ++-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index f2be62a026..d7cb5b4756 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -28,6 +28,8 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) , + _switchModeButton(NULL), + _debugDetails(NULL), _previousScreen(NULL), _hmdScreen(NULL), _previousDialogScreen(NULL), @@ -37,21 +39,17 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : // Create layouter QFormLayout* form = new QFormLayout(); + const int WIDTH = 350; // Add a button to enter - QPushButton* enterModeButton = new QPushButton("Enter HMD Mode"); - form->addRow("", enterModeButton); - connect(enterModeButton,SIGNAL(clicked(bool)),this,SLOT(enterModeClicked(bool))); - - // Add a button to leave - QPushButton* leaveModeButton = new QPushButton("Leave HMD Mode"); - form->addRow("", leaveModeButton); - connect(leaveModeButton,SIGNAL(clicked(bool)),this,SLOT(leaveModeClicked(bool))); + _switchModeButton = new QPushButton("Enter HMD Mode"); + _switchModeButton->setFixedWidth(WIDTH); + form->addRow("", _switchModeButton); + connect(_switchModeButton,SIGNAL(clicked(bool)),this,SLOT(switchModeClicked(bool))); // Create a label with debug details... _debugDetails = new QLabel(); _debugDetails->setText(getDebugDetails()); - const int WIDTH = 350; const int HEIGHT = 100; _debugDetails->setFixedSize(WIDTH, HEIGHT); form->addRow("", _debugDetails); @@ -163,12 +161,17 @@ QString HMDToolsDialog::getDebugDetails() const { return results; } -void HMDToolsDialog::enterModeClicked(bool checked) { - enterHDMMode(); +void HMDToolsDialog::switchModeClicked(bool checked) { + if (!_inHDMMode) { + enterHDMMode(); + } else { + leaveHDMMode(); + } } void HMDToolsDialog::enterHDMMode() { if (!_inHDMMode) { + _switchModeButton->setText("Leave HMD Mode"); _debugDetails->setText(getDebugDetails()); int hmdScreen = OculusManager::getHMDScreen(); @@ -212,13 +215,9 @@ void HMDToolsDialog::activateWindowAfterEnterMode() { centerCursorOnWidget(Application::getInstance()->getWindow()); } -void HMDToolsDialog::leaveModeClicked(bool checked) { - leaveHDMMode(); -} - - void HMDToolsDialog::leaveHDMMode() { if (_inHDMMode) { + _switchModeButton->setText("Enter HMD Mode"); _debugDetails->setText(getDebugDetails()); Application::getInstance()->setFullscreen(false); diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index d2068d9e82..91db300224 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -28,8 +28,7 @@ signals: public slots: void reject(); - void enterModeClicked(bool checked); - void leaveModeClicked(bool checked); + void switchModeClicked(bool checked); void activateWindowAfterEnterMode(); void moveWindowAfterLeaveMode(); void applicationWindowScreenChanged(QScreen* screen); @@ -51,6 +50,7 @@ private: QRect _previousRect; QScreen* _previousScreen; QScreen* _hmdScreen; + QPushButton* _switchModeButton; QLabel* _debugDetails; QRect _previousDialogRect; From 39042f61cd8a535d0afb7e87e2110230d8824508 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 26 Nov 2014 19:57:18 -0800 Subject: [PATCH 08/18] 1P mirror can lean fwd/back --- interface/src/Application.cpp | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 58b28fcef9..a1f374c3c6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -650,20 +650,11 @@ void Application::paintGL() { } } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - //Only behave like a true mirror when in the OR - if (OculusManager::isConnected()) { - _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); - _myCamera.setPosition(_myAvatar->getHead()->getEyePosition() + - glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) + - (_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * - glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); - } else { - _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); - _myCamera.setPosition(_myAvatar->getHead()->getEyePosition() + - glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) + - (_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * - glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); - } + _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); + _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) + + (_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * + glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); } // Update camera position From fe010b685a6a9ccf71348986ce85e5605ba145c5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 26 Nov 2014 20:19:23 -0800 Subject: [PATCH 09/18] more HMD Tools improvements, better support for detecting adding/removing screens --- interface/src/ui/HMDToolsDialog.cpp | 47 ++++++++++++++++++++++------- interface/src/ui/HMDToolsDialog.h | 6 ++-- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index d7cb5b4756..88924f68d1 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -28,10 +28,11 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) , - _switchModeButton(NULL), - _debugDetails(NULL), _previousScreen(NULL), _hmdScreen(NULL), + _hmdScreenNumber(-1), + _switchModeButton(NULL), + _debugDetails(NULL), _previousDialogScreen(NULL), _inHDMMode(false) { @@ -75,6 +76,9 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : // when the application is about to quit, leave HDM mode connect(Application::getInstance(), SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); + + // keep track of changes to the number of screens + connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &HMDToolsDialog::screenCountChanged); } @@ -99,11 +103,11 @@ void HMDToolsDialog::dialogWindowScreenChanged(QScreen* screen) { // if we have more than one screen, and a known hmdScreen then try to // keep our dialog off of the hmdScreen if (QApplication::desktop()->screenCount() > 1) { - int hmdScreenNumber = OculusManager::getHMDScreen(); - - if (hmdScreenNumber >= 0) { - QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber]; + // we want to use a local variable here because we are not necesarily in HMD mode + int hmdScreenNumber = OculusManager::getHMDScreen(); + if (_hmdScreenNumber >= 0) { + QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber]; if (screen == hmdScreen) { qDebug() << "HMD Tools: Whoa! What are you doing? You don't want to move me to the HMD Screen!"; QWindow* dialogWindow = windowHandle(); @@ -157,6 +161,7 @@ QString HMDToolsDialog::getDebugDetails() const { results += "Application Primary Screen: " + QGuiApplication::primaryScreen()->name() + "\n"; QScreen* mainWindowScreen = Application::getInstance()->getWindow()->windowHandle()->screen(); results += "Application Main Window Screen: " + mainWindowScreen->name() + "\n"; + results += "Total Screens: " + QString::number(QApplication::desktop()->screenCount()) + "\n"; return results; } @@ -174,18 +179,17 @@ void HMDToolsDialog::enterHDMMode() { _switchModeButton->setText("Leave HMD Mode"); _debugDetails->setText(getDebugDetails()); - int hmdScreen = OculusManager::getHMDScreen(); - qDebug() << "enterModeClicked().... hmdScreen:" << hmdScreen; + _hmdScreenNumber = OculusManager::getHMDScreen(); - if (hmdScreen >= 0) { + if (_hmdScreenNumber >= 0) { QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - _hmdScreen = QGuiApplication::screens()[hmdScreen]; + _hmdScreen = QGuiApplication::screens()[_hmdScreenNumber]; _previousRect = Application::getInstance()->getWindow()->rect(); _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), mainWindow->mapToGlobal(_previousRect.bottomRight())); _previousScreen = mainWindow->screen(); - QRect rect = QApplication::desktop()->screenGeometry(hmdScreen); + QRect rect = QApplication::desktop()->screenGeometry(_hmdScreenNumber); mainWindow->setScreen(_hmdScreen); mainWindow->setGeometry(rect); @@ -281,4 +285,25 @@ void HMDToolsDialog::aboutToQuit() { } } +void HMDToolsDialog::screenCountChanged(int newCount) { + if (!OculusManager::isConnected()) { + OculusManager::connect(); + } + int hmdScreenNumber = OculusManager::getHMDScreen(); + + if (_inHDMMode && _hmdScreenNumber != hmdScreenNumber) { + qDebug() << "HMD Display changed WHILE IN HMD MODE"; + leaveHDMMode(); + + // if there is a new best HDM screen then go back into HDM mode after done leaving + if (hmdScreenNumber >= 0) { + qDebug() << "Trying to go back into HDM Mode"; + const int SLIGHT_DELAY = 2000; + QTimer::singleShot(SLIGHT_DELAY, this, SLOT(enterHDMMode())); + } + } + _debugDetails->setText(getDebugDetails()); +} + + diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index 91db300224..e3e5573533 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -34,8 +34,9 @@ public slots: void applicationWindowScreenChanged(QScreen* screen); void dialogWindowScreenChanged(QScreen* screen); void dialogWindowGeometryChanged(int arg); - void aboutToQuit(); - + void aboutToQuit(); + void screenCountChanged(int newCount); + protected: virtual void closeEvent(QCloseEvent*); // Emits a 'closed' signal when this dialog is closed. virtual void showEvent(QShowEvent* event); @@ -50,6 +51,7 @@ private: QRect _previousRect; QScreen* _previousScreen; QScreen* _hmdScreen; + int _hmdScreenNumber; QPushButton* _switchModeButton; QLabel* _debugDetails; From c78af1c982f3f891ca413b7c9f2058ee4e1f8740 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 27 Nov 2014 10:48:36 -0800 Subject: [PATCH 10/18] fixing the bug when lighmaps are diasppearing in the , i don;t understand why --- interface/src/renderer/Model.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2e17cc2605..b2570b7c28 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2381,24 +2381,27 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (locations->emissiveTextureUnit >= 0) { - // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader - float emissiveOffset = part.emissiveParams.x; - float emissiveScale = part.emissiveParams.y; - GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); - - GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); - Texture* emissiveMap = networkPart.emissiveTexture.data(); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? - Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); - GLBATCH(glActiveTexture)(GL_TEXTURE0); - } - if (args) { args->_materialSwitches++; } } + + // HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every + // drawcall with an emissive, so let's do it for now. + if (locations->emissiveTextureUnit >= 0) { + // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + float emissiveOffset = part.emissiveParams.x; + float emissiveScale = part.emissiveParams.y; + GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); + + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); + Texture* emissiveMap = networkPart.emissiveTexture.data(); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? + Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); + GLBATCH(glActiveTexture)(GL_TEXTURE0); + } + lastMaterialID = part.materialID; } From 583e079d3a1f3650e7fb063f308f86848adaa97e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 28 Nov 2014 10:01:15 -0800 Subject: [PATCH 11/18] Fix Hydra cursors in VR display They weren't being drawn at the correct location an so weren't matching up with location of voxel being added or deleted, for example. --- interface/src/devices/SixenseManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index d636f8929c..6d227027ed 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -477,7 +477,8 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { triggerButton = Qt::LeftButton; } - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers) + || Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { pos = application->getApplicationOverlay().getPalmClickLocation(palm); } else { // Get directon relative to avatar orientation From 5c2cc20313e14757e14399051dd814846b543b7f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 28 Nov 2014 17:36:55 -0800 Subject: [PATCH 12/18] fixes the stutter in animation when observer moves --- interface/src/renderer/AnimationHandle.cpp | 8 +++----- libraries/animation/src/AnimationLoop.cpp | 5 +++-- libraries/animation/src/AnimationLoop.h | 4 ++++ libraries/entities/src/ModelEntityItem.cpp | 4 +++- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/interface/src/renderer/AnimationHandle.cpp b/interface/src/renderer/AnimationHandle.cpp index 767f941049..89c265875b 100644 --- a/interface/src/renderer/AnimationHandle.cpp +++ b/interface/src/renderer/AnimationHandle.cpp @@ -138,11 +138,9 @@ void AnimationHandle::simulate(float deltaTime) { return; } - // TODO: When moving the loop/frame calculations to AnimationLoop class, we changed this behavior - // see AnimationLoop class for more details. Do we need to support clamping the endFrameIndex to - // the max number of frames in the geometry??? - // - // float endFrameIndex = qMin(_lastFrame, animationGeometry.animationFrames.size() - (_loop ? 0.0f : 1.0f)); + if (_animationLoop.getMaxFrameIndexHint() != animationGeometry.animationFrames.size()) { + _animationLoop.setMaxFrameIndexHint(animationGeometry.animationFrames.size()); + } // blend between the closest two frames applyFrame(getFrameIndex()); diff --git a/libraries/animation/src/AnimationLoop.cpp b/libraries/animation/src/AnimationLoop.cpp index f81904990f..75a3cdd338 100644 --- a/libraries/animation/src/AnimationLoop.cpp +++ b/libraries/animation/src/AnimationLoop.cpp @@ -20,7 +20,8 @@ AnimationLoop::AnimationLoop() : _firstFrame(0.0f), _lastFrame(FLT_MAX), _running(false), - _frameIndex(0.0f) + _frameIndex(0.0f), + _maxFrameIndexHint(FLT_MAX) { } @@ -55,7 +56,7 @@ void AnimationLoop::simulate(float deltaTime) { // If we knew the number of frames from the animation, we'd consider using it here // animationGeometry.animationFrames.size() - float maxFrame = _lastFrame; + float maxFrame = _maxFrameIndexHint; float endFrameIndex = qMin(_lastFrame, maxFrame - (_loop ? 0.0f : 1.0f)); float startFrameIndex = qMin(_firstFrame, endFrameIndex); if ((!_loop && (_frameIndex < startFrameIndex || _frameIndex > endFrameIndex)) || startFrameIndex == endFrameIndex) { diff --git a/libraries/animation/src/AnimationLoop.h b/libraries/animation/src/AnimationLoop.h index b56f68f23b..aff2cd86ee 100644 --- a/libraries/animation/src/AnimationLoop.h +++ b/libraries/animation/src/AnimationLoop.h @@ -44,6 +44,9 @@ public: void setFrameIndex(float frameIndex) { _frameIndex = glm::clamp(frameIndex, _firstFrame, _lastFrame); } float getFrameIndex() const { return _frameIndex; } + + void setMaxFrameIndexHint(float value) { _maxFrameIndexHint = value; } + float getMaxFrameIndexHint() const { return _maxFrameIndexHint; } void start() { setRunning(true); } void stop() { setRunning(false); } @@ -58,6 +61,7 @@ private: float _lastFrame; bool _running; float _frameIndex; + float _maxFrameIndexHint; }; #endif // hifi_AnimationLoop_h diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 31a0c57f5b..63fe3daa03 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -344,7 +344,9 @@ QVector ModelEntityItem::getAnimationFrame() { Animation* myAnimation = getAnimation(_animationURL); QVector frames = myAnimation->getFrames(); int frameCount = frames.size(); - + if (_animationLoop.getMaxFrameIndexHint() != frameCount) { + _animationLoop.setMaxFrameIndexHint(frameCount); + } if (frameCount > 0) { int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount; if (animationFrameIndex < 0 || animationFrameIndex > frameCount) { From 709a40516d5ffcc2e3fc5b25c152f8ba3e91c970 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 29 Nov 2014 12:17:38 -0800 Subject: [PATCH 13/18] Add auto-turn of body when head is beyond 45 degrees --- examples/headMove.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/examples/headMove.js b/examples/headMove.js index df5c858b46..4d2e4ded07 100644 --- a/examples/headMove.js +++ b/examples/headMove.js @@ -19,6 +19,7 @@ var warpPosition = { x: 0, y: 0, z: 0 }; var hipsToEyes; var restoreCountdownTimer; +var headTurningTimer = 0.0; // Overlays to show target location @@ -168,6 +169,20 @@ function update(deltaTime) { restoreCountDownTimer = 0.0; } } + var HEAD_TURN_TIME = 0.10; + var HEAD_TURN_DEGREES = 4.0; + var HEAD_TURN_START_ANGLE = 45.0; + var currentYaw = MyAvatar.getHeadFinalYaw(); + if (Math.abs(currentYaw) > HEAD_TURN_START_ANGLE) { + headTurningTimer += deltaTime; + if (headTurningTimer > HEAD_TURN_TIME) { + headTurningTimer = 0.0; + MyAvatar.orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, (currentYaw > 0) ? HEAD_TURN_DEGREES: -HEAD_TURN_DEGREES, 0), + MyAvatar.orientation); + } + } else { + headTurningTimer = 0.0; + } } Controller.keyPressEvent.connect(function(event) { From 321d651d77fe0c8927e003c08715020de8928765 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 30 Nov 2014 12:54:43 -0800 Subject: [PATCH 14/18] Hack for avoiding lightmaps loading in starchamber --- interface/src/renderer/GeometryCache.cpp | 7 ++++++- libraries/fbx/src/FBXReader.cpp | 10 +++++----- libraries/fbx/src/FBXReader.h | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 5ef90732ef..04b59e7ea1 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -834,7 +834,12 @@ void GeometryReader::run() { if (_url.path().toLower().endsWith(".svo")) { fbxgeo = readSVO(_reply->readAll()); } else { - fbxgeo = readFBX(_reply->readAll(), _mapping); + bool grabLightmaps = true; + // HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber... + if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) { + grabLightmaps = false; + } + fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps); } QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo)); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index fd9190f597..d77cbbd0a1 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1194,7 +1194,7 @@ int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const Q } } -FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) { +FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps) { QHash meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; @@ -1704,10 +1704,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (type.contains("shininess")) { counter++; - } else if (type.contains("emissive")) { + } else if (loadLightmaps && type.contains("emissive")) { emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); - } else if (type.contains("ambient")) { + } else if (loadLightmaps && type.contains("ambient")) { ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else { std::string typenam = type.data(); @@ -2372,10 +2372,10 @@ QByteArray writeMapping(const QVariantHash& mapping) { return buffer.data(); } -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping) { +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); - return extractFBXGeometry(parseFBX(&buffer), mapping); + return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps); } bool addMeshVoxelsOperation(OctreeElement* element, void* extraData) { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index d92f787050..3adf5b5ffb 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -253,7 +253,7 @@ QByteArray writeMapping(const QVariantHash& mapping); /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping); +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true); /// Reads SVO geometry from the supplied model data. FBXGeometry readSVO(const QByteArray& model); From fed7d789f6023eef1670974eb75b558691b16a8d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Sun, 30 Nov 2014 17:29:18 -0800 Subject: [PATCH 15/18] have the domain-server write its local port into shared memory --- domain-server/src/DomainServer.cpp | 13 +++++++++++++ libraries/networking/src/LimitedNodeList.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 02f17bc502..84948e2406 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -228,6 +229,18 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { LimitedNodeList* nodeList = LimitedNodeList::createInstance(domainServerPort, domainServerDTLSPort); + // no matter the local port, save it to shared mem so that local assignment clients can ask what it is + QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + quint16 localPort = nodeList->getNodeSocket().localPort(); + + // attempt to create the shared memory segment + if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { + memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); + qDebug() << "Wrote local listening port to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; + } else { + qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; + } + // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain const QString METAVERSE_DOMAIN_ID_KEY_PATH = "metaverse.id"; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 64495fbd34..ad8c1688bb 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -44,6 +44,8 @@ const char DEFAULT_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost"; const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const unsigned short STUN_SERVER_PORT = 3478; +const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; + class HifiSockAddr; typedef QSet NodeSet; From 59432e8d2935f2b1937a26b784fc64fdc29640e4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Sun, 30 Nov 2014 17:54:10 -0800 Subject: [PATCH 16/18] complete sharing of local domain-server port to local AC --- assignment-client/src/AssignmentClient.cpp | 59 +++++++++++++++++----- assignment-client/src/AssignmentClient.h | 4 ++ domain-server/src/DomainServer.cpp | 5 +- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index ae235eb1ff..9972adfda2 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include @@ -38,7 +39,8 @@ int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), _shutdownEventListener(this), - _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME) + _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), + _localASPortSharedMem(NULL) { LogUtils::init(); @@ -89,13 +91,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // create a NodeList as an unassigned client NodeList* nodeList = NodeList::createInstance(NodeType::Unassigned); - unsigned short assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; - - // check for an overriden assignment server port - if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION)) { - assignmentServerPort = - argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toString().toUInt(); - } + quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; // check for an overriden assignment server hostname if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION)) { @@ -103,10 +99,16 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : _assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString(); } - HifiSockAddr assignmentServerSocket(_assignmentServerHostname, assignmentServerPort, true); - nodeList->setAssignmentServerSocket(assignmentServerSocket); + // check for an overriden assignment server port + if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION)) { + assignmentServerPort = + argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toString().toUInt(); + } + + _assignmentServerSocket = HifiSockAddr(_assignmentServerHostname, assignmentServerPort, true); + nodeList->setAssignmentServerSocket(_assignmentServerSocket); - qDebug() << "Assignment server socket is" << assignmentServerSocket; + qDebug() << "Assignment server socket is" << _assignmentServerSocket; // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required qDebug() << "Waiting for assignment -" << _requestAssignment; @@ -129,7 +131,40 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : void AssignmentClient::sendAssignmentRequest() { if (!_currentAssignment) { - NodeList::getInstance()->sendAssignment(_requestAssignment); + + NodeList* nodeList = NodeList::getInstance(); + + if (_assignmentServerHostname == "localhost") { + // we want to check again for the local domain-server port in case the DS has restarted + if (!_localASPortSharedMem) { + _localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + + if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) { + qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY + << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + } + } + + if (_localASPortSharedMem->isAttached()) { + _localASPortSharedMem->lock(); + + quint16 localAssignmentServerPort; + memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort)); + + _localASPortSharedMem->unlock(); + + if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { + qDebug() << "Port for local assignment server read from shared memory is" + << localAssignmentServerPort; + + _assignmentServerSocket.setPort(localAssignmentServerPort); + nodeList->setAssignmentServerSocket(_assignmentServerSocket); + } + } + + } + + nodeList->sendAssignment(_requestAssignment); } } diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 7628aa0a3b..566805d67f 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -17,6 +17,8 @@ #include "ShutdownEventListener.h" #include "ThreadedAssignment.h" +class QSharedMemory; + class AssignmentClient : public QCoreApplication { Q_OBJECT public: @@ -34,6 +36,8 @@ private: static SharedAssignmentPointer _currentAssignment; ShutdownEventListener _shutdownEventListener; QString _assignmentServerHostname; + HifiSockAddr _assignmentServerSocket; + QSharedMemory* _localASPortSharedMem; }; #endif // hifi_AssignmentClient_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 84948e2406..ddc06c8015 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -235,8 +235,11 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { // attempt to create the shared memory segment if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { + sharedPortMem->lock(); memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); - qDebug() << "Wrote local listening port to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; + sharedPortMem->unlock(); + + qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; } else { qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; } From 6d7f799dbe072a857d9ffdf1a9be66c6578f764f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 1 Dec 2014 10:32:35 -0800 Subject: [PATCH 17/18] oculus mirror lean hack --- interface/src/avatar/MyAvatar.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3cbe2ac8ae..3301cf0347 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -367,6 +367,15 @@ void MyAvatar::updateFromTrackers(float deltaTime) { const float TORSO_LENGTH = 0.5f; glm::vec3 relativePosition = estimatedPosition - glm::vec3(0.0f, -TORSO_LENGTH, 0.0f); const float MAX_LEAN = 45.0f; + + // Invert left/right lean when in mirror mode + // NOTE: this is kinda a hack, it's the same hack we use to make the head tilt. But it's not really a mirror + // it just makes you feel like you're looking in a mirror because the body movements of the avatar appear to + // match your body movements. + if (OculusManager::isConnected() && Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) { + relativePosition.x = -relativePosition.x; + } + head->setLeanSideways(glm::clamp(glm::degrees(atanf(relativePosition.x * _leanScale / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)), From 845e687fc579add8016dd593d41f94f9a956dad2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 1 Dec 2014 11:45:07 -0800 Subject: [PATCH 18/18] Adding a Hack for the apaartment model to boost the lightmaps --- interface/src/renderer/GeometryCache.cpp | 5 ++++- libraries/fbx/src/FBXReader.cpp | 7 ++++--- libraries/fbx/src/FBXReader.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 04b59e7ea1..e2517613df 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -835,11 +835,14 @@ void GeometryReader::run() { fbxgeo = readSVO(_reply->readAll()); } else { bool grabLightmaps = true; + float lightmapLevel = 1.0f; // HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber... if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) { grabLightmaps = false; + } else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) { + lightmapLevel = 4.0f; } - fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps); + fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps, lightmapLevel); } QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo)); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index d77cbbd0a1..5f215ac4d0 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1194,7 +1194,7 @@ int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const Q } } -FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps) { +FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { QHash meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; @@ -1954,6 +1954,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, FBXTexture emissiveTexture; glm::vec2 emissiveParams(0.f, 1.f); + emissiveParams.y = lightmapLevel; QString emissiveTextureID = emissiveTextures.value(childID); QString ambientTextureID = ambientTextures.value(childID); if (!emissiveTextureID.isNull() || !ambientTextureID.isNull()) { @@ -2372,10 +2373,10 @@ QByteArray writeMapping(const QVariantHash& mapping) { return buffer.data(); } -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps) { +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); - return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps); + return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps, lightmapLevel); } bool addMeshVoxelsOperation(OctreeElement* element, void* extraData) { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 3adf5b5ffb..a5df7ccc0c 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -253,7 +253,7 @@ QByteArray writeMapping(const QVariantHash& mapping); /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true); +FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f); /// Reads SVO geometry from the supplied model data. FBXGeometry readSVO(const QByteArray& model);