diff --git a/examples/editEntities.js b/examples/editEntities.js index e9f42bf74c..0b5c089c07 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -839,9 +839,11 @@ Controller.keyReleaseEvent.connect(function (event) { selectionDisplay.toggleSpaceMode(); } else if (event.text == "f") { if (isActive) { - cameraManager.focus(selectionManager.worldPosition, - selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + if (selectionManager.hasSelection()) { + cameraManager.focus(selectionManager.worldPosition, + selectionManager.worldDimensions, + Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + } } } else if (event.text == '[') { if (isActive) { @@ -1001,7 +1003,9 @@ PropertiesTool = function(opts) { type: 'update', }; if (selectionManager.hasSelection()) { + data.id = selectionManager.selections[0].id; data.properties = Entities.getEntityProperties(selectionManager.selections[0]); + data.properties.rotation = Quat.safeEulerAngles(data.properties.rotation); } webView.eventBridge.emitScriptEvent(JSON.stringify(data)); }); @@ -1010,8 +1014,59 @@ PropertiesTool = function(opts) { print(data); data = JSON.parse(data); if (data.type == "update") { + selectionManager.saveProperties(); + if (data.properties.rotation !== undefined) { + var rotation = data.properties.rotation; + data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z); + } Entities.editEntity(selectionManager.selections[0], data.properties); + pushCommandForSelections(); selectionManager._update(); + } else if (data.type == "action") { + if (data.action == "moveSelectionToGrid") { + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2), + var diff = { x: 0, y: dY, z: 0 }; + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + var newPosition = Vec3.sum(properties.position, diff); + Entities.editEntity(selectionManager.selections[i], { + position: newPosition, + }); + } + pushCommandForSelections(); + selectionManager._update(); + } + } else if (data.action == "moveAllToGrid") { + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; + var dY = grid.getOrigin().y - bottomY; + var diff = { x: 0, y: dY, z: 0 }; + var newPosition = Vec3.sum(properties.position, diff); + Entities.editEntity(selectionManager.selections[i], { + position: newPosition, + }); + } + pushCommandForSelections(); + selectionManager._update(); + } + } else if (data.action == "resetToNaturalDimensions") { + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + Entities.editEntity(selectionManager.selections[i], { + dimensions: properties.naturalDimensions, + }); + } + pushCommandForSelections(); + selectionManager._update(); + } + } } }); diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 17eb0ad88f..4e22637ad6 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -70,21 +70,29 @@ }; function loaded() { + var elID = document.getElementById("property-id"); var elType = document.getElementById("property-type"); var elLocked = document.getElementById("property-locked"); var elVisible = document.getElementById("property-visible"); var elPositionX = document.getElementById("property-pos-x"); var elPositionY = document.getElementById("property-pos-y"); var elPositionZ = document.getElementById("property-pos-z"); + var elMoveSelectionToGrid = document.getElementById("move-selection-to-grid"); + var elMoveAllToGrid = document.getElementById("move-all-to-grid"); var elDimensionsX = document.getElementById("property-dim-x"); var elDimensionsY = document.getElementById("property-dim-y"); var elDimensionsZ = document.getElementById("property-dim-z"); + var elResetToNaturalDimensions = document.getElementById("reset-to-natural-dimensions"); var elRegistrationX = document.getElementById("property-reg-x"); var elRegistrationY = document.getElementById("property-reg-y"); var elRegistrationZ = document.getElementById("property-reg-z"); + var elRotationX = document.getElementById("property-rot-x"); + var elRotationY = document.getElementById("property-rot-y"); + var elRotationZ = document.getElementById("property-rot-z"); + var elLinearVelocityX = document.getElementById("property-lvel-x"); var elLinearVelocityY = document.getElementById("property-lvel-y"); var elLinearVelocityZ = document.getElementById("property-lvel-z"); @@ -156,6 +164,8 @@ } else { var properties = data.properties; + elID.innerHTML = data.id; + elType.innerHTML = properties.type; elLocked.checked = properties.locked; @@ -181,6 +191,10 @@ elRegistrationY.value = properties.registrationPoint.y.toFixed(2); elRegistrationZ.value = properties.registrationPoint.z.toFixed(2); + elRotationX.value = properties.rotation.x.toFixed(2); + elRotationY.value = properties.rotation.y.toFixed(2); + elRotationZ.value = properties.rotation.z.toFixed(2); + elLinearVelocityX.value = properties.velocity.x.toFixed(2); elLinearVelocityY.value = properties.velocity.y.toFixed(2); elLinearVelocityZ.value = properties.velocity.z.toFixed(2); @@ -302,6 +316,12 @@ elRegistrationY.addEventListener('change', registrationChangeFunction); elRegistrationZ.addEventListener('change', registrationChangeFunction); + var rotationChangeFunction = createEmitVec3PropertyUpdateFunction( + 'rotation', elRotationX, elRotationY, elRotationZ); + elRotationX.addEventListener('change', rotationChangeFunction); + elRotationY.addEventListener('change', rotationChangeFunction); + elRotationZ.addEventListener('change', rotationChangeFunction); + var velocityChangeFunction = createEmitVec3PropertyUpdateFunction( 'velocity', elLinearVelocityX, elLinearVelocityY, elLinearVelocityZ); elLinearVelocityX.addEventListener('change', velocityChangeFunction); @@ -381,6 +401,25 @@ elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction); elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction); + elMoveSelectionToGrid.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "moveSelectionToGrid", + })); + }); + elMoveAllToGrid.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "moveAllToGrid", + })); + }); + elResetToNaturalDimensions.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "resetToNaturalDimensions", + })); + }); + var resizing = false; var startX = 0; @@ -437,6 +476,14 @@ + + + ID + + + + + Type @@ -465,6 +512,10 @@
X
Y
Z
+
+ + +
@@ -483,6 +534,18 @@
X
Y
Z
+
+ +
+ + + + + Rotation + +
Pitch
+
Yaw
+
Roll
diff --git a/examples/html/style.css b/examples/html/style.css index 424933e14e..aa23cf97ab 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -17,6 +17,17 @@ body { user-select: none; } +.selectable { + -webkit-touch-callout: text; + -webkit-user-select: text; + -khtml-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; + + cursor: text; +} + .color-box { display: inline-block; width: 20px; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 94e88394a1..2e03a5beba 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -76,11 +77,14 @@ #include "ModelUploader.h" #include "Util.h" +#include "devices/DdeFaceTracker.h" +#include "devices/Faceshift.h" #include "devices/Leapmotion.h" #include "devices/RealSense.h" #include "devices/MIDIManager.h" #include "devices/OculusManager.h" #include "devices/TV3DManager.h" +#include "devices/Visage.h" #include "renderer/ProgramObject.h" #include "gpu/Batch.h" @@ -191,7 +195,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _isVSyncOn(true), _aboutToQuit(false) { - // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -618,10 +621,10 @@ void Application::paintGL() { // Set the desired FBO texture size. If it hasn't changed, this does nothing. // Otherwise, it must rebuild the FBOs if (OculusManager::isConnected()) { - _textureCache.setFrameBufferSize(OculusManager::getRenderTargetSize()); + DependencyManager::get()->setFrameBufferSize(OculusManager::getRenderTargetSize()); } else { QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); - _textureCache.setFrameBufferSize(fbSize); + DependencyManager::get()->setFrameBufferSize(fbSize); } glEnable(GL_LINE_SMOOTH); @@ -711,7 +714,7 @@ void Application::paintGL() { _glowEffect.prepare(); // Viewport is assigned to the size of the framebuffer - QSize size = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->size(); + QSize size = DependencyManager::get()->getPrimaryFramebufferObject()->size(); glViewport(0, 0, size.width(), size.height()); glMatrixMode(GL_MODELVIEW); @@ -1691,9 +1694,13 @@ int Application::getMouseDragStartedY() const { } FaceTracker* Application::getActiveFaceTracker() { - return (_dde.isActive() ? static_cast(&_dde) : - (_faceshift.isActive() ? static_cast(&_faceshift) : - (_visage.isActive() ? static_cast(&_visage) : NULL))); + Faceshift* faceshift = DependencyManager::get(); + Visage* visage = DependencyManager::get(); + DdeFaceTracker* dde = DependencyManager::get(); + + return (dde->isActive() ? static_cast(dde) : + (faceshift->isActive() ? static_cast(faceshift) : + (visage->isActive() ? static_cast(visage) : NULL))); } struct SendVoxelsOperationArgs { @@ -1977,8 +1984,8 @@ void Application::init() { #endif // initialize our face trackers after loading the menu settings - _faceshift.init(); - _visage.init(); + DependencyManager::get()->init(); + DependencyManager::get()->init(); Leapmotion::init(); RealSense::init(); @@ -2036,6 +2043,9 @@ void Application::init() { // save settings when avatar changes connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings); + + // make sure our texture cache knows about window size changes + DependencyManager::get()->associateWithWidget(getGLWidget()); } void Application::closeMirrorView() { @@ -2103,13 +2113,13 @@ void Application::updateMouseRay() { void Application::updateFaceshift() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateFaceshift()"); - + Faceshift* faceshift = DependencyManager::get(); // Update faceshift - _faceshift.update(); + faceshift->update(); // Copy angular velocity if measured by faceshift, to the head - if (_faceshift.isActive()) { - _myAvatar->getHead()->setAngularVelocity(_faceshift.getHeadAngularVelocity()); + if (faceshift->isActive()) { + _myAvatar->getHead()->setAngularVelocity(faceshift->getHeadAngularVelocity()); } } @@ -2118,7 +2128,7 @@ void Application::updateVisage() { PerformanceWarning warn(showWarnings, "Application::updateVisage()"); // Update Visage - _visage.update(); + DependencyManager::get()->update(); } void Application::updateDDE() { @@ -2126,7 +2136,7 @@ void Application::updateDDE() { PerformanceWarning warn(showWarnings, "Application::updateDDE()"); // Update Cara - _dde.update(); + DependencyManager::get()->update(); } void Application::updateMyAvatarLookAtPosition() { @@ -2766,7 +2776,7 @@ glm::vec3 Application::getSunDirection() { void Application::updateShadowMap() { PerformanceTimer perfTimer("shadowMap"); - QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject(); + QOpenGLFramebufferObject* fbo = DependencyManager::get()->getShadowFramebufferObject(); fbo->bind(); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -2931,7 +2941,7 @@ void Application::setupWorldLight() { } QImage Application::renderAvatarBillboard() { - _textureCache.getPrimaryFramebufferObject()->bind(); + DependencyManager::get()->getPrimaryFramebufferObject()->bind(); // the "glow" here causes an alpha of one Glower glower; @@ -2942,7 +2952,7 @@ QImage Application::renderAvatarBillboard() { QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); - _textureCache.getPrimaryFramebufferObject()->release(); + DependencyManager::get()->getPrimaryFramebufferObject()->release(); return image; } @@ -3072,7 +3082,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr // draw a red sphere float originSphereRadius = 0.05f; glColor3f(1,0,0); - _geometryCache.renderSphere(originSphereRadius, 15, 15); + DependencyManager::get()->renderSphere(originSphereRadius, 15, 15); // Draw voxels if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { @@ -3293,12 +3303,12 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { // set the bounds of rear mirror view if (billboard) { - QSize size = getTextureCache()->getFrameBufferSize(); + QSize size = DependencyManager::get()->getFrameBufferSize(); glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); } else { // if not rendering the billboard, the region is in device independent coordinates; must convert to device - QSize size = getTextureCache()->getFrameBufferSize(); + QSize size = DependencyManager::get()->getFrameBufferSize(); float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; glViewport(x, size.height() - y - height, width, height); @@ -3551,9 +3561,9 @@ void Application::deleteVoxelAt(const VoxelDetail& voxel) { } void Application::resetSensors() { - _faceshift.reset(); - _visage.reset(); - _dde.reset(); + DependencyManager::get()->reset(); + DependencyManager::get()->reset(); + DependencyManager::get()->reset(); OculusManager::reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index f82b14b47e..d4a681f060 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -34,9 +34,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -54,11 +54,8 @@ #include "avatar/Avatar.h" #include "avatar/AvatarManager.h" #include "avatar/MyAvatar.h" -#include "devices/Faceshift.h" #include "devices/PrioVR.h" #include "devices/SixenseManager.h" -#include "devices/Visage.h" -#include "devices/DdeFaceTracker.h" #include "entities/EntityTreeRenderer.h" #include "renderer/AmbientOcclusionEffect.h" #include "renderer/DeferredLightingEffect.h" @@ -100,6 +97,7 @@ class QMouseEvent; class QSettings; class QWheelEvent; +class FaceTracker; class Node; class ProgramObject; @@ -220,10 +218,7 @@ public: int getMouseDragStartedY() const; int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } int getTrueMouseDragStartedY() const { return _mouseDragStartedY; } - bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated;; } - Faceshift* getFaceshift() { return &_faceshift; } - Visage* getVisage() { return &_visage; } - DdeFaceTracker* getDDE() { return &_dde; } + bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; } FaceTracker* getActiveFaceTracker(); PrioVR* getPrioVR() { return &_prioVR; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } @@ -254,9 +249,7 @@ public: ToolWindow* getToolWindow() { return _toolWindow ; } - GeometryCache* getGeometryCache() { return &_geometryCache; } AnimationCache* getAnimationCache() { return &_animationCache; } - TextureCache* getTextureCache() { return &_textureCache; } DeferredLightingEffect* getDeferredLightingEffect() { return &_deferredLightingEffect; } GlowEffect* getGlowEffect() { return &_glowEffect; } ControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } @@ -532,10 +525,6 @@ private: AvatarManager _avatarManager; MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) - Faceshift _faceshift; - Visage _visage; - DdeFaceTracker _dde; - PrioVR _prioVR; Camera _myCamera; // My view onto the world @@ -578,9 +567,7 @@ private: QSet _keysPressed; - GeometryCache _geometryCache; AnimationCache _animationCache; - TextureCache _textureCache; DeferredLightingEffect _deferredLightingEffect; GlowEffect _glowEffect; diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 0ce43ecdaa..fa8f18ac3f 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -261,7 +261,7 @@ void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); - Application::getInstance()->getGeometryCache()->renderSphere(1.0f, 100, 50); //Draw a unit sphere + DependencyManager::get()->renderSphere(1.0f, 100, 50); //Draw a unit sphere glDepthMask(GL_TRUE); program->release(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 406b421938..9ef794db97 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -31,12 +31,16 @@ #include #include -#include +#include #include #include +#include #include "Application.h" #include "AccountManager.h" +#include "devices/Faceshift.h" +#include "devices/OculusManager.h" +#include "devices/Visage.h" #include "Menu.h" #include "scripting/LocationScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" @@ -433,12 +437,12 @@ Menu::Menu() : MenuOption::Faceshift, 0, true, - appInstance->getFaceshift(), + DependencyManager::get(), SLOT(setTCPEnabled(bool))); #endif #ifdef HAVE_VISAGE addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Visage, 0, false, - appInstance->getVisage(), SLOT(updateEnabled())); + DependencyManager::get(), SLOT(updateEnabled())); #endif addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 87060d7dfa..84ccf0f406 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -205,7 +205,7 @@ void MetavoxelSystem::render() { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); + DependencyManager::get()->setPrimaryDrawBuffers(true, true); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); @@ -251,7 +251,7 @@ void MetavoxelSystem::render() { glPopMatrix(); } - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false); _baseHeightfieldProgram.release(); @@ -348,7 +348,7 @@ void MetavoxelSystem::render() { } if (!_voxelBaseBatches.isEmpty()) { - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); + DependencyManager::get()->setPrimaryDrawBuffers(true, true); glEnableClientState(GL_VERTEX_ARRAY); glDisable(GL_BLEND); @@ -383,7 +383,7 @@ void MetavoxelSystem::render() { glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false); if (!_voxelSplatBatches.isEmpty()) { glDepthFunc(GL_LEQUAL); @@ -463,7 +463,7 @@ void MetavoxelSystem::render() { } if (!_hermiteBatches.isEmpty() && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) { - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); + DependencyManager::get()->setPrimaryDrawBuffers(true, true); glEnableClientState(GL_VERTEX_ARRAY); @@ -486,7 +486,7 @@ void MetavoxelSystem::render() { glDisableClientState(GL_VERTEX_ARRAY); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false); } _hermiteBatches.clear(); @@ -797,7 +797,7 @@ void MetavoxelSystem::applyMaterialEdit(const MetavoxelEditMessage& message, boo Q_ARG(bool, reliable)); return; } - QSharedPointer texture = Application::getInstance()->getTextureCache()->getTexture( + QSharedPointer texture = DependencyManager::get()->getTexture( material->getDiffuse(), SPLAT_TEXTURE); if (texture->isLoaded()) { MetavoxelEditMessage newMessage = message; @@ -1177,10 +1177,11 @@ void VoxelBuffer::render(bool cursor) { if (!_materials.isEmpty()) { _networkTextures.resize(_materials.size()); + TextureCache* textureCache = DependencyManager::get(); for (int i = 0; i < _materials.size(); i++) { const SharedObjectPointer material = _materials.at(i); if (material) { - _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture( + _networkTextures[i] = textureCache->getTexture( static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); } } @@ -2188,13 +2189,15 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g bufferPair.second.release(); } if (_heightTextureID == 0) { + // we use non-aligned data for the various layers + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glGenTextures(1, &_heightTextureID); glBindTexture(GL_TEXTURE_2D, _heightTextureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const QVector& heightContents = node->getHeight()->getContents(); glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, width, height, 0, GL_RED, GL_UNSIGNED_SHORT, heightContents.constData()); @@ -2229,10 +2232,11 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g const QVector& materials = node->getMaterial()->getMaterials(); _networkTextures.resize(materials.size()); + TextureCache* textureCache = DependencyManager::get(); for (int i = 0; i < materials.size(); i++) { const SharedObjectPointer& material = materials.at(i); if (material) { - _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture( + _networkTextures[i] = textureCache->getTexture( static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); } } @@ -2241,6 +2245,9 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &ZERO_VALUE); } glBindTexture(GL_TEXTURE_2D, 0); + + // restore the default alignment; it's what Qt uses for image storage + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); } if (cursor) { diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index d9e8ed0c40..6f582d60eb 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -466,17 +466,19 @@ void ModelUploader::processCheck() { _timer.stop(); switch (reply->error()) { - case QNetworkReply::NoError: + case QNetworkReply::NoError: { QMessageBox::information(NULL, QString("ModelUploader::processCheck()"), QString("Your model is now available in the browser."), QMessageBox::Ok); - Application::getInstance()->getGeometryCache()->refresh(_url); + DependencyManager::get()->refresh(_url); + TextureCache* textureCache = DependencyManager::get(); foreach (const QByteArray& filename, _textureFilenames) { - Application::getInstance()->getTextureCache()->refresh(_textureBase + filename); + textureCache->refresh(_textureBase + filename); } deleteLater(); break; + } case QNetworkReply::ContentNotFoundError: if (--_numberOfChecks) { _timer.start(TIMEOUT); diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index c4f2ec8468..6d40726f14 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -71,22 +71,23 @@ void renderWorldBox() { glPushMatrix(); glTranslatef(MARKER_DISTANCE, 0, 0); glColor3fv(red); - Application::getInstance()->getGeometryCache()->renderSphere(MARKER_RADIUS, 10, 10); + GeometryCache* geometryCache = DependencyManager::get(); + geometryCache->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glTranslatef(0, MARKER_DISTANCE, 0); glColor3fv(green); - Application::getInstance()->getGeometryCache()->renderSphere(MARKER_RADIUS, 10, 10); + geometryCache->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glTranslatef(0, 0, MARKER_DISTANCE); glColor3fv(blue); - Application::getInstance()->getGeometryCache()->renderSphere(MARKER_RADIUS, 10, 10); + geometryCache->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); glColor3fv(gray); glTranslatef(MARKER_DISTANCE, 0, MARKER_DISTANCE); - Application::getInstance()->getGeometryCache()->renderSphere(MARKER_RADIUS, 10, 10); + geometryCache->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c680c75056..49a6f436df 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -394,7 +394,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool } else { glTranslatef(_position.x, getDisplayNamePosition().y + LOOK_AT_INDICATOR_OFFSET, _position.z); } - Application::getInstance()->getGeometryCache()->renderSphere(LOOK_AT_INDICATOR_RADIUS, 15, 15); + DependencyManager::get()->renderSphere(LOOK_AT_INDICATOR_RADIUS, 15, 15); glPopMatrix(); } } @@ -422,7 +422,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool glPushMatrix(); glTranslatef(_position.x, _position.y, _position.z); glScalef(height, height, height); - Application::getInstance()->getGeometryCache()->renderSphere(sphereRadius, 15, 15); + DependencyManager::get()->renderSphere(sphereRadius, 15, 15); glPopMatrix(); } diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 148abc3546..9d1ee52fde 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -114,7 +114,7 @@ void Hand::render(bool isMine, Model::RenderMode renderMode) { glPushMatrix(); glTranslatef(position.x, position.y, position.z); glColor3f(0.0f, 1.0f, 0.0f); - Application::getInstance()->getGeometryCache()->renderSphere(PALM_COLLISION_RADIUS * _owningAvatar->getScale(), 10, 10); + DependencyManager::get()->renderSphere(PALM_COLLISION_RADIUS * _owningAvatar->getScale(), 10, 10); glPopMatrix(); } } @@ -179,7 +179,7 @@ void Hand::renderHandTargets(bool isMine) { Avatar::renderJointConnectingCone(root, offsetFromPalm, PALM_DISK_RADIUS, 0.0f); glPushMatrix(); glTranslatef(root.x, root.y, root.z); - Application::getInstance()->getGeometryCache()->renderSphere(PALM_BALL_RADIUS, 20.0f, 20.0f); + DependencyManager::get()->renderSphere(PALM_BALL_RADIUS, 20.0f, 20.0f); glPopMatrix(); } } diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 660ebfcbb3..42b3c968e1 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -10,6 +10,9 @@ #include +#include +#include +#include #include #include "Application.h" @@ -75,11 +78,13 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { // Only use face trackers when not playing back a recording. if (!myAvatar->isPlaying()) { FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); - if ((_isFaceshiftConnected = faceTracker)) { + DdeFaceTracker* dde = DependencyManager::get(); + Faceshift* faceshift = DependencyManager::get(); + + if ((_isFaceshiftConnected = (faceshift == faceTracker))) { _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); - _isFaceshiftConnected = true; - } else if (Application::getInstance()->getDDE()->isActive()) { - faceTracker = Application::getInstance()->getDDE(); + } else if (dde->isActive()) { + faceTracker = dde; _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); } } @@ -196,14 +201,14 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { _mouth2 = glm::mix(_audioJawOpen * MMMM_POWER, _mouth2, MMMM_PERIOD + randFloat() * MMMM_RANDOM_PERIOD); _mouth4 = glm::mix(_audioJawOpen, _mouth4, SMILE_PERIOD + randFloat() * SMILE_RANDOM_PERIOD); - Application::getInstance()->getFaceshift()->updateFakeCoefficients(_leftEyeBlink, - _rightEyeBlink, - _browAudioLift, - _audioJawOpen, - _mouth2, - _mouth3, - _mouth4, - _blendshapeCoefficients); + DependencyManager::get()->updateFakeCoefficients(_leftEyeBlink, + _rightEyeBlink, + _browAudioLift, + _audioJawOpen, + _mouth2, + _mouth3, + _mouth4, + _blendshapeCoefficients); } else { _saccade = glm::vec3(); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 32053ea076..057b1f1fc6 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -393,7 +394,7 @@ void MyAvatar::renderDebugBodyPoints() { glPushMatrix(); glColor4f(0, 1, 0, .5f); glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getGeometryCache()->renderSphere(0.2f, 10.0f, 10.0f); + DependencyManager::get()->renderSphere(0.2f, 10.0f, 10.0f); glPopMatrix(); // Head Sphere @@ -401,7 +402,7 @@ void MyAvatar::renderDebugBodyPoints() { glPushMatrix(); glColor4f(0, 1, 0, .5f); glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getGeometryCache()->renderSphere(0.15f, 10.0f, 10.0f); + DependencyManager::get()->renderSphere(0.15f, 10.0f, 10.0f); glPopMatrix(); } @@ -421,8 +422,7 @@ void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bo } void MyAvatar::renderHeadMouse(int screenWidth, int screenHeight) const { - - Faceshift* faceshift = Application::getInstance()->getFaceshift(); + Faceshift* faceshift = DependencyManager::get(); float pixelsPerDegree = screenHeight / Menu::getInstance()->getFieldOfView(); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 911ebb7412..42c74db143 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -554,6 +554,7 @@ void SkeletonModel::renderRagdoll() { float radius1 = 0.008f; float radius2 = 0.01f; glm::vec3 simulationTranslation = _ragdoll->getTranslationInSimulationFrame(); + GeometryCache* geometryCache = DependencyManager::get(); for (int i = 0; i < numPoints; ++i) { glPushMatrix(); // NOTE: ragdollPoints are in simulation-frame but we want them to be model-relative @@ -561,9 +562,9 @@ void SkeletonModel::renderRagdoll() { glTranslatef(position.x, position.y, position.z); // draw each point as a yellow hexagon with black border glColor4f(0.0f, 0.0f, 0.0f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); glColor4f(1.0f, 1.0f, 0.0f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(radius1, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(radius1, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); glPopMatrix(); } glPopMatrix(); @@ -913,7 +914,8 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { endPoint = endPoint - _translation; glTranslatef(endPoint.x, endPoint.y, endPoint.z); glColor4f(0.6f, 0.6f, 0.8f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + GeometryCache* geometryCache = DependencyManager::get(); + geometryCache->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a yellow sphere at the capsule startpoint glm::vec3 startPoint; @@ -922,7 +924,7 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { glm::vec3 axis = endPoint - startPoint; glTranslatef(-axis.x, -axis.y, -axis.z); glColor4f(0.8f, 0.8f, 0.6f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a green cylinder between the two points glm::vec3 origin(0.0f); @@ -948,6 +950,8 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { continue; } + GeometryCache* geometryCache = DependencyManager::get(); + glPushMatrix(); // shapes are stored in simulation-frame but we want position to be model-relative if (shape->getType() == SPHERE_SHAPE) { @@ -955,7 +959,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { glTranslatef(position.x, position.y, position.z); // draw a grey sphere at shape position glColor4f(0.75f, 0.75f, 0.75f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); } else if (shape->getType() == CAPSULE_SHAPE) { CapsuleShape* capsule = static_cast(shape); @@ -965,7 +969,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { endPoint = endPoint - simulationTranslation; glTranslatef(endPoint.x, endPoint.y, endPoint.z); glColor4f(0.6f, 0.6f, 0.8f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a yellow sphere at the capsule startpoint glm::vec3 startPoint; @@ -974,7 +978,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { glm::vec3 axis = endPoint - startPoint; glTranslatef(-axis.x, -axis.y, -axis.z); glColor4f(0.8f, 0.8f, 0.6f, alpha); - Application::getInstance()->getGeometryCache()->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); + geometryCache->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a green cylinder between the two points glm::vec3 origin(0.0f); diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 68d9e7d487..d80aa043e4 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -14,16 +14,14 @@ #include +#include + #include "FaceTracker.h" -class DdeFaceTracker : public FaceTracker { +class DdeFaceTracker : public FaceTracker, public DependencyManager::Dependency { Q_OBJECT public: - DdeFaceTracker(); - DdeFaceTracker(const QHostAddress& host, quint16 port); - ~DdeFaceTracker(); - //initialization void init(); void reset(); @@ -57,6 +55,11 @@ private slots: void socketStateChanged(QAbstractSocket::SocketState socketState); private: + DdeFaceTracker(); + DdeFaceTracker(const QHostAddress& host, quint16 port); + ~DdeFaceTracker(); + friend DependencyManager; + float getBlendshapeCoefficient(int index) const; void decodePacket(const QByteArray& buffer); diff --git a/interface/src/devices/FaceTracker.h b/interface/src/devices/FaceTracker.h index 459f38cafc..75954871e5 100644 --- a/interface/src/devices/FaceTracker.h +++ b/interface/src/devices/FaceTracker.h @@ -23,8 +23,8 @@ class FaceTracker : public QObject { Q_OBJECT public: - FaceTracker(); + virtual ~FaceTracker() {} const glm::vec3& getHeadTranslation() const { return _headTranslation; } const glm::quat& getHeadRotation() const { return _headRotation; } diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index fb74f416a9..5c1bbfe709 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -14,7 +14,6 @@ #include #include -#include "Application.h" #include "Faceshift.h" #include "Menu.h" #include "Util.h" diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 3b4092c099..3cca8f2bb1 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -19,15 +19,15 @@ #include #endif +#include + #include "FaceTracker.h" /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. -class Faceshift : public FaceTracker { +class Faceshift : public FaceTracker, public DependencyManager::Dependency { Q_OBJECT public: - Faceshift(); - void init(); bool isConnectedOrConnecting() const; @@ -87,6 +87,9 @@ private slots: void readFromSocket(); private: + Faceshift(); + virtual ~Faceshift() {} + friend DependencyManager; float getBlendshapeCoefficient(int index) const; diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index dfec98c358..d27ab09876 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -449,7 +449,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { Application::getInstance()->getGlowEffect()->prepare(); } else { - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); + DependencyManager::get()->getPrimaryFramebufferObject()->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } @@ -555,8 +555,8 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p QOpenGLFramebufferObject* fbo = Application::getInstance()->getGlowEffect()->render(true); glBindTexture(GL_TEXTURE_2D, fbo->texture()); } else { - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->release(); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->texture()); + DependencyManager::get()->getPrimaryFramebufferObject()->release(); + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimaryFramebufferObject()->texture()); } // restore our normal viewport diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 9c7416c219..51b927df75 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -11,12 +11,14 @@ #include + +#include +#include #include #include -#include - #include "Application.h" +#include "Faceshift.h" #include "Visage.h" // this has to go after our normal includes, because its definition of HANDLE conflicts with Qt's @@ -119,7 +121,7 @@ static const QMultiHash >& getActionUnitNameMap() const float TRANSLATION_SCALE = 20.0f; void Visage::init() { - connect(Application::getInstance()->getFaceshift(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); + connect(DependencyManager::get(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); updateEnabled(); } @@ -171,7 +173,7 @@ void Visage::reset() { void Visage::updateEnabled() { setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) && !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && - Application::getInstance()->getFaceshift()->isConnectedOrConnecting())); + DependencyManager::get()->isConnectedOrConnecting())); } void Visage::setEnabled(bool enabled) { diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 33e2f0a7e1..73edddc4d7 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -16,6 +16,8 @@ #include #include +#include + #include "FaceTracker.h" namespace VisageSDK { @@ -24,14 +26,10 @@ namespace VisageSDK { } /// Handles input from the Visage webcam feature tracking software. -class Visage : public FaceTracker { +class Visage : public FaceTracker, public DependencyManager::Dependency { Q_OBJECT public: - - Visage(); - virtual ~Visage(); - void init(); bool isActive() const { return _active; } @@ -44,6 +42,9 @@ public slots: void updateEnabled(); private: + Visage(); + virtual ~Visage(); + friend DependencyManager; #ifdef HAVE_VISAGE VisageSDK::VisageTracker2* _tracker; diff --git a/interface/src/renderer/AmbientOcclusionEffect.cpp b/interface/src/renderer/AmbientOcclusionEffect.cpp index f75ed7e8c3..3354f715cb 100644 --- a/interface/src/renderer/AmbientOcclusionEffect.cpp +++ b/interface/src/renderer/AmbientOcclusionEffect.cpp @@ -98,7 +98,7 @@ void AmbientOcclusionEffect::render() { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPrimaryDepthTextureID()); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, _rotationTextureID); @@ -116,7 +116,7 @@ void AmbientOcclusionEffect::render() { glGetIntegerv(GL_VIEWPORT, viewport); const int VIEWPORT_X_INDEX = 0; const int VIEWPORT_WIDTH_INDEX = 2; - QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* primaryFBO = DependencyManager::get()->getPrimaryFramebufferObject(); float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width(); float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width(); @@ -141,7 +141,7 @@ void AmbientOcclusionEffect::render() { glActiveTexture(GL_TEXTURE0); // now render secondary to primary with 4x4 blur - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); + DependencyManager::get()->getPrimaryFramebufferObject()->bind(); glEnable(GL_BLEND); glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE); diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index be4e457131..22ac5d82b6 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -37,7 +37,7 @@ void DeferredLightingEffect::init() { } void DeferredLightingEffect::bindSimpleProgram() { - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true, true); + DependencyManager::get()->setPrimaryDrawBuffers(true, true, true); _simpleProgram.bind(); _simpleProgram.setUniformValue(_glowIntensityLocation, Application::getInstance()->getGlowEffect()->getIntensity()); glDisable(GL_BLEND); @@ -46,12 +46,12 @@ void DeferredLightingEffect::bindSimpleProgram() { void DeferredLightingEffect::releaseSimpleProgram() { glEnable(GL_BLEND); _simpleProgram.release(); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false, false); } void DeferredLightingEffect::renderSolidSphere(float radius, int slices, int stacks) { bindSimpleProgram(); - Application::getInstance()->getGeometryCache()->renderSphere(radius, slices, stacks); + DependencyManager::get()->renderSphere(radius, slices, stacks); releaseSimpleProgram(); } @@ -75,7 +75,7 @@ void DeferredLightingEffect::renderWireCube(float size) { void DeferredLightingEffect::renderSolidCone(float base, float height, int slices, int stacks) { bindSimpleProgram(); - Application::getInstance()->getGeometryCache()->renderCone(base, height, slices, stacks); + DependencyManager::get()->renderCone(base, height, slices, stacks); releaseSimpleProgram(); } @@ -117,15 +117,16 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu void DeferredLightingEffect::prepare() { // clear the normal and specular buffers - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, false); + TextureCache* textureCache = DependencyManager::get(); + textureCache->setPrimaryDrawBuffers(false, true, false); glClear(GL_COLOR_BUFFER_BIT); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, false, true); + textureCache->setPrimaryDrawBuffers(false, false, true); // clearing to zero alpha for specular causes problems on my Nvidia card; clear to lowest non-zero value instead const float MAX_SPECULAR_EXPONENT = 128.0f; glClearColor(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT); glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false, false); + textureCache->setPrimaryDrawBuffers(true, false, false); } void DeferredLightingEffect::render() { @@ -137,8 +138,10 @@ void DeferredLightingEffect::render() { glDisable(GL_DEPTH_TEST); glDisable(GL_COLOR_MATERIAL); glDepthMask(false); + + TextureCache* textureCache = DependencyManager::get(); - QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); + QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); primaryFBO->release(); QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject(); @@ -148,13 +151,13 @@ void DeferredLightingEffect::render() { glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryNormalTextureID()); + glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryNormalTextureID()); glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimarySpecularTextureID()); + glBindTexture(GL_TEXTURE_2D, textureCache->getPrimarySpecularTextureID()); glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryDepthTextureID()); // get the viewport side (left, right, both) int viewport[4]; @@ -173,7 +176,7 @@ void DeferredLightingEffect::render() { bool shadowsEnabled = Menu::getInstance()->getShadowsEnabled(); if (shadowsEnabled) { glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, textureCache->getShadowDepthTextureID()); program = &_directionalLightShadowMap; locations = &_directionalLightShadowMapLocations; @@ -188,7 +191,7 @@ void DeferredLightingEffect::render() { program->bind(); } program->setUniformValue(locations->shadowScale, - 1.0f / Application::getInstance()->getTextureCache()->getShadowFramebufferObject()->width()); + 1.0f / textureCache->getShadowFramebufferObject()->width()); } else { program->bind(); @@ -234,6 +237,8 @@ void DeferredLightingEffect::render() { const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft()); + + GeometryCache* geometryCache = DependencyManager::get(); if (!_pointLights.isEmpty()) { _pointLight.bind(); @@ -241,7 +246,7 @@ void DeferredLightingEffect::render() { _pointLight.setUniformValue(_pointLightLocations.depthScale, depthScale); _pointLight.setUniformValue(_pointLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); _pointLight.setUniformValue(_pointLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); - + foreach (const PointLight& light, _pointLights) { _pointLight.setUniformValue(_pointLightLocations.radius, light.radius); glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient); @@ -270,7 +275,7 @@ void DeferredLightingEffect::render() { } else { glTranslatef(light.position.x, light.position.y, light.position.z); - Application::getInstance()->getGeometryCache()->renderSphere(expandedRadius, 32, 32); + geometryCache->renderSphere(expandedRadius, 32, 32); } glPopMatrix(); @@ -323,7 +328,7 @@ void DeferredLightingEffect::render() { glm::vec3 axis = glm::axis(spotRotation); glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f)); - Application::getInstance()->getGeometryCache()->renderCone(expandedRadius * glm::tan(light.cutoff), + geometryCache->renderCone(expandedRadius * glm::tan(light.cutoff), expandedRadius, 32, 1); } diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index d753901243..974a542b0e 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -9,19 +9,21 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// include this before QOpenGLBuffer, which includes an earlier version of OpenGL +#include + #include #include #include #include -#include "Application.h" -#include "GeometryCache.h" -#include "Model.h" -#include "world.h" +#include -GeometryCache::GeometryCache() : - _pendingBlenders(0) { +#include "GeometryCache.h" +#include "TextureCache.h" + +GeometryCache::GeometryCache() { } GeometryCache::~GeometryCache() { @@ -505,33 +507,6 @@ QSharedPointer GeometryCache::getGeometry(const QUrl& url, cons return getResource(url, fallback, delayLoad).staticCast(); } -void GeometryCache::noteRequiresBlend(Model* model) { - if (_pendingBlenders < QThread::idealThreadCount()) { - if (model->maybeStartBlender()) { - _pendingBlenders++; - } - return; - } - if (!_modelsRequiringBlends.contains(model)) { - _modelsRequiringBlends.append(model); - } -} - -void GeometryCache::setBlendedVertices(const QPointer& model, int blendNumber, - const QWeakPointer& geometry, const QVector& vertices, const QVector& normals) { - if (!model.isNull()) { - model->setBlendedVertices(blendNumber, geometry, vertices, normals); - } - _pendingBlenders--; - while (!_modelsRequiringBlends.isEmpty()) { - Model* nextModel = _modelsRequiringBlends.takeFirst(); - if (nextModel && nextModel->maybeStartBlender()) { - _pendingBlenders++; - return; - } - } -} - QSharedPointer GeometryCache::createResource(const QUrl& url, const QSharedPointer& fallback, bool delayLoad, const void* extra) { QSharedPointer geometry(new NetworkGeometry(url, fallback.staticCast(), delayLoad), @@ -724,6 +699,7 @@ void NetworkGeometry::clearLoadPriority(const QPointer& owner) { void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& url) { if (_meshes.size() > 0) { + TextureCache* textureCache = DependencyManager::get(); for (int i = 0; i < _meshes.size(); i++) { NetworkMesh& mesh = _meshes[i]; for (int j = 0; j < mesh.parts.size(); j++) { @@ -732,19 +708,19 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u QSharedPointer matchingTexture = QSharedPointer(); if (part.diffuseTextureName == name) { part.diffuseTexture = - Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + textureCache->getTexture(url, DEFAULT_TEXTURE, _geometry.meshes[i].isEye, QByteArray()); part.diffuseTexture->setLoadPriorities(_loadPriorities); } else if (part.normalTextureName == name) { - part.normalTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + part.normalTexture = textureCache->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.normalTexture->setLoadPriorities(_loadPriorities); } else if (part.specularTextureName == name) { - part.specularTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + part.specularTexture = textureCache->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.specularTexture->setLoadPriorities(_loadPriorities); } else if (part.emissiveTextureName == name) { - part.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + part.emissiveTexture = textureCache->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.emissiveTexture->setLoadPriorities(_loadPriorities); } @@ -937,6 +913,8 @@ void NetworkGeometry::reinsert() { void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { _geometry = geometry; + + TextureCache* textureCache = DependencyManager::get(); foreach (const FBXMesh& mesh, _geometry.meshes) { NetworkMesh networkMesh; @@ -945,28 +923,28 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { foreach (const FBXMeshPart& part, mesh.parts) { NetworkMeshPart networkPart; if (!part.diffuseTexture.filename.isEmpty()) { - networkPart.diffuseTexture = Application::getInstance()->getTextureCache()->getTexture( + networkPart.diffuseTexture = textureCache->getTexture( _textureBase.resolved(QUrl(part.diffuseTexture.filename)), DEFAULT_TEXTURE, mesh.isEye, part.diffuseTexture.content); networkPart.diffuseTextureName = part.diffuseTexture.name; networkPart.diffuseTexture->setLoadPriorities(_loadPriorities); } if (!part.normalTexture.filename.isEmpty()) { - networkPart.normalTexture = Application::getInstance()->getTextureCache()->getTexture( + networkPart.normalTexture = textureCache->getTexture( _textureBase.resolved(QUrl(part.normalTexture.filename)), NORMAL_TEXTURE, false, part.normalTexture.content); networkPart.normalTextureName = part.normalTexture.name; networkPart.normalTexture->setLoadPriorities(_loadPriorities); } if (!part.specularTexture.filename.isEmpty()) { - networkPart.specularTexture = Application::getInstance()->getTextureCache()->getTexture( + networkPart.specularTexture = textureCache->getTexture( _textureBase.resolved(QUrl(part.specularTexture.filename)), SPECULAR_TEXTURE, false, part.specularTexture.content); networkPart.specularTextureName = part.specularTexture.name; networkPart.specularTexture->setLoadPriorities(_loadPriorities); } if (!part.emissiveTexture.filename.isEmpty()) { - networkPart.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture( + networkPart.emissiveTexture = textureCache->getTexture( _textureBase.resolved(QUrl(part.emissiveTexture.filename)), EMISSIVE_TEXTURE, false, part.emissiveTexture.content); networkPart.emissiveTextureName = part.emissiveTexture.name; diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 6faad93fe4..2d813ece09 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -26,20 +27,15 @@ #include "gpu/Stream.h" -class Model; class NetworkGeometry; class NetworkMesh; class NetworkTexture; /// Stores cached geometry. -class GeometryCache : public ResourceCache { +class GeometryCache : public ResourceCache, public DependencyManager::Dependency { Q_OBJECT public: - - GeometryCache(); - virtual ~GeometryCache(); - void renderHemisphere(int slices, int stacks); void renderSphere(float radius, int slices, int stacks); void renderSquare(int xDivisions, int yDivisions); @@ -52,20 +48,15 @@ public: /// \param delayLoad if true, don't load the geometry immediately; wait until load is first requested QSharedPointer getGeometry(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false); - /// Adds the specified model to the list requiring vertex blends. - void noteRequiresBlend(Model* model); - -public slots: - - void setBlendedVertices(const QPointer& model, int blendNumber, const QWeakPointer& geometry, - const QVector& vertices, const QVector& normals); - protected: virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, bool delayLoad, const void* extra); private: + GeometryCache(); + virtual ~GeometryCache(); + friend class DependencyManager; typedef QPair IntPair; typedef QPair VerticesIndices; @@ -78,9 +69,6 @@ private: QHash _gridBuffers; QHash > _networkGeometry; - - QList > _modelsRequiringBlends; - int _pendingBlenders; }; /// Geometry loaded from the network. diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index 9e9c1f2ed5..b6896eeaad 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -41,8 +41,8 @@ GlowEffect::~GlowEffect() { QOpenGLFramebufferObject* GlowEffect::getFreeFramebufferObject() const { return (_isOddFrame ? - Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject(): - Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject()); + DependencyManager::get()->getSecondaryFramebufferObject(): + DependencyManager::get()->getTertiaryFramebufferObject()); } static ProgramObject* createProgram(const QString& name) { @@ -88,7 +88,7 @@ void GlowEffect::init() { } void GlowEffect::prepare() { - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); + DependencyManager::get()->getPrimaryFramebufferObject()->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); _isEmpty = true; @@ -122,7 +122,8 @@ static void maybeRelease(QOpenGLFramebufferObject* fbo) { QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { PerformanceTimer perfTimer("glowEffect"); - QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); + TextureCache* textureCache = DependencyManager::get(); + QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); primaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); @@ -138,7 +139,7 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { glDepthMask(GL_FALSE); QOpenGLFramebufferObject* destFBO = toTexture ? - Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject() : NULL; + textureCache->getSecondaryFramebufferObject() : NULL; if (!Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect) || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { @@ -160,9 +161,9 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { } else { // diffuse into the secondary/tertiary (alternating between frames) QOpenGLFramebufferObject* oldDiffusedFBO = - Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject(); + textureCache->getSecondaryFramebufferObject(); QOpenGLFramebufferObject* newDiffusedFBO = - Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject(); + textureCache->getTertiaryFramebufferObject(); if (_isOddFrame) { qSwap(oldDiffusedFBO, newDiffusedFBO); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index fd54f67377..2a6988a984 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -749,7 +749,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { } - /*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers( + /*DependencyManager::get()->setPrimaryDrawBuffers( mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, mode == DEFAULT_RENDER_MODE); @@ -789,7 +789,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); // render translucent meshes afterwards - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); + //DependencyManager::get()->setPrimaryDrawBuffers(false, true, true); { GLenum buffers[2]; int bufferCount = 0; @@ -814,7 +814,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glDepthMask)(false); GLBATCH(glDepthFunc)(GL_LEQUAL); - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); + //DependencyManager::get()->setPrimaryDrawBuffers(true); { GLenum buffers[1]; int bufferCount = 0; @@ -997,7 +997,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo _url = url; // if so instructed, keep the current geometry until the new one is loaded - _nextBaseGeometry = _nextGeometry = Application::getInstance()->getGeometryCache()->getGeometry(url, fallback, delayLoad); + _nextBaseGeometry = _nextGeometry = DependencyManager::get()->getGeometry(url, fallback, delayLoad); _nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS; if (!retainCurrent || !isActive() || _nextGeometry->isLoaded()) { applyNextGeometry(); @@ -1149,7 +1149,7 @@ void Blender::run() { } } // post the result to the geometry cache, which will dispatch to the model if still alive - QMetaObject::invokeMethod(Application::getInstance()->getGeometryCache(), "setBlendedVertices", + QMetaObject::invokeMethod(DependencyManager::get(), "setBlendedVertices", Q_ARG(const QPointer&, _model), Q_ARG(int, _blendNumber), Q_ARG(const QWeakPointer&, _geometry), Q_ARG(const QVector&, vertices), Q_ARG(const QVector&, normals)); @@ -1312,7 +1312,7 @@ void Model::simulateInternal(float deltaTime) { // post the blender if we're not currently waiting for one to finish if (geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { _blendedBlendshapeCoefficients = _blendshapeCoefficients; - Application::getInstance()->getGeometryCache()->noteRequiresBlend(this); + DependencyManager::get()->noteRequiresBlend(this); } } @@ -1705,7 +1705,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { } - /*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers( + /*DependencyManager::get()->setPrimaryDrawBuffers( mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, mode == DEFAULT_RENDER_MODE); @@ -1745,7 +1745,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); // render translucent meshes afterwards - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); + //DependencyManager::get()->setPrimaryDrawBuffers(false, true, true); { GLenum buffers[2]; int bufferCount = 0; @@ -1770,7 +1770,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { GLBATCH(glDepthMask)(false); GLBATCH(glDepthFunc)(GL_LEQUAL); - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); + //DependencyManager::get()->setPrimaryDrawBuffers(true); { GLenum buffers[1]; int bufferCount = 0; @@ -2324,7 +2324,8 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); bool dontReduceMaterialSwitches = Menu::getInstance()->isOptionChecked(MenuOption::DontReduceMaterialSwitches); - + + TextureCache* textureCache = DependencyManager::get(); QString lastMaterialID; int meshPartsRendered = 0; updateVisibleJointStates(); @@ -2446,7 +2447,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (showDiffuse && diffuseMap) { GLBATCH(glBindTexture)(GL_TEXTURE_2D, diffuseMap->getID()); } else { - GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID()); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, textureCache->getWhiteTextureID()); } if (locations->texcoordMatrices >= 0) { @@ -2464,7 +2465,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !normalMap ? - Application::getInstance()->getTextureCache()->getBlueTextureID() : normalMap->getID()); + textureCache->getBlueTextureID() : normalMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2472,7 +2473,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); Texture* specularMap = networkPart.specularTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? - Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); + textureCache->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2493,7 +2494,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? - Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); + textureCache->getWhiteTextureID() : emissiveMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2544,3 +2545,38 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod return meshPartsRendered; } + +ModelBlender::ModelBlender() : + _pendingBlenders(0) { +} + +ModelBlender::~ModelBlender() { +} + +void ModelBlender::noteRequiresBlend(Model* model) { + if (_pendingBlenders < QThread::idealThreadCount()) { + if (model->maybeStartBlender()) { + _pendingBlenders++; + } + return; + } + if (!_modelsRequiringBlends.contains(model)) { + _modelsRequiringBlends.append(model); + } +} + +void ModelBlender::setBlendedVertices(const QPointer& model, int blendNumber, + const QWeakPointer& geometry, const QVector& vertices, const QVector& normals) { + if (!model.isNull()) { + model->setBlendedVertices(blendNumber, geometry, vertices, normals); + } + _pendingBlenders--; + while (!_modelsRequiringBlends.isEmpty()) { + Model* nextModel = _modelsRequiringBlends.takeFirst(); + if (nextModel && nextModel->maybeStartBlender()) { + _pendingBlenders++; + return; + } + } +} + diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index e875c8f06c..9b609de1d0 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -19,6 +19,7 @@ #include "Transform.h" #include #include +#include #include #include @@ -453,12 +454,33 @@ private: static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); - }; Q_DECLARE_METATYPE(QPointer) Q_DECLARE_METATYPE(QWeakPointer) Q_DECLARE_METATYPE(QVector) +/// Handle management of pending models that need blending +class ModelBlender : public QObject, public DependencyManager::Dependency { + Q_OBJECT + +public: + + /// Adds the specified model to the list requiring vertex blends. + void noteRequiresBlend(Model* model); + +public slots: + void setBlendedVertices(const QPointer& model, int blendNumber, const QWeakPointer& geometry, + const QVector& vertices, const QVector& normals); + +private: + ModelBlender(); + virtual ~ModelBlender(); + friend class DependencyManager; + + QList > _modelsRequiringBlends; + int _pendingBlenders; +}; + #endif // hifi_Model_h diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index f40f0e3faf..123a8a5384 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -12,16 +12,17 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" +#include #include #include #include +#include #include #include #include #include -#include "Application.h" #include "TextureCache.h" TextureCache::TextureCache() : @@ -35,7 +36,8 @@ TextureCache::TextureCache() : _secondaryFramebufferObject(NULL), _tertiaryFramebufferObject(NULL), _shadowFramebufferObject(NULL), - _frameBufferSize(100, 100) + _frameBufferSize(100, 100), + _associatedWidget(NULL) { } @@ -350,9 +352,16 @@ QSharedPointer TextureCache::createResource(const QUrl& url, &Resource::allReferencesCleared); } +void TextureCache::associateWithWidget(QGLWidget* widget) { + if (_associatedWidget) { + _associatedWidget->removeEventFilter(this); + } + _associatedWidget = widget; + _associatedWidget->installEventFilter(this); +} + QOpenGLFramebufferObject* TextureCache::createFramebufferObject() { QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(_frameBufferSize); - Application::getInstance()->getGLWidget()->installEventFilter(this); glBindTexture(GL_TEXTURE_2D, fbo->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index 66734da9cd..2bdfda3217 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -14,7 +14,9 @@ #include #include +#include +#include #include #include "InterfaceConfig.h" @@ -28,13 +30,12 @@ typedef QSharedPointer NetworkTexturePointer; enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, SPLAT_TEXTURE }; /// Stores cached textures, including render-to-texture targets. -class TextureCache : public ResourceCache { +class TextureCache : public ResourceCache, public DependencyManager::Dependency { Q_OBJECT public: - - TextureCache(); - virtual ~TextureCache(); + + void associateWithWidget(QGLWidget* widget); /// Sets the desired texture resolution for the framebuffer objects. void setFrameBufferSize(QSize frameBufferSize); @@ -93,7 +94,9 @@ protected: const QSharedPointer& fallback, bool delayLoad, const void* extra); private: - + TextureCache(); + virtual ~TextureCache(); + friend class DependencyManager; friend class DilatableNetworkTexture; QOpenGLFramebufferObject* createFramebufferObject(); @@ -115,6 +118,7 @@ private: GLuint _shadowDepthTextureID; QSize _frameBufferSize; + QGLWidget* _associatedWidget; }; /// A simple object wrapper for an OpenGL texture. diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 97c4c08b41..158532e19a 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -353,7 +353,7 @@ void MetavoxelEditor::render() { _gridProgram.bind(); - Application::getInstance()->getGeometryCache()->renderGrid(GRID_DIVISIONS, GRID_DIVISIONS); + DependencyManager::get()->renderGrid(GRID_DIVISIONS, GRID_DIVISIONS); _gridProgram.release(); @@ -916,7 +916,7 @@ void MaterialControl::updateTexture() { _texture.clear(); return; } - _texture = Application::getInstance()->getTextureCache()->getTexture(material->getDiffuse(), SPLAT_TEXTURE); + _texture = DependencyManager::get()->getTexture(material->getDiffuse(), SPLAT_TEXTURE); if (_texture) { if (_texture->isLoaded()) { textureLoaded(); diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index 03daef934d..c095a544b7 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -16,7 +16,7 @@ #include #include "Base3DOverlay.h" -#include "../../renderer/TextureCache.h" +#include "renderer/TextureCache.h" class BillboardOverlay : public Base3DOverlay { Q_OBJECT diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index 4bf0d9ce93..d1086ae534 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -87,7 +87,7 @@ void Grid3DOverlay::render(RenderArgs* args) { float scale = MINOR_GRID_DIVISIONS * spacing; glScalef(scale, scale, scale); - Application::getInstance()->getGeometryCache()->renderGrid(MINOR_GRID_DIVISIONS, MINOR_GRID_DIVISIONS); + DependencyManager::get()->renderGrid(MINOR_GRID_DIVISIONS, MINOR_GRID_DIVISIONS); } glPopMatrix(); @@ -102,7 +102,7 @@ void Grid3DOverlay::render(RenderArgs* args) { float scale = MAJOR_GRID_DIVISIONS * spacing; glScalef(scale, scale, scale); - Application::getInstance()->getGeometryCache()->renderGrid(MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS); + DependencyManager::get()->renderGrid(MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS); } glPopMatrix(); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 34064675e5..ded1b3917c 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -63,7 +63,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { glScalef(dimensions.x, dimensions.y, dimensions.z); //Application::getInstance()->getDeferredLightingEffect()->renderSolidCube(1.0f); if (_isSolid) { - Application::getInstance()->getGeometryCache()->renderSphere(1.0f, SLICES, SLICES); + DependencyManager::get()->renderSphere(1.0f, SLICES, SLICES); } else { glutWireSphere(1.0f, SLICES, SLICES); } diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 2f4fd3f0fa..357bfe9c3e 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -9,7 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - #include #include #include // to load voxels from file @@ -874,7 +873,6 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo if (node->getShouldRender()) { glm::vec3 startVertex = node->getCorner(); float voxelScale = node->getScale(); - nodeColor const & color = node->getColor(); glBufferIndex nodeIndex = GLBUFFER_INDEX_UNKNOWN; if (reuseIndex && node->isKnownBufferIndex()) { @@ -1172,7 +1170,7 @@ void VoxelSystem::render() { void VoxelSystem::applyScaleAndBindProgram(bool texture) { if (texture) { bindPerlinModulateProgram(); - glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID()); + glBindTexture(GL_TEXTURE_2D, DependencyManager::get()->getPermutationNormalTextureID()); } else { _program.bind(); } @@ -1180,7 +1178,7 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { glPushMatrix(); glScalef(_treeScale, _treeScale, _treeScale); - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); + DependencyManager::get()->setPrimaryDrawBuffers(true, true); } void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { @@ -1194,7 +1192,7 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { _program.release(); } - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); + DependencyManager::get()->setPrimaryDrawBuffers(true, false); } int VoxelSystem::_nodeCount = 0; diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp new file mode 100644 index 0000000000..c858cb7059 --- /dev/null +++ b/libraries/shared/src/DependencyManager.cpp @@ -0,0 +1,24 @@ +// +// DependencyManager.cpp +// +// +// Created by Clément Brisset on 12/10/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "DependencyManager.h" + +DependencyManager& DependencyManager::getInstance() { + static DependencyManager instance; + return instance; +} + +DependencyManager::~DependencyManager() { + foreach (Dependency* instance, _instanceHash) { + delete instance; + } + _instanceHash.clear(); +} \ No newline at end of file diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h new file mode 100644 index 0000000000..87c7c7b4a6 --- /dev/null +++ b/libraries/shared/src/DependencyManager.h @@ -0,0 +1,66 @@ +// +// DependencyManager.h +// +// +// Created by Clément Brisset on 12/10/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_DependencyManager_h +#define hifi_DependencyManager_h + +#include +#include + +#include +#include + +class DependencyManager { +public: + // Only accessible method. + // usage: T* instance = DependencyManager::get(); + template + static T* get(); + + // Any class T in the DependencyManager needs to subclass Dependency + // They also need to have protected constructor(s) and virtual destructor + // As well as declare DependencyManager a friend class + class Dependency { + protected: + Dependency() {} + virtual ~Dependency() {} // Ensure the proper destruction of the object + friend DependencyManager; + }; + +private: + static DependencyManager& getInstance(); + DependencyManager() {} + ~DependencyManager(); + + typedef QHash InstanceHash; + static InstanceHash& getInstanceHash() { return getInstance()._instanceHash; } + InstanceHash _instanceHash; +}; + +template +T* DependencyManager::get() { + const QString& typeId = typeid(T).name(); + + // Search the hash for global instance + Dependency* instance = getInstanceHash().value(typeId, NULL); + if (instance) { + return dynamic_cast(instance); + } + + // Found no instance in hash so we create one. + T* newInstance = new T(); + instance = dynamic_cast(newInstance); + assert(instance != NULL); // If this triggers, check that T is derived from Dependency + getInstanceHash().insert(typeId, instance); + return newInstance; +} + +#endif // hifi_DependencyManager_h