From bbef07172349a785a9fc7913cf981f494db515ee Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 1 Nov 2016 16:23:53 -0700 Subject: [PATCH 01/14] Update interface to default to HMD display plugin --- interface/src/Application.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5fe15fa8e5..f4596f5ea2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5669,13 +5669,22 @@ void Application::updateDisplayMode() { standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); standard.insert(std::end(standard), std::begin(developer), std::end(developer)); + DisplayPluginPointer defaultDisplayPlugin; + + // Default to the first HMD plugin, otherwise use the first in the list. + auto hmdPluginIt = find_if(standard.begin(), standard.end(), [](DisplayPluginPointer& plugin) { return plugin->isHmd(); }); + if (hmdPluginIt != standard.end()) { + defaultDisplayPlugin = *hmdPluginIt; + } else if (standard.size() > 0) { + defaultDisplayPlugin = standard[0]; + } + foreach(auto displayPlugin, standard) { - addDisplayPluginToMenu(displayPlugin, first); + addDisplayPluginToMenu(displayPlugin, displayPlugin.get() == defaultDisplayPlugin.get()); auto displayPluginName = displayPlugin->getName(); QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) { resizeGL(); }); - first = false; } // after all plugins have been added to the menu, add a separator to the menu From 26e0d02d6067019e605b8ce3bf600aee5f8be9ad Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 1 Nov 2016 16:40:41 -0700 Subject: [PATCH 02/14] Remove unused 'first' variable --- interface/src/Application.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f4596f5ea2..c6a0bce2f5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5643,8 +5643,6 @@ void Application::updateDisplayMode() { static std::once_flag once; std::call_once(once, [&] { - bool first = true; - // first sort the plugins into groupings: standard, advanced, developer DisplayPluginList standard; DisplayPluginList advanced; From 7655f906f1d17519d706494c05988b4a7bc900b1 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 Nov 2016 19:26:30 -0700 Subject: [PATCH 03/14] Starting adding a timer for the frame --- interface/src/Application.cpp | 2 ++ libraries/gpu/src/gpu/Context.cpp | 8 ++++++++ libraries/gpu/src/gpu/Context.h | 8 ++++++++ 3 files changed, 18 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 867761e012..57586d734e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1238,7 +1238,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto glInfo = getGLContextData(); properties["gl_info"] = glInfo; + properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemory()); properties["gpu_free_memory"] = (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemory()); + properties["gpu_frame_time"] = (int)(qApp->getRenderEngine()->); properties["ideal_thread_count"] = QThread::idealThreadCount(); auto hmdHeadPose = getHMDSensorPose(); diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index ab6bba178a..f1fc1067c3 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -34,6 +34,10 @@ void Context::beginFrame(const glm::mat4& renderPose) { _frameActive = true; _currentFrame = std::make_shared(); _currentFrame->pose = renderPose; + + if (!_frameRangeTimer) { + _frameRangeTimer = std::make_shared("gpu::Frame"); + } } void Context::appendFrameBatch(Batch& batch) { @@ -183,6 +187,10 @@ Size Context::getFreeGPUMemory() { return _freeGPUMemory.load(); } +Size Context::getUsedGPUMemory() { + return getTextureGPUMemoryUsage() + getBufferGPUMemoryUsage(); +}; + void Context::incrementBufferGPUCount() { static std::atomic max { 0 }; auto total = ++_bufferGPUCount; diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 763e91b3e4..6e3e976034 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -203,12 +203,16 @@ public: void getStats(ContextStats& stats) const; + double getFrameTimerGPUAverage() const; + double getFrameTimerBatchAverage() const; + static uint32_t getBufferGPUCount(); static Size getBufferGPUMemoryUsage(); static uint32_t getTextureGPUCount(); static uint32_t getTextureGPUSparseCount(); static Size getFreeGPUMemory(); + static Size getUsedGPUMemory(); static Size getTextureGPUMemoryUsage(); static Size getTextureGPUVirtualMemoryUsage(); static Size getTextureGPUFramebufferMemoryUsage(); @@ -221,8 +225,12 @@ protected: std::shared_ptr _backend; bool _frameActive { false }; FramePointer _currentFrame; + RangeTimerPointer _frameRangeTimer; StereoState _stereo; + double getGPUAverage() const; + double getBatchAverage() const; + // This function can only be called by "static Shader::makeProgram()" // makeProgramShader(...) make a program shader ready to be used in a Batch. // It compiles the sub shaders, link them and defines the Slots and their bindings. From 76aa541d4aed128201e7ab61cb4b954408ef0629 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 4 Nov 2016 11:49:52 -0700 Subject: [PATCH 04/14] Adding the frame gpu and batch timer --- interface/resources/qml/Stats.qml | 9 +++++++++ interface/src/Application.cpp | 3 ++- interface/src/ui/Stats.cpp | 6 ++++++ interface/src/ui/Stats.h | 4 ++++ libraries/gpu/src/gpu/Context.cpp | 26 +++++++++++++++++++++++++- 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 1c5df5c71d..9c55b1ce2d 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -189,6 +189,15 @@ Item { Column { id: octreeCol spacing: 4; x: 4; y: 4; + StatText { + text: " Frame timing:" + } + StatText { + text: " Batch: " + root.batchFrameTime.toFixed(1) + " ms" + } + StatText { + text: " GPU: " + root.gpuFrameTime.toFixed(1) + " ms" + } StatText { text: "Triangles: " + root.triangles + " / Material Switches: " + root.materialSwitches diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 57586d734e..93a1952212 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1240,7 +1240,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["gl_info"] = glInfo; properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemory()); properties["gpu_free_memory"] = (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemory()); - properties["gpu_frame_time"] = (int)(qApp->getRenderEngine()->); + properties["gpu_frame_time"] = (float)(qApp->getGPUContext()->getFrameTimerGPUAverage()); + properties["batch_frame_time"] = (float)(qApp->getGPUContext()->getFrameTimerBatchAverage()); properties["ideal_thread_count"] = QThread::idealThreadCount(); auto hmdHeadPose = getHMDSensorPose(); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 05632cb1e6..7fc6a3af80 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -290,6 +290,12 @@ void Stats::updateStats(bool force) { STAT_UPDATE(sendingMode, sendingModeResult); } + auto& GPUContext = qApp->getGPUContext(); + + // Update Frame timing (in ms) + STAT_UPDATE(gpuFrameTime, (float) GPUContext->getFrameTimerGPUAverage()); + STAT_UPDATE(batchFrameTime, (float)GPUContext->getFrameTimerBatchAverage()); + STAT_UPDATE(gpuBuffers, (int)gpu::Context::getBufferGPUCount()); STAT_UPDATE(gpuBufferMemory, (int)BYTES_TO_MB(gpu::Context::getBufferGPUMemoryUsage())); STAT_UPDATE(gpuTextures, (int)gpu::Context::getTextureGPUCount()); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 76c6effed7..ffa5c08bc6 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -101,6 +101,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, gpuTextureSparseMemory, 0) STATS_PROPERTY(int, gpuSparseTextureEnabled, 0) STATS_PROPERTY(int, gpuFreeMemory, 0) + STATS_PROPERTY(float, gpuFrameTime, 0) + STATS_PROPERTY(float, batchFrameTime, 0) public: static Stats* getInstance(); @@ -198,6 +200,8 @@ signals: void gpuTextureSparseMemoryChanged(); void gpuSparseTextureEnabledChanged(); void gpuFreeMemoryChanged(); + void gpuFrameTimeChanged(); + void batchFrameTimeChanged(); void rectifiedTextureCountChanged(); void decimatedTextureCountChanged(); diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index f1fc1067c3..4344cd4d2c 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -36,7 +36,7 @@ void Context::beginFrame(const glm::mat4& renderPose) { _currentFrame->pose = renderPose; if (!_frameRangeTimer) { - _frameRangeTimer = std::make_shared("gpu::Frame"); + _frameRangeTimer = std::make_shared(); } } @@ -77,10 +77,18 @@ void Context::executeFrame(const FramePointer& frame) const { consumeFrameUpdates(frame); _backend->setStereoState(frame->stereoState); { + Batch beginBatch; + _frameRangeTimer->begin(beginBatch); + _backend->render(beginBatch); + // Execute the frame rendering commands for (auto& batch : frame->batches) { _backend->render(batch); } + + Batch endBatch; + _frameRangeTimer->end(endBatch); + _backend->render(endBatch); } } @@ -131,6 +139,20 @@ void Context::getStats(ContextStats& stats) const { _backend->getStats(stats); } +double Context::getFrameTimerGPUAverage() const { + if (_frameRangeTimer) { + return _frameRangeTimer->getGPUAverage(); + } + return 0.0; +} + +double Context::getFrameTimerBatchAverage() const { + if (_frameRangeTimer) { + return _frameRangeTimer->getBatchAverage(); + } + return 0.0; +} + const Backend::TransformCamera& Backend::TransformCamera::recomputeDerived(const Transform& xformView) const { _projectionInverse = glm::inverse(_projection); @@ -357,3 +379,5 @@ void Backend::updateTextureGPUFramebufferMemoryUsage(Resource::Size prevObjectSi void Backend::updateTextureGPUSparseMemoryUsage(Resource::Size prevObjectSize, Resource::Size newObjectSize) { Context::updateTextureGPUSparseMemoryUsage(prevObjectSize, newObjectSize); } void Backend::incrementTextureGPUTransferCount() { Context::incrementTextureGPUTransferCount(); } void Backend::decrementTextureGPUTransferCount() { Context::decrementTextureGPUTransferCount(); } + + From 3ad9c1a797761c08b2098102e2cc8cf2af1675c3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 4 Nov 2016 12:26:20 -0700 Subject: [PATCH 05/14] Add check to go into HMD on first run if available --- interface/src/Application.cpp | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c6a0bce2f5..abcc82d1c3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3362,13 +3362,31 @@ void Application::loadSettings() { // If there is a preferred plugin, we probably messed it up with the menu settings, so fix it. auto pluginManager = PluginManager::getInstance(); auto plugins = pluginManager->getPreferredDisplayPlugins(); - for (auto plugin : plugins) { - auto menu = Menu::getInstance(); - if (auto action = menu->getActionForOption(plugin->getName())) { - action->setChecked(true); - action->trigger(); - // Find and activated highest priority plugin, bail for the rest - break; + auto menu = Menu::getInstance(); + if (plugins.size() > 0) { + for (auto plugin : plugins) { + if (auto action = menu->getActionForOption(plugin->getName())) { + action->setChecked(true); + action->trigger(); + // Find and activated highest priority plugin, bail for the rest + break; + } + } + } else { + // If this is our first run, and no preferred devices were set, default to + // an HMD device if available. + Setting::Handle firstRun { Settings::firstRun, true }; + if (firstRun.get()) { + auto displayPlugins = pluginManager->getDisplayPlugins(); + for (auto& plugin : displayPlugins) { + if (plugin->isHmd()) { + if (auto action = menu->getActionForOption(plugin->getName())) { + action->setChecked(true); + action->trigger(); + break; + } + } + } } } From 0dac2c999eefb758a4b5eadcf32ab028c52b6a58 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 4 Nov 2016 12:27:04 -0700 Subject: [PATCH 06/14] Revert "Remove unused 'first' variable" This reverts commit 26e0d02d6067019e605b8ce3bf600aee5f8be9ad. --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index abcc82d1c3..2594b55370 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5661,6 +5661,8 @@ void Application::updateDisplayMode() { static std::once_flag once; std::call_once(once, [&] { + bool first = true; + // first sort the plugins into groupings: standard, advanced, developer DisplayPluginList standard; DisplayPluginList advanced; From 0cec62b3a3681a21f6de3262c7b13b8442d009f8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 4 Nov 2016 12:27:15 -0700 Subject: [PATCH 07/14] Revert "Update interface to default to HMD display plugin" This reverts commit bbef07172349a785a9fc7913cf981f494db515ee. --- interface/src/Application.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2594b55370..b651926622 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5687,22 +5687,13 @@ void Application::updateDisplayMode() { standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); standard.insert(std::end(standard), std::begin(developer), std::end(developer)); - DisplayPluginPointer defaultDisplayPlugin; - - // Default to the first HMD plugin, otherwise use the first in the list. - auto hmdPluginIt = find_if(standard.begin(), standard.end(), [](DisplayPluginPointer& plugin) { return plugin->isHmd(); }); - if (hmdPluginIt != standard.end()) { - defaultDisplayPlugin = *hmdPluginIt; - } else if (standard.size() > 0) { - defaultDisplayPlugin = standard[0]; - } - foreach(auto displayPlugin, standard) { - addDisplayPluginToMenu(displayPlugin, displayPlugin.get() == defaultDisplayPlugin.get()); + addDisplayPluginToMenu(displayPlugin, first); auto displayPluginName = displayPlugin->getName(); QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) { resizeGL(); }); + first = false; } // after all plugins have been added to the menu, add a separator to the menu From 449add6b3452fea62e0df7e890564357206d9183 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 4 Nov 2016 13:29:27 -0700 Subject: [PATCH 08/14] Fix bad variable initialization --- interface/src/ui/Stats.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 7fc6a3af80..edf72d9758 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -290,11 +290,11 @@ void Stats::updateStats(bool force) { STAT_UPDATE(sendingMode, sendingModeResult); } - auto& GPUContext = qApp->getGPUContext(); + auto gpuContext = qApp->getGPUContext(); // Update Frame timing (in ms) - STAT_UPDATE(gpuFrameTime, (float) GPUContext->getFrameTimerGPUAverage()); - STAT_UPDATE(batchFrameTime, (float)GPUContext->getFrameTimerBatchAverage()); + STAT_UPDATE(gpuFrameTime, (float)gpuContext->getFrameTimerGPUAverage()); + STAT_UPDATE(batchFrameTime, (float)gpuContext->getFrameTimerBatchAverage()); STAT_UPDATE(gpuBuffers, (int)gpu::Context::getBufferGPUCount()); STAT_UPDATE(gpuBufferMemory, (int)BYTES_TO_MB(gpu::Context::getBufferGPUMemoryUsage())); @@ -308,7 +308,7 @@ void Stats::updateStats(bool force) { STAT_UPDATE(gpuTextureVirtualMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUVirtualMemoryUsage())); STAT_UPDATE(gpuTextureFramebufferMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUFramebufferMemoryUsage())); STAT_UPDATE(gpuTextureSparseMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUSparseMemoryUsage())); - STAT_UPDATE(gpuSparseTextureEnabled, qApp->getGPUContext()->getBackend()->isTextureManagementSparseEnabled() ? 1 : 0); + STAT_UPDATE(gpuSparseTextureEnabled, gpuContext->getBackend()->isTextureManagementSparseEnabled() ? 1 : 0); STAT_UPDATE(gpuFreeMemory, (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemory())); STAT_UPDATE(rectifiedTextureCount, (int)RECTIFIED_TEXTURE_COUNT.load()); STAT_UPDATE(decimatedTextureCount, (int)DECIMATED_TEXTURE_COUNT.load()); From 1732448d3c3f6bd443ec17a660d995b36d0634b6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 4 Nov 2016 13:52:16 -0700 Subject: [PATCH 09/14] Added tools/skeleton-dump tool Debug tool that prints out the skeleton hierarchy of fbx files including joint indices, bindPose and defaultPoses. The verbose option also prints the full FBX transformation set, pre/post rotations etc. --- libraries/animation/src/AnimSkeleton.cpp | 42 +++++++------- libraries/animation/src/AnimSkeleton.h | 4 +- tools/CMakeLists.txt | 4 ++ tools/skeleton-dump/CMakeLists.txt | 4 ++ tools/skeleton-dump/src/SkeletonDumpApp.cpp | 63 +++++++++++++++++++++ tools/skeleton-dump/src/SkeletonDumpApp.h | 29 ++++++++++ tools/skeleton-dump/src/main.cpp | 22 +++++++ 7 files changed, 143 insertions(+), 25 deletions(-) create mode 100644 tools/skeleton-dump/CMakeLists.txt create mode 100644 tools/skeleton-dump/src/SkeletonDumpApp.cpp create mode 100644 tools/skeleton-dump/src/SkeletonDumpApp.h create mode 100644 tools/skeleton-dump/src/main.cpp diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index a379ebd80a..0fd8ff595f 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -228,9 +228,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints) } } -#ifndef NDEBUG -#define DUMP_FBX_JOINTS -void AnimSkeleton::dump() const { +void AnimSkeleton::dump(bool verbose) const { qCDebug(animation) << "["; for (int i = 0; i < getNumJoints(); i++) { qCDebug(animation) << " {"; @@ -240,24 +238,24 @@ void AnimSkeleton::dump() const { qCDebug(animation) << " relBindPose =" << getRelativeBindPose(i); qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i); qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i); -#ifdef DUMP_FBX_JOINTS - qCDebug(animation) << " fbxJoint ="; - qCDebug(animation) << " isFree =" << _joints[i].isFree; - qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage; - qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex; - qCDebug(animation) << " translation =" << _joints[i].translation; - qCDebug(animation) << " preTransform =" << _joints[i].preTransform; - qCDebug(animation) << " preRotation =" << _joints[i].preRotation; - qCDebug(animation) << " rotation =" << _joints[i].rotation; - qCDebug(animation) << " postRotation =" << _joints[i].postRotation; - qCDebug(animation) << " postTransform =" << _joints[i].postTransform; - qCDebug(animation) << " transform =" << _joints[i].transform; - qCDebug(animation) << " rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax; - qCDebug(animation) << " inverseDefaultRotation" << _joints[i].inverseDefaultRotation; - qCDebug(animation) << " inverseBindRotation" << _joints[i].inverseBindRotation; - qCDebug(animation) << " bindTransform" << _joints[i].bindTransform; - qCDebug(animation) << " isSkeletonJoint" << _joints[i].isSkeletonJoint; -#endif + if (verbose) { + qCDebug(animation) << " fbxJoint ="; + qCDebug(animation) << " isFree =" << _joints[i].isFree; + qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage; + qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex; + qCDebug(animation) << " translation =" << _joints[i].translation; + qCDebug(animation) << " preTransform =" << _joints[i].preTransform; + qCDebug(animation) << " preRotation =" << _joints[i].preRotation; + qCDebug(animation) << " rotation =" << _joints[i].rotation; + qCDebug(animation) << " postRotation =" << _joints[i].postRotation; + qCDebug(animation) << " postTransform =" << _joints[i].postTransform; + qCDebug(animation) << " transform =" << _joints[i].transform; + qCDebug(animation) << " rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax; + qCDebug(animation) << " inverseDefaultRotation" << _joints[i].inverseDefaultRotation; + qCDebug(animation) << " inverseBindRotation" << _joints[i].inverseBindRotation; + qCDebug(animation) << " bindTransform" << _joints[i].bindTransform; + qCDebug(animation) << " isSkeletonJoint" << _joints[i].isSkeletonJoint; + } if (getParentIndex(i) >= 0) { qCDebug(animation) << " parent =" << getJointName(getParentIndex(i)); } @@ -284,4 +282,4 @@ void AnimSkeleton::dump(const AnimPoseVec& poses) const { } qCDebug(animation) << "]"; } -#endif + diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index e1c6ae95c8..f588c14f90 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -63,10 +63,8 @@ public: void mirrorRelativePoses(AnimPoseVec& poses) const; void mirrorAbsolutePoses(AnimPoseVec& poses) const; -#ifndef NDEBUG - void dump() const; + void dump(bool verbose) const; void dump(const AnimPoseVec& poses) const; -#endif protected: void buildSkeletonFromJoints(const std::vector& joints); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index cf0e25a757..a85a112bf5 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -13,3 +13,7 @@ set_target_properties(ice-client PROPERTIES FOLDER "Tools") add_subdirectory(ac-client) set_target_properties(ac-client PROPERTIES FOLDER "Tools") + +add_subdirectory(skeleton-dump) +set_target_properties(skeleton-dump PROPERTIES FOLDER "Tools") + diff --git a/tools/skeleton-dump/CMakeLists.txt b/tools/skeleton-dump/CMakeLists.txt new file mode 100644 index 0000000000..04d450d9c2 --- /dev/null +++ b/tools/skeleton-dump/CMakeLists.txt @@ -0,0 +1,4 @@ +set(TARGET_NAME skeleton-dump) +setup_hifi_project(Core Widgets) +link_hifi_libraries(shared fbx model gpu gl animation) + diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.cpp b/tools/skeleton-dump/src/SkeletonDumpApp.cpp new file mode 100644 index 0000000000..23bb8c27f0 --- /dev/null +++ b/tools/skeleton-dump/src/SkeletonDumpApp.cpp @@ -0,0 +1,63 @@ +// +// SkeletonDumpApp.h +// tools/skeleton-dump/src +// +// Created by Anthony Thibault on 11/4/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "SkeletonDumpApp.h" +#include +#include +#include +#include + +SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { + + // parse command-line + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity FBX Skeleton Analyzer"); + const QCommandLineOption helpOption = parser.addHelpOption(); + + const QCommandLineOption verboseOutput("v", "verbose output"); + parser.addOption(verboseOutput); + + const QCommandLineOption inputFilenameOption("i", "input file", "filename.fbx"); + parser.addOption(inputFilenameOption); + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + _returnCode = 1; + return; + } + + if (parser.isSet(helpOption)) { + parser.showHelp(); + return; + } + + bool verbose = parser.isSet(verboseOutput); + + QString inputFilename; + if (parser.isSet(inputFilenameOption)) { + inputFilename = parser.value(inputFilenameOption); + } + + QFile file(inputFilename); + if (!file.open(QIODevice::ReadOnly)) { + qCritical() << "Failed to open file " << inputFilename; + _returnCode = 2; + return; + } + QByteArray blob = file.readAll(); + std::unique_ptr fbxGeometry(readFBX(blob, QVariantHash())); + std::unique_ptr skeleton(new AnimSkeleton(*fbxGeometry)); + skeleton->dump(verbose); +} + +SkeletonDumpApp::~SkeletonDumpApp() { +} diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.h b/tools/skeleton-dump/src/SkeletonDumpApp.h new file mode 100644 index 0000000000..b292d4fa2f --- /dev/null +++ b/tools/skeleton-dump/src/SkeletonDumpApp.h @@ -0,0 +1,29 @@ +// +// VHACDUtil.h +// tools/skeleton-dump/src +// +// Created by Anthony Thibault on 11/4/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SkeletonDumpApp_h +#define hifi_SkeletonDumpApp_h + +#include + +class SkeletonDumpApp : public QCoreApplication { + Q_OBJECT +public: + SkeletonDumpApp(int argc, char* argv[]); + ~SkeletonDumpApp(); + + int getReturnCode() const { return _returnCode; } + +private: + int _returnCode { 0 }; +}; + +#endif //hifi_SkeletonDumpApp_h diff --git a/tools/skeleton-dump/src/main.cpp b/tools/skeleton-dump/src/main.cpp new file mode 100644 index 0000000000..6cf4d41f31 --- /dev/null +++ b/tools/skeleton-dump/src/main.cpp @@ -0,0 +1,22 @@ +// +// main.cpp +// tools/skeleton-dump/src +// +// Created by Anthony Thibault on 11/4/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#include +#include +#include +#include +#include + +#include "SkeletonDumpApp.h" + +int main(int argc, char * argv[]) { + SkeletonDumpApp app(argc, argv); + return app.getReturnCode(); +} From 69fc048e5ee48571d4aee2f1c84b7ad985a97e9d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 4 Nov 2016 14:03:59 -0700 Subject: [PATCH 10/14] typo fixes in license comments --- tools/skeleton-dump/src/SkeletonDumpApp.cpp | 2 +- tools/skeleton-dump/src/SkeletonDumpApp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.cpp b/tools/skeleton-dump/src/SkeletonDumpApp.cpp index 23bb8c27f0..e9d8243e38 100644 --- a/tools/skeleton-dump/src/SkeletonDumpApp.cpp +++ b/tools/skeleton-dump/src/SkeletonDumpApp.cpp @@ -1,5 +1,5 @@ // -// SkeletonDumpApp.h +// SkeletonDumpApp.cpp // tools/skeleton-dump/src // // Created by Anthony Thibault on 11/4/16. diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.h b/tools/skeleton-dump/src/SkeletonDumpApp.h index b292d4fa2f..40df98eb65 100644 --- a/tools/skeleton-dump/src/SkeletonDumpApp.h +++ b/tools/skeleton-dump/src/SkeletonDumpApp.h @@ -1,5 +1,5 @@ // -// VHACDUtil.h +// SkeletonDumpApp.h // tools/skeleton-dump/src // // Created by Anthony Thibault on 11/4/16. From ae29fe8ab24456699ca0bca1f5c2482bb28ed4be Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 27 Oct 2016 18:29:22 -0700 Subject: [PATCH 11/14] Logging improvements --- assignment-client/src/AssignmentClient.cpp | 3 -- assignment-client/src/AssignmentClientApp.cpp | 3 -- .../src/AssignmentClientMonitor.cpp | 3 -- assignment-client/src/main.cpp | 9 ++-- domain-server/src/DomainServer.cpp | 10 +---- domain-server/src/DomainServer.h | 6 --- domain-server/src/main.cpp | 7 +-- ice-server/src/main.cpp | 3 +- interface/src/Application.cpp | 3 +- libraries/shared/src/LogHandler.cpp | 44 +++++++++++-------- libraries/shared/src/LogHandler.h | 2 + .../shared/src/ShutdownEventListener.cpp | 9 ++-- libraries/shared/src/shared/FileLogger.cpp | 3 +- libraries/shared/src/shared/FileLogger.h | 2 +- 14 files changed, 50 insertions(+), 57 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 3b4300b6fd..8fe618b70d 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -175,9 +175,6 @@ AssignmentClient::~AssignmentClient() { void AssignmentClient::aboutToQuit() { stopAssignmentClient(); - - // clear the log handler so that Qt doesn't call the destructor on LogHandler - qInstallMessageHandler(0); } void AssignmentClient::setUpStatusToMonitor() { diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index c425a239dd..68e7b9b997 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -45,9 +45,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : setApplicationName("assignment-client"); setApplicationVersion(BuildInfo::VERSION); - // use the verbose message handler in Logging - qInstallMessageHandler(LogHandler::verboseMessageHandler); - // parse command-line QCommandLineParser parser; parser.setApplicationDescription("High Fidelity Assignment Client"); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 8ba253d549..1ee876ceea 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -126,9 +126,6 @@ void AssignmentClientMonitor::stopChildProcesses() { void AssignmentClientMonitor::aboutToQuit() { stopChildProcesses(); - - // clear the log handler so that Qt doesn't call the destructor on LogHandler - qInstallMessageHandler(0); } void AssignmentClientMonitor::spawnChildClient() { diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 052c4755f8..cf8d9ebe31 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -9,8 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - +#include #include #include "AssignmentClientApp.h" @@ -18,10 +17,14 @@ int main(int argc, char* argv[]) { disableQtBearerPoll(); // Fixes wifi ping spikes + qInstallMessageHandler(LogHandler::verboseMessageHandler); + qInfo() << "Starting."; + AssignmentClientApp app(argc, argv); int acReturn = app.exec(); qDebug() << "assignment-client process" << app.applicationPid() << "exiting with status code" << acReturn; - + + qInfo() << "Quitting."; return acReturn; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8b73b851b2..d13f9b883f 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -72,13 +72,10 @@ DomainServer::DomainServer(int argc, char* argv[]) : _iceServerPort(ICE_SERVER_DEFAULT_PORT) { parseCommandLine(); - qInstallMessageHandler(LogHandler::verboseMessageHandler); LogUtils::init(); Setting::init(); - connect(this, &QCoreApplication::aboutToQuit, this, &DomainServer::aboutToQuit); - setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); setOrganizationDomain("highfidelity.io"); setApplicationName("domain-server"); @@ -211,6 +208,7 @@ void DomainServer::parseCommandLine() { } DomainServer::~DomainServer() { + qInfo() << "Domain Server is shutting down."; // destroy the LimitedNodeList before the DomainServer QCoreApplication is down DependencyManager::destroy(); } @@ -223,12 +221,6 @@ void DomainServer::queuedQuit(QString quitMessage, int exitCode) { QCoreApplication::exit(exitCode); } -void DomainServer::aboutToQuit() { - - // clear the log handler so that Qt doesn't call the destructor on LogHandler - qInstallMessageHandler(0); -} - void DomainServer::restart() { qDebug() << "domain-server is restarting."; diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 6330cf51a5..c14ec5eee0 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -72,8 +72,6 @@ public slots: void processICEServerHeartbeatACK(QSharedPointer message); private slots: - void aboutToQuit(); - void setupPendingAssignmentCredits(); void sendPendingTransactionsToServer(); @@ -150,13 +148,9 @@ private: bool isAuthenticatedRequest(HTTPConnection* connection, const QUrl& url); - void handleTokenRequestFinished(); QNetworkReply* profileRequestGivenTokenReply(QNetworkReply* tokenReply); - void handleProfileRequestFinished(); Headers setupCookieHeadersFromProfileReply(QNetworkReply* profileReply); - void loadExistingSessionsFromSettings(); - QJsonObject jsonForSocket(const HifiSockAddr& socket); QJsonObject jsonObjectForNode(const SharedNodePointer& node); diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index b3b5c8b9be..fdf7a598aa 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -15,8 +15,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include #include @@ -29,6 +27,9 @@ int main(int argc, char* argv[]) { setvbuf(stdout, NULL, _IOLBF, 0); #endif + qInstallMessageHandler(LogHandler::verboseMessageHandler); + qInfo() << "Starting."; + int currentExitCode = 0; // use a do-while to handle domain-server restart @@ -37,7 +38,7 @@ int main(int argc, char* argv[]) { currentExitCode = domainServer.exec(); } while (currentExitCode == DomainServer::EXIT_CODE_REBOOT); - + qInfo() << "Quitting."; return currentExitCode; } diff --git a/ice-server/src/main.cpp b/ice-server/src/main.cpp index 2326984668..ec8b9957cf 100644 --- a/ice-server/src/main.cpp +++ b/ice-server/src/main.cpp @@ -19,8 +19,9 @@ int main(int argc, char* argv[]) { #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif - + qInstallMessageHandler(LogHandler::verboseMessageHandler); + qInfo() << "Starting."; IceServer iceServer(argc, argv); return iceServer.exec(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 867761e012..ffe62f71de 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1654,7 +1654,8 @@ Application::~Application() { _window->deleteLater(); - qInstallMessageHandler(nullptr); // NOTE: Do this as late as possible so we continue to get our log messages + // Can't log to file passed this point, FileLogger about to be deleted + qInstallMessageHandler(LogHandler::verboseMessageHandler); } void Application::initializeGL() { diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index d142e3f839..35a3361c38 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -10,17 +10,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - -#include -#include -#include -#include -#include -#include - #include "LogHandler.h" +#include + +#include +#include +#include +#include +#include +#include +#include + QMutex LogHandler::_mutex; LogHandler& LogHandler::getInstance() { @@ -28,16 +29,15 @@ LogHandler& LogHandler::getInstance() { return staticInstance; } -LogHandler::LogHandler() -{ - // setup our timer to flush the verbose logs every 5 seconds - QTimer* logFlushTimer = new QTimer(this); - connect(logFlushTimer, &QTimer::timeout, this, &LogHandler::flushRepeatedMessages); - logFlushTimer->start(VERBOSE_LOG_INTERVAL_SECONDS * 1000); - +LogHandler::LogHandler() { // when the log handler is first setup we should print our timezone QString timezoneString = "Time zone: " + QDateTime::currentDateTime().toString("t"); - printf("%s\n", qPrintable(timezoneString)); + printMessage(LogMsgType::LogInfo, QMessageLogContext(), timezoneString); +} + +LogHandler::~LogHandler() { + flushRepeatedMessages(); + printMessage(LogMsgType::LogDebug, QMessageLogContext(), "LogHandler shutdown."); } const char* stringForLogType(LogMsgType msgType) { @@ -165,7 +165,7 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont stringForLogType(type), context.category); if (_shouldOutputProcessID) { - prefixString.append(QString(" [%1]").arg(QCoreApplication::instance()->applicationPid())); + prefixString.append(QString(" [%1]").arg(QCoreApplication::applicationPid())); } if (_shouldOutputThreadID) { @@ -187,6 +187,14 @@ void LogHandler::verboseMessageHandler(QtMsgType type, const QMessageLogContext& } const QString& LogHandler::addRepeatedMessageRegex(const QString& regexString) { + static std::once_flag once; + std::call_once(once, [&] { + // setup our timer to flush the verbose logs every 5 seconds + QTimer* logFlushTimer = new QTimer(this); + connect(logFlushTimer, &QTimer::timeout, this, &LogHandler::flushRepeatedMessages); + logFlushTimer->start(VERBOSE_LOG_INTERVAL_SECONDS * 1000); + }); + QMutexLocker lock(&_mutex); return *_repeatedMessageRegexes.insert(regexString); } diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index 890497b891..f80fad4c6a 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -52,8 +52,10 @@ public: const QString& addRepeatedMessageRegex(const QString& regexString); const QString& addOnlyOnceMessageRegex(const QString& regexString); + private: LogHandler(); + ~LogHandler(); void flushRepeatedMessages(); diff --git a/libraries/shared/src/ShutdownEventListener.cpp b/libraries/shared/src/ShutdownEventListener.cpp index e640126b7b..6f043cd43e 100644 --- a/libraries/shared/src/ShutdownEventListener.cpp +++ b/libraries/shared/src/ShutdownEventListener.cpp @@ -9,8 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "ShutdownEventListener.h" #ifdef Q_OS_WIN @@ -19,6 +17,9 @@ #include #endif +#include +#include + ShutdownEventListener& ShutdownEventListener::getInstance() { static ShutdownEventListener staticInstance; return staticInstance; @@ -29,9 +30,7 @@ void signalHandler(int param) { QMetaObject::invokeMethod(qApp, "quit"); } -ShutdownEventListener::ShutdownEventListener(QObject* parent) : - QObject(parent) -{ +ShutdownEventListener::ShutdownEventListener(QObject* parent) : QObject(parent) { #ifndef Q_OS_WIN // be a signal handler for SIGTERM so we can stop our children when we get it signal(SIGTERM, signalHandler); diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp index ef3436a8d7..143438ba68 100644 --- a/libraries/shared/src/shared/FileLogger.cpp +++ b/libraries/shared/src/shared/FileLogger.cpp @@ -109,7 +109,8 @@ bool FilePersistThread::processQueueItems(const Queue& messages) { } FileLogger::FileLogger(QObject* parent) : - AbstractLoggerInterface(parent), _fileName(getLogFilename()) + AbstractLoggerInterface(parent), + _fileName(getLogFilename()) { _persistThreadInstance = new FilePersistThread(*this); _persistThreadInstance->initialize(true, QThread::LowestPriority); diff --git a/libraries/shared/src/shared/FileLogger.h b/libraries/shared/src/shared/FileLogger.h index 697b96c6d8..f0f6dd5c09 100644 --- a/libraries/shared/src/shared/FileLogger.h +++ b/libraries/shared/src/shared/FileLogger.h @@ -24,7 +24,7 @@ public: FileLogger(QObject* parent = NULL); virtual ~FileLogger(); - QString getFilename() { return _fileName; } + QString getFilename() const { return _fileName; } virtual void addMessage(const QString&) override; virtual QString getLogData() override; virtual void locateLog() override; From 3c76dad4549efc5d7378256c6e45b7cf2bbaceca Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Nov 2016 10:42:59 -0800 Subject: [PATCH 12/14] Force sandbox config saves --- server-console/src/main.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server-console/src/main.js b/server-console/src/main.js index 6c82230601..a7855ab063 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -623,6 +623,7 @@ function checkNewContent() { } else { // They don't want to update, mark content set as current userConfig.set('homeContentLastModified', new Date()); + userConfig.save(configPath); } }); } @@ -676,6 +677,7 @@ function maybeInstallDefaultContentSet(onComplete) { } log.debug('Copied home content over to: ' + getRootHifiDataDirectory()); userConfig.set('homeContentLastModified', new Date()); + userConfig.save(configPath); onComplete(); }); return; @@ -756,6 +758,7 @@ function maybeInstallDefaultContentSet(onComplete) { // response and decompression complete, return log.debug("Finished unarchiving home content set"); userConfig.set('homeContentLastModified', new Date()); + userConfig.save(configPath); sendStateUpdate('complete'); }); @@ -766,6 +769,7 @@ function maybeInstallDefaultContentSet(onComplete) { }); userConfig.set('hasRun', true); + userConfig.save(configPath); }); } From c4f35bf7bf8dbc62bdf3de45e88852a2a4e82272 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 7 Nov 2016 11:39:23 -0800 Subject: [PATCH 13/14] Fix userData in edit.js sometimes showing wrong value when locked --- scripts/system/html/js/entityProperties.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index d6d9098e21..4fe13196f3 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -445,13 +445,11 @@ function hideUserDataTextArea() { }; function showStaticUserData() { - $('#static-userdata').show(); - $('#static-userdata').css('height', $('#userdata-editor').height()) if (editor !== null) { + $('#static-userdata').show(); + $('#static-userdata').css('height', $('#userdata-editor').height()) $('#static-userdata').text(editor.getText()); } - - }; function removeStaticUserData() { From e3941617c145e16e5183f7f02fc8dcc3ce3bad55 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 7 Nov 2016 11:43:29 -0800 Subject: [PATCH 14/14] Decrease the volume of the tutorial firecracker --- tutorial/tutorial.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorial/tutorial.js b/tutorial/tutorial.js index 3d2b4ce36b..957316734a 100644 --- a/tutorial/tutorial.js +++ b/tutorial/tutorial.js @@ -233,7 +233,7 @@ function playSuccessSound() { function playFirecrackerSound(position) { Audio.playSound(firecrackerSound, { position: position, - volume: 0.7, + volume: 0.5, loop: false }); }