From 9648f560625429f03644b5bde64175ff9ca4a684 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 15 Sep 2015 15:48:21 -0700 Subject: [PATCH 01/38] some fixups to spray paint script --- examples/entityScripts/sprayPaintCan.js | 20 +++++++------------- examples/sprayPaintSpawner.js | 5 ++--- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/examples/entityScripts/sprayPaintCan.js b/examples/entityScripts/sprayPaintCan.js index 4407140184..e1d8a2535b 100644 --- a/examples/entityScripts/sprayPaintCan.js +++ b/examples/entityScripts/sprayPaintCan.js @@ -1,6 +1,7 @@ (function() { // Script.include("../libraries/utils.js"); //Need absolute path for now, for testing before PR merge and s3 cloning. Will change post-merge + Script.include("https://hifi-public.s3.amazonaws.com/scripts/libraries/utils.js"); GRAB_FRAME_USER_DATA_KEY = "grabFrame"; this.userData = {}; @@ -60,22 +61,16 @@ if (self.activated !== true) { //We were just grabbed, so create a particle system self.grab(); - Entities.editEntity(self.paintStream, { - animationSettings: startSetting - }); } //Move emitter to where entity is always when its activated self.sprayStream(); } else if (self.userData.grabKey && self.userData.grabKey.activated === false && self.activated) { - Entities.editEntity(self.paintStream, { - animationSettings: stopSetting - }); - self.activated = false; + self.letGo(); } } this.grab = function() { - self.activated = true; + this.activated = true; var animationSettings = JSON.stringify({ fps: 30, loop: true, @@ -109,7 +104,7 @@ } this.letGo = function() { - self.activated = false; + this.activated = false; Entities.deleteEntity(this.paintStream); } @@ -123,8 +118,7 @@ } this.sprayStream = function() { - var forwardVec = Quat.getFront(self.properties.rotation); - forwardVec = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, 90, 0), forwardVec); + var forwardVec = Quat.getFront(Quat.multiply(self.properties.rotation , Quat.fromPitchYawRollDegrees(0, 90, 0))); forwardVec = Vec3.normalize(forwardVec); var upVec = Quat.getUp(self.properties.rotation); @@ -132,11 +126,10 @@ position = Vec3.sum(position, Vec3.multiply(upVec, TIP_OFFSET_Y)) Entities.editEntity(self.paintStream, { position: position, - emitVelocity: Vec3.multiply(forwardVec, 4) + emitVelocity: Vec3.multiply(5, forwardVec) }); //Now check for an intersection with an entity - //move forward so ray doesnt intersect with gun var origin = Vec3.sum(position, forwardVec); var pickRay = { @@ -244,6 +237,7 @@ }); + function randFloat(min, max) { return Math.random() * (max - min) + min; } diff --git a/examples/sprayPaintSpawner.js b/examples/sprayPaintSpawner.js index 77b74e6520..6d7243cb45 100644 --- a/examples/sprayPaintSpawner.js +++ b/examples/sprayPaintSpawner.js @@ -11,7 +11,6 @@ //Just temporarily using my own bucket here so others can test the entity. Once PR is tested and merged, then the entity script will appear in its proper place in S3, and I wil switch it var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v1"; var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; -var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); var sprayCan = Entities.addEntity({ type: "Model", @@ -27,8 +26,8 @@ var sprayCan = Entities.addEntity({ collisionsWillMove: true, shapeType: 'box', script: scriptURL, - gravity: {x: 0, y: -0.5, z: 0}, - velocity: {x: 0, y: -1, z: 0} + // gravity: {x: 0, y: -0.5, z: 0}, + // velocity: {x: 0, y: -1, z: 0} }); function cleanup() { From f6b5f3925acbdc18a43abf6c21673efa566aaf84 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 15 Sep 2015 16:43:52 -0700 Subject: [PATCH 02/38] Place head at requested position in all modes. (At least, until we can figure out how to get underpose position cleanly without tilt.) --- libraries/animation/src/Rig.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 076baf92c5..7e1d9a27e4 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -996,12 +996,9 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) { _animVars.set("headRotation", realLocalHeadOrientation); auto rootTrans = _animSkeleton->getAbsoluteBindPose(_rootJointIndex).trans; - - if (params.isInHMD) { - _animVars.set("headPosition", params.localHeadPosition + rootTrans); - } else { - _animVars.unset("headPosition"); - } + // There's a theory that when not in hmd, we should _animVars.unset("headPosition"). + // However, until that works well, let's always request head be positioned where requested by hmd, camera, or default. + _animVars.set("headPosition", params.localHeadPosition + rootTrans); } else if (!_enableAnimGraph) { auto& state = _jointStates[index]; From da208526cc4a44df99967d9bed5aa4af100082ec Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 15 Sep 2015 16:48:28 -0700 Subject: [PATCH 03/38] spray can tweaks --- examples/entityScripts/sprayPaintCan.js | 4 +--- examples/sprayPaintSpawner.js | 10 ++++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/entityScripts/sprayPaintCan.js b/examples/entityScripts/sprayPaintCan.js index e1d8a2535b..02ddb91534 100644 --- a/examples/entityScripts/sprayPaintCan.js +++ b/examples/entityScripts/sprayPaintCan.js @@ -98,9 +98,8 @@ green: 20, blue: 150 }, - lifetime: 500, //probably wont be holding longer than this straight + lifetime: 50, //probably wont be holding longer than this straight }); - } this.letGo = function() { @@ -228,7 +227,6 @@ this.unload = function() { Script.update.disconnect(this.update); - Entities.deleteEntity(this.paintStream); this.strokes.forEach(function(stroke) { Entities.deleteEntity(stroke); }); diff --git a/examples/sprayPaintSpawner.js b/examples/sprayPaintSpawner.js index 6d7243cb45..56cf6cccdc 100644 --- a/examples/sprayPaintSpawner.js +++ b/examples/sprayPaintSpawner.js @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html //Just temporarily using my own bucket here so others can test the entity. Once PR is tested and merged, then the entity script will appear in its proper place in S3, and I wil switch it -var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v1"; +var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v3"; var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; var sprayCan = Entities.addEntity({ @@ -26,12 +26,14 @@ var sprayCan = Entities.addEntity({ collisionsWillMove: true, shapeType: 'box', script: scriptURL, - // gravity: {x: 0, y: -0.5, z: 0}, - // velocity: {x: 0, y: -1, z: 0} + gravity: {x: 0, y: -0.5, z: 0}, + velocity: {x: 0, y: -1, z: 0} }); function cleanup() { - Entities.deleteEntity(sprayCan); + + // Uncomment the below line to delete sprayCan on script reload- for faster iteration during development + // Entities.deleteEntity(sprayCan); } Script.scriptEnding.connect(cleanup); From eabee9857acc38a0879af7daa79172eec1618078 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 14 Sep 2015 17:23:53 +0200 Subject: [PATCH 04/38] Enum coding standard --- interface/src/Application.cpp | 2 ++ libraries/networking/src/AssetClient.cpp | 8 ++++---- libraries/networking/src/AssetRequest.cpp | 3 +-- libraries/networking/src/AssetResourceRequest.cpp | 4 +--- libraries/networking/src/HTTPResourceRequest.cpp | 5 ++--- libraries/networking/src/NetworkAccessManager.cpp | 1 + libraries/networking/src/NetworkAccessManager.h | 2 +- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b6e0a871b3..261cd5f2e0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -370,6 +370,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _lastFaceTrackerUpdate(0), _applicationOverlay() { + thread()->setObjectName("Main Thread"); + setInstance(this); _entityClipboard->createRootElement(); diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index c13bc07be1..12f974796a 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -11,16 +11,16 @@ #include "AssetClient.h" -#include -#include - #include +#include +#include + #include "AssetRequest.h" #include "AssetUpload.h" +#include "AssetUtils.h" #include "NodeList.h" #include "PacketReceiver.h" -#include "AssetUtils.h" MessageID AssetClient::_currentID = 0; diff --git a/libraries/networking/src/AssetRequest.cpp b/libraries/networking/src/AssetRequest.cpp index 45e925389d..7490e2eb27 100644 --- a/libraries/networking/src/AssetRequest.cpp +++ b/libraries/networking/src/AssetRequest.cpp @@ -13,7 +13,7 @@ #include -#include +#include #include "AssetClient.h" #include "NetworkLogging.h" @@ -59,7 +59,6 @@ void AssetRequest::start() { if (_error != NoError) { qCDebug(networking) << "Got error retrieving asset info for" << _hash; - _state = Finished; emit finished(this); diff --git a/libraries/networking/src/AssetResourceRequest.cpp b/libraries/networking/src/AssetResourceRequest.cpp index 6b419fc293..ecbe80cddb 100644 --- a/libraries/networking/src/AssetResourceRequest.cpp +++ b/libraries/networking/src/AssetResourceRequest.cpp @@ -32,7 +32,6 @@ void AssetResourceRequest::doSend() { _state = Finished; emit finished(); - return; } @@ -43,12 +42,11 @@ void AssetResourceRequest::doSend() { _state = Finished; emit finished(); - return; } connect(_assetRequest, &AssetRequest::progress, this, &AssetResourceRequest::progress); - QObject::connect(_assetRequest, &AssetRequest::finished, [this](AssetRequest* req) mutable { + connect(_assetRequest, &AssetRequest::finished, [this](AssetRequest* req) { Q_ASSERT(_state == InProgress); Q_ASSERT(req == _assetRequest); Q_ASSERT(req->getState() == AssetRequest::Finished); diff --git a/libraries/networking/src/HTTPResourceRequest.cpp b/libraries/networking/src/HTTPResourceRequest.cpp index fd650df348..34c9c1dad2 100644 --- a/libraries/networking/src/HTTPResourceRequest.cpp +++ b/libraries/networking/src/HTTPResourceRequest.cpp @@ -29,8 +29,7 @@ HTTPResourceRequest::~HTTPResourceRequest() { } void HTTPResourceRequest::doSend() { - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkRequest networkRequest = QNetworkRequest(_url); + QNetworkRequest networkRequest(_url); networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); if (_cacheEnabled) { @@ -39,7 +38,7 @@ void HTTPResourceRequest::doSend() { networkRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); } - _reply = networkAccessManager.get(networkRequest); + _reply = NetworkAccessManager::getInstance().get(networkRequest); connect(_reply, &QNetworkReply::finished, this, &HTTPResourceRequest::onRequestFinished); connect(_reply, &QNetworkReply::downloadProgress, this, &HTTPResourceRequest::onDownloadProgress); diff --git a/libraries/networking/src/NetworkAccessManager.cpp b/libraries/networking/src/NetworkAccessManager.cpp index 841b7491c7..97171d5ad7 100644 --- a/libraries/networking/src/NetworkAccessManager.cpp +++ b/libraries/networking/src/NetworkAccessManager.cpp @@ -18,6 +18,7 @@ QThreadStorage networkAccessManagers; QNetworkAccessManager& NetworkAccessManager::getInstance() { if (!networkAccessManagers.hasLocalData()) { networkAccessManagers.setLocalData(new QNetworkAccessManager()); + } return *networkAccessManagers.localData(); diff --git a/libraries/networking/src/NetworkAccessManager.h b/libraries/networking/src/NetworkAccessManager.h index 5a64f4ae0a..c4b435adb6 100644 --- a/libraries/networking/src/NetworkAccessManager.h +++ b/libraries/networking/src/NetworkAccessManager.h @@ -12,7 +12,7 @@ #ifndef hifi_NetworkAccessManager_h #define hifi_NetworkAccessManager_h -#include +#include /// Wrapper around QNetworkAccessManager to restrict at one instance by thread class NetworkAccessManager : public QObject { From 9678e704440544d3c15e426eac23c363e98053bc Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 15 Sep 2015 15:27:38 +0200 Subject: [PATCH 05/38] Asset caching --- interface/src/Application.cpp | 15 ++--- interface/src/ui/DiskCacheEditor.cpp | 3 +- libraries/networking/src/AssetClient.cpp | 41 ++++++++--- libraries/networking/src/AssetClient.h | 2 + libraries/networking/src/AssetRequest.cpp | 75 +++++++++++++++++++-- libraries/networking/src/AssetRequest.h | 4 ++ libraries/networking/src/AssetUpload.cpp | 3 +- libraries/networking/src/NetworkLogging.cpp | 1 + libraries/networking/src/NetworkLogging.h | 1 + libraries/networking/src/ResourceCache.cpp | 2 - libraries/networking/src/ResourceCache.h | 1 + 11 files changed, 118 insertions(+), 30 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 261cd5f2e0..3cb75b55ec 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -182,9 +182,6 @@ public: using namespace std; -// Starfield information -const qint64 MAXIMUM_CACHE_SIZE = 10 * BYTES_PER_GIGABYTES; // 10GB - static QTimer* locationUpdateTimer = NULL; static QTimer* balanceUpdateTimer = NULL; static QTimer* identityPacketTimer = NULL; @@ -462,13 +459,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : audioThread->start(); - QThread* assetThread = new QThread; - - assetThread->setObjectName("Asset Thread"); + // Setup AssetClient auto assetClient = DependencyManager::get(); - + QThread* assetThread = new QThread; + assetThread->setObjectName("Asset Thread"); assetClient->moveToThread(assetThread); - + connect(assetThread, &QThread::started, assetClient.data(), &AssetClient::init); assetThread->start(); const DomainHandler& domainHandler = nodeList->getDomainHandler(); @@ -857,8 +853,7 @@ void Application::cleanupBeforeQuit() { } void Application::emptyLocalCache() { - QNetworkDiskCache* cache = qobject_cast(NetworkAccessManager::getInstance().cache()); - if (cache) { + if (auto cache = NetworkAccessManager::getInstance().cache()) { qDebug() << "DiskCacheEditor::clear(): Clearing disk cache."; cache->clear(); } diff --git a/interface/src/ui/DiskCacheEditor.cpp b/interface/src/ui/DiskCacheEditor.cpp index 2f2b924e13..a33f28e240 100644 --- a/interface/src/ui/DiskCacheEditor.cpp +++ b/interface/src/ui/DiskCacheEditor.cpp @@ -140,8 +140,7 @@ void DiskCacheEditor::clear() { "You are about to erase all the content of the disk cache," "are you sure you want to do that?"); if (buttonClicked == QMessageBox::Yes) { - QNetworkDiskCache* cache = qobject_cast(NetworkAccessManager::getInstance().cache()); - if (cache) { + if (auto cache = NetworkAccessManager::getInstance().cache()) { qDebug() << "DiskCacheEditor::clear(): Clearing disk cache."; cache->clear(); } diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index 12f974796a..87e9b4c060 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -14,13 +14,18 @@ #include #include +#include #include +#include #include "AssetRequest.h" #include "AssetUpload.h" #include "AssetUtils.h" +#include "NetworkAccessManager.h" +#include "NetworkLogging.h" #include "NodeList.h" #include "PacketReceiver.h" +#include "ResourceCache.h" MessageID AssetClient::_currentID = 0; @@ -40,9 +45,25 @@ AssetClient::AssetClient() { connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &AssetClient::handleNodeKilled); } +void AssetClient::init() { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "init", Qt::BlockingQueuedConnection); + } + + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + if (!networkAccessManager.cache()) { + QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + QNetworkDiskCache* cache = new QNetworkDiskCache(); + cache->setMaximumCacheSize(MAXIMUM_CACHE_SIZE); + cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache"); + networkAccessManager.setCache(cache); + qCDebug(asset_client) << "AssetClient disk cache setup."; + } +} + AssetRequest* AssetClient::createRequest(const QString& hash, const QString& extension) { if (hash.length() != SHA256_HASH_HEX_LENGTH) { - qDebug() << "Invalid hash size"; + qCWarning(asset_client) << "Invalid hash size"; return nullptr; } @@ -50,7 +71,7 @@ AssetRequest* AssetClient::createRequest(const QString& hash, const QString& ext SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); if (!assetServer) { - qDebug().nospace() << "Could not request " << hash << "." << extension + qCWarning(asset_client).nospace() << "Could not request " << hash << "." << extension << " since you are not currently connected to an asset-server."; return nullptr; } @@ -68,7 +89,7 @@ AssetUpload* AssetClient::createUpload(const QString& filename) { SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); if (!assetServer) { - qDebug() << "Could not upload" << filename << "since you are not currently connected to an asset-server."; + qCWarning(asset_client) << "Could not upload" << filename << "since you are not currently connected to an asset-server."; return nullptr; } @@ -82,7 +103,7 @@ AssetUpload* AssetClient::createUpload(const QString& filename) { bool AssetClient::getAsset(const QString& hash, const QString& extension, DataOffset start, DataOffset end, ReceivedAssetCallback callback) { if (hash.length() != SHA256_HASH_HEX_LENGTH) { - qDebug() << "Invalid hash size"; + qCWarning(asset_client) << "Invalid hash size"; return false; } @@ -97,7 +118,7 @@ bool AssetClient::getAsset(const QString& hash, const QString& extension, DataOf + sizeof(start) + sizeof(end); auto packet = NLPacket::create(PacketType::AssetGet, payloadSize, true); - qDebug() << "Requesting data from" << start << "to" << end << "of" << hash << "from asset-server."; + qCDebug(asset_client) << "Requesting data from" << start << "to" << end << "of" << hash << "from asset-server."; packet->writePrimitive(messageID); @@ -184,7 +205,7 @@ void AssetClient::handleAssetGetReply(QSharedPointer packetList, S packet.open(QIODevice::ReadOnly); auto assetHash = packet.read(SHA256_HASH_LENGTH); - qDebug() << "Got reply for asset: " << assetHash.toHex(); + qCDebug(asset_client) << "Got reply for asset: " << assetHash.toHex(); MessageID messageID; packet.read(reinterpret_cast(&messageID), sizeof(messageID)); @@ -198,7 +219,7 @@ void AssetClient::handleAssetGetReply(QSharedPointer packetList, S packet.read(reinterpret_cast(&length), sizeof(DataOffset)); data = packet.read(length); } else { - qDebug() << "Failure getting asset: " << error; + qCWarning(asset_client) << "Failure getting asset: " << error; } // Check if we have any pending requests for this node @@ -254,15 +275,15 @@ void AssetClient::handleAssetUploadReply(QSharedPointer packet, Shared AssetServerError error; packet->readPrimitive(&error); - QString hashString { "" }; + QString hashString; if (error) { - qDebug() << "Error uploading file to asset server"; + qCWarning(asset_client) << "Error uploading file to asset server"; } else { auto hash = packet->read(SHA256_HASH_LENGTH); hashString = hash.toHex(); - qDebug() << "Successfully uploaded asset to asset-server - SHA256 hash is " << hashString; + qCDebug(asset_client) << "Successfully uploaded asset to asset-server - SHA256 hash is " << hashString; } // Check if we have any pending requests for this node diff --git a/libraries/networking/src/AssetClient.h b/libraries/networking/src/AssetClient.h index 6557954467..9b82e63b58 100644 --- a/libraries/networking/src/AssetClient.h +++ b/libraries/networking/src/AssetClient.h @@ -40,6 +40,8 @@ class AssetClient : public QObject, public Dependency { Q_OBJECT public: AssetClient(); + + Q_INVOKABLE void init(); Q_INVOKABLE AssetRequest* createRequest(const QString& hash, const QString& extension); Q_INVOKABLE AssetUpload* createUpload(const QString& filename); diff --git a/libraries/networking/src/AssetRequest.cpp b/libraries/networking/src/AssetRequest.cpp index 7490e2eb27..934d64c263 100644 --- a/libraries/networking/src/AssetRequest.cpp +++ b/libraries/networking/src/AssetRequest.cpp @@ -14,17 +14,19 @@ #include #include +#include #include "AssetClient.h" +#include "NetworkAccessManager.h" #include "NetworkLogging.h" #include "NodeList.h" +#include "ResourceCache.h" AssetRequest::AssetRequest(const QString& hash, const QString& extension) : QObject(), _hash(hash), _extension(extension) { - } void AssetRequest::start() { @@ -34,7 +36,18 @@ void AssetRequest::start() { } if (_state != NotStarted) { - qCWarning(networking) << "AssetRequest already started."; + qCWarning(asset_client) << "AssetRequest already started."; + return; + } + + if (loadFromCache()) { + _info.hash = _hash; + _info.size = _data.size(); + _error = NoError; + + _state = Finished; + emit finished(this); + qCDebug(asset_client) << getUrl().toDisplayString() << "loaded from disk cache."; return; } @@ -58,7 +71,7 @@ void AssetRequest::start() { } if (_error != NoError) { - qCDebug(networking) << "Got error retrieving asset info for" << _hash; + qCWarning(asset_client) << "Got error retrieving asset info for" << _hash; _state = Finished; emit finished(this); @@ -68,7 +81,7 @@ void AssetRequest::start() { _state = WaitingForData; _data.resize(info.size); - qCDebug(networking) << "Got size of " << _hash << " : " << info.size << " bytes"; + qCDebug(asset_client) << "Got size of " << _hash << " : " << info.size << " bytes"; int start = 0, end = _info.size; @@ -97,6 +110,10 @@ void AssetRequest::start() { memcpy(_data.data() + start, data.constData(), data.size()); _totalReceived += data.size(); emit progress(_totalReceived, _info.size); + + if (saveToCache(data)) { + qCDebug(asset_client) << getUrl().toDisplayString() << "saved to disk cache"; + } } else { // hash doesn't match - we have an error _error = HashVerificationFailed; @@ -105,7 +122,7 @@ void AssetRequest::start() { } if (_error != NoError) { - qCDebug(networking) << "Got error retrieving asset" << _hash << "- error code" << _error; + qCWarning(asset_client) << "Got error retrieving asset" << _hash << "- error code" << _error; } _state = Finished; @@ -113,3 +130,51 @@ void AssetRequest::start() { }); }); } + +QUrl AssetRequest::getUrl() const { + if (!_extension.isEmpty()) { + return QUrl(QString("%1:%2.%3").arg(URL_SCHEME_ATP, _hash, _extension)); + } else { + return QUrl(QString("%1:%2").arg(URL_SCHEME_ATP, _hash)); + } +} + +bool AssetRequest::loadFromCache() { + if (auto cache = NetworkAccessManager::getInstance().cache()) { + auto url = getUrl(); + if (auto ioDevice = cache->data(url)) { + _data = ioDevice->readAll(); + return true; + } else { + qCDebug(asset_client) << url.toDisplayString() << "not in disk cache"; + } + } else { + qCWarning(asset_client) << "No disk cache to load assets from."; + } + return false; +} + +bool AssetRequest::saveToCache(const QByteArray& file) const { + if (auto cache = NetworkAccessManager::getInstance().cache()) { + auto url = getUrl(); + + if (!cache->metaData(url).isValid()) { + QNetworkCacheMetaData metaData; + metaData.setUrl(url); + metaData.setSaveToDisk(true); + metaData.setLastModified(QDateTime::currentDateTime()); + metaData.setExpirationDate(QDateTime()); // Never expires + + if (auto ioDevice = cache->prepare(metaData)) { + ioDevice->write(file); + cache->insert(ioDevice); + return true; + } + qCWarning(asset_client) << "Could not save" << url.toDisplayString() << "to disk cache."; + } + } else { + qCWarning(asset_client) << "No disk cache to save assets to."; + } + return false; +} + diff --git a/libraries/networking/src/AssetRequest.h b/libraries/networking/src/AssetRequest.h index 9bd224b35e..75e2353425 100644 --- a/libraries/networking/src/AssetRequest.h +++ b/libraries/networking/src/AssetRequest.h @@ -46,12 +46,16 @@ public: const QByteArray& getData() const { return _data; } const State& getState() const { return _state; } const Error& getError() const { return _error; } + QUrl getUrl() const; signals: void finished(AssetRequest* thisRequest); void progress(qint64 totalReceived, qint64 total); private: + bool loadFromCache(); + bool saveToCache(const QByteArray& file) const; + State _state = NotStarted; Error _error = NoError; AssetInfo _info; diff --git a/libraries/networking/src/AssetUpload.cpp b/libraries/networking/src/AssetUpload.cpp index 9c9d172959..92632a43e5 100644 --- a/libraries/networking/src/AssetUpload.cpp +++ b/libraries/networking/src/AssetUpload.cpp @@ -15,6 +15,7 @@ #include #include "AssetClient.h" +#include "NetworkLogging.h" AssetUpload::AssetUpload(QObject* object, const QString& filename) : _filename(filename) @@ -41,7 +42,7 @@ void AssetUpload::start() { // ask the AssetClient to upload the asset and emit the proper signals from the passed callback auto assetClient = DependencyManager::get(); - qDebug() << "Attempting to upload" << _filename << "to asset-server."; + qCDebug(asset_client) << "Attempting to upload" << _filename << "to asset-server."; assetClient->uploadAsset(data, _extension, [this](bool responseReceived, AssetServerError error, const QString& hash){ if (!responseReceived) { diff --git a/libraries/networking/src/NetworkLogging.cpp b/libraries/networking/src/NetworkLogging.cpp index 45ff716a97..28b209960e 100644 --- a/libraries/networking/src/NetworkLogging.cpp +++ b/libraries/networking/src/NetworkLogging.cpp @@ -12,3 +12,4 @@ #include "NetworkLogging.h" Q_LOGGING_CATEGORY(networking, "hifi.networking") +Q_LOGGING_CATEGORY(asset_client, "hifi.networking.asset_client") diff --git a/libraries/networking/src/NetworkLogging.h b/libraries/networking/src/NetworkLogging.h index 47a6a34264..838bbb57d2 100644 --- a/libraries/networking/src/NetworkLogging.h +++ b/libraries/networking/src/NetworkLogging.h @@ -15,5 +15,6 @@ #include Q_DECLARE_LOGGING_CATEGORY(networking) +Q_DECLARE_LOGGING_CATEGORY(asset_client) #endif // hifi_NetworkLogging_h diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 18135cf6df..5c47a831e8 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -12,8 +12,6 @@ #include #include -#include -#include #include #include diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 3bae7f5b9d..97e46f088a 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -35,6 +35,7 @@ class Resource; static const qint64 BYTES_PER_MEGABYTES = 1024 * 1024; static const qint64 BYTES_PER_GIGABYTES = 1024 * BYTES_PER_MEGABYTES; +static const qint64 MAXIMUM_CACHE_SIZE = 10 * BYTES_PER_GIGABYTES; // 10GB // Windows can have troubles allocating that much memory in ram sometimes // so default cache size at 100 MB on windows (1GB otherwise) From dd0244b15da45d28ab4184ff8578c89b5751305b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 15 Sep 2015 15:41:34 +0200 Subject: [PATCH 06/38] Added a couple comments --- libraries/networking/src/AssetClient.cpp | 1 + libraries/networking/src/AssetRequest.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index 87e9b4c060..e4c3f468c6 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -50,6 +50,7 @@ void AssetClient::init() { QMetaObject::invokeMethod(this, "init", Qt::BlockingQueuedConnection); } + // Setup disk cache if not already QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); if (!networkAccessManager.cache()) { QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); diff --git a/libraries/networking/src/AssetRequest.cpp b/libraries/networking/src/AssetRequest.cpp index 934d64c263..b4e3882a5e 100644 --- a/libraries/networking/src/AssetRequest.cpp +++ b/libraries/networking/src/AssetRequest.cpp @@ -40,6 +40,7 @@ void AssetRequest::start() { return; } + // Try to load from cache if (loadFromCache()) { _info.hash = _hash; _info.size = _data.size(); From 88d073b4ac1e4a44ea7b4b71297145335e5af751 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 16 Sep 2015 15:20:48 +0200 Subject: [PATCH 07/38] More disk cache debug info --- libraries/networking/src/AssetClient.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index e4c3f468c6..87af2a5cf8 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -54,11 +54,14 @@ void AssetClient::init() { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); if (!networkAccessManager.cache()) { QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + cachePath = !cachePath.isEmpty() ? cachePath : "interfaceCache"; + QNetworkDiskCache* cache = new QNetworkDiskCache(); cache->setMaximumCacheSize(MAXIMUM_CACHE_SIZE); - cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache"); + cache->setCacheDirectory(cachePath); networkAccessManager.setCache(cache); - qCDebug(asset_client) << "AssetClient disk cache setup."; + qCDebug(asset_client) << "AssetClient disk cache setup at" << cachePath + << "(size:" << MAXIMUM_CACHE_SIZE / BYTES_PER_GIGABYTES << "GB)"; } } From def24a15ad1d206b102ad4cec5ac164757b85c8f Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 16 Sep 2015 09:00:41 -0700 Subject: [PATCH 08/38] fix audio int16_t to float scaling --- libraries/audio/src/AudioBuffer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio/src/AudioBuffer.h b/libraries/audio/src/AudioBuffer.h index 558d686861..2d23be864b 100644 --- a/libraries/audio/src/AudioBuffer.h +++ b/libraries/audio/src/AudioBuffer.h @@ -239,7 +239,7 @@ inline void AudioFrameBuffer< T >::copyFrames(uint32_t channelCount, const uint3 if(typeid(T) == typeid(float32_t) && typeid(S) == typeid(int16_t)) { // source and destination aare not the same, convert from float32_t to int16_t and copy out - const int scale = (2 << ((8 * sizeof(S)) - 1)); + const int scale = (1 << ((8 * sizeof(S)) - 1)); if (frameAlignment16 && (_channelCount == 1 || _channelCount == 2)) { @@ -382,7 +382,7 @@ inline void AudioFrameBuffer< T >::copyFrames(uint32_t channelCount, const uint3 if(typeid(T) == typeid(float32_t) && typeid(S) == typeid(int16_t)) { // source and destination aare not the same, convert from int16_t to float32_t and copy in - const int scale = (2 << ((8 * sizeof(S)) - 1)); + const int scale = (1 << ((8 * sizeof(S)) - 1)); if (frameAlignment16 && (_channelCount == 1 || _channelCount == 2)) { From 0b21cc1777356ee8a2b0fa59ca0da36777fd7205 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 16 Sep 2015 09:59:35 -0700 Subject: [PATCH 09/38] paint can tweaks --- examples/entityScripts/sprayPaintCan.js | 9 ++++++++- examples/sprayPaintSpawner.js | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/entityScripts/sprayPaintCan.js b/examples/entityScripts/sprayPaintCan.js index 02ddb91534..bad13d43d7 100644 --- a/examples/entityScripts/sprayPaintCan.js +++ b/examples/entityScripts/sprayPaintCan.js @@ -57,7 +57,8 @@ timeSinceLastMoved = 0; } - if (self.userData.grabKey && self.userData.grabKey.activated === true) { + //Only activate for the user who grabbed the object + if (self.userData.grabKey && self.userData.grabKey.activated === true && this.userData.grabKey.avatarId == MyAvatar.sessionUUID) { if (self.activated !== true) { //We were just grabbed, so create a particle system self.grab(); @@ -105,6 +106,7 @@ this.letGo = function() { this.activated = false; Entities.deleteEntity(this.paintStream); + this.paintStream = null; } this.reset = function() { @@ -208,6 +210,8 @@ this.entityId = entityId; this.properties = Entities.getEntityProperties(self.entityId); this.getUserData(); + + //Only activate for the avatar who is grabbing the can! if (this.userData.grabKey && this.userData.grabKey.activated) { this.activated = true; } @@ -227,6 +231,9 @@ this.unload = function() { Script.update.disconnect(this.update); + if(this.paintStream) { + Entities.deleteEntity(this.paintStream); + } this.strokes.forEach(function(stroke) { Entities.deleteEntity(stroke); }); diff --git a/examples/sprayPaintSpawner.js b/examples/sprayPaintSpawner.js index 56cf6cccdc..87b96ae1b7 100644 --- a/examples/sprayPaintSpawner.js +++ b/examples/sprayPaintSpawner.js @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html //Just temporarily using my own bucket here so others can test the entity. Once PR is tested and merged, then the entity script will appear in its proper place in S3, and I wil switch it -var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v3"; +var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v6"; var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; var sprayCan = Entities.addEntity({ @@ -37,3 +37,4 @@ function cleanup() { } Script.scriptEnding.connect(cleanup); + From 5df7ce7424b8b4855a7e43f3df573726b91772a8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 16 Sep 2015 11:43:28 -0700 Subject: [PATCH 10/38] fix for missing jurisdiction listener in Agent --- assignment-client/src/Agent.cpp | 6 ++++++ libraries/entities/src/EntityScriptingInterface.h | 2 +- libraries/octree/src/OctreeHeadlessViewer.cpp | 6 ++---- libraries/octree/src/OctreeHeadlessViewer.h | 4 ++-- libraries/octree/src/OctreeScriptingInterface.cpp | 1 + libraries/octree/src/OctreeScriptingInterface.h | 7 +++---- libraries/script-engine/src/ScriptEngine.cpp | 3 ++- 7 files changed, 17 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index fda226b934..f2d73bd1a6 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -191,8 +191,14 @@ void Agent::run() { auto entityScriptingInterface = DependencyManager::get(); _scriptEngine->registerGlobalObject("EntityViewer", &_entityViewer); + + // we need to make sure that init has been called for our EntityScriptingInterface + // so that it actually has a jurisdiction listener when we ask it for it next + entityScriptingInterface->init(); _entityViewer.setJurisdictionListener(entityScriptingInterface->getJurisdictionListener()); + _entityViewer.init(); + entityScriptingInterface->setEntityTree(_entityViewer.getTree()); // wire up our additional agent related processing to the update signal diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 581eed184d..8d2b0b6892 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -1,6 +1,6 @@ // // EntityScriptingInterface.h -// libraries/models/src +// libraries/entities/src // // Created by Brad Hefta-Gaub on 12/6/13. // Copyright 2013 High Fidelity, Inc. diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index 3a80180008..88a77a4c53 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -23,9 +23,6 @@ OctreeHeadlessViewer::OctreeHeadlessViewer() : _viewFrustum.setProjection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), DEFAULT_ASPECT_RATIO, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); } -OctreeHeadlessViewer::~OctreeHeadlessViewer() { -} - void OctreeHeadlessViewer::init() { OctreeRenderer::init(); setViewFrustum(&_viewFrustum); @@ -34,8 +31,9 @@ void OctreeHeadlessViewer::init() { void OctreeHeadlessViewer::queryOctree() { char serverType = getMyNodeType(); PacketType packetType = getMyQueryMessageType(); + NodeToJurisdictionMap& jurisdictions = *_jurisdictionListener->getJurisdictions(); - + bool wantExtraDebugging = false; if (wantExtraDebugging) { diff --git a/libraries/octree/src/OctreeHeadlessViewer.h b/libraries/octree/src/OctreeHeadlessViewer.h index be076e7b5f..5a17f48a19 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.h +++ b/libraries/octree/src/OctreeHeadlessViewer.h @@ -29,7 +29,7 @@ class OctreeHeadlessViewer : public OctreeRenderer { Q_OBJECT public: OctreeHeadlessViewer(); - virtual ~OctreeHeadlessViewer(); + virtual ~OctreeHeadlessViewer() {}; virtual void renderElement(OctreeElementPointer element, RenderArgs* args) { /* swallow these */ } virtual void init(); @@ -65,7 +65,7 @@ public slots: private: ViewFrustum _viewFrustum; - JurisdictionListener* _jurisdictionListener; + JurisdictionListener* _jurisdictionListener = nullptr; OctreeQuery _octreeQuery; float _voxelSizeScale; int _boundaryLevelAdjust; diff --git a/libraries/octree/src/OctreeScriptingInterface.cpp b/libraries/octree/src/OctreeScriptingInterface.cpp index 97e7f67ff5..8913e88cf5 100644 --- a/libraries/octree/src/OctreeScriptingInterface.cpp +++ b/libraries/octree/src/OctreeScriptingInterface.cpp @@ -54,6 +54,7 @@ void OctreeScriptingInterface::init() { if (_initialized) { return; } + if (_jurisdictionListener) { _managedJurisdictionListener = false; } else { diff --git a/libraries/octree/src/OctreeScriptingInterface.h b/libraries/octree/src/OctreeScriptingInterface.h index ea897bbb4f..47b01c64f9 100644 --- a/libraries/octree/src/OctreeScriptingInterface.h +++ b/libraries/octree/src/OctreeScriptingInterface.h @@ -21,8 +21,7 @@ class OctreeScriptingInterface : public QObject { Q_OBJECT public: - OctreeScriptingInterface(OctreeEditPacketSender* packetSender = NULL, - JurisdictionListener* jurisdictionListener = NULL); + OctreeScriptingInterface(OctreeEditPacketSender* packetSender = NULL, JurisdictionListener* jurisdictionListener = NULL); ~OctreeScriptingInterface(); @@ -86,8 +85,8 @@ public slots: protected: /// attached OctreeEditPacketSender that handles queuing and sending of packets to VS - OctreeEditPacketSender* _packetSender; - JurisdictionListener* _jurisdictionListener; + OctreeEditPacketSender* _packetSender = nullptr; + JurisdictionListener* _jurisdictionListener = nullptr; bool _managedPacketSender; bool _managedJurisdictionListener; bool _initialized; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index a7136edd7b..cd9e9d2e6c 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -263,7 +263,7 @@ void ScriptEngine::init() { } _isInitialized = true; - + auto entityScriptingInterface = DependencyManager::get(); entityScriptingInterface->init(); @@ -559,6 +559,7 @@ void ScriptEngine::run() { if (!_isInitialized) { init(); } + _isRunning = true; _isFinished = false; if (_wantSignals) { From bca00db4a8f4d0d74cc3b8e3d014333c847d1642 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 16 Sep 2015 11:48:15 -0700 Subject: [PATCH 11/38] use unique_ptr for Agent ScriptEngine --- assignment-client/src/Agent.cpp | 13 +++---------- assignment-client/src/Agent.h | 3 ++- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index f2d73bd1a6..58d8c931f8 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -153,11 +153,11 @@ void Agent::run() { qDebug() << "Downloaded script:" << scriptContents; - _scriptEngine = new ScriptEngine(scriptContents, _payload); + _scriptEngine = std::unique_ptr(new ScriptEngine(scriptContents, _payload)); _scriptEngine->setParent(this); // be the parent of the script engine so it gets moved when we do // setup an Avatar for the script to use - ScriptableAvatar scriptedAvatar(_scriptEngine); + ScriptableAvatar scriptedAvatar(_scriptEngine.get()); scriptedAvatar.setForceFaceTrackerConnected(true); // call model URL setters with empty URLs so our avatar, if user, will have the default models @@ -202,17 +202,10 @@ void Agent::run() { entityScriptingInterface->setEntityTree(_entityViewer.getTree()); // wire up our additional agent related processing to the update signal - QObject::connect(_scriptEngine, &ScriptEngine::update, this, &Agent::processAgentAvatarAndAudio); + QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatarAndAudio); _scriptEngine->run(); setFinished(true); - - // kill the avatar identity timer - delete _avatarIdentityTimer; - - // delete the script engine - delete _scriptEngine; - } void Agent::setIsAvatar(bool isAvatar) { diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 33a8eb58c2..ab000015d5 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -12,6 +12,7 @@ #ifndef hifi_Agent_h #define hifi_Agent_h +#include #include #include @@ -61,7 +62,7 @@ private slots: void processAgentAvatarAndAudio(float deltaTime); private: - ScriptEngine* _scriptEngine; + std::unique_ptr _scriptEngine; EntityEditPacketSender _entityEditSender; EntityTreeHeadlessViewer _entityViewer; QTimer* _pingTimer; From 229e73f88c4444bf3f8d9812ceb061192ea96477 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 16 Sep 2015 11:52:05 -0700 Subject: [PATCH 12/38] protect the agent from null timers in avatar stop --- assignment-client/src/Agent.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 58d8c931f8..157154606f 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -226,10 +226,17 @@ void Agent::setIsAvatar(bool isAvatar) { } if (!_isAvatar) { - delete _avatarIdentityTimer; - _avatarIdentityTimer = NULL; - delete _avatarBillboardTimer; - _avatarBillboardTimer = NULL; + if (_avatarIdentityTimer) { + _avatarIdentityTimer->stop(); + delete _avatarIdentityTimer; + _avatarIdentityTimer = nullptr; + } + + if (_avatarBillboardTimer) { + _avatarIdentityTimer->stop(); + delete _avatarIdentityTimer; + _avatarBillboardTimer = nullptr; + } } } From 500a96ee7ce32f77463db3036f99e1e49152e85d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 16 Sep 2015 12:25:03 -0700 Subject: [PATCH 13/38] guard perpetual AC domain connection if NL thread locked --- libraries/networking/src/ThreadedAssignment.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index aee2805f32..a57bbc847c 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -43,7 +43,9 @@ void ThreadedAssignment::setFinished(bool isFinished) { packetReceiver.setShouldDropPackets(true); if (_domainServerTimer) { - _domainServerTimer->stop(); + // stop the domain-server check in timer by calling deleteLater so it gets cleaned up on NL thread + _domainServerTimer->deleteLater(); + _domainServerTimer = nullptr; } if (_statsTimer) { @@ -65,9 +67,12 @@ void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeTy auto nodeList = DependencyManager::get(); nodeList->setOwnerType(nodeType); - _domainServerTimer = new QTimer(this); + _domainServerTimer = new QTimer(nodeList.data()); connect(_domainServerTimer, SIGNAL(timeout()), this, SLOT(checkInWithDomainServerOrExit())); _domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); + + // move the domain server time to the NL so check-ins fire from there + _domainServerTimer->moveToThread(nodeList->thread()); if (shouldSendStats) { // start sending stats packet once we connect to the domain From cc8ad868b8c36a0b5567c2c5bedb19e0e56ab74e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 16 Sep 2015 12:27:57 -0700 Subject: [PATCH 14/38] don't parent DS timer to object in another thread --- libraries/networking/src/ThreadedAssignment.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index a57bbc847c..5f0db9412c 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -67,7 +67,7 @@ void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeTy auto nodeList = DependencyManager::get(); nodeList->setOwnerType(nodeType); - _domainServerTimer = new QTimer(nodeList.data()); + _domainServerTimer = new QTimer; connect(_domainServerTimer, SIGNAL(timeout()), this, SLOT(checkInWithDomainServerOrExit())); _domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); From bbf6e8b599ead168d5441d9edfebaafcc890fbe6 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 16 Sep 2015 13:52:29 -0700 Subject: [PATCH 15/38] using relative paths for entity scripts --- examples/entityScripts/sprayPaintCan.js | 10 +++++----- examples/sprayPaintSpawner.js | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/entityScripts/sprayPaintCan.js b/examples/entityScripts/sprayPaintCan.js index bad13d43d7..aa04e94341 100644 --- a/examples/entityScripts/sprayPaintCan.js +++ b/examples/entityScripts/sprayPaintCan.js @@ -2,7 +2,7 @@ // Script.include("../libraries/utils.js"); //Need absolute path for now, for testing before PR merge and s3 cloning. Will change post-merge - Script.include("https://hifi-public.s3.amazonaws.com/scripts/libraries/utils.js"); + Script.include("../libraries/utils.js"); GRAB_FRAME_USER_DATA_KEY = "grabFrame"; this.userData = {}; @@ -58,7 +58,7 @@ } //Only activate for the user who grabbed the object - if (self.userData.grabKey && self.userData.grabKey.activated === true && this.userData.grabKey.avatarId == MyAvatar.sessionUUID) { + if (self.userData.grabKey && self.userData.grabKey.activated === true && self.userData.grabKey.avatarId == MyAvatar.sessionUUID) { if (self.activated !== true) { //We were just grabbed, so create a particle system self.grab(); @@ -88,9 +88,9 @@ emitVelocity: ZERO_VEC, emitAcceleration: ZERO_VEC, velocitySpread: { - x: .02, - y: .02, - z: 0.02 + x: .1, + y: .1, + z: 0.1 }, emitRate: 100, particleRadius: 0.01, diff --git a/examples/sprayPaintSpawner.js b/examples/sprayPaintSpawner.js index 87b96ae1b7..3b9cee6ef4 100644 --- a/examples/sprayPaintSpawner.js +++ b/examples/sprayPaintSpawner.js @@ -9,7 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html //Just temporarily using my own bucket here so others can test the entity. Once PR is tested and merged, then the entity script will appear in its proper place in S3, and I wil switch it -var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v6"; +// var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v6 "; +var scriptURL = Script.resolvePath("entityScripts/sprayPaintCan.js?v2"); var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; var sprayCan = Entities.addEntity({ From cbb8bee9621050be4c21cf8a0b3d473b6c1ca6f7 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 16 Sep 2015 14:59:38 -0700 Subject: [PATCH 16/38] Trying to fix ScriptEngine location property --- libraries/script-engine/src/ScriptEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index a7136edd7b..518279b21d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -405,7 +405,7 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func QScriptValue setterFunction = newFunction(setter, 1); QScriptValue getterFunction = newFunction(getter); - if (!parent.isNull()) { + if (!parent.isNull() && !parent.isEmpty()) { QScriptValue object = globalObject().property(parent); if (object.isValid()) { object.setProperty(name, setterFunction, QScriptValue::PropertySetter); From fae4b08eb056a838e5265c25b0a26ca85effec70 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 16 Sep 2015 15:11:53 -0700 Subject: [PATCH 17/38] AnimController Node Bug fixes AnimController: proper support for alpha AnimController: bug fix for translation. AnimOverlay: renamed local var when building hand boneSets from head to hand. --- libraries/animation/src/AnimController.cpp | 24 ++++++++++++---------- libraries/animation/src/AnimOverlay.cpp | 8 ++++---- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/libraries/animation/src/AnimController.cpp b/libraries/animation/src/AnimController.cpp index c021124732..f74f30b631 100644 --- a/libraries/animation/src/AnimController.cpp +++ b/libraries/animation/src/AnimController.cpp @@ -9,6 +9,7 @@ // #include "AnimController.h" +#include "AnimUtil.h" #include "AnimationLogging.h" AnimController::AnimController(const std::string& id, float alpha) : @@ -40,38 +41,39 @@ const AnimPoseVec& AnimController::overlay(const AnimVariantMap& animVars, float if (jointVar.jointIndex >= 0) { - AnimPose defaultPose; - glm::quat absRot; - glm::quat parentAbsRot; + AnimPose defaultAbsPose; + AnimPose parentAbsPose = AnimPose::identity; if (jointVar.jointIndex <= (int)underPoses.size()) { // jointVar is an absolute rotation, if it is not set we will use the underPose as our default value - defaultPose = _skeleton->getAbsolutePose(jointVar.jointIndex, underPoses); - absRot = animVars.lookup(jointVar.var, defaultPose.rot); + defaultAbsPose = _skeleton->getAbsolutePose(jointVar.jointIndex, underPoses); + defaultAbsPose.rot = animVars.lookup(jointVar.var, defaultAbsPose.rot); // because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose. int parentIndex = _skeleton->getParentIndex(jointVar.jointIndex); if (parentIndex >= 0) { - parentAbsRot = _skeleton->getAbsolutePose(parentIndex, underPoses).rot; + parentAbsPose = _skeleton->getAbsolutePose(parentIndex, underPoses); } } else { // jointVar is an absolute rotation, if it is not set we will use the bindPose as our default value - defaultPose = _skeleton->getAbsoluteBindPose(jointVar.jointIndex); - absRot = animVars.lookup(jointVar.var, defaultPose.rot); + defaultAbsPose = _skeleton->getAbsoluteBindPose(jointVar.jointIndex); + defaultAbsPose.rot = animVars.lookup(jointVar.var, defaultAbsPose.rot); // because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose // here we use the bind pose int parentIndex = _skeleton->getParentIndex(jointVar.jointIndex); if (parentIndex >= 0) { - parentAbsRot = _skeleton->getAbsoluteBindPose(parentIndex).rot; + parentAbsPose = _skeleton->getAbsoluteBindPose(parentIndex); } } // convert from absolute to relative - glm::quat relRot = glm::inverse(parentAbsRot) * absRot; - _poses[jointVar.jointIndex] = AnimPose(defaultPose.scale, relRot, defaultPose.trans); + AnimPose relPose = parentAbsPose.inverse() * defaultAbsPose; + + // blend with underPose + ::blend(1, &underPoses[jointVar.jointIndex], &relPose, _alpha, &_poses[jointVar.jointIndex]); } } diff --git a/libraries/animation/src/AnimOverlay.cpp b/libraries/animation/src/AnimOverlay.cpp index 1a0a16ca8a..760a683aa6 100644 --- a/libraries/animation/src/AnimOverlay.cpp +++ b/libraries/animation/src/AnimOverlay.cpp @@ -173,8 +173,8 @@ void AnimOverlay::buildEmptyBoneSet() { void AnimOverlay::buildLeftHandBoneSet() { assert(_skeleton); buildEmptyBoneSet(); - int headJoint = _skeleton->nameToJointIndex("LeftHand"); - for_each_child_joint(_skeleton, headJoint, [&](int i) { + int handJoint = _skeleton->nameToJointIndex("LeftHand"); + for_each_child_joint(_skeleton, handJoint, [&](int i) { _boneSetVec[i] = 1.0f; }); } @@ -182,8 +182,8 @@ void AnimOverlay::buildLeftHandBoneSet() { void AnimOverlay::buildRightHandBoneSet() { assert(_skeleton); buildEmptyBoneSet(); - int headJoint = _skeleton->nameToJointIndex("RightHand"); - for_each_child_joint(_skeleton, headJoint, [&](int i) { + int handJoint = _skeleton->nameToJointIndex("RightHand"); + for_each_child_joint(_skeleton, handJoint, [&](int i) { _boneSetVec[i] = 1.0f; }); } From 5aeebba90e565a43d0e0d3d23858de9fbdc0682d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 16 Sep 2015 15:49:47 -0700 Subject: [PATCH 18/38] Renamed AnimController to AnimManipulator, Removed offsets on IK targets --- interface/src/avatar/MyAvatar.cpp | 2 +- ...AnimController.cpp => AnimManipulator.cpp} | 27 ++++++++++--------- .../{AnimController.h => AnimManipulator.h} | 18 ++++++------- libraries/animation/src/AnimNode.h | 2 +- libraries/animation/src/AnimNodeLoader.cpp | 20 +++++++------- libraries/animation/src/Rig.cpp | 9 +++---- tests/animation/src/data/avatar.json | 4 +-- 7 files changed, 41 insertions(+), 41 deletions(-) rename libraries/animation/src/{AnimController.cpp => AnimManipulator.cpp} (75%) rename libraries/animation/src/{AnimController.h => AnimManipulator.h} (79%) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e165b5c617..69f7516430 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1302,7 +1302,7 @@ void MyAvatar::initAnimGraph() { // or run a local web-server // python -m SimpleHTTPServer& //auto graphUrl = QUrl("http://localhost:8000/avatar.json"); - auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/04a02c47eb56d8bfaebb/raw/5f2a4e268d35147c83d44881e268f83a6296e89b/ik-avatar-hands.json"); + auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/04a02c47eb56d8bfaebb/raw/72517b231f606b724c5169e02642e401f9af5a54/ik-avatar-hands.json"); _rig->initAnimGraph(graphUrl, _skeletonModel.getGeometry()->getFBXGeometry()); } diff --git a/libraries/animation/src/AnimController.cpp b/libraries/animation/src/AnimManipulator.cpp similarity index 75% rename from libraries/animation/src/AnimController.cpp rename to libraries/animation/src/AnimManipulator.cpp index f74f30b631..c2951681e1 100644 --- a/libraries/animation/src/AnimController.cpp +++ b/libraries/animation/src/AnimManipulator.cpp @@ -1,5 +1,5 @@ // -// AnimController.cpp +// AnimManipulator.cpp // // Created by Anthony J. Thibault on 9/8/15. // Copyright (c) 2015 High Fidelity, Inc. All rights reserved. @@ -8,25 +8,25 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "AnimController.h" +#include "AnimManipulator.h" #include "AnimUtil.h" #include "AnimationLogging.h" -AnimController::AnimController(const std::string& id, float alpha) : - AnimNode(AnimNode::Type::Controller, id), +AnimManipulator::AnimManipulator(const std::string& id, float alpha) : + AnimNode(AnimNode::Type::Manipulator, id), _alpha(alpha) { } -AnimController::~AnimController() { +AnimManipulator::~AnimManipulator() { } -const AnimPoseVec& AnimController::evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) { +const AnimPoseVec& AnimManipulator::evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) { return overlay(animVars, dt, triggersOut, _skeleton->getRelativeBindPoses()); } -const AnimPoseVec& AnimController::overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) { +const AnimPoseVec& AnimManipulator::overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) { _alpha = animVars.lookup(_alphaVar, _alpha); for (auto& jointVar : _jointVars) { @@ -34,7 +34,7 @@ const AnimPoseVec& AnimController::overlay(const AnimVariantMap& animVars, float QString qJointName = QString::fromStdString(jointVar.jointName); jointVar.jointIndex = _skeleton->nameToJointIndex(qJointName); if (jointVar.jointIndex < 0) { - qCWarning(animation) << "AnimController could not find jointName" << qJointName << "in skeleton"; + qCWarning(animation) << "AnimManipulator could not find jointName" << qJointName << "in skeleton"; } jointVar.hasPerformedJointLookup = true; } @@ -42,10 +42,12 @@ const AnimPoseVec& AnimController::overlay(const AnimVariantMap& animVars, float if (jointVar.jointIndex >= 0) { AnimPose defaultAbsPose; + AnimPose defaultRelPose; AnimPose parentAbsPose = AnimPose::identity; if (jointVar.jointIndex <= (int)underPoses.size()) { // jointVar is an absolute rotation, if it is not set we will use the underPose as our default value + defaultRelPose = underPoses[jointVar.jointIndex]; defaultAbsPose = _skeleton->getAbsolutePose(jointVar.jointIndex, underPoses); defaultAbsPose.rot = animVars.lookup(jointVar.var, defaultAbsPose.rot); @@ -58,6 +60,7 @@ const AnimPoseVec& AnimController::overlay(const AnimVariantMap& animVars, float } else { // jointVar is an absolute rotation, if it is not set we will use the bindPose as our default value + defaultRelPose = AnimPose::identity; defaultAbsPose = _skeleton->getAbsoluteBindPose(jointVar.jointIndex); defaultAbsPose.rot = animVars.lookup(jointVar.var, defaultAbsPose.rot); @@ -73,14 +76,14 @@ const AnimPoseVec& AnimController::overlay(const AnimVariantMap& animVars, float AnimPose relPose = parentAbsPose.inverse() * defaultAbsPose; // blend with underPose - ::blend(1, &underPoses[jointVar.jointIndex], &relPose, _alpha, &_poses[jointVar.jointIndex]); + ::blend(1, &defaultRelPose, &relPose, _alpha, &_poses[jointVar.jointIndex]); } } return _poses; } -void AnimController::setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) { +void AnimManipulator::setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) { AnimNode::setSkeletonInternal(skeleton); // invalidate all jointVar indices @@ -99,10 +102,10 @@ void AnimController::setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) { } // for AnimDebugDraw rendering -const AnimPoseVec& AnimController::getPosesInternal() const { +const AnimPoseVec& AnimManipulator::getPosesInternal() const { return _poses; } -void AnimController::addJointVar(const JointVar& jointVar) { +void AnimManipulator::addJointVar(const JointVar& jointVar) { _jointVars.push_back(jointVar); } diff --git a/libraries/animation/src/AnimController.h b/libraries/animation/src/AnimManipulator.h similarity index 79% rename from libraries/animation/src/AnimController.h rename to libraries/animation/src/AnimManipulator.h index 15805d72fd..c04853b8e0 100644 --- a/libraries/animation/src/AnimController.h +++ b/libraries/animation/src/AnimManipulator.h @@ -1,5 +1,5 @@ // -// AnimController.h +// AnimManipulator.h // // Created by Anthony J. Thibault on 9/8/15. // Copyright (c) 2015 High Fidelity, Inc. All rights reserved. @@ -8,19 +8,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_AnimController_h -#define hifi_AnimController_h +#ifndef hifi_AnimManipulator_h +#define hifi_AnimManipulator_h #include "AnimNode.h" // Allows procedural control over a set of joints. -class AnimController : public AnimNode { +class AnimManipulator : public AnimNode { public: friend class AnimTests; - AnimController(const std::string& id, float alpha); - virtual ~AnimController() override; + AnimManipulator(const std::string& id, float alpha); + virtual ~AnimManipulator() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override; @@ -50,9 +50,9 @@ protected: std::vector _jointVars; // no copies - AnimController(const AnimController&) = delete; - AnimController& operator=(const AnimController&) = delete; + AnimManipulator(const AnimManipulator&) = delete; + AnimManipulator& operator=(const AnimManipulator&) = delete; }; -#endif // hifi_AnimController_h +#endif // hifi_AnimManipulator_h diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index f994867181..b4992f95a3 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -40,7 +40,7 @@ public: BlendLinear, Overlay, StateMachine, - Controller, + Manipulator, InverseKinematics, NumTypes }; diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index 9d6eb12e44..23bea83e1c 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -20,7 +20,7 @@ #include "AnimOverlay.h" #include "AnimNodeLoader.h" #include "AnimStateMachine.h" -#include "AnimController.h" +#include "AnimManipulator.h" #include "AnimInverseKinematics.h" using NodeLoaderFunc = AnimNode::Pointer (*)(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); @@ -31,7 +31,7 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString& static AnimNode::Pointer loadBlendLinearNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); static AnimNode::Pointer loadOverlayNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); static AnimNode::Pointer loadStateMachineNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); -static AnimNode::Pointer loadControllerNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); +static AnimNode::Pointer loadManipulatorNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); static AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); // called after children have been loaded @@ -40,7 +40,7 @@ static bool processClipNode(AnimNode::Pointer node, const QJsonObject& jsonObj, static bool processBlendLinearNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { return true; } static bool processOverlayNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { return true; } bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); -static bool processControllerNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { return true; } +static bool processManipulatorNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { return true; } static bool processInverseKinematicsNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { return true; } static const char* animNodeTypeToString(AnimNode::Type type) { @@ -49,7 +49,7 @@ static const char* animNodeTypeToString(AnimNode::Type type) { case AnimNode::Type::BlendLinear: return "blendLinear"; case AnimNode::Type::Overlay: return "overlay"; case AnimNode::Type::StateMachine: return "stateMachine"; - case AnimNode::Type::Controller: return "controller"; + case AnimNode::Type::Manipulator: return "manipulator"; case AnimNode::Type::InverseKinematics: return "inverseKinematics"; case AnimNode::Type::NumTypes: return nullptr; }; @@ -62,7 +62,7 @@ static NodeLoaderFunc animNodeTypeToLoaderFunc(AnimNode::Type type) { case AnimNode::Type::BlendLinear: return loadBlendLinearNode; case AnimNode::Type::Overlay: return loadOverlayNode; case AnimNode::Type::StateMachine: return loadStateMachineNode; - case AnimNode::Type::Controller: return loadControllerNode; + case AnimNode::Type::Manipulator: return loadManipulatorNode; case AnimNode::Type::InverseKinematics: return loadInverseKinematicsNode; case AnimNode::Type::NumTypes: return nullptr; }; @@ -75,7 +75,7 @@ static NodeProcessFunc animNodeTypeToProcessFunc(AnimNode::Type type) { case AnimNode::Type::BlendLinear: return processBlendLinearNode; case AnimNode::Type::Overlay: return processOverlayNode; case AnimNode::Type::StateMachine: return processStateMachineNode; - case AnimNode::Type::Controller: return processControllerNode; + case AnimNode::Type::Manipulator: return processManipulatorNode; case AnimNode::Type::InverseKinematics: return processInverseKinematicsNode; case AnimNode::Type::NumTypes: return nullptr; }; @@ -122,7 +122,7 @@ static NodeProcessFunc animNodeTypeToProcessFunc(AnimNode::Type type) { static AnimNode::Type stringToEnum(const QString& str) { // O(n), move to map when number of types becomes large. const int NUM_TYPES = static_cast(AnimNode::Type::NumTypes); - for (int i = 0; i < NUM_TYPES; i++ ) { + for (int i = 0; i < NUM_TYPES; i++) { AnimNode::Type type = static_cast(i); if (str == animNodeTypeToString(type)) { return type; @@ -288,10 +288,10 @@ static AnimNode::Pointer loadStateMachineNode(const QJsonObject& jsonObj, const return node; } -static AnimNode::Pointer loadControllerNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { +static AnimNode::Pointer loadManipulatorNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { READ_FLOAT(alpha, jsonObj, id, jsonUrl, nullptr); - auto node = std::make_shared(id.toStdString(), alpha); + auto node = std::make_shared(id.toStdString(), alpha); READ_OPTIONAL_STRING(alphaVar, jsonObj); if (!alphaVar.isEmpty()) { @@ -315,7 +315,7 @@ static AnimNode::Pointer loadControllerNode(const QJsonObject& jsonObj, const QS READ_STRING(var, jointObj, id, jsonUrl, nullptr); READ_STRING(jointName, jointObj, id, jsonUrl, nullptr); - AnimController::JointVar jointVar(var.toStdString(), jointName.toStdString()); + AnimManipulator::JointVar jointVar(var.toStdString(), jointName.toStdString()); node->addJointVar(jointVar); }; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 7e1d9a27e4..8b5bad5605 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -742,12 +742,10 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q if (_enableAnimGraph && _animSkeleton) { if (endIndex == _leftHandJointIndex) { - auto rootTrans = _animSkeleton->getAbsoluteBindPose(_rootJointIndex).trans; - _animVars.set("leftHandPosition", targetPosition + rootTrans); + _animVars.set("leftHandPosition", targetPosition); _animVars.set("leftHandRotation", targetRotation); } else if (endIndex == _rightHandJointIndex) { - auto rootTrans = _animSkeleton->getAbsoluteBindPose(_rootJointIndex).trans; - _animVars.set("rightHandPosition", targetPosition + rootTrans); + _animVars.set("rightHandPosition", targetPosition); _animVars.set("rightHandRotation", targetRotation); } return; @@ -995,10 +993,9 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) { glm::angleAxis(glm::radians(-params.localHeadPitch), X_AXIS)); _animVars.set("headRotation", realLocalHeadOrientation); - auto rootTrans = _animSkeleton->getAbsoluteBindPose(_rootJointIndex).trans; // There's a theory that when not in hmd, we should _animVars.unset("headPosition"). // However, until that works well, let's always request head be positioned where requested by hmd, camera, or default. - _animVars.set("headPosition", params.localHeadPosition + rootTrans); + _animVars.set("headPosition", params.localHeadPosition); } else if (!_enableAnimGraph) { auto& state = _jointStates[index]; diff --git a/tests/animation/src/data/avatar.json b/tests/animation/src/data/avatar.json index f5adfe2bfd..d1f6166b3d 100644 --- a/tests/animation/src/data/avatar.json +++ b/tests/animation/src/data/avatar.json @@ -33,7 +33,7 @@ "children": [] }, { - "id": "controllerOverlay", + "id": "manipulatorOverlay", "type": "overlay", "data": { "alpha": 1.0, @@ -42,7 +42,7 @@ "children": [ { "id": "spineLean", - "type": "controller", + "type": "manipulator", "data": { "alpha": 1.0, "joints": [ From 882ca5d6c07198c273baae5a7e9c00ad33960f31 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 16 Sep 2015 15:57:35 -0700 Subject: [PATCH 19/38] Fix the lights not rendering roperly --- libraries/render-utils/src/DeferredLightingEffect.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 0ec8b4ad24..b19e2f62b7 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -373,7 +373,10 @@ void DeferredLightingEffect::render(RenderArgs* args) { projMats[0] = monoProjMat; deferredTransforms[0].projection = monoProjMat; + deferredTransforms[0].viewInverse = monoViewMat; + viewTransforms[0] = monoViewTransform; + deferredTransforms[0].stereoSide = 0.0f; clipQuad[0] = glm::vec4(sMin, tMin, sWidth, tHeight); From 7840f122dc6a90f54eb89e4d845b9ba2b62deed6 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 16 Sep 2015 16:45:26 -0700 Subject: [PATCH 20/38] add reload all support for entity scripts --- interface/src/Application.cpp | 2 ++ libraries/entities-renderer/src/EntityTreeRenderer.cpp | 10 ++++++++++ libraries/entities-renderer/src/EntityTreeRenderer.h | 4 ++++ libraries/script-engine/src/ScriptCache.cpp | 7 +++++++ libraries/script-engine/src/ScriptCache.h | 1 + libraries/script-engine/src/ScriptEngine.cpp | 5 ++++- libraries/script-engine/src/ScriptEngine.h | 4 ++-- 7 files changed, 30 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3cb75b55ec..a313308023 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4347,6 +4347,8 @@ void Application::stopScript(const QString &scriptName, bool restart) { } void Application::reloadAllScripts() { + DependencyManager::get()->clearCache(); + getEntities()->reloadEntityScripts(); stopAllScripts(true); } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 2fd760bbd3..fa186b15f8 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -93,6 +93,15 @@ void EntityTreeRenderer::clear() { OctreeRenderer::clear(); } +void EntityTreeRenderer::reloadEntityScripts() { + _entitiesScriptEngine->unloadAllEntityScripts(); + foreach(auto entity, _entitiesInScene) { + if (!entity->getScript().isEmpty()) { + _entitiesScriptEngine->loadEntityScript(entity->getEntityItemID(), entity->getScript(), true); + } + } +} + void EntityTreeRenderer::init() { OctreeRenderer::init(); EntityTreePointer entityTree = std::static_pointer_cast(_tree); @@ -769,6 +778,7 @@ void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) { void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID, const bool reload) { + qDebug() << "entitySciptChanging() entityID:" << entityID << "reload:" << reload; if (_tree && !_shuttingDown) { _entitiesScriptEngine->unloadEntityScript(entityID); checkAndCallPreload(entityID, reload); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index a2f343efd2..6bacb23a3f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -62,6 +62,10 @@ public: /// clears the tree virtual void clear(); + /// reloads the entity scripts, calling unload and preload + void reloadEntityScripts(); + + /// if a renderable entity item needs a model, we will allocate it for them Q_INVOKABLE Model* allocateModel(const QString& url, const QString& collisionUrl); diff --git a/libraries/script-engine/src/ScriptCache.cpp b/libraries/script-engine/src/ScriptCache.cpp index e2c07c05d0..fb0edb1e49 100644 --- a/libraries/script-engine/src/ScriptCache.cpp +++ b/libraries/script-engine/src/ScriptCache.cpp @@ -27,6 +27,11 @@ ScriptCache::ScriptCache(QObject* parent) { // nothing to do here... } +void ScriptCache::clearCache() { + _scriptCache.clear(); +} + + QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUser, bool& isPending, bool reload) { QUrl url = ResourceManager::normalizeURL(unnormalizedURL); QString scriptContents; @@ -95,6 +100,8 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable return; } + qCDebug(scriptengine) << "ScriptCache::getScriptContents() scriptOrURL:" << scriptOrURL << " forceDownload:" << forceDownload << " on thread[" << QThread::currentThread() << "] expected thread[" << thread() << "]"; + if (_scriptCache.contains(url) && !forceDownload) { qCDebug(scriptengine) << "Found script in cache:" << url.toString(); #if 1 // def THREAD_DEBUGGING diff --git a/libraries/script-engine/src/ScriptCache.h b/libraries/script-engine/src/ScriptCache.h index 7de14a09f7..b786422b3f 100644 --- a/libraries/script-engine/src/ScriptCache.h +++ b/libraries/script-engine/src/ScriptCache.h @@ -28,6 +28,7 @@ class ScriptCache : public QObject, public Dependency { SINGLETON_DEPENDENCY public: + void clearCache(); void getScriptContents(const QString& scriptOrURL, contentAvailableCallback contentAvailable, bool forceDownload = false); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 692a320b4e..d8392f1598 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -909,7 +909,10 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& #ifdef THREAD_DEBUGGING qDebug() << "ScriptEngine::loadEntityScript() calling scriptCache->getScriptContents() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; #endif - DependencyManager::get()->getScriptContents(entityScript, [=](const QString& scriptOrURL, const QString& contents, bool isURL, bool success) { + + qDebug() << "ScriptEngine::loadEntityScript() calling scriptCache->getScriptContents() scriptOrURL:" << entityScript << "forceDownload:" << forceRedownload << "on thread[" << QThread::currentThread() << "] expected thread[" << thread() << "]"; + + DependencyManager::get()->getScriptContents(entityScript, [=](const QString& scriptOrURL, const QString& contents, bool isURL, bool success) { #ifdef THREAD_DEBUGGING qDebug() << "ScriptEngine::entityScriptContentAvailable() IN LAMBDA contentAvailable on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; #endif diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 83e65823a5..001f54221b 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -109,8 +109,8 @@ public: // Entity Script Related methods Q_INVOKABLE void loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload = false); // will call the preload method once loaded Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID); // will call unload method - Q_INVOKABLE void unloadAllEntityScripts(); - Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName); + Q_INVOKABLE void unloadAllEntityScripts(); + Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName); Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const MouseEvent& event); Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision); From fa6396bbfa907b6ee8535dadf7e62b2770b37536 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 16 Sep 2015 16:53:20 -0700 Subject: [PATCH 21/38] fix white space --- .../entities-renderer/src/EntityTreeRenderer.cpp | 13 ++++++------- libraries/script-engine/src/ScriptCache.cpp | 5 +---- libraries/script-engine/src/ScriptCache.h | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 4 +--- libraries/script-engine/src/ScriptEngine.h | 4 ++-- 5 files changed, 11 insertions(+), 17 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index fa186b15f8..c55eaaeff9 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -94,12 +94,12 @@ void EntityTreeRenderer::clear() { } void EntityTreeRenderer::reloadEntityScripts() { - _entitiesScriptEngine->unloadAllEntityScripts(); - foreach(auto entity, _entitiesInScene) { - if (!entity->getScript().isEmpty()) { - _entitiesScriptEngine->loadEntityScript(entity->getEntityItemID(), entity->getScript(), true); - } - } + _entitiesScriptEngine->unloadAllEntityScripts(); + foreach(auto entity, _entitiesInScene) { + if (!entity->getScript().isEmpty()) { + _entitiesScriptEngine->loadEntityScript(entity->getEntityItemID(), entity->getScript(), true); + } + } } void EntityTreeRenderer::init() { @@ -778,7 +778,6 @@ void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) { void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID, const bool reload) { - qDebug() << "entitySciptChanging() entityID:" << entityID << "reload:" << reload; if (_tree && !_shuttingDown) { _entitiesScriptEngine->unloadEntityScript(entityID); checkAndCallPreload(entityID, reload); diff --git a/libraries/script-engine/src/ScriptCache.cpp b/libraries/script-engine/src/ScriptCache.cpp index fb0edb1e49..96e624c187 100644 --- a/libraries/script-engine/src/ScriptCache.cpp +++ b/libraries/script-engine/src/ScriptCache.cpp @@ -28,10 +28,9 @@ ScriptCache::ScriptCache(QObject* parent) { } void ScriptCache::clearCache() { - _scriptCache.clear(); + _scriptCache.clear(); } - QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUser, bool& isPending, bool reload) { QUrl url = ResourceManager::normalizeURL(unnormalizedURL); QString scriptContents; @@ -100,8 +99,6 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable return; } - qCDebug(scriptengine) << "ScriptCache::getScriptContents() scriptOrURL:" << scriptOrURL << " forceDownload:" << forceDownload << " on thread[" << QThread::currentThread() << "] expected thread[" << thread() << "]"; - if (_scriptCache.contains(url) && !forceDownload) { qCDebug(scriptengine) << "Found script in cache:" << url.toString(); #if 1 // def THREAD_DEBUGGING diff --git a/libraries/script-engine/src/ScriptCache.h b/libraries/script-engine/src/ScriptCache.h index b786422b3f..da9f1a409c 100644 --- a/libraries/script-engine/src/ScriptCache.h +++ b/libraries/script-engine/src/ScriptCache.h @@ -28,7 +28,7 @@ class ScriptCache : public QObject, public Dependency { SINGLETON_DEPENDENCY public: - void clearCache(); + void clearCache(); void getScriptContents(const QString& scriptOrURL, contentAvailableCallback contentAvailable, bool forceDownload = false); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index d8392f1598..771906aa95 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -910,9 +910,7 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& qDebug() << "ScriptEngine::loadEntityScript() calling scriptCache->getScriptContents() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; #endif - qDebug() << "ScriptEngine::loadEntityScript() calling scriptCache->getScriptContents() scriptOrURL:" << entityScript << "forceDownload:" << forceRedownload << "on thread[" << QThread::currentThread() << "] expected thread[" << thread() << "]"; - - DependencyManager::get()->getScriptContents(entityScript, [=](const QString& scriptOrURL, const QString& contents, bool isURL, bool success) { + DependencyManager::get()->getScriptContents(entityScript, [=](const QString& scriptOrURL, const QString& contents, bool isURL, bool success) { #ifdef THREAD_DEBUGGING qDebug() << "ScriptEngine::entityScriptContentAvailable() IN LAMBDA contentAvailable on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; #endif diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 001f54221b..83e65823a5 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -109,8 +109,8 @@ public: // Entity Script Related methods Q_INVOKABLE void loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload = false); // will call the preload method once loaded Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID); // will call unload method - Q_INVOKABLE void unloadAllEntityScripts(); - Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName); + Q_INVOKABLE void unloadAllEntityScripts(); + Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName); Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const MouseEvent& event); Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision); From 2021a15527daff4137e7225b16dae68cb0ec1f01 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 16 Sep 2015 16:54:21 -0700 Subject: [PATCH 22/38] fix white space --- libraries/entities-renderer/src/EntityTreeRenderer.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 6bacb23a3f..18874957fd 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -62,9 +62,8 @@ public: /// clears the tree virtual void clear(); - /// reloads the entity scripts, calling unload and preload - void reloadEntityScripts(); - + /// reloads the entity scripts, calling unload and preload + void reloadEntityScripts(); /// if a renderable entity item needs a model, we will allocate it for them Q_INVOKABLE Model* allocateModel(const QString& url, const QString& collisionUrl); From 089c71961288a777071c61ff1b3ac64037060f03 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 15 Sep 2015 15:47:50 -0700 Subject: [PATCH 23/38] minor cleanup --- .../animation/src/AnimInverseKinematics.cpp | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 49ff7feda6..89ed8141f9 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -9,6 +9,7 @@ #include "AnimInverseKinematics.h" +#include #include #include @@ -109,9 +110,6 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar } } - // RELAX! Don't do it. - // relaxTowardDefaults(dt); - if (_absoluteTargets.empty()) { // no IK targets but still need to enforce constraints std::map::iterator constraintItr = _constraints.begin(); @@ -277,10 +275,6 @@ void AnimInverseKinematics::clearConstraints() { _constraints.clear(); } -const glm::vec3 xAxis(1.0f, 0.0f, 0.0f); -const glm::vec3 yAxis(0.0f, 1.0f, 0.0f); -const glm::vec3 zAxis(0.0f, 0.0f, 1.0f); - void AnimInverseKinematics::initConstraints() { if (!_skeleton) { return; @@ -306,7 +300,7 @@ void AnimInverseKinematics::initConstraints() { // y | // | | // | O---O---O RightUpLeg - // z | | | + // z | | Hips2 | // \ | | | // \| | | // x -----+ O O RightLeg @@ -334,7 +328,7 @@ void AnimInverseKinematics::initConstraints() { _constraints.clear(); for (int i = 0; i < numJoints; ++i) { - // compute the joint's baseName and remember if it was Left or not + // compute the joint's baseName and remember whether its prefix was "Left" or not QString baseName = _skeleton->getJointName(i); bool isLeft = baseName.startsWith("Left", Qt::CaseInsensitive); float mirror = isLeft ? -1.0f : 1.0f; @@ -467,6 +461,18 @@ void AnimInverseKinematics::initConstraints() { minDots.push_back(cosf(MAX_SPINE_SWING)); stConstraint->setSwingLimits(minDots); + constraint = static_cast(stConstraint); + } else if (baseName.startsWith("Hips2", Qt::CaseInsensitive)) { + SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); + stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); + const float MAX_SPINE_TWIST = PI / 8.0f; + stConstraint->setTwistLimits(-MAX_SPINE_TWIST, MAX_SPINE_TWIST); + + std::vector minDots; + const float MAX_SPINE_SWING = PI / 14.0f; + minDots.push_back(cosf(MAX_SPINE_SWING)); + stConstraint->setSwingLimits(minDots); + constraint = static_cast(stConstraint); } else if (0 == baseName.compare("Neck", Qt::CaseInsensitive)) { SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); @@ -488,18 +494,18 @@ void AnimInverseKinematics::initConstraints() { // we determine the max/min angles by rotating the swing limit lines from parent- to child-frame // then measure the angles to swing the yAxis into alignment - glm::vec3 hingeAxis = - mirror * zAxis; + glm::vec3 hingeAxis = - mirror * Vectors::UNIT_Z; const float MIN_ELBOW_ANGLE = 0.05f; const float MAX_ELBOW_ANGLE = 11.0f * PI / 12.0f; glm::quat invReferenceRotation = glm::inverse(referenceRotation); - glm::vec3 minSwingAxis = invReferenceRotation * glm::angleAxis(MIN_ELBOW_ANGLE, hingeAxis) * yAxis; - glm::vec3 maxSwingAxis = invReferenceRotation * glm::angleAxis(MAX_ELBOW_ANGLE, hingeAxis) * yAxis; + glm::vec3 minSwingAxis = invReferenceRotation * glm::angleAxis(MIN_ELBOW_ANGLE, hingeAxis) * Vectors::UNIT_Y; + glm::vec3 maxSwingAxis = invReferenceRotation * glm::angleAxis(MAX_ELBOW_ANGLE, hingeAxis) * Vectors::UNIT_Y; // for the rest of the math we rotate hingeAxis into the child frame hingeAxis = referenceRotation * hingeAxis; eConstraint->setHingeAxis(hingeAxis); - glm::vec3 projectedYAxis = glm::normalize(yAxis - glm::dot(yAxis, hingeAxis) * hingeAxis); + glm::vec3 projectedYAxis = glm::normalize(Vectors::UNIT_Y - glm::dot(Vectors::UNIT_Y, hingeAxis) * hingeAxis); float minAngle = acosf(glm::dot(projectedYAxis, minSwingAxis)); if (glm::dot(hingeAxis, glm::cross(projectedYAxis, minSwingAxis)) < 0.0f) { minAngle = - minAngle; @@ -516,21 +522,21 @@ void AnimInverseKinematics::initConstraints() { ElbowConstraint* eConstraint = new ElbowConstraint(); glm::quat referenceRotation = _defaultRelativePoses[i].rot; eConstraint->setReferenceRotation(referenceRotation); - glm::vec3 hingeAxis = -1.0f * xAxis; + glm::vec3 hingeAxis = -1.0f * Vectors::UNIT_X; // we determine the max/min angles by rotating the swing limit lines from parent- to child-frame // then measure the angles to swing the yAxis into alignment const float MIN_KNEE_ANGLE = 0.0f; const float MAX_KNEE_ANGLE = 3.0f * PI / 4.0f; glm::quat invReferenceRotation = glm::inverse(referenceRotation); - glm::vec3 minSwingAxis = invReferenceRotation * glm::angleAxis(MIN_KNEE_ANGLE, hingeAxis) * yAxis; - glm::vec3 maxSwingAxis = invReferenceRotation * glm::angleAxis(MAX_KNEE_ANGLE, hingeAxis) * yAxis; + glm::vec3 minSwingAxis = invReferenceRotation * glm::angleAxis(MIN_KNEE_ANGLE, hingeAxis) * Vectors::UNIT_Y; + glm::vec3 maxSwingAxis = invReferenceRotation * glm::angleAxis(MAX_KNEE_ANGLE, hingeAxis) * Vectors::UNIT_Y; // for the rest of the math we rotate hingeAxis into the child frame hingeAxis = referenceRotation * hingeAxis; eConstraint->setHingeAxis(hingeAxis); - glm::vec3 projectedYAxis = glm::normalize(yAxis - glm::dot(yAxis, hingeAxis) * hingeAxis); + glm::vec3 projectedYAxis = glm::normalize(Vectors::UNIT_Y - glm::dot(Vectors::UNIT_Y, hingeAxis) * hingeAxis); float minAngle = acosf(glm::dot(projectedYAxis, minSwingAxis)); if (glm::dot(hingeAxis, glm::cross(projectedYAxis, minSwingAxis)) < 0.0f) { minAngle = - minAngle; @@ -550,8 +556,8 @@ void AnimInverseKinematics::initConstraints() { // these directions are approximate swing limits in parent-frame // NOTE: they don't need to be normalized std::vector swungDirections; - swungDirections.push_back(yAxis); - swungDirections.push_back(xAxis); + swungDirections.push_back(Vectors::UNIT_Y); + swungDirections.push_back(Vectors::UNIT_X); swungDirections.push_back(glm::vec3(1.0f, 1.0f, 1.0f)); swungDirections.push_back(glm::vec3(1.0f, 1.0f, -1.0f)); From 9a86fc2e62c0864f21d33117ee538f8f638a6600 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 16 Sep 2015 12:10:22 -0700 Subject: [PATCH 24/38] build local list of IK targets every frame --- .../animation/src/AnimInverseKinematics.cpp | 128 +++++++++++------- .../animation/src/AnimInverseKinematics.h | 10 +- libraries/animation/src/AnimVariant.h | 2 + 3 files changed, 85 insertions(+), 55 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 89ed8141f9..ca619f9641 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -55,7 +55,20 @@ void AnimInverseKinematics::computeAbsolutePoses(AnimPoseVec& absolutePoses) con void AnimInverseKinematics::setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar) { // if there are dups, last one wins. - _targetVarVec.push_back(IKTargetVar(jointName, positionVar.toStdString(), rotationVar.toStdString())); + bool found = false; + for (auto& targetVar: _targetVarVec) { + if (targetVar.jointName == jointName) { + // update existing targetVar + targetVar.positionVar = positionVar.toStdString(); + targetVar.rotationVar = rotationVar.toStdString(); + found = true; + break; + } + } + if (!found) { + // create a new entry + _targetVarVec.push_back(IKTargetVar(jointName, positionVar.toStdString(), rotationVar.toStdString())); + } } static int findRootJointInSkeleton(AnimSkeleton::ConstPointer skeleton, int index) { @@ -69,6 +82,12 @@ static int findRootJointInSkeleton(AnimSkeleton::ConstPointer skeleton, int inde return rootIndex; } +struct IKTarget { + AnimPose pose; + int index; + int rootIndex; +}; + //virtual const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVars, float dt, AnimNode::Triggers& triggersOut) { @@ -77,40 +96,53 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar return _relativePoses; } - // evaluate target vars + // build a list of targets from _targetVarVec + std::vector targets; + bool removeUnfoundJoints = false; for (auto& targetVar : _targetVarVec) { - - // lazy look up of jointIndices and insertion into _absoluteTargets map - if (!targetVar.hasPerformedJointLookup) { - targetVar.jointIndex = _skeleton->nameToJointIndex(targetVar.jointName); - if (targetVar.jointIndex >= 0) { - // insert into _absoluteTargets map - IKTarget target; - target.pose = AnimPose::identity; - target.rootIndex = findRootJointInSkeleton(_skeleton, targetVar.jointIndex); - _absoluteTargets[targetVar.jointIndex] = target; - - if (targetVar.jointIndex > _maxTargetIndex) { - _maxTargetIndex = targetVar.jointIndex; - } + if (targetVar.jointIndex == -1) { + // this targetVar hasn't been validated yet... + int jointIndex = _skeleton->nameToJointIndex(targetVar.jointName); + if (jointIndex >= 0) { + // this targetVar has a valid joint --> cache the indices + targetVar.jointIndex = jointIndex; + targetVar.rootIndex = findRootJointInSkeleton(_skeleton, jointIndex); } else { qCWarning(animation) << "AnimInverseKinematics could not find jointName" << targetVar.jointName << "in skeleton"; + removeUnfoundJoints = true; } - targetVar.hasPerformedJointLookup = true; - } - - if (targetVar.jointIndex >= 0) { - // update pose in _absoluteTargets map - auto iter = _absoluteTargets.find(targetVar.jointIndex); - if (iter != _absoluteTargets.end()) { + } else { + // TODO: get this done without a double-lookup of each var in animVars + if (animVars.hasKey(targetVar.positionVar) || animVars.hasKey(targetVar.rotationVar)) { + IKTarget target; AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, _relativePoses); - iter->second.pose.trans = animVars.lookup(targetVar.positionVar, defaultPose.trans); - iter->second.pose.rot = animVars.lookup(targetVar.rotationVar, defaultPose.rot); + target.pose.trans = animVars.lookup(targetVar.positionVar, defaultPose.trans); + target.pose.rot = animVars.lookup(targetVar.rotationVar, defaultPose.rot); + target.rootIndex = targetVar.rootIndex; + target.index = targetVar.jointIndex; + targets.push_back(target); } } } - if (_absoluteTargets.empty()) { + if (removeUnfoundJoints) { + int numVars = _targetVarVec.size(); + int i = 0; + while (i < numVars) { + if (_targetVarVec[i].jointIndex == -1) { + if (numVars > 1) { + // swap i for last element + _targetVarVec[i] = _targetVarVec[numVars - 1]; + } + _targetVarVec.pop_back(); + --numVars; + } else { + ++i; + } + } + } + + if (targets.empty()) { // no IK targets but still need to enforce constraints std::map::iterator constraintItr = _constraints.begin(); while (constraintItr != _constraints.end()) { @@ -133,11 +165,11 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar quint64 expiry = usecTimestampNow() + MAX_IK_TIME; do { largestError = 0.0f; - for (auto& targetPair: _absoluteTargets) { + for (auto& target: targets) { int lowestMovedIndex = _relativePoses.size() - 1; - int tipIndex = targetPair.first; - AnimPose targetPose = targetPair.second.pose; - int rootIndex = targetPair.second.rootIndex; + int tipIndex = target.index; + AnimPose targetPose = target.pose; + int rootIndex = target.rootIndex; if (rootIndex != -1) { // transform targetPose into skeleton's absolute frame AnimPose& rootPose = _relativePoses[rootIndex]; @@ -148,11 +180,11 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar glm::vec3 tip = absolutePoses[tipIndex].trans; float error = glm::length(targetPose.trans - tip); - // descend toward root, rotating each joint to get tip closer to target - int index = _skeleton->getParentIndex(tipIndex); - while (index != -1 && error > ACCEPTABLE_RELATIVE_ERROR) { + // descend toward root, pivoting each joint to get tip closer to target + int pivotIndex = _skeleton->getParentIndex(tipIndex); + while (pivotIndex != -1 && error > ACCEPTABLE_RELATIVE_ERROR) { // compute the two lines that should be aligned - glm::vec3 jointPosition = absolutePoses[index].trans; + glm::vec3 jointPosition = absolutePoses[pivotIndex].trans; glm::vec3 leverArm = tip - jointPosition; glm::vec3 targetLine = targetPose.trans - jointPosition; @@ -171,29 +203,34 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar angle = 0.5f * angle; glm::quat deltaRotation = glm::angleAxis(angle, axis); - int parentIndex = _skeleton->getParentIndex(index); + int parentIndex = _skeleton->getParentIndex(pivotIndex); if (parentIndex == -1) { // TODO? apply constraints to root? // TODO? harvest the root's transform as movement of entire skeleton? } else { // compute joint's new parent-relative rotation // Q' = dQ * Q and Q = Qp * q --> q' = Qp^ * dQ * Q - glm::quat newRot = glm::normalize(glm::inverse(absolutePoses[parentIndex].rot) * deltaRotation * absolutePoses[index].rot); - RotationConstraint* constraint = getConstraint(index); + glm::quat newRot = glm::normalize(glm::inverse( + absolutePoses[parentIndex].rot) * + deltaRotation * + absolutePoses[pivotIndex].rot); + RotationConstraint* constraint = getConstraint(pivotIndex); if (constraint) { bool constrained = constraint->apply(newRot); if (constrained) { // the constraint will modify the movement of the tip so we have to compute the modified // model-frame deltaRotation // Q' = Qp^ * dQ * Q --> dQ = Qp * Q' * Q^ - deltaRotation = absolutePoses[parentIndex].rot * newRot * glm::inverse(absolutePoses[index].rot); + deltaRotation = absolutePoses[parentIndex].rot * + newRot * + glm::inverse(absolutePoses[pivotIndex].rot); } } - _relativePoses[index].rot = newRot; + _relativePoses[pivotIndex].rot = newRot; } // this joint has been changed so we check to see if it has the lowest index - if (index < lowestMovedIndex) { - lowestMovedIndex = index; + if (pivotIndex < lowestMovedIndex) { + lowestMovedIndex = pivotIndex; } // keep track of tip's new position as we descend towards root @@ -201,7 +238,7 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar error = glm::length(targetPose.trans - tip); } } - index = _skeleton->getParentIndex(index); + pivotIndex = _skeleton->getParentIndex(pivotIndex); } if (largestError < error) { largestError = error; @@ -581,13 +618,10 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele AnimNode::setSkeletonInternal(skeleton); // invalidate all targetVars - for (auto& targetVar : _targetVarVec) { - targetVar.hasPerformedJointLookup = false; + for (auto& targetVar: _targetVarVec) { + targetVar.jointIndex = -1; } - // invalidate all targets - _absoluteTargets.clear(); - _maxTargetIndex = 0; if (skeleton) { diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index 41e380f64c..eabc3448de 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -50,23 +50,17 @@ protected: rotationVar(rotationVarIn), jointName(jointNameIn), jointIndex(-1), - hasPerformedJointLookup(false) {} + rootIndex(-1) {} std::string positionVar; std::string rotationVar; QString jointName; int jointIndex; // cached joint index - bool hasPerformedJointLookup = false; - }; - - struct IKTarget { - AnimPose pose; - int rootIndex; + int rootIndex; // cached root index }; std::map _constraints; std::vector _targetVarVec; - std::map _absoluteTargets; // IK targets of end-points AnimPoseVec _defaultRelativePoses; // poses of the relaxed state AnimPoseVec _relativePoses; // current relative poses diff --git a/libraries/animation/src/AnimVariant.h b/libraries/animation/src/AnimVariant.h index ac84aafc32..bcff4b2a9b 100644 --- a/libraries/animation/src/AnimVariant.h +++ b/libraries/animation/src/AnimVariant.h @@ -154,6 +154,8 @@ public: void setTrigger(const std::string& key) { _triggers.insert(key); } void clearTriggers() { _triggers.clear(); } + bool hasKey(const std::string& key) const { return _map.find(key) != _map.end(); } + protected: std::map _map; std::set _triggers; From d4ea661aca6adda2bc3c414e58d0c58e49478191 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 16 Sep 2015 12:18:59 -0700 Subject: [PATCH 25/38] cleanup whitespace --- libraries/animation/src/AnimInverseKinematics.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index ca619f9641..3b3af762bf 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -211,8 +211,8 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar // compute joint's new parent-relative rotation // Q' = dQ * Q and Q = Qp * q --> q' = Qp^ * dQ * Q glm::quat newRot = glm::normalize(glm::inverse( - absolutePoses[parentIndex].rot) * - deltaRotation * + absolutePoses[parentIndex].rot) * + deltaRotation * absolutePoses[pivotIndex].rot); RotationConstraint* constraint = getConstraint(pivotIndex); if (constraint) { @@ -221,8 +221,8 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar // the constraint will modify the movement of the tip so we have to compute the modified // model-frame deltaRotation // Q' = Qp^ * dQ * Q --> dQ = Qp * Q' * Q^ - deltaRotation = absolutePoses[parentIndex].rot * - newRot * + deltaRotation = absolutePoses[parentIndex].rot * + newRot * glm::inverse(absolutePoses[pivotIndex].rot); } } @@ -319,7 +319,7 @@ void AnimInverseKinematics::initConstraints() { // We create constraints for the joints shown here // (and their Left counterparts if applicable). // - // + // // O RightHand // Head / // O / @@ -473,7 +473,7 @@ void AnimInverseKinematics::initConstraints() { const float MAX_HAND_SWING = PI / 2.0f; minDots.push_back(cosf(MAX_HAND_SWING)); stConstraint->setSwingLimits(minDots); - + constraint = static_cast(stConstraint); } else if (baseName.startsWith("Shoulder", Qt::CaseInsensitive)) { SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); From e1fc1900ab08af7418417c50fb2931a02558c6ed Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 16 Sep 2015 15:23:52 -0700 Subject: [PATCH 26/38] remove IK 'flutter' bug --- libraries/animation/src/AnimInverseKinematics.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 3b3af762bf..863970ccaa 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -283,12 +283,16 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars loadPoses(underPoses); } else { // relax toward underpose - const float RELAXATION_TIMESCALE = 0.125f; - const float alpha = glm::clamp(dt / RELAXATION_TIMESCALE, 0.0f, 1.0f); + // HACK: this relaxation needs to be constant per-frame rather than per-realtime + // in order to prevent IK "flutter" for bad FPS. The bad news is that the good parts + // of this relaxation will be FPS dependent (low FPS will make the limbs align slower + // in real-time), however most people will not notice this and this problem is less + // annoying than the flutter. + const float blend = (1.0f / 60.0f) / (0.25f); // effectively: dt / RELAXATION_TIMESCALE int numJoints = (int)_relativePoses.size(); for (int i = 0; i < numJoints; ++i) { float dotSign = copysignf(1.0f, glm::dot(_relativePoses[i].rot, underPoses[i].rot)); - _relativePoses[i].rot = glm::normalize(glm::lerp(_relativePoses[i].rot, dotSign * underPoses[i].rot, alpha)); + _relativePoses[i].rot = glm::normalize(glm::lerp(_relativePoses[i].rot, dotSign * underPoses[i].rot, blend)); } } return evaluate(animVars, dt, triggersOut); From b645d994123ce816ec15e5ad2b5b2c57729d9d27 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 16 Sep 2015 17:07:12 -0700 Subject: [PATCH 27/38] CR feedback --- libraries/script-engine/src/ScriptEngine.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 771906aa95..692a320b4e 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -909,7 +909,6 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& #ifdef THREAD_DEBUGGING qDebug() << "ScriptEngine::loadEntityScript() calling scriptCache->getScriptContents() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; #endif - DependencyManager::get()->getScriptContents(entityScript, [=](const QString& scriptOrURL, const QString& contents, bool isURL, bool success) { #ifdef THREAD_DEBUGGING qDebug() << "ScriptEngine::entityScriptContentAvailable() IN LAMBDA contentAvailable on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; From 5ba6242bdab337c075bba3e6f20226302d834dc9 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 16 Sep 2015 13:22:37 -0700 Subject: [PATCH 28/38] Support a debug oculus plugin for performance testing --- .../src/display-plugins/DisplayPlugin.cpp | 5 + .../oculus/OculusBaseDisplayPlugin.cpp | 151 +++++++++++ .../oculus/OculusBaseDisplayPlugin.h | 79 ++++++ .../oculus/OculusDebugDisplayPlugin.cpp | 40 +++ .../oculus/OculusDebugDisplayPlugin.h | 26 ++ .../oculus/OculusDisplayPlugin.cpp | 251 +----------------- .../oculus/OculusDisplayPlugin.h | 52 +--- 7 files changed, 314 insertions(+), 290 deletions(-) create mode 100644 libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h create mode 100644 libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.h diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp index 598e78e500..4af45d299b 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp @@ -16,6 +16,7 @@ #include "openvr/OpenVrDisplayPlugin.h" #include "oculus/OculusDisplayPlugin.h" +#include "oculus/OculusDebugDisplayPlugin.h" #include "oculus/OculusLegacyDisplayPlugin.h" const QString& DisplayPlugin::MENU_PATH() { @@ -42,6 +43,10 @@ DisplayPluginList getDisplayPlugins() { // Windows Oculus SDK new OculusDisplayPlugin(), + // Windows Oculus Simulator... uses head tracking and the same rendering + // as the connected hardware, but without using the SDK to display to the + // Rift. Useful for debugging Rift performance with nSight. + new OculusDebugDisplayPlugin(), // Mac/Linux Oculus SDK (0.5) new OculusLegacyDisplayPlugin(), #ifdef Q_OS_WIN diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp new file mode 100644 index 0000000000..fa9d09e392 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp @@ -0,0 +1,151 @@ +// +// Created by Bradley Austin Davis on 2014/04/13. +// Copyright 2015 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 "OculusBaseDisplayPlugin.h" + +#include + +#include "OculusHelpers.h" + +uvec2 OculusBaseDisplayPlugin::getRecommendedRenderSize() const { + return _desiredFramebufferSize; +} + +void OculusBaseDisplayPlugin::preRender() { +#if (OVR_MAJOR_VERSION >= 6) + ovrFrameTiming ftiming = ovr_GetFrameTiming(_hmd, _frameIndex); + _trackingState = ovr_GetTrackingState(_hmd, ftiming.DisplayMidpointSeconds); + ovr_CalcEyePoses(_trackingState.HeadPose.ThePose, _eyeOffsets, _eyePoses); +#endif +} + +glm::mat4 OculusBaseDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { + return _eyeProjections[eye]; +} + +void OculusBaseDisplayPlugin::resetSensors() { +#if (OVR_MAJOR_VERSION >= 6) + ovr_RecenterPose(_hmd); +#endif +} + +glm::mat4 OculusBaseDisplayPlugin::getEyePose(Eye eye) const { + return toGlm(_eyePoses[eye]); +} + +glm::mat4 OculusBaseDisplayPlugin::getHeadPose() const { + return toGlm(_trackingState.HeadPose.ThePose); +} + +bool OculusBaseDisplayPlugin::isSupported() const { +#if (OVR_MAJOR_VERSION >= 6) + if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { + return false; + } + bool result = false; + if (ovrHmd_Detect() > 0) { + result = true; + } + ovr_Shutdown(); + return result; +#else + return false; +#endif +} + +void OculusBaseDisplayPlugin::init() { +} + +void OculusBaseDisplayPlugin::deinit() { +} + +void OculusBaseDisplayPlugin::activate() { +#if (OVR_MAJOR_VERSION >= 6) + if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { + qFatal("Could not init OVR"); + } + +#if (OVR_MAJOR_VERSION == 6) + if (!OVR_SUCCESS(ovr_Create(0, &_hmd))) { +#elif (OVR_MAJOR_VERSION == 7) + if (!OVR_SUCCESS(ovr_Create(&_hmd, &_luid))) { +#endif + Q_ASSERT(false); + qFatal("Failed to acquire HMD"); + } + + _hmdDesc = ovr_GetHmdDesc(_hmd); + + _ipd = ovr_GetFloat(_hmd, OVR_KEY_IPD, _ipd); + + glm::uvec2 eyeSizes[2]; + ovr_for_each_eye([&](ovrEyeType eye) { + _eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye]; + ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_hmd, eye, _eyeFovs[eye]); + ovrMatrix4f ovrPerspectiveProjection = + ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); + _eyeProjections[eye] = toGlm(ovrPerspectiveProjection); + + ovrPerspectiveProjection = + ovrMatrix4f_Projection(erd.Fov, 0.001f, 10.0f, ovrProjection_RightHanded); + _compositeEyeProjections[eye] = toGlm(ovrPerspectiveProjection); + + _eyeOffsets[eye] = erd.HmdToEyeViewOffset; + eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f)); + }); + ovrFovPort combined = _eyeFovs[Left]; + combined.LeftTan = std::max(_eyeFovs[Left].LeftTan, _eyeFovs[Right].LeftTan); + combined.RightTan = std::max(_eyeFovs[Left].RightTan, _eyeFovs[Right].RightTan); + ovrMatrix4f ovrPerspectiveProjection = + ovrMatrix4f_Projection(combined, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); + _eyeProjections[Mono] = toGlm(ovrPerspectiveProjection); + + + + _desiredFramebufferSize = uvec2( + eyeSizes[0].x + eyeSizes[1].x, + std::max(eyeSizes[0].y, eyeSizes[1].y)); + + _frameIndex = 0; + + if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd, + ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { + qFatal("Could not attach to sensor device"); + } + + // Parent class relies on our _hmd intialization, so it must come after that. + memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov)); + _sceneLayer.Header.Type = ovrLayerType_EyeFov; + _sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; + ovr_for_each_eye([&](ovrEyeType eye) { + ovrFovPort & fov = _sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov; + ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_hmd, eye, fov, 1.0f); + _sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 }; + }); + + if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd, + ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { + qFatal("Could not attach to sensor device"); + } +#endif + + WindowOpenGLDisplayPlugin::activate(); +} + +void OculusBaseDisplayPlugin::deactivate() { + WindowOpenGLDisplayPlugin::deactivate(); + +#if (OVR_MAJOR_VERSION >= 6) + ovr_Destroy(_hmd); + _hmd = nullptr; + ovr_Shutdown(); +#endif +} + +void OculusBaseDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) { + ++_frameIndex; +} diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h new file mode 100644 index 0000000000..12023db1ae --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h @@ -0,0 +1,79 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// Copyright 2015 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 +// +#pragma once + +#include "../WindowOpenGLDisplayPlugin.h" + +#include + +#include + +class OculusBaseDisplayPlugin : public WindowOpenGLDisplayPlugin { +public: + virtual bool isSupported() const override; + + virtual void init() override final; + virtual void deinit() override final; + + virtual void activate() override; + virtual void deactivate() override; + + // Stereo specific methods + virtual bool isHmd() const override final { return true; } + virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; + virtual glm::uvec2 getRecommendedRenderSize() const override final; + virtual glm::uvec2 getRecommendedUiSize() const override final { return uvec2(1920, 1080); } + virtual void resetSensors() override final; + virtual glm::mat4 getEyePose(Eye eye) const override final; + virtual glm::mat4 getHeadPose() const override final; + +protected: + virtual void preRender() override final; + virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; + +protected: + ovrPosef _eyePoses[2]; + + mat4 _eyeProjections[3]; + mat4 _compositeEyeProjections[2]; + uvec2 _desiredFramebufferSize; + ovrTrackingState _trackingState; + unsigned int _frameIndex{ 0 }; + +#if (OVR_MAJOR_VERSION >= 6) + ovrHmd _hmd; + float _ipd{ OVR_DEFAULT_IPD }; + ovrEyeRenderDesc _eyeRenderDescs[2]; + ovrVector3f _eyeOffsets[2]; + ovrFovPort _eyeFovs[2]; + ovrHmdDesc _hmdDesc; + ovrLayerEyeFov _sceneLayer; +#endif +#if (OVR_MAJOR_VERSION == 7) + ovrGraphicsLuid _luid; +#endif +}; + +#if (OVR_MAJOR_VERSION == 6) +#define ovr_Create ovrHmd_Create +#define ovr_CreateSwapTextureSetGL ovrHmd_CreateSwapTextureSetGL +#define ovr_CreateMirrorTextureGL ovrHmd_CreateMirrorTextureGL +#define ovr_Destroy ovrHmd_Destroy +#define ovr_DestroySwapTextureSet ovrHmd_DestroySwapTextureSet +#define ovr_DestroyMirrorTexture ovrHmd_DestroyMirrorTexture +#define ovr_GetFloat ovrHmd_GetFloat +#define ovr_GetFovTextureSize ovrHmd_GetFovTextureSize +#define ovr_GetFrameTiming ovrHmd_GetFrameTiming +#define ovr_GetTrackingState ovrHmd_GetTrackingState +#define ovr_GetRenderDesc ovrHmd_GetRenderDesc +#define ovr_RecenterPose ovrHmd_RecenterPose +#define ovr_SubmitFrame ovrHmd_SubmitFrame +#define ovr_ConfigureTracking ovrHmd_ConfigureTracking + +#define ovr_GetHmdDesc(X) *X +#endif diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.cpp new file mode 100644 index 0000000000..2021ce1c5a --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.cpp @@ -0,0 +1,40 @@ +// +// Created by Bradley Austin Davis on 2014/04/13. +// Copyright 2015 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 "OculusDebugDisplayPlugin.h" +#include + +const QString OculusDebugDisplayPlugin::NAME("Oculus Rift (Simulator)"); + +const QString & OculusDebugDisplayPlugin::getName() const { + return NAME; +} + +static const QString DEBUG_FLAG("HIFI_DEBUG_OCULUS"); +static bool enableDebugOculus = QProcessEnvironment::systemEnvironment().contains("HIFI_DEBUG_OCULUS"); + +bool OculusDebugDisplayPlugin::isSupported() const { + if (!enableDebugOculus) { + return false; + } + return OculusBaseDisplayPlugin::isSupported(); +} + +void OculusDebugDisplayPlugin::customizeContext() { + WindowOpenGLDisplayPlugin::customizeContext(); + enableVsync(false); +} + +void OculusDebugDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) { + WindowOpenGLDisplayPlugin::display(finalTexture, sceneSize); + OculusBaseDisplayPlugin::display(finalTexture, sceneSize); +} + +void OculusDebugDisplayPlugin::finishFrame() { + swapBuffers(); + doneCurrent(); +}; diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.h new file mode 100644 index 0000000000..d23c6ba567 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.h @@ -0,0 +1,26 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// Copyright 2015 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 +// +#pragma once + +#include "OculusBaseDisplayPlugin.h" + +class OculusDebugDisplayPlugin : public OculusBaseDisplayPlugin { +public: + virtual const QString & getName() const override; + virtual bool isSupported() const override; + +protected: + virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; + virtual void customizeContext() override; + // Do not perform swap in finish + virtual void finishFrame() override; + +private: + static const QString NAME; +}; + diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.cpp index 2f4a9c93cf..58675eab4d 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.cpp @@ -7,59 +7,10 @@ // #include "OculusDisplayPlugin.h" -#include - -#include #include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -#if defined(__GNUC__) && !defined(__clang__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdouble-promotion" -#endif - -#include - -#if defined(__GNUC__) && !defined(__clang__) - #pragma GCC diagnostic pop -#endif - - -#include -#include -#include #include "OculusHelpers.h" -#if (OVR_MAJOR_VERSION == 6) -#define ovr_Create ovrHmd_Create -#define ovr_CreateSwapTextureSetGL ovrHmd_CreateSwapTextureSetGL -#define ovr_CreateMirrorTextureGL ovrHmd_CreateMirrorTextureGL -#define ovr_Destroy ovrHmd_Destroy -#define ovr_DestroySwapTextureSet ovrHmd_DestroySwapTextureSet -#define ovr_DestroyMirrorTexture ovrHmd_DestroyMirrorTexture -#define ovr_GetFloat ovrHmd_GetFloat -#define ovr_GetFovTextureSize ovrHmd_GetFovTextureSize -#define ovr_GetFrameTiming ovrHmd_GetFrameTiming -#define ovr_GetTrackingState ovrHmd_GetTrackingState -#define ovr_GetRenderDesc ovrHmd_GetRenderDesc -#define ovr_RecenterPose ovrHmd_RecenterPose -#define ovr_SubmitFrame ovrHmd_SubmitFrame -#define ovr_ConfigureTracking ovrHmd_ConfigureTracking - -#define ovr_GetHmdDesc(X) *X -#endif - #if (OVR_MAJOR_VERSION >= 6) // A base class for FBO wrappers that need to use the Oculus C @@ -180,160 +131,21 @@ private: const QString OculusDisplayPlugin::NAME("Oculus Rift"); -uvec2 OculusDisplayPlugin::getRecommendedRenderSize() const { - return _desiredFramebufferSize; -} - -void OculusDisplayPlugin::preRender() { -#if (OVR_MAJOR_VERSION >= 6) - ovrFrameTiming ftiming = ovr_GetFrameTiming(_hmd, _frameIndex); - _trackingState = ovr_GetTrackingState(_hmd, ftiming.DisplayMidpointSeconds); - ovr_CalcEyePoses(_trackingState.HeadPose.ThePose, _eyeOffsets, _eyePoses); -#endif -} - -glm::mat4 OculusDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { - return _eyeProjections[eye]; -} - -void OculusDisplayPlugin::resetSensors() { -#if (OVR_MAJOR_VERSION >= 6) - ovr_RecenterPose(_hmd); -#endif -} - -glm::mat4 OculusDisplayPlugin::getEyePose(Eye eye) const { - return toGlm(_eyePoses[eye]); -} - -glm::mat4 OculusDisplayPlugin::getHeadPose() const { - return toGlm(_trackingState.HeadPose.ThePose); -} - const QString & OculusDisplayPlugin::getName() const { return NAME; } -bool OculusDisplayPlugin::isSupported() const { -#if (OVR_MAJOR_VERSION >= 6) - if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { - return false; - } - bool result = false; - if (ovrHmd_Detect() > 0) { - result = true; - } - ovr_Shutdown(); - return result; -#else - return false; -#endif -} - -void OculusDisplayPlugin::init() { - if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { - qFatal("Could not init OVR"); - } -} - -void OculusDisplayPlugin::deinit() { - ovr_Shutdown(); -} - -#if (OVR_MAJOR_VERSION >= 6) -ovrLayerEyeFov& OculusDisplayPlugin::getSceneLayer() { - return _sceneLayer; -} -#endif - -//static gpu::TexturePointer _texture; - -void OculusDisplayPlugin::activate() { -#if (OVR_MAJOR_VERSION >= 6) - if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { - Q_ASSERT(false); - qFatal("Failed to Initialize SDK"); - } - -// CONTAINER->getPrimarySurface()->makeCurrent(); -#if (OVR_MAJOR_VERSION == 6) - if (!OVR_SUCCESS(ovr_Create(0, &_hmd))) { -#elif (OVR_MAJOR_VERSION == 7) - if (!OVR_SUCCESS(ovr_Create(&_hmd, &_luid))) { -#endif - Q_ASSERT(false); - qFatal("Failed to acquire HMD"); - } - - _hmdDesc = ovr_GetHmdDesc(_hmd); - - _ipd = ovr_GetFloat(_hmd, OVR_KEY_IPD, _ipd); - - glm::uvec2 eyeSizes[2]; - ovr_for_each_eye([&](ovrEyeType eye) { - _eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye]; - ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_hmd, eye, _eyeFovs[eye]); - ovrMatrix4f ovrPerspectiveProjection = - ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); - _eyeProjections[eye] = toGlm(ovrPerspectiveProjection); - - ovrPerspectiveProjection = - ovrMatrix4f_Projection(erd.Fov, 0.001f, 10.0f, ovrProjection_RightHanded); - _compositeEyeProjections[eye] = toGlm(ovrPerspectiveProjection); - - _eyeOffsets[eye] = erd.HmdToEyeViewOffset; - eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f)); - }); - ovrFovPort combined = _eyeFovs[Left]; - combined.LeftTan = std::max(_eyeFovs[Left].LeftTan, _eyeFovs[Right].LeftTan); - combined.RightTan = std::max(_eyeFovs[Left].RightTan, _eyeFovs[Right].RightTan); - ovrMatrix4f ovrPerspectiveProjection = - ovrMatrix4f_Projection(combined, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); - _eyeProjections[Mono] = toGlm(ovrPerspectiveProjection); - - - - _desiredFramebufferSize = uvec2( - eyeSizes[0].x + eyeSizes[1].x, - std::max(eyeSizes[0].y, eyeSizes[1].y)); - - _frameIndex = 0; - - if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd, - ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { - qFatal("Could not attach to sensor device"); - } - - WindowOpenGLDisplayPlugin::activate(); - - // Parent class relies on our _hmd intialization, so it must come after that. - ovrLayerEyeFov& sceneLayer = getSceneLayer(); - memset(&sceneLayer, 0, sizeof(ovrLayerEyeFov)); - sceneLayer.Header.Type = ovrLayerType_EyeFov; - sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; - ovr_for_each_eye([&](ovrEyeType eye) { - ovrFovPort & fov = sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov; - ovrSizei & size = sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_hmd, eye, fov, 1.0f); - sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 }; - }); - // We're rendering both eyes to the same texture, so only one of the - // pointers is populated - sceneLayer.ColorTexture[0] = _sceneFbo->color; - // not needed since the structure was zeroed on init, but explicit - sceneLayer.ColorTexture[1] = nullptr; - - if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd, - ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { - qFatal("Could not attach to sensor device"); - } -#endif -} - void OculusDisplayPlugin::customizeContext() { WindowOpenGLDisplayPlugin::customizeContext(); #if (OVR_MAJOR_VERSION >= 6) _sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd)); _sceneFbo->Init(getRecommendedRenderSize()); + + // We're rendering both eyes to the same texture, so only one of the + // pointers is populated + _sceneLayer.ColorTexture[0] = _sceneFbo->color; + // not needed since the structure was zeroed on init, but explicit + _sceneLayer.ColorTexture[1] = nullptr; #endif enableVsync(false); // Only enable mirroring if we know vsync is disabled @@ -345,13 +157,9 @@ void OculusDisplayPlugin::deactivate() { makeCurrent(); _sceneFbo.reset(); doneCurrent(); - - WindowOpenGLDisplayPlugin::deactivate(); - - ovr_Destroy(_hmd); - _hmd = nullptr; - ovr_Shutdown(); #endif + + OculusBaseDisplayPlugin::deactivate(); } void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) { @@ -379,9 +187,8 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi drawUnitQuad(); }); - ovrLayerEyeFov& sceneLayer = getSceneLayer(); ovr_for_each_eye([&](ovrEyeType eye) { - sceneLayer.RenderPose[eye] = _eyePoses[eye]; + _sceneLayer.RenderPose[eye] = _eyePoses[eye]; }); auto windowSize = toGlm(_window->size()); @@ -391,7 +198,7 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi viewScaleDesc.HmdToEyeViewOffset[0] = _eyeOffsets[0]; viewScaleDesc.HmdToEyeViewOffset[1] = _eyeOffsets[1]; - ovrLayerHeader* layers = &sceneLayer.Header; + ovrLayerHeader* layers = &_sceneLayer.Header; ovrResult result = ovr_SubmitFrame(_hmd, 0, &viewScaleDesc, &layers, 1); if (!OVR_SUCCESS(result)) { qDebug() << result; @@ -403,11 +210,6 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi #endif } -// Pass input events on to the application -bool OculusDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { - return WindowOpenGLDisplayPlugin::eventFilter(receiver, event); -} - /* The swapbuffer call here is only required if we want to mirror the content to the screen. However, it should only be done if we can reliably disable v-sync on the mirror surface, @@ -419,36 +221,3 @@ void OculusDisplayPlugin::finishFrame() { } doneCurrent(); }; - - -#if 0 -/* -An alternative way to render the UI is to pass it specifically as a composition layer to -the Oculus SDK which should technically result in higher quality. However, the SDK doesn't -have a mechanism to present the image as a sphere section, which is our desired look. -*/ -ovrLayerQuad& uiLayer = getUiLayer(); -if (nullptr == uiLayer.ColorTexture || overlaySize != _uiFbo->size) { - _uiFbo->Resize(overlaySize); - uiLayer.ColorTexture = _uiFbo->color; - uiLayer.Viewport.Size.w = overlaySize.x; - uiLayer.Viewport.Size.h = overlaySize.y; - float overlayAspect = aspect(overlaySize); - uiLayer.QuadSize.x = 1.0f; - uiLayer.QuadSize.y = 1.0f / overlayAspect; -} - -_uiFbo->Bound([&] { - Q_ASSERT(0 == glGetError()); - using namespace oglplus; - Context::Viewport(_uiFbo->size.x, _uiFbo->size.y); - glClearColor(0, 0, 0, 0); - Context::Clear().ColorBuffer(); - - _program->Bind(); - glBindTexture(GL_TEXTURE_2D, overlayTexture); - _plane->Use(); - _plane->Draw(); - Q_ASSERT(0 == glGetError()); -}); -#endif diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.h index d30356daa0..7db83884cd 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.h @@ -7,43 +7,17 @@ // #pragma once -#include "../WindowOpenGLDisplayPlugin.h" +#include "OculusBaseDisplayPlugin.h" -#include - -#include - -class OffscreenGlCanvas; struct SwapFramebufferWrapper; -struct MirrorFramebufferWrapper; - using SwapFboPtr = QSharedPointer; -using MirrorFboPtr = QSharedPointer; -class OculusDisplayPlugin : public WindowOpenGLDisplayPlugin { +class OculusDisplayPlugin : public OculusBaseDisplayPlugin { public: - virtual bool isSupported() const override; + virtual void deactivate() override; virtual const QString & getName() const override; - virtual void init() override; - virtual void deinit() override; - - virtual void activate() override; - virtual void deactivate() override; - - virtual bool eventFilter(QObject* receiver, QEvent* event) override; - - // Stereo specific methods - virtual bool isHmd() const override { return true; } - virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; - virtual glm::uvec2 getRecommendedRenderSize() const override; - virtual glm::uvec2 getRecommendedUiSize() const override { return uvec2(1920, 1080); } - virtual void resetSensors() override; - virtual glm::mat4 getEyePose(Eye eye) const override; - virtual glm::mat4 getHeadPose() const override; - protected: - virtual void preRender() override; virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; virtual void customizeContext() override; // Do not perform swap in finish @@ -51,30 +25,10 @@ protected: private: static const QString NAME; - - ovrPosef _eyePoses[2]; - - mat4 _eyeProjections[3]; - mat4 _compositeEyeProjections[2]; - uvec2 _desiredFramebufferSize; - ovrTrackingState _trackingState; bool _enableMirror{ false }; #if (OVR_MAJOR_VERSION >= 6) - ovrHmd _hmd; - float _ipd{ OVR_DEFAULT_IPD }; - unsigned int _frameIndex; - ovrEyeRenderDesc _eyeRenderDescs[2]; - ovrVector3f _eyeOffsets[2]; - ovrFovPort _eyeFovs[2]; - - ovrLayerEyeFov& getSceneLayer(); - ovrHmdDesc _hmdDesc; SwapFboPtr _sceneFbo; - ovrLayerEyeFov _sceneLayer; -#endif -#if (OVR_MAJOR_VERSION == 7) - ovrGraphicsLuid _luid; #endif }; From bef136d8110f513e5cb6a2926738ac27f58436d4 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 17 Sep 2015 11:21:14 -0700 Subject: [PATCH 29/38] AnimGraph: prefer QString over std::string --- libraries/animation/src/AnimBlendLinear.cpp | 2 +- libraries/animation/src/AnimBlendLinear.h | 6 +- libraries/animation/src/AnimClip.cpp | 8 +-- libraries/animation/src/AnimClip.h | 26 ++++---- .../animation/src/AnimInverseKinematics.cpp | 8 +-- .../animation/src/AnimInverseKinematics.h | 8 +-- libraries/animation/src/AnimManipulator.cpp | 7 +-- libraries/animation/src/AnimManipulator.h | 12 ++-- libraries/animation/src/AnimNode.h | 10 ++-- libraries/animation/src/AnimNodeLoader.cpp | 56 +++++++++-------- libraries/animation/src/AnimOverlay.cpp | 2 +- libraries/animation/src/AnimOverlay.h | 10 ++-- libraries/animation/src/AnimStateMachine.cpp | 8 +-- libraries/animation/src/AnimStateMachine.h | 24 ++++---- libraries/animation/src/AnimVariant.h | 60 +++++++++---------- 15 files changed, 122 insertions(+), 125 deletions(-) diff --git a/libraries/animation/src/AnimBlendLinear.cpp b/libraries/animation/src/AnimBlendLinear.cpp index 63c66a2b9d..bc95565f6f 100644 --- a/libraries/animation/src/AnimBlendLinear.cpp +++ b/libraries/animation/src/AnimBlendLinear.cpp @@ -13,7 +13,7 @@ #include "AnimationLogging.h" #include "AnimUtil.h" -AnimBlendLinear::AnimBlendLinear(const std::string& id, float alpha) : +AnimBlendLinear::AnimBlendLinear(const QString& id, float alpha) : AnimNode(AnimNode::Type::BlendLinear, id), _alpha(alpha) { diff --git a/libraries/animation/src/AnimBlendLinear.h b/libraries/animation/src/AnimBlendLinear.h index 3a09245575..56acd5c2f7 100644 --- a/libraries/animation/src/AnimBlendLinear.h +++ b/libraries/animation/src/AnimBlendLinear.h @@ -27,12 +27,12 @@ class AnimBlendLinear : public AnimNode { public: friend class AnimTests; - AnimBlendLinear(const std::string& id, float alpha); + AnimBlendLinear(const QString& id, float alpha); virtual ~AnimBlendLinear() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; - void setAlphaVar(const std::string& alphaVar) { _alphaVar = alphaVar; } + void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; } protected: // for AnimDebugDraw rendering @@ -42,7 +42,7 @@ protected: float _alpha; - std::string _alphaVar; + QString _alphaVar; // no copies AnimBlendLinear(const AnimBlendLinear&) = delete; diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index fdc5fc504a..23aa884933 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -13,7 +13,7 @@ #include "AnimationLogging.h" #include "AnimUtil.h" -AnimClip::AnimClip(const std::string& id, const std::string& url, float startFrame, float endFrame, float timeScale, bool loopFlag) : +AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag) : AnimNode(AnimNode::Type::Clip, id), _startFrame(startFrame), _endFrame(endFrame), @@ -68,9 +68,9 @@ const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, float dt, return _poses; } -void AnimClip::loadURL(const std::string& url) { +void AnimClip::loadURL(const QString& url) { auto animCache = DependencyManager::get(); - _networkAnim = animCache->getAnimation(QString::fromStdString(url)); + _networkAnim = animCache->getAnimation(url); _url = url; } @@ -127,7 +127,7 @@ void AnimClip::copyFromNetworkAnim() { for (int i = 0; i < animJointCount; i++) { int skeletonJoint = _skeleton->nameToJointIndex(animJoints.at(i).name); if (skeletonJoint == -1) { - qCWarning(animation) << "animation contains joint =" << animJoints.at(i).name << " which is not in the skeleton, url =" << _url.c_str(); + qCWarning(animation) << "animation contains joint =" << animJoints.at(i).name << " which is not in the skeleton, url =" << _url; } jointMap.push_back(skeletonJoint); } diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index 1b9649cc3e..3a76870c98 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -25,19 +25,19 @@ class AnimClip : public AnimNode { public: friend class AnimTests; - AnimClip(const std::string& id, const std::string& url, float startFrame, float endFrame, float timeScale, bool loopFlag); + AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag); virtual ~AnimClip() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; - void setStartFrameVar(const std::string& startFrameVar) { _startFrameVar = startFrameVar; } - void setEndFrameVar(const std::string& endFrameVar) { _endFrameVar = endFrameVar; } - void setTimeScaleVar(const std::string& timeScaleVar) { _timeScaleVar = timeScaleVar; } - void setLoopFlagVar(const std::string& loopFlagVar) { _loopFlagVar = loopFlagVar; } - void setFrameVar(const std::string& frameVar) { _frameVar = frameVar; } + void setStartFrameVar(const QString& startFrameVar) { _startFrameVar = startFrameVar; } + void setEndFrameVar(const QString& endFrameVar) { _endFrameVar = endFrameVar; } + void setTimeScaleVar(const QString& timeScaleVar) { _timeScaleVar = timeScaleVar; } + void setLoopFlagVar(const QString& loopFlagVar) { _loopFlagVar = loopFlagVar; } + void setFrameVar(const QString& frameVar) { _frameVar = frameVar; } protected: - void loadURL(const std::string& url); + void loadURL(const QString& url); virtual void setCurrentFrameInternal(float frame) override; @@ -53,18 +53,18 @@ protected: // _anim[frame][joint] std::vector _anim; - std::string _url; + QString _url; float _startFrame; float _endFrame; float _timeScale; bool _loopFlag; float _frame; - std::string _startFrameVar; - std::string _endFrameVar; - std::string _timeScaleVar; - std::string _loopFlagVar; - std::string _frameVar; + QString _startFrameVar; + QString _endFrameVar; + QString _timeScaleVar; + QString _loopFlagVar; + QString _frameVar; // no copies AnimClip(const AnimClip&) = delete; diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 863970ccaa..36b23c313e 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -17,7 +17,7 @@ #include "SwingTwistConstraint.h" #include "AnimationLogging.h" -AnimInverseKinematics::AnimInverseKinematics(const std::string& id) : AnimNode(AnimNode::Type::InverseKinematics, id) { +AnimInverseKinematics::AnimInverseKinematics(const QString& id) : AnimNode(AnimNode::Type::InverseKinematics, id) { } AnimInverseKinematics::~AnimInverseKinematics() { @@ -59,15 +59,15 @@ void AnimInverseKinematics::setTargetVars(const QString& jointName, const QStrin for (auto& targetVar: _targetVarVec) { if (targetVar.jointName == jointName) { // update existing targetVar - targetVar.positionVar = positionVar.toStdString(); - targetVar.rotationVar = rotationVar.toStdString(); + targetVar.positionVar = positionVar; + targetVar.rotationVar = rotationVar; found = true; break; } } if (!found) { // create a new entry - _targetVarVec.push_back(IKTargetVar(jointName, positionVar.toStdString(), rotationVar.toStdString())); + _targetVarVec.push_back(IKTargetVar(jointName, positionVar, rotationVar)); } } diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index eabc3448de..b59fb4d5fc 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -19,7 +19,7 @@ class RotationConstraint; class AnimInverseKinematics : public AnimNode { public: - AnimInverseKinematics(const std::string& id); + AnimInverseKinematics(const QString& id); virtual ~AnimInverseKinematics() override; void loadDefaultPoses(const AnimPoseVec& poses); @@ -45,15 +45,15 @@ protected: void initConstraints(); struct IKTargetVar { - IKTargetVar(const QString& jointNameIn, const std::string& positionVarIn, const std::string& rotationVarIn) : + IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn) : positionVar(positionVarIn), rotationVar(rotationVarIn), jointName(jointNameIn), jointIndex(-1), rootIndex(-1) {} - std::string positionVar; - std::string rotationVar; + QString positionVar; + QString rotationVar; QString jointName; int jointIndex; // cached joint index int rootIndex; // cached root index diff --git a/libraries/animation/src/AnimManipulator.cpp b/libraries/animation/src/AnimManipulator.cpp index c2951681e1..0640c418e3 100644 --- a/libraries/animation/src/AnimManipulator.cpp +++ b/libraries/animation/src/AnimManipulator.cpp @@ -12,7 +12,7 @@ #include "AnimUtil.h" #include "AnimationLogging.h" -AnimManipulator::AnimManipulator(const std::string& id, float alpha) : +AnimManipulator::AnimManipulator(const QString& id, float alpha) : AnimNode(AnimNode::Type::Manipulator, id), _alpha(alpha) { @@ -31,10 +31,9 @@ const AnimPoseVec& AnimManipulator::overlay(const AnimVariantMap& animVars, floa for (auto& jointVar : _jointVars) { if (!jointVar.hasPerformedJointLookup) { - QString qJointName = QString::fromStdString(jointVar.jointName); - jointVar.jointIndex = _skeleton->nameToJointIndex(qJointName); + jointVar.jointIndex = _skeleton->nameToJointIndex(jointVar.jointName); if (jointVar.jointIndex < 0) { - qCWarning(animation) << "AnimManipulator could not find jointName" << qJointName << "in skeleton"; + qCWarning(animation) << "AnimManipulator could not find jointName" << jointVar.jointName << "in skeleton"; } jointVar.hasPerformedJointLookup = true; } diff --git a/libraries/animation/src/AnimManipulator.h b/libraries/animation/src/AnimManipulator.h index c04853b8e0..eca1a4aa71 100644 --- a/libraries/animation/src/AnimManipulator.h +++ b/libraries/animation/src/AnimManipulator.h @@ -19,20 +19,20 @@ class AnimManipulator : public AnimNode { public: friend class AnimTests; - AnimManipulator(const std::string& id, float alpha); + AnimManipulator(const QString& id, float alpha); virtual ~AnimManipulator() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override; - void setAlphaVar(const std::string& alphaVar) { _alphaVar = alphaVar; } + void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; } virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) override; struct JointVar { - JointVar(const std::string& varIn, const std::string& jointNameIn) : var(varIn), jointName(jointNameIn), jointIndex(-1), hasPerformedJointLookup(false) {} - std::string var = ""; - std::string jointName = ""; + JointVar(const QString& varIn, const QString& jointNameIn) : var(varIn), jointName(jointNameIn), jointIndex(-1), hasPerformedJointLookup(false) {} + QString var = ""; + QString jointName = ""; int jointIndex = -1; bool hasPerformedJointLookup = false; }; @@ -45,7 +45,7 @@ protected: AnimPoseVec _poses; float _alpha; - std::string _alphaVar; + QString _alphaVar; std::vector _jointVars; diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index b4992f95a3..9325ef3835 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -46,16 +46,16 @@ public: }; using Pointer = std::shared_ptr; using ConstPointer = std::shared_ptr; - using Triggers = std::vector; + using Triggers = std::vector; friend class AnimDebugDraw; - friend void buildChildMap(std::map& map, Pointer node); + friend void buildChildMap(std::map& map, Pointer node); friend class AnimStateMachine; - AnimNode(Type type, const std::string& id) : _type(type), _id(id) {} + AnimNode(Type type, const QString& id) : _type(type), _id(id) {} virtual ~AnimNode() {} - const std::string& getID() const { return _id; } + const QString& getID() const { return _id; } Type getType() const { return _type; } // hierarchy accessors @@ -105,7 +105,7 @@ protected: virtual const AnimPoseVec& getPosesInternal() const = 0; Type _type; - std::string _id; + QString _id; std::vector _children; AnimSkeleton::ConstPointer _skeleton; diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index 23bea83e1c..b2afae4728 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -200,19 +200,19 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString& READ_OPTIONAL_STRING(timeScaleVar, jsonObj); READ_OPTIONAL_STRING(loopFlagVar, jsonObj); - auto node = std::make_shared(id.toStdString(), url.toStdString(), startFrame, endFrame, timeScale, loopFlag); + auto node = std::make_shared(id, url, startFrame, endFrame, timeScale, loopFlag); if (!startFrameVar.isEmpty()) { - node->setStartFrameVar(startFrameVar.toStdString()); + node->setStartFrameVar(startFrameVar); } if (!endFrameVar.isEmpty()) { - node->setEndFrameVar(endFrameVar.toStdString()); + node->setEndFrameVar(endFrameVar); } if (!timeScaleVar.isEmpty()) { - node->setTimeScaleVar(timeScaleVar.toStdString()); + node->setTimeScaleVar(timeScaleVar); } if (!loopFlagVar.isEmpty()) { - node->setLoopFlagVar(loopFlagVar.toStdString()); + node->setLoopFlagVar(loopFlagVar); } return node; @@ -224,10 +224,10 @@ static AnimNode::Pointer loadBlendLinearNode(const QJsonObject& jsonObj, const Q READ_OPTIONAL_STRING(alphaVar, jsonObj); - auto node = std::make_shared(id.toStdString(), alpha); + auto node = std::make_shared(id, alpha); if (!alphaVar.isEmpty()) { - node->setAlphaVar(alphaVar.toStdString()); + node->setAlphaVar(alphaVar); } return node; @@ -271,31 +271,31 @@ static AnimNode::Pointer loadOverlayNode(const QJsonObject& jsonObj, const QStri READ_OPTIONAL_STRING(boneSetVar, jsonObj); READ_OPTIONAL_STRING(alphaVar, jsonObj); - auto node = std::make_shared(id.toStdString(), boneSetEnum, alpha); + auto node = std::make_shared(id, boneSetEnum, alpha); if (!boneSetVar.isEmpty()) { - node->setBoneSetVar(boneSetVar.toStdString()); + node->setBoneSetVar(boneSetVar); } if (!alphaVar.isEmpty()) { - node->setAlphaVar(alphaVar.toStdString()); + node->setAlphaVar(alphaVar); } return node; } static AnimNode::Pointer loadStateMachineNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { - auto node = std::make_shared(id.toStdString()); + auto node = std::make_shared(id); return node; } static AnimNode::Pointer loadManipulatorNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { READ_FLOAT(alpha, jsonObj, id, jsonUrl, nullptr); - auto node = std::make_shared(id.toStdString(), alpha); + auto node = std::make_shared(id, alpha); READ_OPTIONAL_STRING(alphaVar, jsonObj); if (!alphaVar.isEmpty()) { - node->setAlphaVar(alphaVar.toStdString()); + node->setAlphaVar(alphaVar); } auto jointsValue = jsonObj.value("joints"); @@ -315,7 +315,7 @@ static AnimNode::Pointer loadManipulatorNode(const QJsonObject& jsonObj, const Q READ_STRING(var, jointObj, id, jsonUrl, nullptr); READ_STRING(jointName, jointObj, id, jsonUrl, nullptr); - AnimManipulator::JointVar jointVar(var.toStdString(), jointName.toStdString()); + AnimManipulator::JointVar jointVar(var, jointName); node->addJointVar(jointVar); }; @@ -323,7 +323,7 @@ static AnimNode::Pointer loadManipulatorNode(const QJsonObject& jsonObj, const Q } AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { - auto node = std::make_shared(id.toStdString()); + auto node = std::make_shared(id); auto targetsValue = jsonObj.value("targets"); if (!targetsValue.isArray()) { @@ -349,9 +349,9 @@ AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QS return node; } -void buildChildMap(std::map& map, AnimNode::Pointer node) { +void buildChildMap(std::map& map, AnimNode::Pointer node) { for ( auto child : node->_children ) { - map.insert(std::pair(child->_id, child)); + map.insert(std::pair(child->_id, child)); } } @@ -368,15 +368,15 @@ bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, } // build a map for all children by name. - std::map childMap; + std::map childMap; buildChildMap(childMap, node); // first pass parse all the states and build up the state and transition map. - using StringPair = std::pair; + using StringPair = std::pair; using TransitionMap = std::multimap; TransitionMap transitionMap; - using StateMap = std::map; + using StateMap = std::map; StateMap stateMap; auto statesArray = statesValue.toArray(); @@ -394,22 +394,20 @@ bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, READ_OPTIONAL_STRING(interpTargetVar, stateObj); READ_OPTIONAL_STRING(interpDurationVar, stateObj); - auto stdId = id.toStdString(); - - auto iter = childMap.find(stdId); + auto iter = childMap.find(id); if (iter == childMap.end()) { qCCritical(animation) << "AnimNodeLoader, could not find stateMachine child (state) with nodeId =" << nodeId << "stateId =" << id << "url =" << jsonUrl.toDisplayString(); return false; } - auto statePtr = std::make_shared(stdId, iter->second, interpTarget, interpDuration); + auto statePtr = std::make_shared(id, iter->second, interpTarget, interpDuration); assert(statePtr); if (!interpTargetVar.isEmpty()) { - statePtr->setInterpTargetVar(interpTargetVar.toStdString()); + statePtr->setInterpTargetVar(interpTargetVar); } if (!interpDurationVar.isEmpty()) { - statePtr->setInterpDurationVar(interpDurationVar.toStdString()); + statePtr->setInterpDurationVar(interpDurationVar); } smNode->addState(statePtr); @@ -432,7 +430,7 @@ bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, READ_STRING(var, transitionObj, nodeId, jsonUrl, false); READ_STRING(state, transitionObj, nodeId, jsonUrl, false); - transitionMap.insert(TransitionMap::value_type(statePtr, StringPair(var.toStdString(), state.toStdString()))); + transitionMap.insert(TransitionMap::value_type(statePtr, StringPair(var, state))); } } @@ -443,12 +441,12 @@ bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, if (iter != stateMap.end()) { srcState->addTransition(AnimStateMachine::State::Transition(transition.second.first, iter->second)); } else { - qCCritical(animation) << "AnimNodeLoader, bad state machine transtion from srcState =" << srcState->_id.c_str() << "dstState =" << transition.second.second.c_str() << "nodeId =" << nodeId << "url = " << jsonUrl.toDisplayString(); + qCCritical(animation) << "AnimNodeLoader, bad state machine transtion from srcState =" << srcState->_id << "dstState =" << transition.second.second << "nodeId =" << nodeId << "url = " << jsonUrl.toDisplayString(); return false; } } - auto iter = stateMap.find(currentState.toStdString()); + auto iter = stateMap.find(currentState); if (iter == stateMap.end()) { qCCritical(animation) << "AnimNodeLoader, bad currentState =" << currentState << "could not find child node" << "id =" << nodeId << "url = " << jsonUrl.toDisplayString(); } diff --git a/libraries/animation/src/AnimOverlay.cpp b/libraries/animation/src/AnimOverlay.cpp index 760a683aa6..08c4304b08 100644 --- a/libraries/animation/src/AnimOverlay.cpp +++ b/libraries/animation/src/AnimOverlay.cpp @@ -12,7 +12,7 @@ #include "AnimUtil.h" #include -AnimOverlay::AnimOverlay(const std::string& id, BoneSet boneSet, float alpha) : +AnimOverlay::AnimOverlay(const QString& id, BoneSet boneSet, float alpha) : AnimNode(AnimNode::Type::Overlay, id), _boneSet(boneSet), _alpha(alpha) { } diff --git a/libraries/animation/src/AnimOverlay.h b/libraries/animation/src/AnimOverlay.h index 2a87c54997..eda8847d40 100644 --- a/libraries/animation/src/AnimOverlay.h +++ b/libraries/animation/src/AnimOverlay.h @@ -40,13 +40,13 @@ public: NumBoneSets }; - AnimOverlay(const std::string& id, BoneSet boneSet, float alpha); + AnimOverlay(const QString& id, BoneSet boneSet, float alpha); virtual ~AnimOverlay() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; - void setBoneSetVar(const std::string& boneSetVar) { _boneSetVar = boneSetVar; } - void setAlphaVar(const std::string& alphaVar) { _alphaVar = alphaVar; } + void setBoneSetVar(const QString& boneSetVar) { _boneSetVar = boneSetVar; } + void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; } protected: void buildBoneSet(BoneSet boneSet); @@ -60,8 +60,8 @@ public: float _alpha; std::vector _boneSetVec; - std::string _boneSetVar; - std::string _alphaVar; + QString _boneSetVar; + QString _alphaVar; void buildFullBodyBoneSet(); void buildUpperBodyBoneSet(); diff --git a/libraries/animation/src/AnimStateMachine.cpp b/libraries/animation/src/AnimStateMachine.cpp index 5de379dd33..8ce0fc95b0 100644 --- a/libraries/animation/src/AnimStateMachine.cpp +++ b/libraries/animation/src/AnimStateMachine.cpp @@ -12,7 +12,7 @@ #include "AnimUtil.h" #include "AnimationLogging.h" -AnimStateMachine::AnimStateMachine(const std::string& id) : +AnimStateMachine::AnimStateMachine(const QString& id) : AnimNode(AnimNode::Type::StateMachine, id) { } @@ -23,7 +23,7 @@ AnimStateMachine::~AnimStateMachine() { const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) { - std::string desiredStateID = animVars.lookup(_currentStateVar, _currentState->getID()); + QString desiredStateID = animVars.lookup(_currentStateVar, _currentState->getID()); if (_currentState->getID() != desiredStateID) { // switch states bool foundState = false; @@ -35,7 +35,7 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, fl } } if (!foundState) { - qCCritical(animation) << "AnimStateMachine could not find state =" << desiredStateID.c_str() << ", referenced by _currentStateVar =" << _currentStateVar.c_str(); + qCCritical(animation) << "AnimStateMachine could not find state =" << desiredStateID << ", referenced by _currentStateVar =" << _currentStateVar; } } @@ -77,7 +77,7 @@ void AnimStateMachine::addState(State::Pointer state) { void AnimStateMachine::switchState(const AnimVariantMap& animVars, State::Pointer desiredState) { - qCDebug(animation) << "AnimStateMachine::switchState:" << _currentState->getID().c_str() << "->" << desiredState->getID().c_str(); + qCDebug(animation) << "AnimStateMachine::switchState:" << _currentState->getID() << "->" << desiredState->getID(); const float FRAMES_PER_SECOND = 30.0f; diff --git a/libraries/animation/src/AnimStateMachine.h b/libraries/animation/src/AnimStateMachine.h index f2d941a568..cb6c99f067 100644 --- a/libraries/animation/src/AnimStateMachine.h +++ b/libraries/animation/src/AnimStateMachine.h @@ -49,23 +49,23 @@ protected: class Transition { public: friend AnimStateMachine; - Transition(const std::string& var, State::Pointer state) : _var(var), _state(state) {} + Transition(const QString& var, State::Pointer state) : _var(var), _state(state) {} protected: - std::string _var; + QString _var; State::Pointer _state; }; - State(const std::string& id, AnimNode::Pointer node, float interpTarget, float interpDuration) : + State(const QString& id, AnimNode::Pointer node, float interpTarget, float interpDuration) : _id(id), _node(node), _interpTarget(interpTarget), _interpDuration(interpDuration) {} - void setInterpTargetVar(const std::string& interpTargetVar) { _interpTargetVar = interpTargetVar; } - void setInterpDurationVar(const std::string& interpDurationVar) { _interpDurationVar = interpDurationVar; } + void setInterpTargetVar(const QString& interpTargetVar) { _interpTargetVar = interpTargetVar; } + void setInterpDurationVar(const QString& interpDurationVar) { _interpDurationVar = interpDurationVar; } AnimNode::Pointer getNode() const { return _node; } - const std::string& getID() const { return _id; } + const QString& getID() const { return _id; } protected: @@ -74,13 +74,13 @@ protected: void addTransition(const Transition& transition) { _transitions.push_back(transition); } - std::string _id; + QString _id; AnimNode::Pointer _node; float _interpTarget; // frames float _interpDuration; // frames - std::string _interpTargetVar; - std::string _interpDurationVar; + QString _interpTargetVar; + QString _interpDurationVar; std::vector _transitions; @@ -92,12 +92,12 @@ protected: public: - AnimStateMachine(const std::string& id); + AnimStateMachine(const QString& id); virtual ~AnimStateMachine() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; - void setCurrentStateVar(std::string& currentStateVar) { _currentStateVar = currentStateVar; } + void setCurrentStateVar(QString& currentStateVar) { _currentStateVar = currentStateVar; } protected: @@ -123,7 +123,7 @@ protected: State::Pointer _currentState; std::vector _states; - std::string _currentStateVar; + QString _currentStateVar; private: // no copies diff --git a/libraries/animation/src/AnimVariant.h b/libraries/animation/src/AnimVariant.h index bcff4b2a9b..de224f936a 100644 --- a/libraries/animation/src/AnimVariant.h +++ b/libraries/animation/src/AnimVariant.h @@ -37,7 +37,7 @@ public: AnimVariant(const glm::vec3& value) : _type(Type::Vec3) { *reinterpret_cast(&_val) = value; } AnimVariant(const glm::quat& value) : _type(Type::Quat) { *reinterpret_cast(&_val) = value; } AnimVariant(const glm::mat4& value) : _type(Type::Mat4) { *reinterpret_cast(&_val) = value; } - AnimVariant(const std::string& value) : _type(Type::String) { _stringVal = value; } + AnimVariant(const QString& value) : _type(Type::String) { _stringVal = value; } bool isBool() const { return _type == Type::Bool; } bool isInt() const { return _type == Type::Int; } @@ -53,7 +53,7 @@ public: void setVec3(const glm::vec3& value) { assert(_type == Type::Vec3); *reinterpret_cast(&_val) = value; } void setQuat(const glm::quat& value) { assert(_type == Type::Quat); *reinterpret_cast(&_val) = value; } void setMat4(const glm::mat4& value) { assert(_type == Type::Mat4); *reinterpret_cast(&_val) = value; } - void setString(const std::string& value) { assert(_type == Type::String); _stringVal = value; } + void setString(const QString& value) { assert(_type == Type::String); _stringVal = value; } bool getBool() const { assert(_type == Type::Bool); return _val.boolVal; } int getInt() const { assert(_type == Type::Int); return _val.intVal; } @@ -61,11 +61,11 @@ public: const glm::vec3& getVec3() const { assert(_type == Type::Vec3); return *reinterpret_cast(&_val); } const glm::quat& getQuat() const { assert(_type == Type::Quat); return *reinterpret_cast(&_val); } const glm::mat4& getMat4() const { assert(_type == Type::Mat4); return *reinterpret_cast(&_val); } - const std::string& getString() const { assert(_type == Type::String); return _stringVal; } + const QString& getString() const { assert(_type == Type::String); return _stringVal; } protected: Type _type; - std::string _stringVal; + QString _stringVal; union { bool boolVal; int intVal; @@ -76,9 +76,9 @@ protected: class AnimVariantMap { public: - bool lookup(const std::string& key, bool defaultValue) const { + bool lookup(const QString& key, bool defaultValue) const { // check triggers first, then map - if (key.empty()) { + if (key.isEmpty()) { return defaultValue; } else if (_triggers.find(key) != _triggers.end()) { return true; @@ -88,8 +88,8 @@ public: } } - int lookup(const std::string& key, int defaultValue) const { - if (key.empty()) { + int lookup(const QString& key, int defaultValue) const { + if (key.isEmpty()) { return defaultValue; } else { auto iter = _map.find(key); @@ -97,8 +97,8 @@ public: } } - float lookup(const std::string& key, float defaultValue) const { - if (key.empty()) { + float lookup(const QString& key, float defaultValue) const { + if (key.isEmpty()) { return defaultValue; } else { auto iter = _map.find(key); @@ -106,8 +106,8 @@ public: } } - const glm::vec3& lookup(const std::string& key, const glm::vec3& defaultValue) const { - if (key.empty()) { + const glm::vec3& lookup(const QString& key, const glm::vec3& defaultValue) const { + if (key.isEmpty()) { return defaultValue; } else { auto iter = _map.find(key); @@ -115,8 +115,8 @@ public: } } - const glm::quat& lookup(const std::string& key, const glm::quat& defaultValue) const { - if (key.empty()) { + const glm::quat& lookup(const QString& key, const glm::quat& defaultValue) const { + if (key.isEmpty()) { return defaultValue; } else { auto iter = _map.find(key); @@ -124,8 +124,8 @@ public: } } - const glm::mat4& lookup(const std::string& key, const glm::mat4& defaultValue) const { - if (key.empty()) { + const glm::mat4& lookup(const QString& key, const glm::mat4& defaultValue) const { + if (key.isEmpty()) { return defaultValue; } else { auto iter = _map.find(key); @@ -133,8 +133,8 @@ public: } } - const std::string& lookup(const std::string& key, const std::string& defaultValue) const { - if (key.empty()) { + const QString& lookup(const QString& key, const QString& defaultValue) const { + if (key.isEmpty()) { return defaultValue; } else { auto iter = _map.find(key); @@ -142,23 +142,23 @@ public: } } - void set(const std::string& key, bool value) { _map[key] = AnimVariant(value); } - void set(const std::string& key, int value) { _map[key] = AnimVariant(value); } - void set(const std::string& key, float value) { _map[key] = AnimVariant(value); } - void set(const std::string& key, const glm::vec3& value) { _map[key] = AnimVariant(value); } - void set(const std::string& key, const glm::quat& value) { _map[key] = AnimVariant(value); } - void set(const std::string& key, const glm::mat4& value) { _map[key] = AnimVariant(value); } - void set(const std::string& key, const std::string& value) { _map[key] = AnimVariant(value); } - void unset(const std::string& key) { _map.erase(key); } + void set(const QString& key, bool value) { _map[key] = AnimVariant(value); } + void set(const QString& key, int value) { _map[key] = AnimVariant(value); } + void set(const QString& key, float value) { _map[key] = AnimVariant(value); } + void set(const QString& key, const glm::vec3& value) { _map[key] = AnimVariant(value); } + void set(const QString& key, const glm::quat& value) { _map[key] = AnimVariant(value); } + void set(const QString& key, const glm::mat4& value) { _map[key] = AnimVariant(value); } + void set(const QString& key, const QString& value) { _map[key] = AnimVariant(value); } + void unset(const QString& key) { _map.erase(key); } - void setTrigger(const std::string& key) { _triggers.insert(key); } + void setTrigger(const QString& key) { _triggers.insert(key); } void clearTriggers() { _triggers.clear(); } - bool hasKey(const std::string& key) const { return _map.find(key) != _map.end(); } + bool hasKey(const QString& key) const { return _map.find(key) != _map.end(); } protected: - std::map _map; - std::set _triggers; + std::map _map; + std::set _triggers; }; #endif // hifi_AnimVariant_h From b207d97f72c31c46c395021dcdefcdddcdfd0954 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 17 Sep 2015 12:28:17 -0700 Subject: [PATCH 30/38] Fix the lighting when the rear view mirror is showing up --- libraries/gpu/src/gpu/Resource.h | 25 ++++++++++++------- .../src/DeferredLightingEffect.cpp | 1 + 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libraries/gpu/src/gpu/Resource.h b/libraries/gpu/src/gpu/Resource.h index 42897e9947..177c798e2c 100644 --- a/libraries/gpu/src/gpu/Resource.h +++ b/libraries/gpu/src/gpu/Resource.h @@ -160,15 +160,22 @@ typedef std::vector< BufferPointer > Buffers; class BufferView { +protected: + void initFromBuffer(const BufferPointer& buffer) { + _buffer = (buffer); + if (_buffer) { + _size = (buffer->getSize()); + } + } public: typedef Resource::Size Size; typedef int Index; BufferPointer _buffer; - Size _offset; - Size _size; + Size _offset{ 0 }; + Size _size{ 0 }; Element _element; - uint16 _stride; + uint16 _stride{ 1 }; BufferView() : _buffer(NULL), @@ -188,19 +195,19 @@ public: // create the BufferView and own the Buffer BufferView(Buffer* newBuffer, const Element& element = Element(gpu::SCALAR, gpu::UINT8, gpu::RAW)) : - _buffer(newBuffer), _offset(0), - _size(newBuffer->getSize()), _element(element), _stride(uint16(element.getSize())) - {}; + { + initFromBuffer(BufferPointer(newBuffer)); + }; BufferView(const BufferPointer& buffer, const Element& element = Element(gpu::SCALAR, gpu::UINT8, gpu::RAW)) : - _buffer(buffer), _offset(0), - _size(buffer->getSize()), _element(element), _stride(uint16(element.getSize())) - {}; + { + initFromBuffer(buffer); + }; BufferView(const BufferPointer& buffer, Size offset, Size size, const Element& element = Element(gpu::SCALAR, gpu::UINT8, gpu::RAW)) : _buffer(buffer), _offset(offset), diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index b19e2f62b7..ce387e648b 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -582,6 +582,7 @@ void DeferredLightingEffect::render(RenderArgs* args) { batch.setResourceTexture(1, nullptr); batch.setResourceTexture(2, nullptr); batch.setResourceTexture(3, nullptr); + batch.setUniformBuffer(_directionalLightLocations->deferredTransformBuffer, nullptr); args->_context->render(batch); From 4758dd2a53975315d8a4f3212ffd92ef4b6d1440 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 17 Sep 2015 14:13:24 -0700 Subject: [PATCH 31/38] correct locking races in SendQueue/Connection cleanup --- libraries/networking/src/udt/Connection.cpp | 30 ++++++++++------ libraries/networking/src/udt/Connection.h | 5 +++ libraries/networking/src/udt/SendQueue.cpp | 35 +++++++++++++----- libraries/networking/src/udt/SendQueue.h | 8 ++++- libraries/networking/src/udt/Socket.cpp | 40 +++++++++++++++++---- 5 files changed, 90 insertions(+), 28 deletions(-) diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index 2fb28f81ee..1bda840a6c 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -56,14 +56,15 @@ void Connection::stopSendQueue() { // grab the send queue thread so we can wait on it QThread* sendQueueThread = _sendQueue->thread(); - // since we're stopping the send queue we should consider our handshake ACK not receieved - _hasReceivedHandshakeACK = false; - // tell the send queue to stop and be deleted + _sendQueue->stop(); _sendQueue->deleteLater(); _sendQueue.release(); + // since we're stopping the send queue we should consider our handshake ACK not receieved + _hasReceivedHandshakeACK = false; + // wait on the send queue thread so we know the send queue is gone sendQueueThread->quit(); sendQueueThread->wait(); @@ -111,7 +112,7 @@ void Connection::queueInactive() { qCDebug(networking) << "Connection SendQueue to" << _destination << "stopped and no data is being received - stopping connection."; #endif - emit connectionInactive(_destination); + deactivate(); } } @@ -170,7 +171,9 @@ void Connection::sync() { qCDebug(networking) << "Connection to" << _destination << "no longer receiving any data and there is currently no send queue - stopping connection."; #endif - emit connectionInactive(_destination); + deactivate(); + + return; } } @@ -207,7 +210,9 @@ void Connection::sync() { << CONNECTION_NOT_USED_EXPIRY_SECONDS << "seconds - stopping connection."; #endif - emit connectionInactive(_destination); + deactivate(); + + return; } } } @@ -728,11 +733,14 @@ void Connection::processHandshake(std::unique_ptr controlPacket) } void Connection::processHandshakeACK(std::unique_ptr controlPacket) { - // hand off this handshake ACK to the send queue so it knows it can start sending - getSendQueue().handshakeACK(); - - // indicate that handshake ACK was received - _hasReceivedHandshakeACK = true; + // if we've decided to clean up the send queue then this handshake ACK should be ignored, it's useless + if (_sendQueue) { + // hand off this handshake ACK to the send queue so it knows it can start sending + getSendQueue().handshakeACK(); + + // indicate that handshake ACK was received + _hasReceivedHandshakeACK = true; + } } void Connection::processTimeoutNAK(std::unique_ptr controlPacket) { diff --git a/libraries/networking/src/udt/Connection.h b/libraries/networking/src/udt/Connection.h index 2b1dec1ae9..13756c12f9 100644 --- a/libraries/networking/src/udt/Connection.h +++ b/libraries/networking/src/udt/Connection.h @@ -71,6 +71,8 @@ public: void queueReceivedMessagePacket(std::unique_ptr packet); ConnectionStats::Stats sampleStats() { return _stats.sample(); } + + bool isActive() const { return _isActive; } signals: void packetSent(); @@ -100,6 +102,8 @@ private: void resetReceiveState(); void resetRTT(); + void deactivate() { _isActive = false; emit connectionInactive(_destination); } + SendQueue& getSendQueue(); SequenceNumber nextACK() const; void updateRTT(int rtt); @@ -123,6 +127,7 @@ private: p_high_resolution_clock::time_point _lastReceiveTime; // holds the last time we received anything from sender bool _isReceivingData { false }; // flag used for expiry of receipt portion of connection + bool _isActive { true }; // flag used for inactivity of connection LossList _lossList; // List of all missing packets SequenceNumber _lastReceivedSequenceNumber; // The largest sequence number received from the peer diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index a09ea6ca9a..31c2f41259 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -65,6 +65,7 @@ std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destin // Move queue to private thread and start it queue->moveToThread(thread); + thread->start(); return std::move(queue); @@ -89,7 +90,8 @@ void SendQueue::queuePacket(std::unique_ptr packet) { // call notify_one on the condition_variable_any in case the send thread is sleeping waiting for packets _emptyCondition.notify_one(); } - if (!this->thread()->isRunning()) { + + if (!this->thread()->isRunning() && _state == State::NotStarted) { this->thread()->start(); } } @@ -135,14 +137,15 @@ void SendQueue::queuePacketList(std::unique_ptr packetList) { // call notify_one on the condition_variable_any in case the send thread is sleeping waiting for packets _emptyCondition.notify_one(); } - + if (!this->thread()->isRunning()) { this->thread()->start(); } } void SendQueue::stop() { - _isRunning = false; + + _state = State::Stopped; // in case we're waiting to send another handshake, release the condition_variable now so we cleanup sooner _handshakeACKCondition.notify_one(); @@ -268,9 +271,23 @@ void SendQueue::sendNewPacketAndAddToSentList(std::unique_ptr newPacket, } void SendQueue::run() { - _isRunning = true; + if (_state == State::Stopped) { + // we've already been asked to stop before we even got a chance to start + // don't start now +#ifdef UDT_CONNECTION_DEBUG + qDebug() << "SendQueue asked to run after being told to stop. Will not run."; +#endif + return; + } else if (_state == State::Running) { +#ifdef UDT_CONNECTION_DEBUG + qDebug() << "SendQueue asked to run but is already running (according to state). Will not re-run."; +#endif + return; + } - while (_isRunning) { + _state = State::Running; + + while (_state == State::Running) { // Record how long the loop takes to execute auto loopStartTimestamp = p_high_resolution_clock::now(); @@ -314,11 +331,11 @@ void SendQueue::run() { } // since we're a while loop, give the thread a chance to process events - QCoreApplication::processEvents(); + QCoreApplication::sendPostedEvents(this, 0); // we just processed events so check now if we were just told to stop - if (!_isRunning) { - break; + if (_state != State::Running) { + return; } if (_hasReceivedHandshakeACK && !sentAPacket) { @@ -525,5 +542,5 @@ void SendQueue::deactivate() { // this queue is inactive - emit that signal and stop the while emit queueInactive(); - _isRunning = false; + _state = State::Stopped; } diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index 2e7ec90c45..88b6b045b0 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -45,6 +45,12 @@ class SendQueue : public QObject { Q_OBJECT public: + enum class State { + NotStarted, + Running, + Stopped + }; + static std::unique_ptr create(Socket* socket, HifiSockAddr destination); void queuePacket(std::unique_ptr packet); @@ -106,7 +112,7 @@ private: std::atomic _atomicCurrentSequenceNumber { 0 };// Atomic for last sequence number sent out std::atomic _packetSendPeriod { 0 }; // Interval between two packet send event in microseconds, set from CC - std::atomic _isRunning { false }; + std::atomic _state { State::NotStarted }; std::atomic _estimatedTimeout { 0 }; // Estimated timeout, set from CC std::atomic _timeoutExpiryCount { 0 }; // The number of times the timeout has expired without response from client diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 56a00c6808..c148374edb 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -183,8 +183,7 @@ Connection& Socket::findOrCreateConnection(const HifiSockAddr& sockAddr) { auto connection = std::unique_ptr(new Connection(this, sockAddr, _ccFactory->create())); // we queue the connection to cleanup connection in case it asks for it during its own rate control sync - QObject::connect(connection.get(), &Connection::connectionInactive, this, &Socket::cleanupConnection, - Qt::QueuedConnection); + QObject::connect(connection.get(), &Connection::connectionInactive, this, &Socket::cleanupConnection); #ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "Creating new connection to" << sockAddr; @@ -208,11 +207,15 @@ void Socket::clearConnections() { } void Socket::cleanupConnection(HifiSockAddr sockAddr) { -#ifdef UDT_CONNECTION_DEBUG - qCDebug(networking) << "Socket::cleanupConnection called for UDT connection to" << sockAddr; -#endif + auto it = _connectionsHash.find(sockAddr); - _connectionsHash.erase(sockAddr); + if (it != _connectionsHash.end()) { +#ifdef UDT_CONNECTION_DEBUG + qCDebug(networking) << "Socket::cleanupConnection called for UDT connection to" << sockAddr; +#endif + + _connectionsHash.erase(sockAddr); + } } void Socket::messageReceived(std::unique_ptr packetList) { @@ -297,8 +300,31 @@ void Socket::connectToSendSignal(const HifiSockAddr& destinationAddr, QObject* r void Socket::rateControlSync() { // enumerate our list of connections and ask each of them to send off periodic ACK packet for rate control + + // this way we do this is a little funny looking - we need to avoid the case where we call sync and + // (because of our Qt direct connection to the Connection's signal that it has been deactivated) + // an iterator on _connectionsHash would be invalidated by our own call to cleanupConnection + + // collect the sockets for all connections in a vector + + std::vector sockAddrVector; + sockAddrVector.reserve(_connectionsHash.size()); + for (auto& connection : _connectionsHash) { - connection.second->sync(); + sockAddrVector.emplace_back(connection.first); + } + + // enumerate that vector of HifiSockAddr objects + for (auto& sockAddr : sockAddrVector) { + // pull out the respective connection via a quick find on the unordered_map + auto it = _connectionsHash.find(sockAddr); + + if (it != _connectionsHash.end()) { + // if the connection is erased while calling sync since we are not holding an iterator that was invalidated + // we're good to go + auto& connection = _connectionsHash[sockAddr]; + connection->sync(); + } } if (_synTimer->interval() != _synInterval) { From 36e2d4fc76f201c315df315f60fd50689b6a3baa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 17 Sep 2015 14:16:03 -0700 Subject: [PATCH 32/38] add check for NotStarted state in PL queue --- libraries/networking/src/udt/SendQueue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 31c2f41259..ac6c8238e8 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -138,7 +138,7 @@ void SendQueue::queuePacketList(std::unique_ptr packetList) { _emptyCondition.notify_one(); } - if (!this->thread()->isRunning()) { + if (!this->thread()->isRunning() && _state == State::NotStarted) { this->thread()->start(); } } From 1f9bb22b9efe4c86e7c6b778d23baf64805cd684 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 17 Sep 2015 14:17:03 -0700 Subject: [PATCH 33/38] fix some wording in Socket comment --- libraries/networking/src/udt/Socket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index c148374edb..55e807301e 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -301,7 +301,7 @@ void Socket::rateControlSync() { // enumerate our list of connections and ask each of them to send off periodic ACK packet for rate control - // this way we do this is a little funny looking - we need to avoid the case where we call sync and + // the way we do this is a little funny looking - we need to avoid the case where we call sync and // (because of our Qt direct connection to the Connection's signal that it has been deactivated) // an iterator on _connectionsHash would be invalidated by our own call to cleanupConnection From a914ec82c315d87e6b994d6c579feb9330ffd91f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 17 Sep 2015 14:17:43 -0700 Subject: [PATCH 34/38] more comment correctness for Socket --- libraries/networking/src/udt/Socket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 55e807301e..3327ea9dc7 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -320,7 +320,7 @@ void Socket::rateControlSync() { auto it = _connectionsHash.find(sockAddr); if (it != _connectionsHash.end()) { - // if the connection is erased while calling sync since we are not holding an iterator that was invalidated + // if the connection is erased while calling sync since we are re-using the iterator that was invalidated // we're good to go auto& connection = _connectionsHash[sockAddr]; connection->sync(); From 285a6cc7385f8c946685b3f39164df6e179e4288 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 17 Sep 2015 14:51:48 -0700 Subject: [PATCH 35/38] use erase directly for cleanupConnection --- libraries/networking/src/udt/Socket.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 3327ea9dc7..50f2e67007 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -207,14 +207,12 @@ void Socket::clearConnections() { } void Socket::cleanupConnection(HifiSockAddr sockAddr) { - auto it = _connectionsHash.find(sockAddr); + auto numErased = _connectionsHash.erase(sockAddr); - if (it != _connectionsHash.end()) { + if (numErased > 0) { #ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "Socket::cleanupConnection called for UDT connection to" << sockAddr; #endif - - _connectionsHash.erase(sockAddr); } } From 9746d31f5ef46b698fd5c7f6a0709b8f6605fb26 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 16 Sep 2015 17:41:29 -0700 Subject: [PATCH 36/38] notes for moving hand updates --- libraries/animation/src/Rig.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 8b5bad5605..7180838f89 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -735,12 +735,8 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q return; } - if (freeLineage.isEmpty()) { - return; - } - int numFree = freeLineage.size(); - if (_enableAnimGraph && _animSkeleton) { + // adebug: comment this stuff out to disable normal hand updates if (endIndex == _leftHandJointIndex) { _animVars.set("leftHandPosition", targetPosition); _animVars.set("leftHandRotation", targetRotation); @@ -751,6 +747,10 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q return; } + if (freeLineage.isEmpty()) { + return; + } + // store and remember topmost parent transform glm::mat4 topParentTransform; { @@ -766,6 +766,7 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q // relax toward default rotation // NOTE: ideally this should use dt and a relaxation timescale to compute how much to relax + int numFree = freeLineage.size(); for (int j = 0; j < numFree; j++) { int nextIndex = freeLineage.at(j); JointState& nextState = _jointStates[nextIndex]; @@ -987,6 +988,7 @@ void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, floa void Rig::updateNeckJoint(int index, const HeadParameters& params) { if (index >= 0 && _jointStates[index].getParentIndex() >= 0) { if (_enableAnimGraph && _animSkeleton) { + // adebug comment this block out out to disable head target // the params.localHeadOrientation is composed incorrectly, so re-compose it correctly from pitch, yaw and roll. glm::quat realLocalHeadOrientation = (glm::angleAxis(glm::radians(-params.localHeadRoll), Z_AXIS) * glm::angleAxis(glm::radians(params.localHeadYaw), Y_AXIS) * @@ -1046,6 +1048,26 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) { if (_enableAnimGraph && _animSkeleton) { + /* adebug add thsi stuff to update hands from another path + auto rootPose = _animSkeleton->getAbsoluteBindPose(_rootJointIndex); + // TODO: figure out how to get away without using this HACK + glm::quat yFlipHACK = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); + if (params.isLeftEnabled) { + _animVars.set("leftHandPosition", yFlipHACK * (rootPose.trans + rootPose.rot * params.leftPosition)); + _animVars.set("leftHandRotation", yFlipHACK * rootPose.rot * params.leftOrientation); + } else { + _animVars.unset("leftHandPosition"); + _animVars.unset("leftHandRotation"); + } + if (params.isRightEnabled) { + _animVars.set("rightHandPosition", yFlipHACK * (rootPose.trans + rootPose.rot * params.rightPosition)); + _animVars.set("rightHandRotation", yFlipHACK * rootPose.rot * params.rightOrientation); + } else { + _animVars.unset("rightHandPosition"); + _animVars.unset("rightHandRotation"); + } + */ + // set leftHand grab vars _animVars.set("isLeftHandIdle", false); _animVars.set("isLeftHandPoint", false); From 4505d5999ca4ad72ec82baa8de880d166dc207c7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 17 Sep 2015 15:54:36 -0700 Subject: [PATCH 37/38] route hand data differently for new Anim system --- libraries/animation/src/Rig.cpp | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 7180838f89..025cb5f3d1 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -736,14 +736,7 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q } if (_enableAnimGraph && _animSkeleton) { - // adebug: comment this stuff out to disable normal hand updates - if (endIndex == _leftHandJointIndex) { - _animVars.set("leftHandPosition", targetPosition); - _animVars.set("leftHandRotation", targetRotation); - } else if (endIndex == _rightHandJointIndex) { - _animVars.set("rightHandPosition", targetPosition); - _animVars.set("rightHandRotation", targetRotation); - } + // the hand data goes through a different path: Rig::updateFromHandParameters() --> early-exit return; } @@ -988,7 +981,6 @@ void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, floa void Rig::updateNeckJoint(int index, const HeadParameters& params) { if (index >= 0 && _jointStates[index].getParentIndex() >= 0) { if (_enableAnimGraph && _animSkeleton) { - // adebug comment this block out out to disable head target // the params.localHeadOrientation is composed incorrectly, so re-compose it correctly from pitch, yaw and roll. glm::quat realLocalHeadOrientation = (glm::angleAxis(glm::radians(-params.localHeadRoll), Z_AXIS) * glm::angleAxis(glm::radians(params.localHeadYaw), Y_AXIS) * @@ -1048,25 +1040,22 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) { if (_enableAnimGraph && _animSkeleton) { - /* adebug add thsi stuff to update hands from another path - auto rootPose = _animSkeleton->getAbsoluteBindPose(_rootJointIndex); - // TODO: figure out how to get away without using this HACK + // TODO: figure out how to obtain the yFlip from where it is actually stored glm::quat yFlipHACK = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); if (params.isLeftEnabled) { - _animVars.set("leftHandPosition", yFlipHACK * (rootPose.trans + rootPose.rot * params.leftPosition)); - _animVars.set("leftHandRotation", yFlipHACK * rootPose.rot * params.leftOrientation); + _animVars.set("leftHandPosition", yFlipHACK * params.leftPosition); + _animVars.set("leftHandRotation", yFlipHACK * params.leftOrientation); } else { _animVars.unset("leftHandPosition"); _animVars.unset("leftHandRotation"); } if (params.isRightEnabled) { - _animVars.set("rightHandPosition", yFlipHACK * (rootPose.trans + rootPose.rot * params.rightPosition)); - _animVars.set("rightHandRotation", yFlipHACK * rootPose.rot * params.rightOrientation); + _animVars.set("rightHandPosition", yFlipHACK * params.rightPosition); + _animVars.set("rightHandRotation", yFlipHACK * params.rightOrientation); } else { _animVars.unset("rightHandPosition"); _animVars.unset("rightHandRotation"); } - */ // set leftHand grab vars _animVars.set("isLeftHandIdle", false); From 4459708b0e928e708bd1498973d6f223c7ab1879 Mon Sep 17 00:00:00 2001 From: Shared Vive Room Date: Thu, 17 Sep 2015 17:16:12 -0700 Subject: [PATCH 38/38] Fix for getEyePose in OpenVRDisplayPlugin --- .../src/display-plugins/openvr/OpenVrDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp index 95e0ef741d..fab9cc5dd4 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp @@ -161,7 +161,7 @@ void OpenVrDisplayPlugin::resetSensors() { } glm::mat4 OpenVrDisplayPlugin::getEyePose(Eye eye) const { - return _eyesData[eye]._eyeOffset * getHeadPose(); + return getHeadPose() * _eyesData[eye]._eyeOffset; } glm::mat4 OpenVrDisplayPlugin::getHeadPose() const {