diff --git a/examples/dialTone.js b/examples/dialTone.js index 0748d0ba94..135acb17f4 100644 --- a/examples/dialTone.js +++ b/examples/dialTone.js @@ -14,10 +14,10 @@ var connectSound = SoundCache.getSound("file://" + Paths.resources + "sounds/sho // setup the options needed for that sound var connectSoundOptions = { - localOnly: true + localOnly: true } // play the sound locally once we get the first audio packet from a mixer Audio.receivedFirstPacket.connect(function(){ - Audio.playSound(connectSound, connectSoundOptions); + Audio.playSound(connectSound, connectSoundOptions); }); diff --git a/examples/paint.js b/examples/paint.js index 6e4438d2ea..8bba4e2571 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // Script.include('lineRider.js') -var MAX_POINTS_PER_LINE = 30; +var MAX_POINTS_PER_LINE = 80; var colorPalette = [{ diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d2749c9a1d..1763623fa6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -336,7 +336,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _enableProcessOctreeThread(true), _octreeProcessor(), _nodeBoundsDisplay(this), - _applicationOverlay(), _runningScriptsWidget(NULL), _runningScriptsWidgetWasVisible(false), _trayIcon(new QSystemTrayIcon(_window)), @@ -347,7 +346,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _notifiedPacketVersionMismatchThisDomain(false), _domainConnectionRefusals(QList()), _maxOctreePPS(maxOctreePacketsPerSecond.get()), - _lastFaceTrackerUpdate(0) + _lastFaceTrackerUpdate(0), + _applicationOverlay() { setInstance(this); #ifdef Q_OS_WIN diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 8708a2b2b0..02af30b426 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -304,6 +304,7 @@ bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_renderItemID); _skeletonModel.removeFromScene(scene, pendingChanges); + getHead()->getFaceModel().removeFromScene(scene, pendingChanges); } void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting) { diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 49a8012cd9..f16173b79e 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -55,7 +55,7 @@ AvatarManager::AvatarManager(QObject* parent) : _avatarFades() { // register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar qRegisterMetaType >("NodeWeakPointer"); - _myAvatar = std::shared_ptr(new MyAvatar()); + _myAvatar = std::make_shared(); } void AvatarManager::init() { @@ -97,9 +97,9 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { // simulate avatars AvatarHash::iterator avatarIterator = _avatarHash.begin(); while (avatarIterator != _avatarHash.end()) { - Avatar* avatar = reinterpret_cast(avatarIterator.value().get()); + auto avatar = std::dynamic_pointer_cast(avatarIterator.value()); - if (avatar == _myAvatar.get() || !avatar->isInitialized()) { + if (avatar == _myAvatar || !avatar->isInitialized()) { // DO NOT update _myAvatar! Its update has already been done earlier in the main loop. // DO NOT update or fade out uninitialized Avatars ++avatarIterator; @@ -121,26 +121,30 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { const float SHRINK_RATE = 0.9f; const float MIN_FADE_SCALE = 0.001f; - + + render::ScenePointer scene = Application::getInstance()->getMain3DScene(); + render::PendingChanges pendingChanges; while (fadingIterator != _avatarFades.end()) { - Avatar* avatar = static_cast(fadingIterator->get()); + auto avatar = std::static_pointer_cast(*fadingIterator); avatar->setTargetScale(avatar->getScale() * SHRINK_RATE, true); if (avatar->getTargetScale() < MIN_FADE_SCALE) { + avatar->removeFromScene(*fadingIterator, scene, pendingChanges); fadingIterator = _avatarFades.erase(fadingIterator); } else { avatar->simulate(deltaTime); ++fadingIterator; } } + scene->enqueuePendingChanges(pendingChanges); } AvatarSharedPointer AvatarManager::newSharedAvatar() { - return AvatarSharedPointer(new Avatar()); + return AvatarSharedPointer(std::make_shared()); } // virtual AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer) { - std::shared_ptr avatar = std::dynamic_pointer_cast(AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer)); + auto avatar = std::dynamic_pointer_cast(AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer)); render::ScenePointer scene = Application::getInstance()->getMain3DScene(); render::PendingChanges pendingChanges; avatar->addToScene(avatar, scene, pendingChanges); @@ -171,10 +175,6 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) { _avatarFades.push_back(avatarIterator.value()); _avatarHash.erase(avatarIterator); } - render::ScenePointer scene = Application::getInstance()->getMain3DScene(); - render::PendingChanges pendingChanges; - avatar->removeFromScene(avatar, scene, pendingChanges); - scene->enqueuePendingChanges(pendingChanges); } } @@ -182,12 +182,12 @@ void AvatarManager::clearOtherAvatars() { // clear any avatars that came from an avatar-mixer AvatarHash::iterator avatarIterator = _avatarHash.begin(); while (avatarIterator != _avatarHash.end()) { - Avatar* avatar = reinterpret_cast(avatarIterator.value().get()); - if (avatar == _myAvatar.get() || !avatar->isInitialized()) { + auto avatar = std::static_pointer_cast(avatarIterator.value()); + if (avatar == _myAvatar || !avatar->isInitialized()) { // don't remove myAvatar or uninitialized avatars from the list ++avatarIterator; } else { - removeAvatarMotionState(avatar); + removeAvatarMotionState(avatar.get()); _avatarFades.push_back(avatarIterator.value()); avatarIterator = _avatarHash.erase(avatarIterator); } @@ -250,7 +250,7 @@ void AvatarManager::handleCollisionEvents(CollisionEvents& collisionEvents) { void AvatarManager::updateAvatarPhysicsShape(const QUuid& id) { AvatarHash::iterator avatarItr = _avatarHash.find(id); if (avatarItr != _avatarHash.end()) { - Avatar* avatar = static_cast(avatarItr.value().get()); + auto avatar = std::static_pointer_cast(avatarItr.value()); AvatarMotionState* motionState = avatar->_motionState; if (motionState) { motionState->addDirtyFlags(EntityItem::DIRTY_SHAPE); @@ -259,7 +259,7 @@ void AvatarManager::updateAvatarPhysicsShape(const QUuid& id) { avatar->computeShapeInfo(shapeInfo); btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); if (shape) { - AvatarMotionState* motionState = new AvatarMotionState(avatar, shape); + AvatarMotionState* motionState = new AvatarMotionState(avatar.get(), shape); avatar->_motionState = motionState; _motionStatesToAdd.insert(motionState); _avatarMotionStates.insert(motionState); diff --git a/interface/src/devices/MotionTracker.h b/interface/src/devices/MotionTracker.h index 5dd3f1ca3f..edfd3ae991 100644 --- a/interface/src/devices/MotionTracker.h +++ b/interface/src/devices/MotionTracker.h @@ -14,7 +14,18 @@ #include "DeviceTracker.h" +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-compare" +#endif + #include + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + #include #include diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f0b360b685..bc8047fc98 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -267,9 +267,8 @@ void ApplicationOverlay::displayOverlayTexture() { glLoadIdentity(); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); - if (_alpha < 1.0) { - glEnable(GL_BLEND); - } + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glViewport(0, 0, qApp->getDeviceSize().width(), qApp->getDeviceSize().height()); static const glm::vec2 topLeft(-1, 1); @@ -300,12 +299,14 @@ void ApplicationOverlay::displayOverlayTexture() { mousePosition.y *= -1.0f; glEnable(GL_TEXTURE_2D); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f }; DependencyManager::get()->renderQuad( mouseTopLeft + mousePosition, mouseBottomRight + mousePosition, texCoordTopLeft, texCoordBottomRight, reticleColor); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glDisable(GL_TEXTURE_2D); } glPopMatrix(); } @@ -455,6 +456,9 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float } //draw the mouse pointer + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); glm::vec2 canvasSize = qApp->getCanvasSize(); const float reticleSize = 40.0f / canvasSize.x * quadWidth; @@ -584,7 +588,9 @@ void ApplicationOverlay::renderPointers() { _crosshairTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); } glEnable(GL_TEXTURE_2D); - + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); @@ -746,8 +752,14 @@ void ApplicationOverlay::renderControllerPointers() { } void ApplicationOverlay::renderPointersOculus() { + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); glDisable(GL_DEPTH_TEST); + glMatrixMode(GL_MODELVIEW); //Controller Pointers @@ -772,6 +784,8 @@ void ApplicationOverlay::renderPointersOculus() { } glEnable(GL_DEPTH_TEST); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); } //Renders a small magnification of the currently bound texture at the coordinates diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 74aaf615c0..e0bc493a5c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -232,7 +232,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { remapTextures(); { - float alpha = getLocalRenderAlpha(); + // float alpha = getLocalRenderAlpha(); if (!_model || _needsModelReload) { // TODO: this getModel() appears to be about 3% of model render time. We should optimize diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 41c2799d97..bb5932d70c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -213,7 +213,7 @@ uint8_t RenderablePolyVoxEntityItem::getVoxel(int x, int y, int z) { // if _voxelSurfaceStyle is SURFACE_EDGED_CUBIC, we maintain an extra layer of // voxels all around the requested voxel space. Having the empty voxels around // the edges changes how the surface extractor behaves. - + if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC) { return _volData->getVoxelAt(x + 1, y + 1, z + 1); } @@ -239,7 +239,7 @@ void RenderablePolyVoxEntityItem::updateOnCount(int x, int y, int z, uint8_t toV if (!inUserBounds(_volData, _voxelSurfaceStyle, x, y, z)) { return; } - + uint8_t uVoxelValue = getVoxel(x, y, z); if (toValue != 0) { if (uVoxelValue == 0) { @@ -347,8 +347,8 @@ void RenderablePolyVoxEntityItem::getModel() { sizeof(PolyVox::PositionMaterialNormal), gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW))); - - + + // auto normalAttrib = mesh->getAttributeBuffer(gpu::Stream::NORMAL); // for (auto normal = normalAttrib.begin(); normal != normalAttrib.end(); normal++) { // (*normal) = -(*normal); @@ -363,7 +363,7 @@ void RenderablePolyVoxEntityItem::getModel() { // gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::RAW))); - + #ifdef WANT_DEBUG qDebug() << "---- vecIndices.size() =" << vecIndices.size(); qDebug() << "---- vecVertices.size() =" << vecVertices.size(); @@ -379,7 +379,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { if (_needsModelReload) { getModel(); } - + Transform transform; transform.setTranslation(getPosition() - getRegistrationPoint() * getDimensions()); transform.setRotation(getRotation()); @@ -398,7 +398,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { mesh->getVertexBuffer()._stride); batch.setIndexBuffer(gpu::UINT32, mesh->getIndexBuffer()._buffer, 0); batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0); - + RenderableDebugableEntityItem::render(this, args); } @@ -448,14 +448,13 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o glm::vec3 normDirection = glm::normalize(direction); // the PolyVox ray intersection code requires a near and far point. - glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units - // set ray cast length to long enough to cover all of the voxel space + // set ray cast length to long enough to cover all of the voxel space float distanceToEntity = glm::distance(origin, getPosition()); float largestDimension = glm::max(getDimensions().x, getDimensions().y, getDimensions().z) * 2.0f; glm::vec3 farPoint = origin + normDirection * (distanceToEntity + largestDimension); glm::vec4 originInVoxel = wtvMatrix * glm::vec4(origin, 1.0f); glm::vec4 farInVoxel = wtvMatrix * glm::vec4(farPoint, 1.0f); - + PolyVox::Vector3DFloat startPoint(originInVoxel.x, originInVoxel.y, originInVoxel.z); PolyVox::Vector3DFloat endPoint(farInVoxel.x, farInVoxel.y, farInVoxel.z); @@ -479,7 +478,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o } result -= glm::vec4(0.5f, 0.5f, 0.5f, 0.0f); - + glm::vec4 intersectedWorldPosition = voxelToWorldMatrix() * result; distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); @@ -556,9 +555,9 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() { << voxelXSize << voxelYSize << voxelZSize; return; } - + int rawSize = voxelXSize * voxelYSize * voxelZSize; - + QByteArray compressedData; reader >> compressedData; QByteArray uncompressedData = qUncompress(compressedData); @@ -635,9 +634,6 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { float offL = -0.5f; float offH = 0.5f; - // float offL = 0.0f; - // float offH = 1.0f; - glm::vec3 p000 = glm::vec3(wToM * glm::vec4(x + offL, y + offL, z + offL, 1.0f)); glm::vec3 p001 = glm::vec3(wToM * glm::vec4(x + offL, y + offL, z + offH, 1.0f)); glm::vec3 p010 = glm::vec3(wToM * glm::vec4(x + offL, y + offH, z + offL, 1.0f)); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 3d284baab6..94f88b8390 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -191,8 +191,8 @@ void RenderableWebEntityItem::render(RenderArgs* args) { } void RenderableWebEntityItem::setSourceUrl(const QString& value) { - qDebug() << "Setting web entity source URL to " << value; if (_sourceUrl != value) { + qDebug() << "Setting web entity source URL to " << value; _sourceUrl = value; if (_webSurface) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index bb1e3be539..e7e1c90b41 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -86,6 +86,7 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { void LineEntityItem::setLinePoints(const QVector& points) { QVector sanitizedPoints; + int invalidPoints = 0; for (int i = 0; i < points.size(); i++) { glm::vec3 point = points.at(i); // Make sure all of our points are valid numbers. @@ -93,9 +94,12 @@ void LineEntityItem::setLinePoints(const QVector& points) { if (point.x > 0 && point.y > 0 && point.z > 0){ sanitizedPoints << point; } else { - qDebug() << "INVALID POINT"; + ++invalidPoints; } } + if (invalidPoints > 0) { + qDebug() << "Line with" << invalidPoints << "INVALID POINTS"; + } _points = sanitizedPoints; _pointsChanged = true; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 464deb1059..f282f7e35d 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1902,8 +1902,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } else { material._material->setDiffuse(material.diffuse); } - material._material->setSpecular(material.specular); - material._material->setShininess(material.shininess); + material._material->setMetallic(glm::length(material.specular)); + material._material->setGloss(material.shininess); if (material.opacity <= 0.0f) { material._material->setOpacity(1.0f); diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 4a8a2fc53d..080fb98690 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -134,8 +134,8 @@ void setMeshPartDefaults(FBXMeshPart& meshPart, QString materialID) { meshPart._material = model::MaterialPointer(new model::Material()); meshPart._material->setDiffuse(glm::vec3(1.0, 1.0, 1.0)); meshPart._material->setOpacity(1.0); - meshPart._material->setSpecular(glm::vec3(1.0, 1.0, 1.0)); - meshPart._material->setShininess(96.0); + meshPart._material->setMetallic(0.0); + meshPart._material->setGloss(96.0); meshPart._material->setEmissive(glm::vec3(0.0, 0.0, 0.0)); } @@ -481,8 +481,8 @@ FBXGeometry OBJReader::readOBJ(QIODevice* device, const QVariantHash& mapping, Q meshPart.specularTexture.filename = material->specularTextureFilename; // ... and some things are set in the underlying material. meshPart._material->setDiffuse(material->diffuseColor); - meshPart._material->setSpecular(material->specularColor); - meshPart._material->setShininess(material->shininess); + meshPart._material->setMetallic(glm::length(material->specularColor)); + meshPart._material->setGloss(material->shininess); meshPart._material->setOpacity(material->opacity); } // qCDebug(modelformat) << "OBJ Reader part:" << meshPartCount << "name:" << leadFace.groupName << "material:" << groupMaterialName << "diffuse:" << meshPart._material->getDiffuse() << "faces:" << faceGroup.count() << "triangle indices will start with:" << mesh.vertices.count(); @@ -567,10 +567,10 @@ void fbxDebugDump(const FBXGeometry& fbxgeo) { qCDebug(modelformat) << " quadIndices.count() =" << meshPart.quadIndices.count(); qCDebug(modelformat) << " triangleIndices.count() =" << meshPart.triangleIndices.count(); qCDebug(modelformat) << " diffuseColor =" << meshPart.diffuseColor << "mat =" << meshPart._material->getDiffuse(); - qCDebug(modelformat) << " specularColor =" << meshPart.specularColor << "mat =" << meshPart._material->getSpecular(); + qCDebug(modelformat) << " specularColor =" << meshPart.specularColor << "mat =" << meshPart._material->getMetallic(); qCDebug(modelformat) << " emissiveColor =" << meshPart.emissiveColor << "mat =" << meshPart._material->getEmissive(); qCDebug(modelformat) << " emissiveParams =" << meshPart.emissiveParams; - qCDebug(modelformat) << " shininess =" << meshPart.shininess << "mat =" << meshPart._material->getShininess(); + qCDebug(modelformat) << " gloss =" << meshPart.shininess << "mat =" << meshPart._material->getGloss(); qCDebug(modelformat) << " opacity =" << meshPart.opacity << "mat =" << meshPart._material->getOpacity(); qCDebug(modelformat) << " materialID =" << meshPart.materialID; qCDebug(modelformat) << " diffuse texture =" << meshPart.diffuseTexture.filename; diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 9036f0f6db..d5c3635816 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -437,6 +437,8 @@ public: explicit operator bool() const { return bool(_texture); } bool operator !() const { return (!_texture); } + + bool isValid() const { return bool(_texture); } }; typedef std::vector TextureViews; diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index 55572a5122..a3448889b0 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -14,7 +14,7 @@ using namespace model; using namespace gpu; Material::Material() : - _flags(0), + _key(0), _schemaBuffer(), _textureMap() { @@ -26,13 +26,13 @@ Material::Material() : } Material::Material(const Material& material) : - _flags(material._flags), + _key(material._key), _schemaBuffer(material._schemaBuffer), _textureMap(material._textureMap) { } Material& Material::operator= (const Material& material) { - _flags = (material._flags); + _key = (material._key); _schemaBuffer = (material._schemaBuffer); _textureMap = (material._textureMap); @@ -43,52 +43,32 @@ Material::~Material() { } void Material::setDiffuse(const Color& diffuse) { - if (glm::any(glm::greaterThan(diffuse, Color(0.0f)))) { - _flags.set(DIFFUSE_BIT); - } else { - _flags.reset(DIFFUSE_BIT); - } + _key.setDiffuse(glm::any(glm::greaterThan(diffuse, Color(0.0f)))); _schemaBuffer.edit()._diffuse = diffuse; } -void Material::setSpecular(const Color& specular) { - if (glm::any(glm::greaterThan(specular, Color(0.0f)))) { - _flags.set(SPECULAR_BIT); - } else { - _flags.reset(SPECULAR_BIT); - } - _schemaBuffer.edit()._specular = specular; +void Material::setMetallic(float metallic) { + _key.setMetallic(metallic > 0.0f); + _schemaBuffer.edit()._metallic = glm::vec3(metallic); } void Material::setEmissive(const Color& emissive) { - if (glm::any(glm::greaterThan(emissive, Color(0.0f)))) { - _flags.set(EMISSIVE_BIT); - } else { - _flags.reset(EMISSIVE_BIT); - } + _key.setEmissive(glm::any(glm::greaterThan(emissive, Color(0.0f)))); _schemaBuffer.edit()._emissive = emissive; } -void Material::setShininess(float shininess) { - if (shininess > 0.0f) { - _flags.set(SHININESS_BIT); - } else { - _flags.reset(SHININESS_BIT); - } - _schemaBuffer.edit()._shininess = shininess; +void Material::setGloss(float gloss) { + _key.setGloss((gloss > 0.0f)); + _schemaBuffer.edit()._gloss = gloss; } void Material::setOpacity(float opacity) { - if (opacity >= 1.0f) { - _flags.reset(TRANSPARENT_BIT); - } else { - _flags.set(TRANSPARENT_BIT); - } + _key.setTransparent((opacity < 1.0f)); _schemaBuffer.edit()._opacity = opacity; } void Material::setTextureView(MapChannel channel, const gpu::TextureView& view) { - _flags.set(DIFFUSE_MAP_BIT + channel); + _key.setMapChannel(channel, (view.isValid())); _textureMap[channel] = view; } diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index ea0ab808e9..392fd918a1 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -23,6 +23,177 @@ namespace model { +// Material Key is a coarse trait description of a material used to classify the materials +class MaterialKey { +public: + enum FlagBit { + EMISSIVE_VAL_BIT = 0, + DIFFUSE_VAL_BIT, + METALLIC_VAL_BIT, + GLOSS_VAL_BIT, + TRANSPARENT_VAL_BIT, + + EMISSIVE_MAP_BIT, + DIFFUSE_MAP_BIT, + METALLIC_MAP_BIT, + GLOSS_MAP_BIT, + TRANSPARENT_MAP_BIT, + NORMAL_MAP_BIT, + + NUM_FLAGS, + }; + typedef std::bitset Flags; + + enum MapChannel { + EMISSIVE_MAP = 0, + DIFFUSE_MAP, + METALLIC_MAP, + GLOSS_MAP, + TRANSPARENT_MAP, + NORMAL_MAP, + + NUM_MAP_CHANNELS, + }; + + // The signature is the Flags + Flags _flags; + + MaterialKey() : _flags(0) {} + MaterialKey(const Flags& flags) : _flags(flags) {} + + class Builder { + Flags _flags{ 0 }; + public: + Builder() {} + + MaterialKey build() const { return MaterialKey(_flags); } + + Builder& withEmissive() { _flags.set(EMISSIVE_VAL_BIT); return (*this); } + Builder& withDiffuse() { _flags.set(DIFFUSE_VAL_BIT); return (*this); } + Builder& withMetallic() { _flags.set(METALLIC_VAL_BIT); return (*this); } + Builder& withGloss() { _flags.set(GLOSS_VAL_BIT); return (*this); } + Builder& withTransparent() { _flags.set(TRANSPARENT_VAL_BIT); return (*this); } + + Builder& withEmissiveMap() { _flags.set(EMISSIVE_MAP_BIT); return (*this); } + Builder& withDiffuseMap() { _flags.set(DIFFUSE_MAP_BIT); return (*this); } + Builder& withMetallicMap() { _flags.set(METALLIC_MAP_BIT); return (*this); } + Builder& withGlossMap() { _flags.set(GLOSS_MAP_BIT); return (*this); } + Builder& withTransparentMap() { _flags.set(TRANSPARENT_MAP_BIT); return (*this); } + + Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); } + + // Convenient standard keys that we will keep on using all over the place + static MaterialKey opaqueDiffuse() { return Builder().withDiffuse().build(); } + }; + + void setEmissive(bool value) { _flags.set(EMISSIVE_VAL_BIT, value); } + bool isEmissive() const { return _flags[EMISSIVE_VAL_BIT]; } + + void setEmissiveMap(bool value) { _flags.set(EMISSIVE_MAP_BIT, value); } + bool isEmissiveMap() const { return _flags[EMISSIVE_MAP_BIT]; } + + void setDiffuse(bool value) { _flags.set(DIFFUSE_VAL_BIT, value); } + bool isDiffuse() const { return _flags[DIFFUSE_VAL_BIT]; } + + void setDiffuseMap(bool value) { _flags.set(DIFFUSE_MAP_BIT, value); } + bool isDiffuseMap() const { return _flags[DIFFUSE_MAP_BIT]; } + + void setMetallic(bool value) { _flags.set(METALLIC_VAL_BIT, value); } + bool isMetallic() const { return _flags[METALLIC_VAL_BIT]; } + + void setMetallicMap(bool value) { _flags.set(METALLIC_MAP_BIT, value); } + bool isMetallicMap() const { return _flags[METALLIC_MAP_BIT]; } + + void setGloss(bool value) { _flags.set(GLOSS_VAL_BIT, value); } + bool isGloss() const { return _flags[GLOSS_VAL_BIT]; } + + void setGlossMap(bool value) { _flags.set(GLOSS_MAP_BIT, value); } + bool isGlossMap() const { return _flags[GLOSS_MAP_BIT]; } + + void setTransparent(bool value) { _flags.set(TRANSPARENT_VAL_BIT, value); } + bool isTransparent() const { return _flags[TRANSPARENT_VAL_BIT]; } + bool isOpaque() const { return !_flags[TRANSPARENT_VAL_BIT]; } + + void setTransparentMap(bool value) { _flags.set(TRANSPARENT_MAP_BIT, value); } + bool isTransparentMap() const { return _flags[TRANSPARENT_MAP_BIT]; } + + void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); } + bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; } + + void setMapChannel(MapChannel channel, bool value) { _flags.set(EMISSIVE_MAP_BIT + channel, value); } + bool isMapChannel(MapChannel channel) const { return _flags[EMISSIVE_MAP_BIT + channel]; } + +}; + + +class MaterialFilter { +public: + MaterialKey::Flags _value{ 0 }; + MaterialKey::Flags _mask{ 0 }; + + + MaterialFilter(const MaterialKey::Flags& value = MaterialKey::Flags(0), const MaterialKey::Flags& mask = MaterialKey::Flags(0)) : _value(value), _mask(mask) {} + + class Builder { + MaterialKey::Flags _value{ 0 }; + MaterialKey::Flags _mask{ 0 }; + public: + Builder() {} + + MaterialFilter build() const { return MaterialFilter(_value, _mask); } + + Builder& withoutEmissive() { _value.reset(MaterialKey::EMISSIVE_VAL_BIT); _mask.set(MaterialKey::EMISSIVE_VAL_BIT); return (*this); } + Builder& withEmissive() { _value.set(MaterialKey::EMISSIVE_VAL_BIT); _mask.set(MaterialKey::EMISSIVE_VAL_BIT); return (*this); } + + Builder& withoutEmissiveMap() { _value.reset(MaterialKey::EMISSIVE_MAP_BIT); _mask.set(MaterialKey::EMISSIVE_MAP_BIT); return (*this); } + Builder& withEmissiveMap() { _value.set(MaterialKey::EMISSIVE_MAP_BIT); _mask.set(MaterialKey::EMISSIVE_MAP_BIT); return (*this); } + + Builder& withoutDiffuse() { _value.reset(MaterialKey::DIFFUSE_VAL_BIT); _mask.set(MaterialKey::DIFFUSE_VAL_BIT); return (*this); } + Builder& withDiffuse() { _value.set(MaterialKey::DIFFUSE_VAL_BIT); _mask.set(MaterialKey::DIFFUSE_VAL_BIT); return (*this); } + + Builder& withoutDiffuseMap() { _value.reset(MaterialKey::DIFFUSE_MAP_BIT); _mask.set(MaterialKey::DIFFUSE_MAP_BIT); return (*this); } + Builder& withDiffuseMap() { _value.set(MaterialKey::DIFFUSE_MAP_BIT); _mask.set(MaterialKey::DIFFUSE_MAP_BIT); return (*this); } + + Builder& withoutMetallic() { _value.reset(MaterialKey::METALLIC_VAL_BIT); _mask.set(MaterialKey::METALLIC_VAL_BIT); return (*this); } + Builder& withMetallic() { _value.set(MaterialKey::METALLIC_VAL_BIT); _mask.set(MaterialKey::METALLIC_VAL_BIT); return (*this); } + + Builder& withoutMetallicMap() { _value.reset(MaterialKey::METALLIC_MAP_BIT); _mask.set(MaterialKey::METALLIC_MAP_BIT); return (*this); } + Builder& withMetallicMap() { _value.set(MaterialKey::METALLIC_MAP_BIT); _mask.set(MaterialKey::METALLIC_MAP_BIT); return (*this); } + + Builder& withoutGloss() { _value.reset(MaterialKey::GLOSS_VAL_BIT); _mask.set(MaterialKey::GLOSS_VAL_BIT); return (*this); } + Builder& withGloss() { _value.set(MaterialKey::GLOSS_VAL_BIT); _mask.set(MaterialKey::GLOSS_VAL_BIT); return (*this); } + + Builder& withoutGlossMap() { _value.reset(MaterialKey::GLOSS_MAP_BIT); _mask.set(MaterialKey::GLOSS_MAP_BIT); return (*this); } + Builder& withGlossMap() { _value.set(MaterialKey::GLOSS_MAP_BIT); _mask.set(MaterialKey::GLOSS_MAP_BIT); return (*this); } + + Builder& withoutTransparent() { _value.reset(MaterialKey::TRANSPARENT_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_VAL_BIT); return (*this); } + Builder& withTransparent() { _value.set(MaterialKey::TRANSPARENT_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_VAL_BIT); return (*this); } + + Builder& withoutTransparentMap() { _value.reset(MaterialKey::TRANSPARENT_MAP_BIT); _mask.set(MaterialKey::TRANSPARENT_MAP_BIT); return (*this); } + Builder& withTransparentMap() { _value.set(MaterialKey::TRANSPARENT_MAP_BIT); _mask.set(MaterialKey::TRANSPARENT_MAP_BIT); return (*this); } + + Builder& withoutNormalMap() { _value.reset(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); } + Builder& withNormalMap() { _value.set(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); } + + // Convenient standard keys that we will keep on using all over the place + static MaterialFilter opaqueDiffuse() { return Builder().withDiffuse().withoutTransparent().build(); } + }; + + // Item Filter operator testing if a key pass the filter + bool test(const MaterialKey& key) const { return (key._flags & _mask) == (_value & _mask); } + + class Less { + public: + bool operator() (const MaterialFilter& left, const MaterialFilter& right) const { + if (left._value.to_ulong() == right._value.to_ulong()) { + return left._mask.to_ulong() < right._mask.to_ulong(); + } else { + return left._value.to_ulong() < right._value.to_ulong(); + } + } + }; +}; + class Material { public: typedef gpu::BufferView UniformBufferView; @@ -30,52 +201,27 @@ public: typedef glm::vec3 Color; - enum MapChannel { - DIFFUSE_MAP = 0, - SPECULAR_MAP, - SHININESS_MAP, - EMISSIVE_MAP, - OPACITY_MAP, - NORMAL_MAP, - - NUM_MAPS, - }; + typedef MaterialKey::MapChannel MapChannel; typedef std::map TextureMap; - typedef std::bitset MapFlags; - - enum FlagBit { - DIFFUSE_BIT = 0, - SPECULAR_BIT, - SHININESS_BIT, - EMISSIVE_BIT, - TRANSPARENT_BIT, - - DIFFUSE_MAP_BIT, - SPECULAR_MAP_BIT, - SHININESS_MAP_BIT, - EMISSIVE_MAP_BIT, - OPACITY_MAP_BIT, - NORMAL_MAP_BIT, - - NUM_FLAGS, - }; - typedef std::bitset Flags; + typedef std::bitset MapFlags; Material(); Material(const Material& material); Material& operator= (const Material& material); virtual ~Material(); + const MaterialKey& getKey() const { return _key; } + const Color& getEmissive() const { return _schemaBuffer.get()._emissive; } const Color& getDiffuse() const { return _schemaBuffer.get()._diffuse; } - const Color& getSpecular() const { return _schemaBuffer.get()._specular; } - float getShininess() const { return _schemaBuffer.get()._shininess; } + float getMetallic() const { return _schemaBuffer.get()._metallic.x; } + float getGloss() const { return _schemaBuffer.get()._gloss; } float getOpacity() const { return _schemaBuffer.get()._opacity; } - void setDiffuse(const Color& diffuse); - void setSpecular(const Color& specular); void setEmissive(const Color& emissive); - void setShininess(float shininess); + void setDiffuse(const Color& diffuse); + void setMetallic(float metallic); + void setGloss(float gloss); void setOpacity(float opacity); // Schema to access the attribute values of the material @@ -84,8 +230,8 @@ public: Color _diffuse{0.5f}; float _opacity{1.f}; - Color _specular{0.03f}; - float _shininess{0.1f}; + Color _metallic{0.03f}; + float _gloss{0.1f}; Color _emissive{0.0f}; float _spare0{0.0f}; glm::vec4 _spareVec4{0.0f}; // for alignment beauty, Material size == Mat4x4 @@ -100,7 +246,7 @@ public: protected: - Flags _flags; + MaterialKey _key; UniformBufferView _schemaBuffer; TextureMap _textureMap; diff --git a/libraries/model/src/model/Skybox.cpp b/libraries/model/src/model/Skybox.cpp index a34a3be3fd..933c737b83 100755 --- a/libraries/model/src/model/Skybox.cpp +++ b/libraries/model/src/model/Skybox.cpp @@ -44,70 +44,73 @@ void Skybox::setCubemap(const gpu::TexturePointer& cubemap) { void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) { - if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) { + if (skybox.getCubemap()) { + if (skybox.getCubemap()->isDefined()) { - static gpu::PipelinePointer thePipeline; - static gpu::BufferPointer theBuffer; - static gpu::Stream::FormatPointer theFormat; - static gpu::BufferPointer theConstants; - int SKYBOX_CONSTANTS_SLOT = 0; // need to be defined by the compilation of the shader - if (!thePipeline) { - auto skyVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(Skybox_vert))); - auto skyFS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(Skybox_frag))); - auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyVS, skyFS)); + static gpu::PipelinePointer thePipeline; + static gpu::BufferPointer theBuffer; + static gpu::Stream::FormatPointer theFormat; + static gpu::BufferPointer theConstants; + int SKYBOX_CONSTANTS_SLOT = 0; // need to be defined by the compilation of the shader + if (!thePipeline) { + auto skyVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(Skybox_vert))); + auto skyFS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(Skybox_frag))); + auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyVS, skyFS)); - gpu::Shader::BindingSet bindings; - bindings.insert(gpu::Shader::Binding(std::string("cubeMap"), 0)); - if (!gpu::Shader::makeProgram(*skyShader, bindings)) { + gpu::Shader::BindingSet bindings; + bindings.insert(gpu::Shader::Binding(std::string("cubeMap"), 0)); + if (!gpu::Shader::makeProgram(*skyShader, bindings)) { - } + } - SKYBOX_CONSTANTS_SLOT = skyShader->getBuffers().findLocation("skyboxBuffer"); - if (SKYBOX_CONSTANTS_SLOT == gpu::Shader::INVALID_LOCATION) { - SKYBOX_CONSTANTS_SLOT = skyShader->getUniforms().findLocation("skyboxBuffer"); - } + SKYBOX_CONSTANTS_SLOT = skyShader->getBuffers().findLocation("skyboxBuffer"); + if (SKYBOX_CONSTANTS_SLOT == gpu::Shader::INVALID_LOCATION) { + SKYBOX_CONSTANTS_SLOT = skyShader->getUniforms().findLocation("skyboxBuffer"); + } - auto skyState = gpu::StatePointer(new gpu::State()); + auto skyState = gpu::StatePointer(new gpu::State()); - thePipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState)); + thePipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState)); - const float CLIP = 1.0; - const glm::vec2 vertices[4] = { {-CLIP, -CLIP}, {CLIP, -CLIP}, {-CLIP, CLIP}, {CLIP, CLIP}}; - theBuffer.reset(new gpu::Buffer(sizeof(vertices), (const gpu::Byte*) vertices)); + const float CLIP = 1.0; + const glm::vec2 vertices[4] = { {-CLIP, -CLIP}, {CLIP, -CLIP}, {-CLIP, CLIP}, {CLIP, CLIP}}; + theBuffer.reset(new gpu::Buffer(sizeof(vertices), (const gpu::Byte*) vertices)); - theFormat.reset(new gpu::Stream::Format()); - theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); + theFormat.reset(new gpu::Stream::Format()); + theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); - auto color = glm::vec4(1.0f); - theConstants.reset(new gpu::Buffer(sizeof(color), (const gpu::Byte*) &color)); + auto color = glm::vec4(1.0f); + theConstants.reset(new gpu::Buffer(sizeof(color), (const gpu::Byte*) &color)); + } + + glm::mat4 projMat; + viewFrustum.evalProjectionMatrix(projMat); + + Transform viewTransform; + viewFrustum.evalViewTransform(viewTransform); + + if (glm::all(glm::equal(skybox.getColor(), glm::vec3(0.0f)))) { + auto color = glm::vec4(1.0f); + theConstants->setSubData(0, sizeof(color), (const gpu::Byte*) &color); + } else { + theConstants->setSubData(0, sizeof(Color), (const gpu::Byte*) &skybox.getColor()); + } + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewTransform); + batch.setModelTransform(Transform()); // only for Mac + batch.setPipeline(thePipeline); + batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8); + batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, theConstants, 0, theConstants->getSize()); + batch.setInputFormat(theFormat); + batch.setUniformTexture(0, skybox.getCubemap()); + batch.draw(gpu::TRIANGLE_STRIP, 4); } - glm::mat4 projMat; - viewFrustum.evalProjectionMatrix(projMat); - - Transform viewTransform; - viewFrustum.evalViewTransform(viewTransform); - - if (glm::all(glm::equal(skybox.getColor(), glm::vec3(0.0f)))) { - auto color = glm::vec4(1.0f); - theConstants->setSubData(0, sizeof(color), (const gpu::Byte*) &color); - } else { - theConstants->setSubData(0, sizeof(Color), (const gpu::Byte*) &skybox.getColor()); - } - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewTransform); - batch.setModelTransform(Transform()); // only for Mac - batch.setPipeline(thePipeline); - batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8); - batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, theConstants, 0, theConstants->getSize()); - batch.setInputFormat(theFormat); - batch.setUniformTexture(0, skybox.getCubemap()); - batch.draw(gpu::TRIANGLE_STRIP, 4); } else { // skybox has no cubemap, just clear the color buffer auto color = skybox.getColor(); - batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(color, 1.0f), 0.f, 0); + batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(color, 0.0f), 0.f, 0); } } diff --git a/libraries/model/src/model/TextureStorage.h b/libraries/model/src/model/TextureStorage.h index ebc027298b..a6752d21b2 100755 --- a/libraries/model/src/model/TextureStorage.h +++ b/libraries/model/src/model/TextureStorage.h @@ -24,7 +24,7 @@ typedef glm::vec3 Color; class TextureUsage { public: gpu::Texture::Type _type{ gpu::Texture::TEX_2D }; - Material::MapFlags _materialUsage{ Material::DIFFUSE_MAP }; + Material::MapFlags _materialUsage{ MaterialKey::DIFFUSE_MAP }; int _environmentUsage = 0; }; diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index a86ce78655..642ca4748d 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -35,6 +35,7 @@ AddressManager::AddressManager() : _positionGetter(NULL), _orientationGetter(NULL) { + } bool AddressManager::isConnected() { @@ -217,7 +218,7 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const const QString DOMAIN_NETWORK_PORT_KEY = "network_port"; const QString DOMAIN_ICE_SERVER_ADDRESS_KEY = "ice_server_address"; - DependencyManager::get()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::HandleAddress); + DependencyManager::get()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::HandleAddress); const QString DOMAIN_ID_KEY = "id"; QString domainIDString = domainObject[DOMAIN_ID_KEY].toString(); @@ -415,6 +416,9 @@ bool AddressManager::handleViewpoint(const QString& viewpointString, bool should positionRegex.cap(2).toFloat(), positionRegex.cap(3).toFloat()); + // we're about to jump positions - store the current address in our history + addCurrentAddressToHistory(); + if (!isNaN(newPosition.x) && !isNaN(newPosition.y) && !isNaN(newPosition.z)) { glm::quat newOrientation; @@ -467,6 +471,10 @@ bool AddressManager::handleUsername(const QString& lookupString) { void AddressManager::setHost(const QString& host) { if (host != _host) { + + // if the host is being changed we should store current address in the history + addCurrentAddressToHistory(); + _host = host; emit hostChanged(_host); } @@ -474,7 +482,8 @@ void AddressManager::setHost(const QString& host) { void AddressManager::setDomainInfo(const QString& hostname, quint16 port) { - _host = hostname; + setHost(hostname); + _rootPlaceID = QUuid(); qCDebug(networking) << "Possible domain change required to connect to domain at" << hostname << "on" << port; @@ -500,3 +509,22 @@ void AddressManager::copyAddress() { void AddressManager::copyPath() { QApplication::clipboard()->setText(currentPath()); } + +void AddressManager::addCurrentAddressToHistory() { + if (_lastHistoryAppend == 0) { + // we don't store the first address on application load + // just update the last append time so the next is stored + _lastHistoryAppend = usecTimestampNow(); + } else { + const quint64 DOUBLE_STORE_THRESHOLD_USECS = 500000; + + // avoid double storing when the host changes and the viewpoint changes immediately after + if (usecTimestampNow() - _lastHistoryAppend > DOUBLE_STORE_THRESHOLD_USECS) { + // add the current address to the history + _history.append(currentAddress()); + + // change our last history append to now + _lastHistoryAppend = usecTimestampNow(); + } + } +} diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 2b587a9bd7..d950ae0275 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -98,10 +98,15 @@ private: bool handleUsername(const QString& lookupString); bool handleDomainID(const QString& host); + void addCurrentAddressToHistory(); + QString _host; QUuid _rootPlaceID; PositionGetter _positionGetter; OrientationGetter _orientationGetter; + + QList _history; + quint64 _lastHistoryAppend = 0; }; #endif // hifi_AddressManager_h diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index aa0ab262d7..123e140913 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -605,9 +605,6 @@ const int NUM_BYTES_STUN_HEADER = 20; void LimitedNodeList::sendSTUNRequest() { - static quint64 lastTimeStamp = usecTimestampNow(); - lastTimeStamp = usecTimestampNow(); - const int NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL = 10; if (!_hasCompletedInitialSTUN) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index aadc4bffbe..2ae8968571 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -78,8 +78,8 @@ Model::Model(QObject* parent) : _showTrueJointTransforms(true), _lodDistance(0.0f), _pupilDilation(0.0f), - _isVisible(true), _url("http://invalid.com"), + _isVisible(true), _blendNumber(0), _appliedBlendNumber(0), _calculatedMeshPartBoxesValid(false), @@ -891,6 +891,9 @@ namespace render { return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false); } } + /* template <> const model::MaterialKey& shapeGetMaterialKey(const OpaqueMeshPart::Pointer& payload) { + return payload->model->getPartMaterial(payload->meshIndex, payload->partIndex); + }*/ } void Model::setVisibleInScene(bool newValue, std::shared_ptr scene) { @@ -913,8 +916,6 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan bool somethingAdded = false; - qDebug() << "Model::addToScene : " << this->getURL().toString(); - // allow the attachments to add to scene foreach (Model* attachment, _attachments) { bool attachementSomethingAdded = attachment->addToScene(scene, pendingChanges); @@ -954,7 +955,6 @@ void Model::removeFromScene(std::shared_ptr scene, render::Pendin } _renderItems.clear(); _readyWhenAdded = false; - qDebug() << "Model::removeFromScene : " << this->getURL().toString(); } bool Model::render(RenderArgs* renderArgs, float alpha) { @@ -2118,8 +2118,8 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran } Locations* locations = nullptr; - pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, - args, locations); + pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, + args, locations); updateVisibleJointStates(); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 0367ad8d32..6f751a5f8d 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -312,8 +312,7 @@ protected: float getLimbLength(int jointIndex) const; /// Allow sub classes to force invalidating the bboxes - void invalidCalculatedMeshBoxes() { - qDebug() << "invalidCalculatedMeshBoxes()"; + void invalidCalculatedMeshBoxes() { _calculatedMeshBoxesValid = false; _calculatedMeshPartBoxesValid = false; _calculatedMeshTrianglesValid = false; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index f9e78c69bb..777d9466a5 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -44,7 +44,7 @@ template <> void render::jobRun(const ResolveDeferred& job, const SceneContextPo RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(PrepareDeferred())); _jobs.push_back(Job(DrawBackground())); - _jobs.push_back(Job(DrawOpaque())); + _jobs.push_back(Job(DrawOpaqueDeferred())); _jobs.push_back(Job(DrawLight())); _jobs.push_back(Job(ResetGLState())); _jobs.push_back(Job(RenderDeferred())); @@ -78,6 +78,84 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend +template <> void render::jobRun(const DrawOpaqueDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer("DrawOpaqueDeferred"); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + + // render opaques + auto& scene = sceneContext->_scene; + auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape()); + auto& renderDetails = renderContext->args->_details; + + ItemIDsBounds inItems; + inItems.reserve(items.size()); + for (auto id : items) { + inItems.emplace_back(ItemIDAndBounds(id)); + } + ItemIDsBounds& renderedItems = inItems; + + renderContext->_numFeedOpaqueItems = renderedItems.size(); + + ItemIDsBounds culledItems; + culledItems.reserve(inItems.size()); + if (renderContext->_cullOpaque) { + renderDetails.pointTo(RenderDetails::OPAQUE_ITEM); + cullItems(sceneContext, renderContext, renderedItems, culledItems); + renderDetails.pointTo(RenderDetails::OTHER_ITEM); + renderedItems = culledItems; + } + + renderContext->_numDrawnOpaqueItems = renderedItems.size(); + + + ItemIDsBounds sortedItems; + sortedItems.reserve(culledItems.size()); + if (renderContext->_sortOpaque) { + depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items! + renderedItems = sortedItems; + } + + // ItemIDsBounds sortedItems; + /* ItemMaterialBucketMap stateSortedItems; + stateSortedItems.allocateStandardMaterialBuckets(); + if (true) { + for (auto& itemIDAndBound : renderedItems) { + stateSortedItems.insert(itemIDAndBound.id, scene->getItem(itemIDAndBound.id).getMaterialKey()); + } + } +*/ + + if (renderContext->_renderOpaque) { + RenderArgs* args = renderContext->args; + gpu::Batch batch; + args->_batch = &batch; + + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + renderContext->args->_renderMode = RenderArgs::NORMAL_RENDER_MODE; + { + GLenum buffers[3]; + int bufferCount = 0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; + batch._glDrawBuffers(bufferCount, buffers); + } + + renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnOpaqueItems); + + args->_context->render((*args->_batch)); + args->_batch = nullptr; + } +} + + template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { PerformanceTimer perfTimer("DrawTransparentDeferred"); assert(renderContext->args); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 17971dbfac..e2cac53c0d 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -35,6 +35,14 @@ namespace render { template <> void jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); } + +class DrawOpaqueDeferred { +public: +}; +namespace render { +template <> void jobRun(const DrawOpaqueDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); +} + class DrawTransparentDeferred { public: }; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index e58b92aafa..bfc888ea8a 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -174,7 +174,7 @@ void render::renderItems(const SceneContextPointer& sceneContext, const RenderCo auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->args; // render - if ((maxDrawnItems < 0) || (maxDrawnItems > inItems.size())) { + if ((maxDrawnItems < 0) || (maxDrawnItems > (int) inItems.size())) { for (auto itemDetails : inItems) { auto item = scene->getItem(itemDetails.id); item.render(args); @@ -445,3 +445,18 @@ template <> void render::jobRun(const DrawBackground& job, const SceneContextPoi // Force the context sync args->_context->syncCache(); } + + + +void ItemMaterialBucketMap::insert(const ItemID& id, const model::MaterialKey& key) { + // Insert the itemID in every bucket where it filters true + for (auto& bucket : (*this)) { + if (bucket.first.test(key)) { + bucket.second.push_back(id); + } + } +} + +void ItemMaterialBucketMap::allocateStandardMaterialBuckets() { + (*this)[model::MaterialFilter::Builder::opaqueDiffuse()]; +} diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 687287cd56..1f260583f2 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -62,6 +62,10 @@ void depthSortItems(const SceneContextPointer& sceneContext, const RenderContext void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); + +void materialSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); + + class DrawOpaque { public: }; @@ -101,6 +105,20 @@ public: }; + +// A map of ItemIDs allowing to create bucket lists of SHAPE type items which are filtered by their +// Material +class ItemMaterialBucketMap : public std::map { +public: + + ItemMaterialBucketMap() {} + + void insert(const ItemID& id, const model::MaterialKey& key); + + // standard builders allocating the main buckets + void allocateStandardMaterialBuckets(); +}; + } #endif // hifi_render_Task_h diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 054fbeb602..8cb29609ba 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -24,6 +24,8 @@ #include #include +#include "model/Material.h" + namespace render { class Context; @@ -216,6 +218,8 @@ public: virtual void update(const UpdateFunctorPointer& functor) = 0; + virtual const model::MaterialKey getMaterialKey() const = 0; + ~PayloadInterface() {} protected: }; @@ -240,6 +244,9 @@ public: void render(RenderArgs* args) { _payload->render(args); } void update(const UpdateFunctorPointer& updateFunctor) { _payload->update(updateFunctor); } + // Shape Type Interface + const model::MaterialKey& getMaterialKey() const { return _payload->getMaterialKey(); } + protected: PayloadPointer _payload; ItemKey _key; @@ -275,16 +282,23 @@ template const ItemKey payloadGetKey(const std::shared_ptr& payload template const Item::Bound payloadGetBound(const std::shared_ptr& payloadData) { return Item::Bound(); } template void payloadRender(const std::shared_ptr& payloadData, RenderArgs* args) { } +// Shape type interface +template const model::MaterialKey shapeGetMaterialKey(const std::shared_ptr& payloadData) { return model::MaterialKey(); } + template class Payload : public Item::PayloadInterface { public: typedef std::shared_ptr DataPointer; typedef UpdateFunctor Updater; + virtual void update(const UpdateFunctorPointer& functor) { static_cast(functor.get())->_func((*_data)); } + + // Payload general interface virtual const ItemKey getKey() const { return payloadGetKey(_data); } virtual const Item::Bound getBound() const { return payloadGetBound(_data); } - virtual void render(RenderArgs* args) { payloadRender(_data, args); } - - virtual void update(const UpdateFunctorPointer& functor) { static_cast(functor.get())->_func((*_data)); } + virtual void render(RenderArgs* args) { payloadRender(_data, args); } + + // Shape Type interface + virtual const model::MaterialKey getMaterialKey() const { return shapeGetMaterialKey(_data); } Payload(const DataPointer& data) : _data(data) {} protected: