From 440c77905a8aeff4269caabdcf87a9e65da528be Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 7 Jun 2018 11:48:15 -0700 Subject: [PATCH 01/12] Remove functionality for rendering collision meshes directly in the Model class --- .../src/RenderableModelEntityItem.cpp | 11 +- .../render-utils/src/CauterizedModel.cpp | 11 -- libraries/render-utils/src/CauterizedModel.h | 3 +- libraries/render-utils/src/Model.cpp | 178 +++--------------- libraries/render-utils/src/Model.h | 9 - 5 files changed, 34 insertions(+), 178 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index a91534668c..e0039082fa 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1416,19 +1416,18 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce setCollisionMeshKey(entity->getCollisionMeshKey()); _needsCollisionGeometryUpdate = false; ShapeType type = entity->getShapeType(); - if (DependencyManager::get()->shouldRenderDebugHulls() && type != SHAPE_TYPE_STATIC_MESH && type != SHAPE_TYPE_NONE) { + if (DependencyManager::get()->shouldRenderDebugHulls() && type != SHAPE_TYPE_NONE) { // NOTE: it is OK if _collisionMeshKey is nullptr graphics::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey); - // NOTE: the model will render the collisionGeometry if it has one - _model->setCollisionMesh(mesh); + // TODO: Start displaying collision model + } else { if (_collisionMeshKey) { // release mesh collisionMeshCache.releaseMesh(_collisionMeshKey); } - // clear model's collision geometry - graphics::MeshPointer mesh = nullptr; - _model->setCollisionMesh(mesh); + // TODO: Stop displaying collision model + } } diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index b03cc071d3..53dcc74d35 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -98,11 +98,6 @@ void CauterizedModel::createVisibleRenderItemSet() { } } -void CauterizedModel::createCollisionRenderItemSet() { - // Temporary HACK: use base class method for now - Model::createCollisionRenderItemSet(); -} - void CauterizedModel::updateClusterMatrices() { PerformanceTimer perfTimer("CauterizedModel::updateClusterMatrices"); @@ -186,12 +181,6 @@ void CauterizedModel::updateRenderItems() { if (!_addedToScene) { return; } - - glm::vec3 scale = getScale(); - if (_collisionGeometry) { - // _collisionGeometry is already scaled - scale = glm::vec3(1.0f); - } _needsUpdateClusterMatrices = true; _renderItemsNeedUpdate = false; diff --git a/libraries/render-utils/src/CauterizedModel.h b/libraries/render-utils/src/CauterizedModel.h index d16c928ba6..5abefb474f 100644 --- a/libraries/render-utils/src/CauterizedModel.h +++ b/libraries/render-utils/src/CauterizedModel.h @@ -32,8 +32,7 @@ public: bool updateGeometry() override; void createVisibleRenderItemSet() override; - void createCollisionRenderItemSet() override; - + virtual void updateClusterMatrices() override; void updateRenderItems() override; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 7cfb1f6bc8..ca0bde9d6a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -48,50 +48,10 @@ float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f; #define HTTP_INVALID_COM "http://invalid.com" const int NUM_COLLISION_HULL_COLORS = 24; -std::vector _collisionMaterials; - -void initCollisionMaterials() { - // generates bright colors in red, green, blue, yellow, magenta, and cyan spectrums - // (no browns, greys, or dark shades) - float component[NUM_COLLISION_HULL_COLORS] = { - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - 0.2f, 0.4f, 0.6f, 0.8f, - 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - 0.8f, 0.6f, 0.4f, 0.2f - }; - _collisionMaterials.reserve(NUM_COLLISION_HULL_COLORS); - - // each component gets the same cuve - // but offset by a multiple of one third the full width - int numComponents = 3; - int sectionWidth = NUM_COLLISION_HULL_COLORS / numComponents; - int greenPhase = sectionWidth; - int bluePhase = 2 * sectionWidth; - - // we stride through the colors to scatter adjacent shades - // so they don't tend to group together for large models - for (int i = 0; i < sectionWidth; ++i) { - for (int j = 0; j < numComponents; ++j) { - graphics::MaterialPointer material; - material = std::make_shared(); - int index = j * sectionWidth + i; - float red = component[index % NUM_COLLISION_HULL_COLORS]; - float green = component[(index + greenPhase) % NUM_COLLISION_HULL_COLORS]; - float blue = component[(index + bluePhase) % NUM_COLLISION_HULL_COLORS]; - material->setAlbedo(glm::vec3(red, green, blue)); - material->setMetallic(0.02f); - material->setRoughness(0.5f); - _collisionMaterials.push_back(material); - } - } -} Model::Model(QObject* parent, SpatiallyNestable* spatiallyNestableOverride) : QObject(parent), _renderGeometry(), - _collisionGeometry(), _renderWatcher(_renderGeometry), _spatiallyNestableOverride(spatiallyNestableOverride), _translation(0.0f), @@ -310,16 +270,6 @@ void Model::updateRenderItems() { }); } - Transform collisionMeshOffset; - collisionMeshOffset.setIdentity(); - foreach(auto itemID, self->_collisionRenderItemsMap.keys()) { - transaction.updateItem(itemID, [renderItemKeyGlobalFlags, modelTransform, collisionMeshOffset](MeshPartPayload& data) { - // update the model transform for this render item. - data.updateKey(renderItemKeyGlobalFlags); - data.updateTransform(modelTransform, collisionMeshOffset); - }); - } - AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); }); } @@ -777,11 +727,14 @@ void Model::updateRenderItemsKey(const render::ScenePointer& scene) { data.updateKey(renderItemsKey); }); } + //TODO: Remove +#ifdef RENDER_MODEL_BOUNDING_BOXES foreach(auto item, _collisionRenderItemsMap.keys()) { transaction.updateItem(item, [renderItemsKey](ModelMeshPartPayload& data) { data.updateKey(renderItemsKey); }); } +#endif scene->enqueueTransaction(transaction); } @@ -862,49 +815,37 @@ const render::ItemKey Model::getRenderItemKeyGlobalFlags() const { bool Model::addToScene(const render::ScenePointer& scene, render::Transaction& transaction, render::Item::Status::Getters& statusGetters) { - bool readyToRender = _collisionGeometry || isLoaded(); - if (!_addedToScene && readyToRender) { - createRenderItemSet(); + if (!_addedToScene && isLoaded()) { + updateClusterMatrices(); + if (_modelMeshRenderItems.empty()) { + createVisibleRenderItemSet(); + } } bool somethingAdded = false; - if (_collisionGeometry) { - if (_collisionRenderItemsMap.empty()) { - foreach (auto renderItem, _collisionRenderItems) { - auto item = scene->allocateID(); - auto renderPayload = std::make_shared(renderItem); - if (_collisionRenderItems.empty() && statusGetters.size()) { - renderPayload->addStatusGetters(statusGetters); - } - transaction.resetItem(item, renderPayload); - _collisionRenderItemsMap.insert(item, renderPayload); + + if (_modelMeshRenderItemsMap.empty()) { + + bool hasTransparent = false; + size_t verticesCount = 0; + foreach(auto renderItem, _modelMeshRenderItems) { + auto item = scene->allocateID(); + auto renderPayload = std::make_shared(renderItem); + if (_modelMeshRenderItemsMap.empty() && statusGetters.size()) { + renderPayload->addStatusGetters(statusGetters); } - somethingAdded = !_collisionRenderItemsMap.empty(); + transaction.resetItem(item, renderPayload); + + hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent(); + verticesCount += renderItem.get()->getVerticesCount(); + _modelMeshRenderItemsMap.insert(item, renderPayload); + _modelMeshRenderItemIDs.emplace_back(item); } - } else { - if (_modelMeshRenderItemsMap.empty()) { + somethingAdded = !_modelMeshRenderItemsMap.empty(); - bool hasTransparent = false; - size_t verticesCount = 0; - foreach(auto renderItem, _modelMeshRenderItems) { - auto item = scene->allocateID(); - auto renderPayload = std::make_shared(renderItem); - if (_modelMeshRenderItemsMap.empty() && statusGetters.size()) { - renderPayload->addStatusGetters(statusGetters); - } - transaction.resetItem(item, renderPayload); - - hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent(); - verticesCount += renderItem.get()->getVerticesCount(); - _modelMeshRenderItemsMap.insert(item, renderPayload); - _modelMeshRenderItemIDs.emplace_back(item); - } - somethingAdded = !_modelMeshRenderItemsMap.empty(); - - _renderInfoVertexCount = verticesCount; - _renderInfoDrawCalls = _modelMeshRenderItemsMap.count(); - _renderInfoHasTransparent = hasTransparent; - } + _renderInfoVertexCount = verticesCount; + _renderInfoDrawCalls = _modelMeshRenderItemsMap.count(); + _renderInfoHasTransparent = hasTransparent; } if (somethingAdded) { @@ -926,11 +867,6 @@ void Model::removeFromScene(const render::ScenePointer& scene, render::Transacti _modelMeshMaterialNames.clear(); _modelMeshRenderItemShapes.clear(); - foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.removeItem(item); - } - _collisionRenderItems.clear(); - _collisionRenderItemsMap.clear(); _addedToScene = false; _renderInfoVertexCount = 0; @@ -1505,7 +1441,6 @@ void Model::deleteGeometry() { _rig.destroyAnimGraph(); _blendedBlendshapeCoefficients.clear(); _renderGeometry.reset(); - _collisionGeometry.reset(); } void Model::overrideModelTransformAndOffset(const Transform& transform, const glm::vec3& offset) { @@ -1533,19 +1468,6 @@ const render::ItemIDs& Model::fetchRenderItemIDs() const { return _modelMeshRenderItemIDs; } -void Model::createRenderItemSet() { - updateClusterMatrices(); - if (_collisionGeometry) { - if (_collisionRenderItems.empty()) { - createCollisionRenderItemSet(); - } - } else { - if (_modelMeshRenderItems.empty()) { - createVisibleRenderItemSet(); - } - } -}; - void Model::createVisibleRenderItemSet() { assert(isLoaded()); const auto& meshes = _renderGeometry->getMeshes(); @@ -1592,41 +1514,6 @@ void Model::createVisibleRenderItemSet() { } } -void Model::createCollisionRenderItemSet() { - assert((bool)_collisionGeometry); - if (_collisionMaterials.empty()) { - initCollisionMaterials(); - } - - const auto& meshes = _collisionGeometry->getMeshes(); - - // We should not have any existing renderItems if we enter this section of code - Q_ASSERT(_collisionRenderItems.isEmpty()); - - Transform identity; - identity.setIdentity(); - Transform offset; - offset.postTranslate(_offset); - - // Run through all of the meshes, and place them into their segregated, but unsorted buckets - uint32_t numMeshes = (uint32_t)meshes.size(); - for (uint32_t i = 0; i < numMeshes; i++) { - const auto& mesh = meshes.at(i); - if (!mesh) { - continue; - } - - // Create the render payloads - int numParts = (int)mesh->getNumParts(); - for (int partIndex = 0; partIndex < numParts; partIndex++) { - graphics::MaterialPointer& material = _collisionMaterials[partIndex % NUM_COLLISION_HULL_COLORS]; - auto payload = std::make_shared(mesh, partIndex, material); - payload->updateTransform(identity, offset); - _collisionRenderItems << payload; - } - } -} - bool Model::isRenderable() const { return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty()); } @@ -1710,15 +1597,6 @@ public: } }; -void Model::setCollisionMesh(graphics::MeshPointer mesh) { - if (mesh) { - _collisionGeometry = std::make_shared(mesh); - } else { - _collisionGeometry.reset(); - } - _needsFixupInScene = true; -} - ModelBlender::ModelBlender() : _pendingBlenders(0) { } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 4180288106..d15ea6f33b 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -153,8 +153,6 @@ public: /// Returns a reference to the shared geometry. const Geometry::Pointer& getGeometry() const { return _renderGeometry; } - /// Returns a reference to the shared collision geometry. - const Geometry::Pointer& getCollisionGeometry() const { return _collisionGeometry; } const QVariantMap getTextures() const { assert(isLoaded()); return _renderGeometry->getTextures(); } Q_INVOKABLE virtual void setTextures(const QVariantMap& textures); @@ -260,7 +258,6 @@ public: // returns 'true' if needs fullUpdate after geometry change virtual bool updateGeometry(); - void setCollisionMesh(graphics::MeshPointer mesh); void setLoadingPriority(float priority) { _loadingPriority = priority; } @@ -362,7 +359,6 @@ protected: bool getJointPosition(int jointIndex, glm::vec3& position) const; Geometry::Pointer _renderGeometry; // only ever set by its watcher - Geometry::Pointer _collisionGeometry; GeometryResourceWatcher _renderWatcher; @@ -430,9 +426,7 @@ protected: QVector _modelSpaceMeshTriangleSets; // model space triangles for all sub meshes - void createRenderItemSet(); virtual void createVisibleRenderItemSet(); - virtual void createCollisionRenderItemSet(); bool _isWireframe; bool _useDualQuaternionSkinning { false }; @@ -443,9 +437,6 @@ protected: static AbstractViewStateInterface* _viewState; - QVector> _collisionRenderItems; - QMap _collisionRenderItemsMap; - QVector> _modelMeshRenderItems; QMap _modelMeshRenderItemsMap; render::ItemIDs _modelMeshRenderItemIDs; From 4c39d08358cfc152258d96b33fadf99de0f40549 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Mon, 11 Jun 2018 11:02:25 -0700 Subject: [PATCH 02/12] Remove "Draw Collision Shapes" option from developer physics menu --- interface/src/Application.cpp | 3 --- interface/src/Application_render.cpp | 4 ---- interface/src/Menu.cpp | 1 - interface/src/Menu.h | 1 - libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 1 + 5 files changed, 1 insertion(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c5857dac53..ab494a2f93 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2250,9 +2250,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setSetPrecisionPickingOperator([&](unsigned int rayPickID, bool value) { DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); - EntityTreeRenderer::setRenderDebugHullsOperator([] { - return Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls); - }); // Preload Tablet sounds DependencyManager::get()->preloadSounds(); diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 2208b3187c..2daa49dcf7 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -205,10 +205,6 @@ void Application::runRenderFrame(RenderArgs* renderArgs) { RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE; - if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls)) { - renderDebugFlags = static_cast(renderDebugFlags | - static_cast(RenderArgs::RENDER_DEBUG_HULLS)); - } renderArgs->_debugFlags = renderDebugFlags; } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6f4300862d..20aefbe7e0 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -725,7 +725,6 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowOwned, 0, false, drawStatusConfig, SLOT(setShowNetwork(bool))); } - addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls, 0, false, qApp->getEntities().data(), SIGNAL(setRenderDebugHulls())); addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletWireframe, 0, false, qApp, SLOT(setShowBulletWireframe(bool))); addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletAABBs, 0, false, qApp, SLOT(setShowBulletAABBs(bool))); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 6fb089acd8..1ab7faa82b 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -141,7 +141,6 @@ namespace MenuOption { const QString Overlays = "Show Overlays"; const QString PackageModel = "Package Model as .fst..."; const QString Pair = "Pair"; - const QString PhysicsShowHulls = "Draw Collision Shapes"; const QString PhysicsShowOwned = "Highlight Simulation Ownership"; const QString VerboseLogging = "Verbose Logging"; const QString PhysicsShowBulletWireframe = "Show Bullet Collision"; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e0039082fa..f12d2dc180 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1052,6 +1052,7 @@ using namespace render; using namespace render::entities; ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { + // TODO: Re-add menu item in Menu.ccp/Menu.h when collision model updates in doRenderUpdateSynchronousTyped(...) are re-implemented connect(DependencyManager::get().data(), &EntityTreeRenderer::setRenderDebugHulls, this, [&] { _needsCollisionGeometryUpdate = true; emit requestRenderUpdate(); From a6202cf3cbe2834551720c6d31b9887aaeb30d8f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 13 Jun 2018 11:31:14 -0700 Subject: [PATCH 03/12] fixing invisible cursor --- .../controllers/controllerModules/mouseHMD.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/controllerModules/mouseHMD.js b/scripts/system/controllers/controllerModules/mouseHMD.js index 1d8aeee1f9..101a3502e1 100644 --- a/scripts/system/controllers/controllerModules/mouseHMD.js +++ b/scripts/system/controllers/controllerModules/mouseHMD.js @@ -101,12 +101,15 @@ this.isReady = function(controllerData, deltaTime) { var now = Date.now(); this.triggersPressed(controllerData, now); - if ((HMD.active && !this.mouseActivity.expired(now)) && _this.handControllerActivity.expired()) { - Reticle.visible = true; - return ControllerDispatcherUtils.makeRunningValues(true, [], []); - } if (HMD.active) { - Reticle.visible = false; + if (!this.mouseActivity.expired(now) && _this.handControllerActivity.expired()) { + Reticle.visible = true; + return ControllerDispatcherUtils.makeRunningValues(true, [], []); + } else { + Reticle.visible = false; + } + } else if (!Reticle.visible) { + Reticle.visible = true; } return ControllerDispatcherUtils.makeRunningValues(false, [], []); From 82fddfc31f6ff521a1386b429e9c2e504f637aa6 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Wed, 13 Jun 2018 13:03:07 -0700 Subject: [PATCH 04/12] Remove unused constant in Model.cpp --- libraries/render-utils/src/Model.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index ca0bde9d6a..1e15bacb03 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -47,8 +47,6 @@ int vec3VectorTypeId = qRegisterMetaType >(); float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f; #define HTTP_INVALID_COM "http://invalid.com" -const int NUM_COLLISION_HULL_COLORS = 24; - Model::Model(QObject* parent, SpatiallyNestable* spatiallyNestableOverride) : QObject(parent), _renderGeometry(), From 6b59b5b53cb5194e70e2ef6a0bac3d2aedf084a6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 13 Jun 2018 13:23:43 -0700 Subject: [PATCH 05/12] MS15501: Fix keyboard in Create -> Model in HMD --- interface/resources/qml/hifi/tablet/NewModelDialog.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/NewModelDialog.qml b/interface/resources/qml/hifi/tablet/NewModelDialog.qml index a349653525..8f6718e1f3 100644 --- a/interface/resources/qml/hifi/tablet/NewModelDialog.qml +++ b/interface/resources/qml/hifi/tablet/NewModelDialog.qml @@ -24,6 +24,7 @@ Rectangle { color: hifi.colors.baseGray; signal sendToScript(var message); property bool keyboardEnabled: false + property bool keyboardRaised: false property bool punctuationMode: false property bool keyboardRasied: false @@ -235,10 +236,11 @@ Rectangle { Keyboard { id: keyboard - raised: parent.keyboardEnabled + raised: parent.keyboardEnabled && parent.keyboardRaised numeric: parent.punctuationMode anchors { bottom: parent.bottom + bottomMargin: 40 left: parent.left right: parent.right } From abee3e8b96d36ce6430633d9463b827ee79b198f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 13 Jun 2018 17:07:05 -0700 Subject: [PATCH 06/12] fix focus issue when mouse is offscreen --- scripts/system/away.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/system/away.js b/scripts/system/away.js index dc9b33e952..a2e73ae63c 100644 --- a/scripts/system/away.js +++ b/scripts/system/away.js @@ -177,6 +177,10 @@ function goActive() { UserActivityLogger.toggledAway(false); MyAvatar.isAway = false; + + if (!Window.hasFocus()) { + Window.setFocus(); + } } MyAvatar.wentAway.connect(setAwayProperties); From 3c681554de188c06a91a0a04d9ef02f1d0f4d7d4 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 13 Jun 2018 16:07:53 -0700 Subject: [PATCH 07/12] Fix MS13202: Don't save incomplete list of scripts to Settings while reloading scripts --- libraries/script-engine/src/ScriptEngines.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index ad6e1debe9..b481a14f14 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -594,7 +594,7 @@ void ScriptEngines::onScriptFinished(const QString& rawScriptURL, ScriptEnginePo } } - if (removed) { + if (removed && !_isReloading) { // Update settings with removed script saveScripts(); emit scriptCountChanged(); From 8b4b95f89021610ab3acef5e04dbd0fa53d5c0fc Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 14 Jun 2018 14:00:40 -0700 Subject: [PATCH 08/12] prevent have more than one instance of a script after reloading script --- libraries/script-engine/src/ScriptEngines.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index ad6e1debe9..0a4834fd8d 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -432,10 +432,13 @@ bool ScriptEngines::stopScript(const QString& rawScriptURL, bool restart) { ScriptEngine::Type type = scriptEngine->getType(); auto scriptCache = DependencyManager::get(); scriptCache->deleteScript(scriptURL); - connect(scriptEngine.data(), &ScriptEngine::finished, - this, [this, isUserLoaded, type](QString scriptName, ScriptEnginePointer engine) { - reloadScript(scriptName, isUserLoaded)->setType(type); - }); + + if (!scriptEngine->isStopping()) { + connect(scriptEngine.data(), &ScriptEngine::finished, + this, [this, isUserLoaded, type](QString scriptName, ScriptEnginePointer engine) { + reloadScript(scriptName, isUserLoaded)->setType(type); + }); + } } scriptEngine->stop(); stoppedScript = true; From 3c4050884e053a8e2feaee3a69ffbfe668b083a3 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 14 Jun 2018 14:40:22 -0700 Subject: [PATCH 09/12] Remove straggler ifdef in Model class --- libraries/render-utils/src/Model.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 1e15bacb03..4ef0481633 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -725,14 +725,6 @@ void Model::updateRenderItemsKey(const render::ScenePointer& scene) { data.updateKey(renderItemsKey); }); } - //TODO: Remove -#ifdef RENDER_MODEL_BOUNDING_BOXES - foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [renderItemsKey](ModelMeshPartPayload& data) { - data.updateKey(renderItemsKey); - }); - } -#endif scene->enqueueTransaction(transaction); } From b2ec7f78c136dd1f47d8d1389421723673774bec Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 14 Jun 2018 14:53:44 -0700 Subject: [PATCH 10/12] Remove signaling and render code for collision models in RenderableModelEntityItem and EntityTreeRenderer --- .../src/EntityTreeRenderer.cpp | 1 - .../src/EntityTreeRenderer.h | 6 --- .../src/RenderableModelEntityItem.cpp | 45 +------------------ .../src/RenderableModelEntityItem.h | 2 - 4 files changed, 2 insertions(+), 52 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 600d1c32a8..ab282ea6f9 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -42,7 +42,6 @@ size_t std::hash::operator()(const EntityItemID& id) const { return qHash(id); } std::function EntityTreeRenderer::_entitiesShouldFadeFunction; -std::function EntityTreeRenderer::_renderDebugHullsOperator = [] { return false; }; EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, AbstractScriptingServicesInterface* scriptingServices) : diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 882ec2fd5b..de3033936a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -116,14 +116,10 @@ public: EntityItemPointer getEntity(const EntityItemID& id); void onEntityChanged(const EntityItemID& id); - static void setRenderDebugHullsOperator(std::function renderDebugHullsOperator) { _renderDebugHullsOperator = renderDebugHullsOperator; } - static bool shouldRenderDebugHulls() { return _renderDebugHullsOperator(); } - signals: void enterEntity(const EntityItemID& entityItemID); void leaveEntity(const EntityItemID& entityItemID); void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); - void setRenderDebugHulls(); public slots: void addingEntity(const EntityItemID& entityID); @@ -259,8 +255,6 @@ private: static int _entitiesScriptEngineCount; static CalculateEntityLoadingPriority _calculateEntityLoadingPriorityFunc; static std::function _entitiesShouldFadeFunction; - - static std::function _renderDebugHullsOperator; }; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f12d2dc180..be385008a3 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -35,8 +34,6 @@ #include "EntitiesRendererLogging.h" -static CollisionRenderMeshCache collisionMeshCache; - void ModelEntityWrapper::setModel(const ModelPointer& model) { withWriteLock([&] { if (_model != model) { @@ -1052,11 +1049,7 @@ using namespace render; using namespace render::entities; ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { - // TODO: Re-add menu item in Menu.ccp/Menu.h when collision model updates in doRenderUpdateSynchronousTyped(...) are re-implemented - connect(DependencyManager::get().data(), &EntityTreeRenderer::setRenderDebugHulls, this, [&] { - _needsCollisionGeometryUpdate = true; - emit requestRenderUpdate(); - }); + } void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) { @@ -1216,10 +1209,6 @@ bool ModelEntityRenderer::needsRenderUpdate() const { if (model->getRenderItemsNeedUpdate()) { return true; } - - if (_needsCollisionGeometryUpdate) { - return true; - } } return Parent::needsRenderUpdate(); } @@ -1286,12 +1275,7 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin } void ModelEntityRenderer::setCollisionMeshKey(const void*key) { - if (key != _collisionMeshKey) { - if (_collisionMeshKey) { - collisionMeshCache.releaseMesh(_collisionMeshKey); - } - _collisionMeshKey = key; - } + _collisionMeshKey = key; } void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { @@ -1340,7 +1324,6 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _didLastVisualGeometryRequestSucceed = didVisualGeometryRequestSucceed; }); connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate); - connect(entity.get(), &RenderableModelEntityItem::requestCollisionGeometryUpdate, this, &ModelEntityRenderer::flagForCollisionGeometryUpdate); model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity)); entity->setModel(model); withWriteLock([&] { _model = model; }); @@ -1413,25 +1396,6 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce model->setCanCastShadow(_canCastShadow, scene); } - if (_needsCollisionGeometryUpdate) { - setCollisionMeshKey(entity->getCollisionMeshKey()); - _needsCollisionGeometryUpdate = false; - ShapeType type = entity->getShapeType(); - if (DependencyManager::get()->shouldRenderDebugHulls() && type != SHAPE_TYPE_NONE) { - // NOTE: it is OK if _collisionMeshKey is nullptr - graphics::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey); - // TODO: Start displaying collision model - - } else { - if (_collisionMeshKey) { - // release mesh - collisionMeshCache.releaseMesh(_collisionMeshKey); - } - // TODO: Stop displaying collision model - - } - } - { DETAILED_PROFILE_RANGE(simulation_physics, "Fixup"); if (model->needsFixupInScene()) { @@ -1487,11 +1451,6 @@ void ModelEntityRenderer::setIsVisibleInSecondaryCamera(bool value) { setKey(_didLastVisualGeometryRequestSucceed); } -void ModelEntityRenderer::flagForCollisionGeometryUpdate() { - _needsCollisionGeometryUpdate = true; - emit requestRenderUpdate(); -} - // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items void ModelEntityRenderer::doRender(RenderArgs* args) { DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender"); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index f1748ca069..50d8801363 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -161,7 +161,6 @@ protected: virtual bool needsRenderUpdate() const override; virtual void doRender(RenderArgs* args) override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; - void flagForCollisionGeometryUpdate(); void setCollisionMeshKey(const void* key); render::hifi::Tag getTagMask() const override; @@ -189,7 +188,6 @@ private: #endif bool _needsJointSimulation { false }; - bool _needsCollisionGeometryUpdate { false }; const void* _collisionMeshKey { nullptr }; // used on client side From 79fd3cb181e001dd25ef157de5db98bebb08aa5a Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Thu, 14 Jun 2018 14:59:01 -0700 Subject: [PATCH 11/12] Rename createVisibleRenderItemSet() to createRenderItemSet() in Model class --- libraries/render-utils/src/CauterizedModel.cpp | 4 ++-- libraries/render-utils/src/CauterizedModel.h | 2 +- libraries/render-utils/src/Model.cpp | 4 ++-- libraries/render-utils/src/Model.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 53dcc74d35..80a9c5ccae 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -47,7 +47,7 @@ bool CauterizedModel::updateGeometry() { return needsFullUpdate; } -void CauterizedModel::createVisibleRenderItemSet() { +void CauterizedModel::createRenderItemSet() { if (_isCauterized) { assert(isLoaded()); const auto& meshes = _renderGeometry->getMeshes(); @@ -94,7 +94,7 @@ void CauterizedModel::createVisibleRenderItemSet() { } } } else { - Model::createVisibleRenderItemSet(); + Model::createRenderItemSet(); } } diff --git a/libraries/render-utils/src/CauterizedModel.h b/libraries/render-utils/src/CauterizedModel.h index 5abefb474f..36a96fb006 100644 --- a/libraries/render-utils/src/CauterizedModel.h +++ b/libraries/render-utils/src/CauterizedModel.h @@ -31,7 +31,7 @@ public: void deleteGeometry() override; bool updateGeometry() override; - void createVisibleRenderItemSet() override; + void createRenderItemSet() override; virtual void updateClusterMatrices() override; void updateRenderItems() override; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 4ef0481633..562c7e2217 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -808,7 +808,7 @@ bool Model::addToScene(const render::ScenePointer& scene, if (!_addedToScene && isLoaded()) { updateClusterMatrices(); if (_modelMeshRenderItems.empty()) { - createVisibleRenderItemSet(); + createRenderItemSet(); } } @@ -1458,7 +1458,7 @@ const render::ItemIDs& Model::fetchRenderItemIDs() const { return _modelMeshRenderItemIDs; } -void Model::createVisibleRenderItemSet() { +void Model::createRenderItemSet() { assert(isLoaded()); const auto& meshes = _renderGeometry->getMeshes(); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index d15ea6f33b..4331c431c9 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -426,7 +426,7 @@ protected: QVector _modelSpaceMeshTriangleSets; // model space triangles for all sub meshes - virtual void createVisibleRenderItemSet(); + virtual void createRenderItemSet(); bool _isWireframe; bool _useDualQuaternionSkinning { false }; From a932a509224fab3beac6de05e46bea00c0bb3ba2 Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 11 Jun 2018 18:42:10 -0700 Subject: [PATCH 12/12] Add audio dissector --- tools/dissectors/{hfudt.lua => 1-hfudt.lua} | 624 +++++++++--------- tools/dissectors/2-hf-audio.lua | 46 ++ .../{hf-avatar.lua => 3-hf-avatar.lua} | 2 + .../{hf-entity.lua => 4-hf-entity.lua} | 2 + .../{hf-domain.lua => 5-hf-domain.lua} | 0 5 files changed, 365 insertions(+), 309 deletions(-) rename tools/dissectors/{hfudt.lua => 1-hfudt.lua} (97%) create mode 100644 tools/dissectors/2-hf-audio.lua rename tools/dissectors/{hf-avatar.lua => 3-hf-avatar.lua} (99%) rename tools/dissectors/{hf-entity.lua => 4-hf-entity.lua} (99%) rename tools/dissectors/{hf-domain.lua => 5-hf-domain.lua} (100%) diff --git a/tools/dissectors/hfudt.lua b/tools/dissectors/1-hfudt.lua similarity index 97% rename from tools/dissectors/hfudt.lua rename to tools/dissectors/1-hfudt.lua index c8b1d9feee..fa491723fb 100644 --- a/tools/dissectors/hfudt.lua +++ b/tools/dissectors/1-hfudt.lua @@ -1,309 +1,315 @@ -print("Loading hfudt") - --- create the HFUDT protocol -p_hfudt = Proto("hfudt", "HFUDT Protocol") - --- create fields shared between packets in HFUDT -local f_data = ProtoField.string("hfudt.data", "Data") - --- create the fields for data packets in HFUDT -local f_length = ProtoField.uint16("hfudt.length", "Length", base.DEC) -local f_control_bit = ProtoField.uint8("hfudt.control", "Control Bit", base.DEC) -local f_reliable_bit = ProtoField.uint8("hfudt.reliable", "Reliability Bit", base.DEC) -local f_message_bit = ProtoField.uint8("hfudt.message", "Message Bit", base.DEC) -local f_obfuscation_level = ProtoField.uint8("hfudt.obfuscation_level", "Obfuscation Level", base.DEC) -local f_sequence_number = ProtoField.uint32("hfudt.sequence_number", "Sequence Number", base.DEC) -local f_message_position = ProtoField.uint8("hfudt.message_position", "Message Position", base.DEC) -local f_message_number = ProtoField.uint32("hfudt.message_number", "Message Number", base.DEC) -local f_message_part_number = ProtoField.uint32("hfudt.message_part_number", "Message Part Number", base.DEC) -local f_type = ProtoField.uint8("hfudt.type", "Type", base.DEC) -local f_version = ProtoField.uint8("hfudt.version", "Version", base.DEC) -local f_type_text = ProtoField.string("hfudt.type_text", "TypeText") -local f_sender_id = ProtoField.uint16("hfudt.sender_id", "Sender ID", base.DEC) -local f_hmac_hash = ProtoField.bytes("hfudt.hmac_hash", "HMAC Hash") - --- create the fields for control packets in HFUDT -local f_control_type = ProtoField.uint16("hfudt.control_type", "Control Type", base.DEC) -local f_control_type_text = ProtoField.string("hfudt.control_type_text", "Control Type Text", base.ASCII) -local f_ack_sequence_number = ProtoField.uint32("hfudt.ack_sequence_number", "ACKed Sequence Number", base.DEC) -local f_control_sub_sequence = ProtoField.uint32("hfudt.control_sub_sequence", "Control Sub-Sequence Number", base.DEC) -local f_nak_sequence_number = ProtoField.uint32("hfudt.nak_sequence_number", "NAKed Sequence Number", base.DEC) -local f_nak_range_end = ProtoField.uint32("hfudt.nak_range_end", "NAK Range End", base.DEC) - -local SEQUENCE_NUMBER_MASK = 0x07FFFFFF - -p_hfudt.fields = { - f_length, - f_control_bit, f_reliable_bit, f_message_bit, f_sequence_number, f_type, f_type_text, f_version, - f_sender_id, f_hmac_hash, - f_message_position, f_message_number, f_message_part_number, f_obfuscation_level, - f_control_type, f_control_type_text, f_control_sub_sequence, f_ack_sequence_number, f_nak_sequence_number, f_nak_range_end, - f_data -} - -local control_types = { - [0] = { "ACK", "Acknowledgement" }, - [1] = { "ACK2", "Acknowledgement of acknowledgement" }, - [2] = { "LightACK", "Light Acknowledgement" }, - [3] = { "NAK", "Loss report (NAK)" }, - [4] = { "TimeoutNAK", "Loss report re-transmission (TimeoutNAK)" }, - [5] = { "Handshake", "Handshake" }, - [6] = { "HandshakeACK", "Acknowledgement of Handshake" }, - [7] = { "ProbeTail", "Probe tail" }, - [8] = { "HandshakeRequest", "Request a Handshake" } -} - -local message_positions = { - [0] = "ONLY", - [1] = "LAST", - [2] = "FIRST", - [3] = "MIDDLE" -} - -local packet_types = { - [0] = "Unknown", - [1] = "StunResponse", - [2] = "DomainList", - [3] = "Ping", - [4] = "PingReply", - [5] = "KillAvatar", - [6] = "AvatarData", - [7] = "InjectAudio", - [8] = "MixedAudio", - [9] = "MicrophoneAudioNoEcho", - [10] = "MicrophoneAudioWithEcho", - [11] = "BulkAvatarData", - [12] = "SilentAudioFrame", - [13] = "DomainListRequest", - [14] = "RequestAssignment", - [15] = "CreateAssignment", - [16] = "DomainConnectionDenied", - [17] = "MuteEnvironment", - [18] = "AudioStreamStats", - [19] = "DomainServerPathQuery", - [20] = "DomainServerPathResponse", - [21] = "DomainServerAddedNode", - [22] = "ICEServerPeerInformation", - [23] = "ICEServerQuery", - [24] = "OctreeStats", - [25] = "Jurisdiction", - [26] = "JurisdictionRequest", - [27] = "AssignmentClientStatus", - [28] = "NoisyMute", - [29] = "AvatarIdentity", - [30] = "AvatarBillboard", - [31] = "DomainConnectRequest", - [32] = "DomainServerRequireDTLS", - [33] = "NodeJsonStats", - [34] = "OctreeDataNack", - [35] = "StopNode", - [36] = "AudioEnvironment", - [37] = "EntityEditNack", - [38] = "ICEServerHeartbeat", - [39] = "ICEPing", - [40] = "ICEPingReply", - [41] = "EntityData", - [42] = "EntityQuery", - [43] = "EntityAdd", - [44] = "EntityErase", - [45] = "EntityEdit", - [46] = "DomainServerConnectionToken", - [47] = "DomainSettingsRequest", - [48] = "DomainSettings", - [49] = "AssetGet", - [50] = "AssetGetReply", - [51] = "AssetUpload", - [52] = "AssetUploadReply", - [53] = "AssetGetInfo", - [54] = "AssetGetInfoReply" -} - -local unsourced_packet_types = { - ["DomainList"] = true -} - -function p_hfudt.dissector(buf, pinfo, tree) - - -- make sure this isn't a STUN packet - those don't follow HFUDT format - if pinfo.dst == Address.ip("stun.highfidelity.io") then return end - - -- validate that the packet length is at least the minimum control packet size - if buf:len() < 4 then return end - - -- create a subtree for HFUDT - subtree = tree:add(p_hfudt, buf(0)) - - -- set the packet length - subtree:add(f_length, buf:len()) - - -- pull out the entire first word - local first_word = buf(0, 4):le_uint() - - -- pull out the control bit and add it to the subtree - local control_bit = bit32.rshift(first_word, 31) - subtree:add(f_control_bit, control_bit) - - local data_length = 0 - - if control_bit == 1 then - -- dissect the control packet - pinfo.cols.protocol = p_hfudt.name .. " Control" - - -- remove the control bit and shift to the right to get the type value - local shifted_type = bit32.rshift(bit32.lshift(first_word, 1), 17) - local type = subtree:add(f_control_type, shifted_type) - - if control_types[shifted_type] ~= nil then - -- if we know this type then add the name - type:append_text(" (".. control_types[shifted_type][1] .. ")") - - subtree:add(f_control_type_text, control_types[shifted_type][1]) - end - - if shifted_type == 0 or shifted_type == 1 then - - -- this has a sub-sequence number - local second_word = buf(4, 4):le_uint() - subtree:add(f_control_sub_sequence, bit32.band(second_word, SEQUENCE_NUMBER_MASK)) - - local data_index = 8 - - if shifted_type == 0 then - -- if this is an ACK let's read out the sequence number - local sequence_number = buf(8, 4):le_uint() - subtree:add(f_ack_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) - - data_index = data_index + 4 - end - - data_length = buf:len() - data_index - - -- set the data from whatever is left in the packet - subtree:add(f_data, buf(data_index, data_length)) - - elseif shifted_type == 2 then - -- this is a Light ACK let's read out the sequence number - local sequence_number = buf(4, 4):le_uint() - subtree:add(f_ack_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) - - data_length = buf:len() - 4 - - -- set the data from whatever is left in the packet - subtree:add(f_data, buf(4, data_length)) - elseif shifted_type == 3 or shifted_type == 4 then - if buf:len() <= 12 then - -- this is a NAK pull the sequence number or range - local sequence_number = buf(4, 4):le_uint() - subtree:add(f_nak_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) - - data_length = buf:len() - 4 - - if buf:len() > 8 then - local range_end = buf(8, 4):le_uint() - subtree:add(f_nak_range_end, bit32.band(range_end, SEQUENCE_NUMBER_MASK)) - - data_length = data_length - 4 - end - end - else - data_length = buf:len() - 4 - - -- no sub-sequence number, just read the data - subtree:add(f_data, buf(4, data_length)) - end - else - -- dissect the data packet - pinfo.cols.protocol = p_hfudt.name - - -- set the reliability bit - subtree:add(f_reliable_bit, bit32.rshift(first_word, 30)) - - local message_bit = bit32.band(0x01, bit32.rshift(first_word, 29)) - - -- set the message bit - subtree:add(f_message_bit, message_bit) - - -- read the obfuscation level - local obfuscation_bits = bit32.band(0x03, bit32.rshift(first_word, 27)) - subtree:add(f_obfuscation_level, obfuscation_bits) - - -- read the sequence number - subtree:add(f_sequence_number, bit32.band(first_word, SEQUENCE_NUMBER_MASK)) - - local payload_offset = 4 - - -- if the message bit is set, handle the second word - if message_bit == 1 then - payload_offset = 12 - - local second_word = buf(4, 4):le_uint() - - -- read message position from upper 2 bits - local message_position = bit32.rshift(second_word, 30) - local position = subtree:add(f_message_position, message_position) - - if message_positions[message_position] ~= nil then - -- if we know this position then add the name - position:append_text(" (".. message_positions[message_position] .. ")") - end - - -- read message number from lower 30 bits - subtree:add(f_message_number, bit32.band(second_word, 0x3FFFFFFF)) - - -- read the message part number - subtree:add(f_message_part_number, buf(8, 4):le_uint()) - end - - -- read the type - local packet_type = buf(payload_offset, 1):le_uint() - local ptype = subtree:add_le(f_type, buf(payload_offset, 1)) - local packet_type_text = packet_types[packet_type] - if packet_type_text ~= nil then - subtree:add(f_type_text, packet_type_text) - -- if we know this packet type then add the name - ptype:append_text(" (".. packet_type_text .. ")") - end - - -- read the version - subtree:add_le(f_version, buf(payload_offset + 1, 1)) - - local i = payload_offset + 2 - - if unsourced_packet_types[packet_type_text] == nil then - -- read node local ID - local sender_id = buf(payload_offset + 2, 2) - subtree:add_le(f_sender_id, sender_id) - i = i + 2 - - -- read HMAC MD5 hash - subtree:add(f_hmac_hash, buf(i, 16)) - i = i + 16 - end - - -- Domain packets - if packet_type_text == "DomainList" then - Dissector.get("hf-domain"):call(buf(i):tvb(), pinfo, tree) - end - - -- AvatarData or BulkAvatarDataPacket - if packet_type_text == "AvatarData" or packet_type_text == "BulkAvatarData" then - Dissector.get("hf-avatar"):call(buf(i):tvb(), pinfo, tree) - end - - if packet_type_text == "EntityEdit" then - Dissector.get("hf-entity"):call(buf(i):tvb(), pinfo, tree) - end - end - - -- return the size of the header - return buf:len() - -end - -function p_hfudt.init() - local udp_dissector_table = DissectorTable.get("udp.port") - - for port=1000, 65000 do - udp_dissector_table:add(port, p_hfudt) - end -end +print("Loading hfudt") + +-- create the HFUDT protocol +p_hfudt = Proto("hfudt", "HFUDT Protocol") + +-- create fields shared between packets in HFUDT +local f_data = ProtoField.string("hfudt.data", "Data") + +-- create the fields for data packets in HFUDT +local f_length = ProtoField.uint16("hfudt.length", "Length", base.DEC) +local f_control_bit = ProtoField.uint8("hfudt.control", "Control Bit", base.DEC) +local f_reliable_bit = ProtoField.uint8("hfudt.reliable", "Reliability Bit", base.DEC) +local f_message_bit = ProtoField.uint8("hfudt.message", "Message Bit", base.DEC) +local f_obfuscation_level = ProtoField.uint8("hfudt.obfuscation_level", "Obfuscation Level", base.DEC) +local f_sequence_number = ProtoField.uint32("hfudt.sequence_number", "Sequence Number", base.DEC) +local f_message_position = ProtoField.uint8("hfudt.message_position", "Message Position", base.DEC) +local f_message_number = ProtoField.uint32("hfudt.message_number", "Message Number", base.DEC) +local f_message_part_number = ProtoField.uint32("hfudt.message_part_number", "Message Part Number", base.DEC) +local f_type = ProtoField.uint8("hfudt.type", "Type", base.DEC) +local f_version = ProtoField.uint8("hfudt.version", "Version", base.DEC) +local f_type_text = ProtoField.string("hfudt.type_text", "TypeText") +local f_sender_id = ProtoField.uint16("hfudt.sender_id", "Sender ID", base.DEC) +local f_hmac_hash = ProtoField.bytes("hfudt.hmac_hash", "HMAC Hash") + +-- create the fields for control packets in HFUDT +local f_control_type = ProtoField.uint16("hfudt.control_type", "Control Type", base.DEC) +local f_control_type_text = ProtoField.string("hfudt.control_type_text", "Control Type Text", base.ASCII) +local f_ack_sequence_number = ProtoField.uint32("hfudt.ack_sequence_number", "ACKed Sequence Number", base.DEC) +local f_control_sub_sequence = ProtoField.uint32("hfudt.control_sub_sequence", "Control Sub-Sequence Number", base.DEC) +local f_nak_sequence_number = ProtoField.uint32("hfudt.nak_sequence_number", "NAKed Sequence Number", base.DEC) +local f_nak_range_end = ProtoField.uint32("hfudt.nak_range_end", "NAK Range End", base.DEC) + +local SEQUENCE_NUMBER_MASK = 0x07FFFFFF + +p_hfudt.fields = { + f_length, + f_control_bit, f_reliable_bit, f_message_bit, f_sequence_number, f_type, f_type_text, f_version, + f_sender_id, f_hmac_hash, + f_message_position, f_message_number, f_message_part_number, f_obfuscation_level, + f_control_type, f_control_type_text, f_control_sub_sequence, f_ack_sequence_number, f_nak_sequence_number, f_nak_range_end, + f_data +} + +local control_types = { + [0] = { "ACK", "Acknowledgement" }, + [1] = { "ACK2", "Acknowledgement of acknowledgement" }, + [2] = { "LightACK", "Light Acknowledgement" }, + [3] = { "NAK", "Loss report (NAK)" }, + [4] = { "TimeoutNAK", "Loss report re-transmission (TimeoutNAK)" }, + [5] = { "Handshake", "Handshake" }, + [6] = { "HandshakeACK", "Acknowledgement of Handshake" }, + [7] = { "ProbeTail", "Probe tail" }, + [8] = { "HandshakeRequest", "Request a Handshake" } +} + +local message_positions = { + [0] = "ONLY", + [1] = "LAST", + [2] = "FIRST", + [3] = "MIDDLE" +} + +local packet_types = { + [0] = "Unknown", + [1] = "StunResponse", + [2] = "DomainList", + [3] = "Ping", + [4] = "PingReply", + [5] = "KillAvatar", + [6] = "AvatarData", + [7] = "InjectAudio", + [8] = "MixedAudio", + [9] = "MicrophoneAudioNoEcho", + [10] = "MicrophoneAudioWithEcho", + [11] = "BulkAvatarData", + [12] = "SilentAudioFrame", + [13] = "DomainListRequest", + [14] = "RequestAssignment", + [15] = "CreateAssignment", + [16] = "DomainConnectionDenied", + [17] = "MuteEnvironment", + [18] = "AudioStreamStats", + [19] = "DomainServerPathQuery", + [20] = "DomainServerPathResponse", + [21] = "DomainServerAddedNode", + [22] = "ICEServerPeerInformation", + [23] = "ICEServerQuery", + [24] = "OctreeStats", + [25] = "Jurisdiction", + [26] = "JurisdictionRequest", + [27] = "AssignmentClientStatus", + [28] = "NoisyMute", + [29] = "AvatarIdentity", + [30] = "AvatarBillboard", + [31] = "DomainConnectRequest", + [32] = "DomainServerRequireDTLS", + [33] = "NodeJsonStats", + [34] = "OctreeDataNack", + [35] = "StopNode", + [36] = "AudioEnvironment", + [37] = "EntityEditNack", + [38] = "ICEServerHeartbeat", + [39] = "ICEPing", + [40] = "ICEPingReply", + [41] = "EntityData", + [42] = "EntityQuery", + [43] = "EntityAdd", + [44] = "EntityErase", + [45] = "EntityEdit", + [46] = "DomainServerConnectionToken", + [47] = "DomainSettingsRequest", + [48] = "DomainSettings", + [49] = "AssetGet", + [50] = "AssetGetReply", + [51] = "AssetUpload", + [52] = "AssetUploadReply", + [53] = "AssetGetInfo", + [54] = "AssetGetInfoReply" +} + +local unsourced_packet_types = { + ["DomainList"] = true +} + +function p_hfudt.dissector(buf, pinfo, tree) + + -- make sure this isn't a STUN packet - those don't follow HFUDT format + if pinfo.dst == Address.ip("stun.highfidelity.io") then return end + + -- validate that the packet length is at least the minimum control packet size + if buf:len() < 4 then return end + + -- create a subtree for HFUDT + subtree = tree:add(p_hfudt, buf(0)) + + -- set the packet length + subtree:add(f_length, buf:len()) + + -- pull out the entire first word + local first_word = buf(0, 4):le_uint() + + -- pull out the control bit and add it to the subtree + local control_bit = bit32.rshift(first_word, 31) + subtree:add(f_control_bit, control_bit) + + local data_length = 0 + + if control_bit == 1 then + -- dissect the control packet + pinfo.cols.protocol = p_hfudt.name .. " Control" + + -- remove the control bit and shift to the right to get the type value + local shifted_type = bit32.rshift(bit32.lshift(first_word, 1), 17) + local type = subtree:add(f_control_type, shifted_type) + + if control_types[shifted_type] ~= nil then + -- if we know this type then add the name + type:append_text(" (".. control_types[shifted_type][1] .. ")") + + subtree:add(f_control_type_text, control_types[shifted_type][1]) + end + + if shifted_type == 0 or shifted_type == 1 then + + -- this has a sub-sequence number + local second_word = buf(4, 4):le_uint() + subtree:add(f_control_sub_sequence, bit32.band(second_word, SEQUENCE_NUMBER_MASK)) + + local data_index = 8 + + if shifted_type == 0 then + -- if this is an ACK let's read out the sequence number + local sequence_number = buf(8, 4):le_uint() + subtree:add(f_ack_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) + + data_index = data_index + 4 + end + + data_length = buf:len() - data_index + + -- set the data from whatever is left in the packet + subtree:add(f_data, buf(data_index, data_length)) + + elseif shifted_type == 2 then + -- this is a Light ACK let's read out the sequence number + local sequence_number = buf(4, 4):le_uint() + subtree:add(f_ack_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) + + data_length = buf:len() - 4 + + -- set the data from whatever is left in the packet + subtree:add(f_data, buf(4, data_length)) + elseif shifted_type == 3 or shifted_type == 4 then + if buf:len() <= 12 then + -- this is a NAK pull the sequence number or range + local sequence_number = buf(4, 4):le_uint() + subtree:add(f_nak_sequence_number, bit32.band(sequence_number, SEQUENCE_NUMBER_MASK)) + + data_length = buf:len() - 4 + + if buf:len() > 8 then + local range_end = buf(8, 4):le_uint() + subtree:add(f_nak_range_end, bit32.band(range_end, SEQUENCE_NUMBER_MASK)) + + data_length = data_length - 4 + end + end + else + data_length = buf:len() - 4 + + -- no sub-sequence number, just read the data + subtree:add(f_data, buf(4, data_length)) + end + else + -- dissect the data packet + pinfo.cols.protocol = p_hfudt.name + + -- set the reliability bit + subtree:add(f_reliable_bit, bit32.rshift(first_word, 30)) + + local message_bit = bit32.band(0x01, bit32.rshift(first_word, 29)) + + -- set the message bit + subtree:add(f_message_bit, message_bit) + + -- read the obfuscation level + local obfuscation_bits = bit32.band(0x03, bit32.rshift(first_word, 27)) + subtree:add(f_obfuscation_level, obfuscation_bits) + + -- read the sequence number + subtree:add(f_sequence_number, bit32.band(first_word, SEQUENCE_NUMBER_MASK)) + + local payload_offset = 4 + + -- if the message bit is set, handle the second word + if message_bit == 1 then + payload_offset = 12 + + local second_word = buf(4, 4):le_uint() + + -- read message position from upper 2 bits + local message_position = bit32.rshift(second_word, 30) + local position = subtree:add(f_message_position, message_position) + + if message_positions[message_position] ~= nil then + -- if we know this position then add the name + position:append_text(" (".. message_positions[message_position] .. ")") + end + + -- read message number from lower 30 bits + subtree:add(f_message_number, bit32.band(second_word, 0x3FFFFFFF)) + + -- read the message part number + subtree:add(f_message_part_number, buf(8, 4):le_uint()) + end + + -- read the type + local packet_type = buf(payload_offset, 1):le_uint() + local ptype = subtree:add_le(f_type, buf(payload_offset, 1)) + local packet_type_text = packet_types[packet_type] + if packet_type_text ~= nil then + subtree:add(f_type_text, packet_type_text) + -- if we know this packet type then add the name + ptype:append_text(" (".. packet_type_text .. ")") + end + + -- read the version + subtree:add_le(f_version, buf(payload_offset + 1, 1)) + + local i = payload_offset + 2 + + if unsourced_packet_types[packet_type_text] == nil then + -- read node local ID + local sender_id = buf(payload_offset + 2, 2) + subtree:add_le(f_sender_id, sender_id) + i = i + 2 + + -- read HMAC MD5 hash + subtree:add(f_hmac_hash, buf(i, 16)) + i = i + 16 + end + + -- Domain packets + if packet_type_text == "DomainList" then + Dissector.get("hf-domain"):call(buf(i):tvb(), pinfo, tree) + end + + -- AvatarData or BulkAvatarDataPacket + if packet_type_text == "AvatarData" or packet_type_text == "BulkAvatarData" then + Dissector.get("hf-avatar"):call(buf(i):tvb(), pinfo, tree) + end + + if packet_type_text == "EntityEdit" then + Dissector.get("hf-entity"):call(buf(i):tvb(), pinfo, tree) + end + + if packet_types[packet_type] == "MicrophoneAudioNoEcho" or + packet_types[packet_type] == "MicrophoneAudioWithEcho" or + packet_types[packet_type] == "SilentAudioFrame" then + Dissector.get("hf-audio"):call(buf(i):tvb(), pinfo, tree) + end + end + + -- return the size of the header + return buf:len() + +end + +function p_hfudt.init() + local udp_dissector_table = DissectorTable.get("udp.port") + + for port=1000, 65000 do + udp_dissector_table:add(port, p_hfudt) + end +end diff --git a/tools/dissectors/2-hf-audio.lua b/tools/dissectors/2-hf-audio.lua new file mode 100644 index 0000000000..fa4d50fab1 --- /dev/null +++ b/tools/dissectors/2-hf-audio.lua @@ -0,0 +1,46 @@ +print("Loading hf-audio") + +-- create the audio protocol +p_hf_audio = Proto("hf-audio", "HF Audio Protocol") + +-- audio packet fields +local f_audio_sequence_number = ProtoField.uint16("hf_audio.sequence_number", "Sequence Number") +local f_audio_codec_size = ProtoField.uint32("hf_audio.codec_size", "Codec Size") +local f_audio_codec = ProtoField.string("hf_audio.codec", "Codec") +local f_audio_is_stereo = ProtoField.bool("hf_audio.is_stereo", "Is Stereo") +local f_audio_num_silent_samples = ProtoField.uint16("hf_audio.num_silent_samples", "Num Silent Samples") + +p_hf_audio.fields = { + f_audio_sequence_number, f_audio_codec_size, f_audio_codec, + f_audio_is_stereo, f_audio_num_silent_samples +} + +local packet_type_extractor = Field.new('hfudt.type_text') + +function p_hf_audio.dissector(buf, pinfo, tree) + pinfo.cols.protocol = p_hf_audio.name + + audio_subtree = tree:add(p_hf_audio, buf()) + + local i = 0 + + audio_subtree:add_le(f_audio_sequence_number, buf(i, 2)) + i = i + 2 + + -- figure out the number of bytes the codec name takes + local codec_name_bytes = buf(i, 4):le_uint() + audio_subtree:add_le(f_audio_codec_size, buf(i, 4)) + i = i + 4 + + audio_subtree:add(f_audio_codec, buf(i, codec_name_bytes)) + i = i + codec_name_bytes + + local packet_type = packet_type_extractor().value + if packet_type == "SilentAudioFrame" then + audio_subtree:add_le(f_audio_num_silent_samples, buf(i, 2)) + i = i + 2 + else + audio_subtree:add_le(f_audio_is_stereo, buf(i, 1)) + i = i + 1 + end +end diff --git a/tools/dissectors/hf-avatar.lua b/tools/dissectors/3-hf-avatar.lua similarity index 99% rename from tools/dissectors/hf-avatar.lua rename to tools/dissectors/3-hf-avatar.lua index 231fd1b354..af648ed5b9 100644 --- a/tools/dissectors/hf-avatar.lua +++ b/tools/dissectors/3-hf-avatar.lua @@ -1,3 +1,5 @@ +print("Loading hf-avatar") + -- create the avatar protocol p_hf_avatar = Proto("hf-avatar", "HF Avatar Protocol") diff --git a/tools/dissectors/hf-entity.lua b/tools/dissectors/4-hf-entity.lua similarity index 99% rename from tools/dissectors/hf-entity.lua rename to tools/dissectors/4-hf-entity.lua index 51daa3497d..568eb5baa3 100644 --- a/tools/dissectors/hf-entity.lua +++ b/tools/dissectors/4-hf-entity.lua @@ -1,3 +1,5 @@ +print("Loading hf-entity") + -- create the entity protocol p_hf_entity = Proto("hf-entity", "HF Entity Protocol") diff --git a/tools/dissectors/hf-domain.lua b/tools/dissectors/5-hf-domain.lua similarity index 100% rename from tools/dissectors/hf-domain.lua rename to tools/dissectors/5-hf-domain.lua