diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0c1a46e3a0..3e7b17764d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1748,7 +1748,10 @@ void Application::setActiveFaceTracker() { DependencyManager::get()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)); #endif #ifdef HAVE_DDE - DependencyManager::get()->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression)); + bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression); + Menu::getInstance()->getActionForOption(MenuOption::DDEFiltering)->setVisible(isUsingDDE); + Menu::getInstance()->getActionForOption(MenuOption::ResetDDETracking)->setVisible(isUsingDDE); + DependencyManager::get()->setEnabled(isUsingDDE); #endif #ifdef HAVE_VISAGE DependencyManager::get()->updateEnabled(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 833d9a6799..b5b2921844 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -210,7 +210,6 @@ public: bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; } FaceTracker* getActiveFaceTracker(); - void setActiveFaceTracker(); QSystemTrayIcon* getTrayIcon() { return _trayIcon; } ApplicationOverlay& getApplicationOverlay() { return _applicationOverlay; } @@ -385,6 +384,8 @@ public slots: void setVSyncEnabled(); void resetSensors(); + void setActiveFaceTracker(); + void aboutApp(); void showEditEntitiesHelp(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index bde0745c4d..8d6a1e3184 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -362,30 +362,32 @@ Menu::Menu() { QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking, 0, true, - this, SLOT(setActiveFaceTracker())); + qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(noFaceTracker); #ifdef HAVE_FACESHIFT QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Faceshift, 0, false, - this, SLOT(setActiveFaceTracker())); + qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(faceshiftFaceTracker); #endif #ifdef HAVE_DDE QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFaceRegression, 0, false, - this, SLOT(setActiveFaceTracker())); + qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(ddeFaceTracker); #endif #ifdef HAVE_VISAGE QAction* visageFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Visage, 0, false, - this, SLOT(setActiveFaceTracker())); + qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(visageFaceTracker); #endif } #ifdef HAVE_DDE faceTrackingMenu->addSeparator(); + QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFiltering, 0, true); + ddeFiltering->setVisible(false); QAction* ddeFaceTrackerReset = addActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::ResetDDETracking, Qt::CTRL | Qt::Key_Apostrophe, DependencyManager::get().data(), SLOT(resetTracking())); @@ -987,11 +989,3 @@ void Menu::visibilityChanged(Discoverability::Mode discoverabilityMode) { qCDebug(interfaceapp) << "ERROR Menu::visibilityChanged() called with unrecognized value."; } } - -void Menu::setActiveFaceTracker() { -#ifdef HAVE_DDE - bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression); - Menu::getInstance()->getActionForOption(MenuOption::ResetDDETracking)->setVisible(isUsingDDE); -#endif - qApp->setActiveFaceTracker(); -} diff --git a/interface/src/Menu.h b/interface/src/Menu.h index f580b9204b..ea34664eaa 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -68,7 +68,6 @@ public slots: private slots: void setVisibility(); - void setActiveFaceTracker(); private: static Menu* _instance; @@ -137,6 +136,7 @@ namespace MenuOption { const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyPath = "Copy Path to Clipboard"; const QString DDEFaceRegression = "DDE Face Regression"; + const QString DDEFiltering = "DDE Filtering"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DeleteBookmark = "Delete Bookmark..."; const QString DisableActivityLogger = "Disable Activity Logger"; diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index c7a8b7d166..50601421c2 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -17,6 +17,8 @@ #include #include +#include + #include "DdeFaceTracker.h" #include "FaceshiftConstants.h" #include "InterfaceLogging.h" @@ -27,9 +29,9 @@ static const QHostAddress DDE_SERVER_ADDR("127.0.0.1"); static const quint16 DDE_SERVER_PORT = 64204; static const quint16 DDE_CONTROL_PORT = 64205; #if defined(Q_OS_WIN) -static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde/dde.exe"; +static const QString DDE_PROGRAM_PATH = "/dde/dde.exe"; #elif defined(Q_OS_MAC) -static const QString DDE_PROGRAM_PATH = QCoreApplication::applicationDirPath() + "/dde.app/Contents/MacOS/dde"; +static const QString DDE_PROGRAM_PATH = "/dde.app/Contents/MacOS/dde"; #endif static const QStringList DDE_ARGUMENTS = QStringList() << "--udp=" + DDE_SERVER_ADDR.toString() + ":" + QString::number(DDE_SERVER_PORT) @@ -132,6 +134,8 @@ struct Packet { char name[MAX_NAME_SIZE + 1]; }; +const float STARTING_DDE_MESSAGE_TIME = 0.033f; + DdeFaceTracker::DdeFaceTracker() : DdeFaceTracker(QHostAddress::Any, DDE_SERVER_PORT, DDE_CONTROL_PORT) { @@ -157,11 +161,16 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui _mouthSmileLeftIndex(28), _mouthSmileRightIndex(29), _jawOpenIndex(21), - _previousTranslation(glm::vec3()), - _previousRotation(glm::quat()) + _lastMessageReceived(0), + _averageMessageTime(STARTING_DDE_MESSAGE_TIME), + _lastHeadTranslation(glm::vec3(0.0f)), + _filteredHeadTranslation(glm::vec3(0.0f)), + _lastLeftEyeBlink(0.0f), + _filteredLeftEyeBlink(0.0f), + _lastRightEyeBlink(0.0f), + _filteredRightEyeBlink(0.0f) { _coefficients.resize(NUM_FACESHIFT_BLENDSHAPES); - _previousCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES); _blendshapeCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES); @@ -272,6 +281,8 @@ float DdeFaceTracker::getBlendshapeCoefficient(int index) const { void DdeFaceTracker::decodePacket(const QByteArray& buffer) { if(buffer.size() > MIN_PACKET_SIZE) { + bool isFiltering = Menu::getInstance()->isOptionChecked(MenuOption::DDEFiltering); + Packet packet; int bytesToCopy = glm::min((int)sizeof(packet), buffer.size()); memset(&packet.name, '\n', MAX_NAME_SIZE + 1); @@ -292,13 +303,36 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { translation -= _referenceTranslation; translation /= LEAN_DAMPING_FACTOR; translation.x *= -1; - _headTranslation = (translation + _previousTranslation) / 2.0f; - _previousTranslation = translation; + if (isFiltering) { + glm::vec3 linearVelocity = (translation - _lastHeadTranslation) / _averageMessageTime; + const float LINEAR_VELOCITY_FILTER_STRENGTH = 0.3f; + float velocityFilter = glm::clamp(1.0f - glm::length(linearVelocity) * + LINEAR_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); + _filteredHeadTranslation = velocityFilter * _filteredHeadTranslation + (1.0f - velocityFilter) * translation; + _lastHeadTranslation = translation; + _headTranslation = _filteredHeadTranslation; + } else { + _headTranslation = translation; + } // Compute relative rotation rotation = glm::inverse(_referenceRotation) * rotation; - _headRotation = (rotation + _previousRotation) / 2.0f; - _previousRotation = rotation; + if (isFiltering) { + glm::quat r = rotation * glm::inverse(_headRotation); + float theta = 2 * acos(r.w); + glm::vec3 angularVelocity; + if (theta > EPSILON) { + float rMag = glm::length(glm::vec3(r.x, r.y, r.z)); + angularVelocity = theta / _averageMessageTime * glm::vec3(r.x, r.y, r.z) / rMag; + } else { + angularVelocity = glm::vec3(0, 0, 0); + } + const float ANGULAR_VELOCITY_FILTER_STRENGTH = 0.3f; + _headRotation = safeMix(_headRotation, rotation, glm::clamp(glm::length(angularVelocity) * + ANGULAR_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f)); + } else { + _headRotation = rotation; + } // Translate DDE coefficients to Faceshift compatible coefficients for (int i = 0; i < NUM_EXPRESSIONS; i += 1) { @@ -307,8 +341,23 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { // Use EyeBlink values to control both EyeBlink and EyeOpen static const float RELAXED_EYE_VALUE = 0.1f; - float leftEye = (_coefficients[_leftBlinkIndex] + _previousCoefficients[_leftBlinkIndex]) / 2.0f; - float rightEye = (_coefficients[_rightBlinkIndex] + _previousCoefficients[_rightBlinkIndex]) / 2.0f; + float leftEye = _coefficients[_leftBlinkIndex]; + float rightEye = _coefficients[_rightBlinkIndex]; + if (isFiltering) { + const float BLINK_VELOCITY_FILTER_STRENGTH = 0.3f; + + float velocity = fabs(leftEye - _lastLeftEyeBlink) / _averageMessageTime; + float velocityFilter = glm::clamp(velocity * BLINK_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); + _filteredLeftEyeBlink = velocityFilter * leftEye + (1.0f - velocityFilter) * _filteredLeftEyeBlink; + _lastLeftEyeBlink = leftEye; + leftEye = _filteredLeftEyeBlink; + + velocity = fabs(rightEye - _lastRightEyeBlink) / _averageMessageTime; + velocityFilter = glm::clamp(velocity * BLINK_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); + _filteredRightEyeBlink = velocityFilter * rightEye + (1.0f - velocityFilter) * _filteredRightEyeBlink; + _lastRightEyeBlink = rightEye; + rightEye = _filteredRightEyeBlink; + } if (leftEye > RELAXED_EYE_VALUE) { _coefficients[_leftBlinkIndex] = leftEye - RELAXED_EYE_VALUE; _coefficients[_leftEyeOpenIndex] = 0.0f; @@ -343,10 +392,18 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { // Scale all coefficients for (int i = 0; i < NUM_EXPRESSIONS; i += 1) { _blendshapeCoefficients[i] - = glm::clamp(DDE_COEFFICIENT_SCALES[i] * (_coefficients[i] + _previousCoefficients[i]) / 2.0f, 0.0f, 1.0f); - _previousCoefficients[i] = _coefficients[i]; + = glm::clamp(DDE_COEFFICIENT_SCALES[i] * _coefficients[i], 0.0f, 1.0f); } + // Calculate average frame time + const float FRAME_AVERAGING_FACTOR = 0.99f; + quint64 usecsNow = usecTimestampNow(); + if (_lastMessageReceived != 0) { + _averageMessageTime = FRAME_AVERAGING_FACTOR * _averageMessageTime + + (1.0f - FRAME_AVERAGING_FACTOR) * (float)(usecsNow - _lastMessageReceived) / 1000000.0f; + } + _lastMessageReceived = usecsNow; + } else { qCDebug(interfaceapp) << "[Error] DDE Face Tracker Decode Error"; } diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 490020e511..aa3e9f3b81 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -101,10 +101,14 @@ private: QVector _coefficients; - // Previous values for simple smoothing - glm::vec3 _previousTranslation; - glm::quat _previousRotation; - QVector _previousCoefficients; + quint64 _lastMessageReceived; + float _averageMessageTime; + glm::vec3 _lastHeadTranslation; + glm::vec3 _filteredHeadTranslation; + float _lastLeftEyeBlink; + float _filteredLeftEyeBlink; + float _lastRightEyeBlink; + float _filteredRightEyeBlink; }; #endif // hifi_DdeFaceTracker_h \ No newline at end of file diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index b9b2f24034..25ea9ef8e1 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1705,7 +1705,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, material._material->setDiffuse(material.diffuse); material._material->setSpecular(material.specular); material._material->setShininess(material.shininess); - material._material->setOpacity(material.opacity); + + if (material.opacity <= 0.0f) { + material._material->setOpacity(1.0f); + } else { + material._material->setOpacity(material.opacity); + } materials.insert(material.id, material); diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index caabff44cf..423e8fcfb6 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -12,4 +12,16 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) +if (WIN32) + if (USE_NSIGHT) + # try to find the Nsight package and add it to the build if we find it + find_package(NSIGHT) + if (NSIGHT_FOUND) + include_directories(${NSIGHT_INCLUDE_DIRS}) + add_definitions(-DNSIGHT_FOUND) + target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") + endif () + endif() +endif (WIN32) + link_hifi_libraries(animation fbx shared gpu) \ No newline at end of file diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 0a36ffa76a..2bbdf2a8f1 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -244,13 +244,6 @@ void Model::initJointTransforms() { void Model::init() { if (_renderPipelineLib.empty()) { - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1)); - slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2)); - slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3)); - // Vertex shaders auto modelVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_vert))); auto modelNormalMapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_normal_map_vert))); @@ -291,10 +284,24 @@ void Model::init() { RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), modelNormalMapVertex, modelNormalSpecularMapPixel); + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_TRANSLUCENT), modelVertex, modelTranslucentPixel); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), + modelNormalMapVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + modelVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + modelNormalMapVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::HAS_LIGHTMAP), modelLightmapVertex, modelLightmapPixel); @@ -310,6 +317,7 @@ void Model::init() { RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_SKINNED), skinModelVertex, modelPixel); @@ -326,15 +334,29 @@ void Model::init() { RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), skinModelNormalMapVertex, modelNormalSpecularMapPixel); + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT), skinModelVertex, modelTranslucentPixel); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), + skinModelNormalMapVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + skinModelVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + skinModelNormalMapVertex, modelTranslucentPixel); + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), modelShadowVertex, modelShadowPixel); + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), skinModelShadowVertex, modelShadowPixel); @@ -1935,55 +1957,7 @@ bool Model::renderInScene(float alpha, RenderArgs* args) { } void Model::segregateMeshGroups() { - _meshesTranslucentTangents.clear(); - _meshesTranslucent.clear(); - _meshesTranslucentTangentsSpecular.clear(); - _meshesTranslucentSpecular.clear(); - - _meshesTranslucentTangentsSkinned.clear(); - _meshesTranslucentSkinned.clear(); - _meshesTranslucentTangentsSpecularSkinned.clear(); - _meshesTranslucentSpecularSkinned.clear(); - - _meshesOpaqueTangents.clear(); - _meshesOpaque.clear(); - _meshesOpaqueTangentsSpecular.clear(); - _meshesOpaqueSpecular.clear(); - - _meshesOpaqueTangentsSkinned.clear(); - _meshesOpaqueSkinned.clear(); - _meshesOpaqueTangentsSpecularSkinned.clear(); - _meshesOpaqueSpecularSkinned.clear(); - - _meshesOpaqueLightmapTangents.clear(); - _meshesOpaqueLightmap.clear(); - _meshesOpaqueLightmapTangentsSpecular.clear(); - _meshesOpaqueLightmapSpecular.clear(); - - _unsortedMeshesTranslucentTangents.clear(); - _unsortedMeshesTranslucent.clear(); - _unsortedMeshesTranslucentTangentsSpecular.clear(); - _unsortedMeshesTranslucentSpecular.clear(); - - _unsortedMeshesTranslucentTangentsSkinned.clear(); - _unsortedMeshesTranslucentSkinned.clear(); - _unsortedMeshesTranslucentTangentsSpecularSkinned.clear(); - _unsortedMeshesTranslucentSpecularSkinned.clear(); - - _unsortedMeshesOpaqueTangents.clear(); - _unsortedMeshesOpaque.clear(); - _unsortedMeshesOpaqueTangentsSpecular.clear(); - _unsortedMeshesOpaqueSpecular.clear(); - - _unsortedMeshesOpaqueTangentsSkinned.clear(); - _unsortedMeshesOpaqueSkinned.clear(); - _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); - _unsortedMeshesOpaqueSpecularSkinned.clear(); - - _unsortedMeshesOpaqueLightmapTangents.clear(); - _unsortedMeshesOpaqueLightmap.clear(); - _unsortedMeshesOpaqueLightmapTangentsSpecular.clear(); - _unsortedMeshesOpaqueLightmapSpecular.clear(); + _renderBuckets.clear(); const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -2017,201 +1991,19 @@ void Model::segregateMeshGroups() { qCDebug(renderutils) << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if (!hasLightmap) { - if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + RenderKey key(translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned); - _unsortedMeshesTranslucent.insertMulti(materialID, i); - - } else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - - _unsortedMeshesTranslucentTangents.insertMulti(materialID, i); - - } else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesTranslucentTangentsSpecular.insertMulti(materialID, i); - - } else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesTranslucentSpecular.insertMulti(materialID, i); - - } else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesTranslucentTangentsSkinned.insertMulti(materialID, i); - - } else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesTranslucentSkinned.insertMulti(materialID, i); - - } else if (translucentMesh && hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesTranslucentTangentsSpecularSkinned.insertMulti(materialID, i); - - } else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesTranslucentSpecularSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - - _unsortedMeshesOpaque.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueTangents.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueTangentsSpecular.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueSpecular.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueTangentsSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueTangentsSpecularSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueSpecularSkinned.insertMulti(materialID, i); - } else { - qCDebug(renderutils) << "unexpected!!! this mesh didn't fall into any or our groups???"; - } - } else { - if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueLightmap.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueLightmapTangents.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueLightmapTangentsSpecular.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - - _unsortedMeshesOpaqueLightmapSpecular.insertMulti(materialID, i); - - } else { - qCDebug(renderutils) << "unexpected!!! this mesh didn't fall into any or our groups???"; - } - } + // reuse or create the bucket corresponding to that key and insert the mesh as unsorted + _renderBuckets[key.getRaw()]._unsortedMeshes.insertMulti(materialID, i); } - foreach(int i, _unsortedMeshesTranslucent) { - _meshesTranslucent.append(i); + for(auto& b : _renderBuckets) { + foreach(auto i, b.second._unsortedMeshes) { + b.second._meshes.append(i); + b.second._unsortedMeshes.clear(); + } } - foreach(int i, _unsortedMeshesTranslucentTangents) { - _meshesTranslucentTangents.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentTangentsSpecular) { - _meshesTranslucentTangentsSpecular.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentSpecular) { - _meshesTranslucentSpecular.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentSkinned) { - _meshesTranslucentSkinned.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentTangentsSkinned) { - _meshesTranslucentTangentsSkinned.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentTangentsSpecularSkinned) { - _meshesTranslucentTangentsSpecularSkinned.append(i); - } - - foreach(int i, _unsortedMeshesTranslucentSpecularSkinned) { - _meshesTranslucentSpecularSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaque) { - _meshesOpaque.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueTangents) { - _meshesOpaqueTangents.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueTangentsSpecular) { - _meshesOpaqueTangentsSpecular.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueSpecular) { - _meshesOpaqueSpecular.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueSkinned) { - _meshesOpaqueSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueTangentsSkinned) { - _meshesOpaqueTangentsSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueTangentsSpecularSkinned) { - _meshesOpaqueTangentsSpecularSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueSpecularSkinned) { - _meshesOpaqueSpecularSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueLightmap) { - _meshesOpaqueLightmap.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueLightmapTangents) { - _meshesOpaqueLightmapTangents.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueLightmapTangentsSpecular) { - _meshesOpaqueLightmapTangentsSpecular.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueLightmapSpecular) { - _meshesOpaqueLightmapSpecular.append(i); - } - - _unsortedMeshesTranslucentTangents.clear(); - _unsortedMeshesTranslucent.clear(); - _unsortedMeshesTranslucentTangentsSpecular.clear(); - _unsortedMeshesTranslucentSpecular.clear(); - - _unsortedMeshesTranslucentTangentsSkinned.clear(); - _unsortedMeshesTranslucentSkinned.clear(); - _unsortedMeshesTranslucentTangentsSpecularSkinned.clear(); - _unsortedMeshesTranslucentSpecularSkinned.clear(); - - _unsortedMeshesOpaqueTangents.clear(); - _unsortedMeshesOpaque.clear(); - _unsortedMeshesOpaqueTangentsSpecular.clear(); - _unsortedMeshesOpaqueSpecular.clear(); - - _unsortedMeshesOpaqueTangentsSkinned.clear(); - _unsortedMeshesOpaqueSkinned.clear(); - _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); - _unsortedMeshesOpaqueSpecularSkinned.clear(); - - _unsortedMeshesOpaqueLightmapTangents.clear(); - _unsortedMeshesOpaqueLightmap.clear(); - _unsortedMeshesOpaqueLightmapTangentsSpecular.clear(); - _unsortedMeshesOpaqueLightmapSpecular.clear(); - _meshGroupsKnown = true; } @@ -2220,52 +2012,14 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h // depending on which parameters we were called with, pick the correct mesh group to render QVector* whichList = NULL; - if (translucent && !hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesTranslucent; - } else if (translucent && hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesTranslucentTangents; - } else if (translucent && hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesTranslucentTangentsSpecular; - } else if (translucent && !hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesTranslucentSpecular; - } else if (translucent && hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesTranslucentTangentsSkinned; - } else if (translucent && !hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesTranslucentSkinned; - } else if (translucent && hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesTranslucentTangentsSpecularSkinned; - } else if (translucent && !hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesTranslucentSpecularSkinned; - } else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaque; - } else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueTangents; - } else if (!translucent && !hasLightmap && hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueTangentsSpecular; - } else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueSpecular; - } else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesOpaqueTangentsSkinned; - } else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesOpaqueSkinned; - } else if (!translucent && !hasLightmap && hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesOpaqueTangentsSpecularSkinned; - } else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesOpaqueSpecularSkinned; + RenderKey key(translucent, hasLightmap, hasTangents, hasSpecular, isSkinned); - } else if (!translucent && hasLightmap && !hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueLightmap; - } else if (!translucent && hasLightmap && hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueLightmapTangents; - } else if (!translucent && hasLightmap && hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueLightmapTangentsSpecular; - } else if (!translucent && hasLightmap && !hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueLightmapSpecular; - - } else { - qCDebug(renderutils) << "unexpected!!! this mesh didn't fall into any or our groups???"; + auto bucket = _renderBuckets.find(key.getRaw()); + if (bucket != _renderBuckets.end()) { + whichList = &(*bucket).second._meshes; } + return whichList; } @@ -2277,6 +2031,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f auto pipeline = _renderPipelineLib.find(key.getRaw()); if (pipeline == _renderPipelineLib.end()) { qDebug() << "No good, couldn't find a pipeline from the key ?" << key.getRaw(); + locations = 0; return; } @@ -2303,7 +2058,7 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool int meshPartsRendered = 0; bool pickProgramsNeeded = true; - Locations* locations; + Locations* locations = nullptr; foreach(Model* model, _modelsInScene) { QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); @@ -2331,20 +2086,19 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; - QVector* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); - + //Pick the mesh list with the requested render flags + QVector* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); if (!whichList) { - qCDebug(renderutils) << "unexpected!!! we don't know which list of meshes to render..."; return 0; } QVector& list = *whichList; // If this list has nothing to render, then don't bother proceeding. This saves us on binding to programs - if (list.size() == 0) { + if (list.empty()) { return 0; } - Locations* locations; + Locations* locations = nullptr; pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations); meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index fce5629b8d..1559e73e61 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -350,58 +350,6 @@ private: bool _meshGroupsKnown; - QMap _unsortedMeshesTranslucent; - QMap _unsortedMeshesTranslucentTangents; - QMap _unsortedMeshesTranslucentTangentsSpecular; - QMap _unsortedMeshesTranslucentSpecular; - - QMap _unsortedMeshesTranslucentSkinned; - QMap _unsortedMeshesTranslucentTangentsSkinned; - QMap _unsortedMeshesTranslucentTangentsSpecularSkinned; - QMap _unsortedMeshesTranslucentSpecularSkinned; - - QMap _unsortedMeshesOpaque; - QMap _unsortedMeshesOpaqueTangents; - QMap _unsortedMeshesOpaqueTangentsSpecular; - QMap _unsortedMeshesOpaqueSpecular; - - QMap _unsortedMeshesOpaqueSkinned; - QMap _unsortedMeshesOpaqueTangentsSkinned; - QMap _unsortedMeshesOpaqueTangentsSpecularSkinned; - QMap _unsortedMeshesOpaqueSpecularSkinned; - - QMap _unsortedMeshesOpaqueLightmap; - QMap _unsortedMeshesOpaqueLightmapTangents; - QMap _unsortedMeshesOpaqueLightmapTangentsSpecular; - QMap _unsortedMeshesOpaqueLightmapSpecular; - - typedef std::unordered_map> MeshListMap; - MeshListMap _sortedMeshes; - - QVector _meshesTranslucent; - QVector _meshesTranslucentTangents; - QVector _meshesTranslucentTangentsSpecular; - QVector _meshesTranslucentSpecular; - - QVector _meshesTranslucentSkinned; - QVector _meshesTranslucentTangentsSkinned; - QVector _meshesTranslucentTangentsSpecularSkinned; - QVector _meshesTranslucentSpecularSkinned; - - QVector _meshesOpaque; - QVector _meshesOpaqueTangents; - QVector _meshesOpaqueTangentsSpecular; - QVector _meshesOpaqueSpecular; - - QVector _meshesOpaqueSkinned; - QVector _meshesOpaqueTangentsSkinned; - QVector _meshesOpaqueTangentsSpecularSkinned; - QVector _meshesOpaqueSpecularSkinned; - - QVector _meshesOpaqueLightmap; - QVector _meshesOpaqueLightmapTangents; - QVector _meshesOpaqueLightmapTangentsSpecular; - QVector _meshesOpaqueLightmapSpecular; // debug rendering support void renderDebugMeshBoxes(); @@ -490,6 +438,17 @@ private: int getRaw() { return *reinterpret_cast(this); } + + RenderKey( + bool translucent, bool hasLightmap, + bool hasTangents, bool hasSpecular, bool isSkinned) : + RenderKey( (translucent ? IS_TRANSLUCENT : 0) + | (hasLightmap ? HAS_LIGHTMAP : 0) + | (hasTangents ? HAS_TANGENTS : 0) + | (hasSpecular ? HAS_SPECULAR : 0) + | (isSkinned ? IS_SKINNED : 0) + ) {} + RenderKey(RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned) : @@ -527,6 +486,19 @@ private: }; static RenderPipelineLib _renderPipelineLib; + + class RenderBucket { + public: + QVector _meshes; + QMap _unsortedMeshes; + }; + typedef std::unordered_map BaseRenderBucketMap; + class RenderBucketMap : public BaseRenderBucketMap { + public: + typedef RenderKey Key; + }; + RenderBucketMap _renderBuckets; + bool _renderCollisionHull; };