diff --git a/animation-server/CMakeLists.txt b/animation-server/CMakeLists.txt
index 42516d2f86..31ed5d98df 100644
--- a/animation-server/CMakeLists.txt
+++ b/animation-server/CMakeLists.txt
@@ -12,6 +12,9 @@ set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
 # setup for find modules
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
 
+find_package(Qt5 COMPONENTS Script)
+include_directories(SYSTEM "${Qt5Script_INCLUDE_DIRS}")
+
 # set up the external glm library
 include("${MACRO_DIR}/IncludeGLM.cmake")
 include_glm(${TARGET_NAME} "${ROOT_DIR}")
@@ -35,4 +38,4 @@ link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
 # add a definition for ssize_t so that windows doesn't bail
 if (WIN32)
   add_definitions(-Dssize_t=long)
-endif ()
\ No newline at end of file
+endif ()
diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp
index 5720ecaaf5..fcd983873d 100644
--- a/assignment-client/src/Agent.cpp
+++ b/assignment-client/src/Agent.cpp
@@ -13,13 +13,13 @@
 #include <QtCore/QEventLoop>
 #include <QtCore/QStandardPaths>
 #include <QtCore/QTimer>
-#include <QtNetwork/QNetworkAccessManager>
 #include <QtNetwork/QNetworkDiskCache>
 #include <QtNetwork/QNetworkRequest>
 #include <QtNetwork/QNetworkReply>
 
 #include <AudioRingBuffer.h>
 #include <AvatarData.h>
+#include <NetworkAccessManager.h>
 #include <NodeList.h>
 #include <PacketHeaders.h>
 #include <ResourceCache.h>
@@ -208,12 +208,14 @@ void Agent::run() {
         scriptURL = QUrl(_payload);
     }
    
-    QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
-    QNetworkReply *reply = networkManager->get(QNetworkRequest(scriptURL));
-    QNetworkDiskCache* cache = new QNetworkDiskCache(networkManager);
+    NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+    QNetworkReply *reply = networkAccessManager.get(QNetworkRequest(scriptURL));
+    QNetworkDiskCache* cache = new QNetworkDiskCache(&networkAccessManager);
     QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
     cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache");
-    networkManager->setCache(cache);
+    QMetaObject::invokeMethod(&networkAccessManager, "setCache",
+                              Qt::BlockingQueuedConnection,
+                              Q_ARG(QAbstractNetworkCache*, cache));
     
     qDebug() << "Downloading script at" << scriptURL.toString();
     
@@ -222,10 +224,6 @@ void Agent::run() {
     
     loop.exec();
     
-    // let the AvatarData and ResourceCache classes use our QNetworkAccessManager
-    AvatarData::setNetworkAccessManager(networkManager);
-    ResourceCache::setNetworkAccessManager(networkManager);
-    
     QString scriptContents(reply->readAll());
     
     qDebug() << "Downloaded script:" << scriptContents;
diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp
index 663aef81a7..1c3046b9b1 100644
--- a/assignment-client/src/audio/AudioMixer.cpp
+++ b/assignment-client/src/audio/AudioMixer.cpp
@@ -38,11 +38,11 @@
 #include <QtCore/QJsonObject>
 #include <QtCore/QJsonValue>
 #include <QtCore/QTimer>
-#include <QtNetwork/QNetworkAccessManager>
 #include <QtNetwork/QNetworkRequest>
 #include <QtNetwork/QNetworkReply>
 
 #include <Logging.h>
+#include <NetworkAccessManager.h>
 #include <NodeList.h>
 #include <Node.h>
 #include <PacketHeaders.h>
@@ -482,8 +482,8 @@ void AudioMixer::run() {
 
     nodeList->linkedDataCreateCallback = attachNewBufferToNode;
     
-    // setup a QNetworkAccessManager to ask the domain-server for our settings
-    QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
+    // setup a NetworkAccessManager to ask the domain-server for our settings
+    NetworkAccessManager& networkManager = NetworkAccessManager::getInstance();
     
     QUrl settingsJSONURL;
     settingsJSONURL.setScheme("http");
@@ -500,7 +500,7 @@ void AudioMixer::run() {
     qDebug() << "Requesting settings for assignment from domain-server at" << settingsJSONURL.toString();
     
     while (!reply || reply->error() != QNetworkReply::NoError) {
-        reply = networkManager->get(QNetworkRequest(settingsJSONURL));
+        reply = networkManager.get(QNetworkRequest(settingsJSONURL));
         
         QEventLoop loop;
         QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp
index 23719b86cf..551bed795d 100644
--- a/assignment-client/src/octree/OctreeServer.cpp
+++ b/assignment-client/src/octree/OctreeServer.cpp
@@ -10,7 +10,6 @@
 //
 
 #include <QJsonObject>
-#include <QNetworkAccessManager>
 #include <QTimer>
 #include <QUuid>
 
diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index 7a2d5f4f99..366a5016f9 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -51,8 +51,6 @@ DomainServer::DomainServer(int argc, char* argv[]) :
 
     _argumentVariantMap = HifiConfigVariantMap::mergeCLParametersWithJSONConfig(arguments());
 
-    _networkAccessManager = new QNetworkAccessManager(this);
-
     if (optionallyReadX509KeyAndCertificate() && optionallySetupOAuth() && optionallySetupAssignmentPayment()) {
         // we either read a certificate and private key or were not passed one
         // and completed login or did not need to
@@ -1196,7 +1194,7 @@ bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &u
             QNetworkRequest tokenRequest(tokenRequestUrl);
             tokenRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
 
-            QNetworkReply* tokenReply = _networkAccessManager->post(tokenRequest, tokenPostBody.toLocal8Bit());
+            QNetworkReply* tokenReply = NetworkAccessManager::getInstance().post(tokenRequest, tokenPostBody.toLocal8Bit());
 
             qDebug() << "Requesting a token for user with session UUID" << uuidStringWithoutCurlyBraces(stateUUID);
 
@@ -1233,7 +1231,7 @@ void DomainServer::handleTokenRequestFinished() {
         profileURL.setPath("/api/v1/users/profile");
         profileURL.setQuery(QString("%1=%2").arg(OAUTH_JSON_ACCESS_TOKEN_KEY, accessToken));
 
-        QNetworkReply* profileReply = _networkAccessManager->get(QNetworkRequest(profileURL));
+        QNetworkReply* profileReply = NetworkAccessManager::getInstance().get(QNetworkRequest(profileURL));
 
         qDebug() << "Requesting access token for user with session UUID" << uuidStringWithoutCurlyBraces(matchingSessionUUID);
 
diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h
index 01f44b698e..cc44bd95a8 100644
--- a/domain-server/src/DomainServer.h
+++ b/domain-server/src/DomainServer.h
@@ -103,8 +103,6 @@ private:
     
     bool _isUsingDTLS;
     
-    QNetworkAccessManager* _networkAccessManager;
-    
     QUrl _oauthProviderURL;
     QString _oauthClientID;
     QString _oauthClientSecret;
diff --git a/interface/external/oculus/readme.txt b/interface/external/oculus/readme.txt
index f689f81478..f68818d1ee 100644
--- a/interface/external/oculus/readme.txt
+++ b/interface/external/oculus/readme.txt
@@ -10,4 +10,7 @@ You can download the Oculus SDK from https://developer.oculusvr.com/ (account cr
    You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects). 
    If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'oculus' that contains the three folders mentioned above.
 
-2. Clear your build directory, run cmake and build, and you should be all set.
\ No newline at end of file
+   NOTE: For Windows users, you should copy libovr.lib and libovrd.lib from the \oculus\Lib\Win32\VS2010 directory to the \oculus\Lib\Win32\ directory.
+
+2. Clear your build directory, run cmake and build, and you should be all set.
+
diff --git a/interface/resources/shaders/perlin_modulate.frag b/interface/resources/shaders/perlin_modulate.frag
index 8693b14e1b..23d31ff72e 100644
--- a/interface/resources/shaders/perlin_modulate.frag
+++ b/interface/resources/shaders/perlin_modulate.frag
@@ -11,18 +11,114 @@
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
 //
 
-// the texture containing our permutations and normals
-uniform sampler2D permutationNormalTexture;
+// implementation based on Ken Perlin's Improved Noise reference implementation (orig. in Java) at
+// http://mrl.nyu.edu/~perlin/noise/
+
+uniform sampler2D permutationTexture;
 
 // the noise frequency
-const float frequency = 65536.0; // looks better with current TREE_SCALE, was 1024 when TREE_SCALE was either 512 or 128
+const float frequency = 256.0;
+//const float frequency = 65536.0; // looks better with current TREE_SCALE, was 1024 when TREE_SCALE was either 512 or 128
 
 // the noise amplitude
-const float amplitude = 0.1;
+const float amplitude = 0.5;
 
 // the position in model space
 varying vec3 position;
 
+// gradient based on gradients from cube edge centers rather than random from texture lookup
+float randomEdgeGrad(int hash, vec3 position){
+    int h = int(mod(hash, 16));
+    float u = h < 8 ? position.x : position.y;
+    float v = h < 4 ? position.y : h == 12 || h == 14 ? position.x : position.z;
+    bool even = mod(hash, 2) == 0;
+    bool four = mod(hash, 4) == 0;
+    return (even ? u : -u) + (four ? v : -v);
+}
+
+// still have the option to lookup based on texture
+float randomTextureGrad(int hash, vec3 position){
+    float u = float(hash) / 256.0;
+    vec3 g = -1 + 2 * texture2D(permutationTexture, vec2(u, 0.75)).rgb;
+    return dot(position, g);
+}
+
+float improvedGrad(int hash, vec3 position){
+// Untested whether texture lookup is faster than math, uncomment one line or the other to try out
+// cube edge gradients versus random spherical gradients sent in texture.
+
+//    return randomTextureGrad(hash, position);
+    return randomEdgeGrad(hash, position);
+}
+
+// 5th order fade function to remove 2nd order discontinuties
+vec3 fade3(vec3 t){
+    return t * t * t * (t * (t * 6 - 15) + 10); 
+}
+
+int permutation(int index){
+    float u = float(index) / 256.0;
+    float t = texture2D(permutationTexture, vec2(u, 0.25)).r;
+    return int(t * 256);
+}
+
+float improvedNoise(vec3 position){
+    int X = int(mod(floor(position.x), 256));
+    int Y = int(mod(floor(position.y), 256));
+    int Z = int(mod(floor(position.z), 256));
+
+    vec3 fracs = fract(position);
+
+    vec3 fades = fade3(fracs);
+
+    int A  = permutation(X + 0) + Y;
+    int AA = permutation(A + 0) + Z;
+    int AB = permutation(A + 1) + Z;
+    int B  = permutation(X + 1) + Y;
+    int BA = permutation(B + 0) + Z;
+    int BB = permutation(B + 1) + Z;
+
+    float gradAA0 = improvedGrad(permutation(AA + 0), vec3(fracs.x    , fracs.y    , fracs.z    ));
+    float gradBA0 = improvedGrad(permutation(BA + 0), vec3(fracs.x - 1, fracs.y    , fracs.z    ));
+    float gradAB0 = improvedGrad(permutation(AB + 0), vec3(fracs.x    , fracs.y - 1, fracs.z    ));
+    float gradBB0 = improvedGrad(permutation(BB + 0), vec3(fracs.x - 1, fracs.y - 1, fracs.z    ));
+    float gradAA1 = improvedGrad(permutation(AA + 1), vec3(fracs.x    , fracs.y    , fracs.z - 1));
+    float gradBA1 = improvedGrad(permutation(BA + 1), vec3(fracs.x - 1, fracs.y    , fracs.z - 1));
+    float gradAB1 = improvedGrad(permutation(AB + 1), vec3(fracs.x    , fracs.y - 1, fracs.z - 1));
+    float gradBB1 = improvedGrad(permutation(BB + 1), vec3(fracs.x - 1, fracs.y - 1, fracs.z - 1));
+
+    return mix(mix(mix(gradAA0, gradBA0, fades.x), mix(gradAB0, gradBB0, fades.x), fades.y), mix(mix(gradAA1, gradBA1, fades.x), mix(gradAB1, gradBB1, fades.x), fades.y), fades.z);
+}
+
+float turbulence(vec3 position, float power){
+    return (1.0f / power) * improvedNoise(power * position);
+}
+
+float turb(vec3 position){
+    return turbulence(position, 1)
+    + turbulence(position, 2), 
+    + turbulence(position, 4) 
+    + turbulence(position, 8) 
+    + turbulence(position, 16) 
+    + turbulence(position, 32)
+    + turbulence(position, 64)
+    + turbulence(position, 128)
+    ;
+}
+
+
+void main(void) {
+
+    // get noise in range 0 .. 1
+    float noise = clamp(0.5f + amplitude * turb(position * frequency), 0, 1); 
+
+    // apply vertex lighting
+    vec3 color = gl_Color.rgb * vec3(noise, noise, noise);
+    gl_FragColor = vec4(color, 1);
+}
+
+
+/* old implementation
 // returns the gradient at a single corner of our sampling cube
 vec3 grad(vec3 location) {
     float p1 = texture2D(permutationNormalTexture, vec2(location.x / 256.0, 0.25)).r;
@@ -60,7 +156,4 @@ float perlin(vec3 location) {
         mix(mix(ffcv, cfcv, params.x), mix(fccv, cccv, params.x), params.y),
         params.z);
 }
-
-void main(void) {
-    gl_FragColor = vec4(gl_Color.rgb * (1.0 + amplitude*(perlin(position * frequency) - 1.0)), 1.0);
-}
+*/
\ No newline at end of file
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 85320a47d7..ecc9c6e481 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -32,7 +32,6 @@
 #include <QKeyEvent>
 #include <QMenuBar>
 #include <QMouseEvent>
-#include <QNetworkAccessManager>
 #include <QNetworkReply>
 #include <QNetworkDiskCache>
 #include <QOpenGLFramebufferObject>
@@ -53,17 +52,18 @@
 
 #include <AccountManager.h>
 #include <AudioInjector.h>
+#include <LocalVoxelsList.h>
 #include <Logging.h>
 #include <ModelsScriptingInterface.h>
+#include <NetworkAccessManager.h>
 #include <OctalCode.h>
+#include <OctreeSceneStats.h>
 #include <PacketHeaders.h>
 #include <ParticlesScriptingInterface.h>
 #include <PerfStat.h>
 #include <ResourceCache.h>
 #include <UserActivityLogger.h>
 #include <UUID.h>
-#include <OctreeSceneStats.h>
-#include <LocalVoxelsList.h>
 
 #include "Application.h"
 #include "InterfaceVersion.h"
@@ -315,12 +315,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
 
     QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
 
-    _networkAccessManager = new QNetworkAccessManager(this);
-    QNetworkDiskCache* cache = new QNetworkDiskCache(_networkAccessManager);
+    NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+    QNetworkDiskCache* cache = new QNetworkDiskCache(&networkAccessManager);
     cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache");
-    _networkAccessManager->setCache(cache);
+    QMetaObject::invokeMethod(&networkAccessManager, "setCache",
+                              Qt::BlockingQueuedConnection,
+                              Q_ARG(QAbstractNetworkCache*, cache));
 
-    ResourceCache::setNetworkAccessManager(_networkAccessManager);
     ResourceCache::setRequestLimit(3);
 
     _window->setCentralWidget(_glWidget);
@@ -403,18 +404,19 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
 }
 
 Application::~Application() {
+    qInstallMessageHandler(NULL);
+    
+    saveSettings();
+    storeSizeAndPosition();
+    saveScripts();
+    
     int DELAY_TIME = 1000;
     UserActivityLogger::getInstance().close(DELAY_TIME);
     
-    qInstallMessageHandler(NULL);
-
     // make sure we don't call the idle timer any more
     delete idleTimer;
-
+    
     _sharedVoxelSystem.changeTree(new VoxelTree);
-
-    saveSettings();
-
     delete _voxelImporter;
 
     // let the avatar mixer know we're out
@@ -437,8 +439,6 @@ Application::~Application() {
     _particleEditSender.terminate();
     _modelEditSender.terminate();
 
-    storeSizeAndPosition();
-    saveScripts();
 
     VoxelTreeElement::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown
     Menu::getInstance()->deleteLater();
@@ -446,8 +446,6 @@ Application::~Application() {
     _myAvatar = NULL;
 
     delete _glWidget;
-
-    AccountManager::getInstance().destroy();
 }
 
 void Application::saveSettings() {
@@ -595,13 +593,17 @@ void Application::paintGL() {
         //Note, the camera distance is set in Camera::setMode() so we dont have to do it here.
         _myCamera.setTightness(0.0f);     //  Camera is directly connected to head without smoothing
         _myCamera.setTargetPosition(_myAvatar->getUprightHeadPosition());
-        _myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation());
+        if (OculusManager::isConnected()) {
+            _myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation());
+        } else {
+            _myCamera.setTargetRotation(_myAvatar->getHead()->getOrientation());
+        }
 
     } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
         _myCamera.setTightness(0.0f);
         _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
         _myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
-        _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
+        _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition() + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0));
     }
 
     // Update camera position
@@ -639,6 +641,10 @@ void Application::paintGL() {
     //If we aren't using the glow shader, we have to clear the color and depth buffer
     if (!glowEnabled) {
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    } else if (OculusManager::isConnected()) {
+        //Clear the color buffer to ensure that there isnt any residual color
+        //Left over from when OR was not connected.
+        glClear(GL_COLOR_BUFFER_BIT);
     }
 
     if (OculusManager::isConnected()) {
@@ -650,13 +656,8 @@ void Application::paintGL() {
         }
 
     } else if (TV3DManager::isConnected()) {
-        if (glowEnabled) {
-            _glowEffect.prepare();
-        }
+       
         TV3DManager::display(whichCamera);
-        if (glowEnabled) {
-            _glowEffect.render();
-        }
 
     } else {
         if (glowEnabled) {
@@ -1144,7 +1145,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
 
     _lastMouseMove = usecTimestampNow();
 
-    if (_mouseHidden && showMouse && !OculusManager::isConnected()) {
+    if (_mouseHidden && showMouse && !OculusManager::isConnected() && !TV3DManager::isConnected()) {
         getGLWidget()->setCursor(Qt::ArrowCursor);
         _mouseHidden = false;
         _seenMouseMove = true;
@@ -3808,7 +3809,8 @@ void Application::initAvatarAndViewFrustum() {
 void Application::checkVersion() {
     QNetworkRequest latestVersionRequest((QUrl(CHECK_VERSION_URL)));
     latestVersionRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
-    connect(Application::getInstance()->getNetworkAccessManager()->get(latestVersionRequest), SIGNAL(finished()), SLOT(parseVersionXml()));
+    QNetworkReply* reply = NetworkAccessManager::getInstance().get(latestVersionRequest);
+    connect(reply, SIGNAL(finished()), SLOT(parseVersionXml()));
 }
 
 void Application::parseVersionXml() {
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 56b6f673ae..11f406abf0 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -97,7 +97,6 @@ class QActionGroup;
 class QGLWidget;
 class QKeyEvent;
 class QMouseEvent;
-class QNetworkAccessManager;
 class QSettings;
 class QWheelEvent;
 
@@ -236,7 +235,6 @@ public:
     void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
     void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); }
 
-    QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
     GeometryCache* getGeometryCache() { return &_geometryCache; }
     AnimationCache* getAnimationCache() { return &_animationCache; }
     TextureCache* getTextureCache() { return &_textureCache; }
@@ -423,7 +421,6 @@ private:
     QThread* _nodeThread;
     DatagramProcessor _datagramProcessor;
 
-    QNetworkAccessManager* _networkAccessManager;
     QMutex _settingsMutex;
     QSettings* _settings;
     int _numChangedSettings;
diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp
index f5f148969c..df9df878bb 100644
--- a/interface/src/Audio.cpp
+++ b/interface/src/Audio.cpp
@@ -432,7 +432,7 @@ void Audio::handleAudioInput() {
 
     float inputToNetworkInputRatio = calculateDeviceToNetworkInputRatio(_numInputCallbackBytes);
 
-    unsigned int inputSamplesRequired = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * inputToNetworkInputRatio;
+    int inputSamplesRequired = (int)((float)NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * inputToNetworkInputRatio);
 
     QByteArray inputByteArray = _inputDevice->readAll();
     
@@ -1379,8 +1379,10 @@ bool Audio::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) {
     
     // cleanup any previously initialized device
     if (_audioInput) {
+        // The call to stop() causes _inputDevice to be destructed.
+        // That in turn causes it to be disconnected (see for example
+        // http://stackoverflow.com/questions/9264750/qt-signals-and-slots-object-disconnect).
         _audioInput->stop();
-        disconnect(_inputDevice);
         _inputDevice = NULL;
 
         delete _audioInput;
diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp
index 402347c5d4..dba5feca9e 100644
--- a/interface/src/Menu.cpp
+++ b/interface/src/Menu.cpp
@@ -91,6 +91,7 @@ Menu::Menu() :
     _jsConsole(NULL),
     _octreeStatsDialog(NULL),
     _lodToolsDialog(NULL),
+    _userLocationsDialog(NULL),
     _maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM),
     _voxelSizeScale(DEFAULT_OCTREE_SIZE_SCALE),
     _oculusUIAngularSize(DEFAULT_OCULUS_UI_ANGULAR_SIZE),
@@ -166,6 +167,11 @@ Menu::Menu() :
                                   Qt::CTRL | Qt::Key_N,
                                   this,
                                   SLOT(nameLocation()));
+    addActionToQMenuAndActionHash(fileMenu,
+                                  MenuOption::MyLocations,
+                                  Qt::CTRL | Qt::Key_K,
+                                  this,
+                                  SLOT(toggleLocationList()));
     addActionToQMenuAndActionHash(fileMenu,
                                   MenuOption::GoTo,
                                   Qt::Key_At,
@@ -1184,6 +1190,17 @@ void Menu::namedLocationCreated(LocationManager::NamedLocationCreateResponse res
     msgBox.exec();
 }
 
+void Menu::toggleLocationList() {
+    if (!_userLocationsDialog) {
+        _userLocationsDialog = new UserLocationsDialog(Application::getInstance()->getWindow());
+    }
+    if (_userLocationsDialog->isVisible()) {
+        _userLocationsDialog->hide();
+    } else {
+        _userLocationsDialog->show();
+    }
+}
+
 void Menu::nameLocation() {
     // check if user is logged in or show login dialog if not
 
diff --git a/interface/src/Menu.h b/interface/src/Menu.h
index a15d3712f1..06b5c5c9f4 100644
--- a/interface/src/Menu.h
+++ b/interface/src/Menu.h
@@ -29,6 +29,7 @@
 #include "ui/JSConsole.h"
 #include "ui/LoginDialog.h"
 #include "ui/ScriptEditorWindow.h"
+#include "ui/UserLocationsDialog.h"
 
 const float ADJUST_LOD_DOWN_FPS = 40.0;
 const float ADJUST_LOD_UP_FPS = 55.0;
@@ -199,6 +200,7 @@ private slots:
     void goToDomainDialog();
     void goToLocation();
     void nameLocation();
+    void toggleLocationList();
     void bandwidthDetailsClosed();
     void octreeStatsDetailsClosed();
     void lodToolsClosed();
@@ -265,6 +267,7 @@ private:
     QDialog* _jsConsole;
     OctreeStatsDialog* _octreeStatsDialog;
     LodToolsDialog* _lodToolsDialog;
+    UserLocationsDialog* _userLocationsDialog;
     int _maxVoxels;
     float _voxelSizeScale;
     float _oculusUIAngularSize;
@@ -395,6 +398,7 @@ namespace MenuOption {
     const QString MoveWithLean = "Move with Lean";
     const QString MuteAudio = "Mute Microphone";
     const QString MuteEnvironment = "Mute Environment";
+    const QString MyLocations = "My Locations...";
     const QString NameLocation = "Name this location";
     const QString NewVoxelCullingMode = "New Voxel Culling Mode";
     const QString OctreeStats = "Voxel and Particle Statistics";
diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp
index 81bca0fc5a..12a4b145cc 100644
--- a/interface/src/ModelUploader.cpp
+++ b/interface/src/ModelUploader.cpp
@@ -396,7 +396,7 @@ void ModelUploader::uploadFailed(QNetworkReply::NetworkError errorCode, const QS
 void ModelUploader::checkS3() {
     qDebug() << "Checking S3 for " << _url;
     QNetworkRequest request(_url);
-    QNetworkReply* reply = _networkAccessManager.head(request);
+    QNetworkReply* reply = NetworkAccessManager::getInstance().head(request);
     connect(reply, SIGNAL(finished()), SLOT(processCheck()));
 }
 
diff --git a/interface/src/ModelUploader.h b/interface/src/ModelUploader.h
index 634de05640..2596120751 100644
--- a/interface/src/ModelUploader.h
+++ b/interface/src/ModelUploader.h
@@ -58,7 +58,6 @@ private:
     bool _readyToSend;
     
     QHttpMultiPart* _dataMultiPart;
-    QNetworkAccessManager _networkAccessManager;
     
     int _numberOfChecks;
     QTimer _timer;
diff --git a/interface/src/ScriptsModel.cpp b/interface/src/ScriptsModel.cpp
index f9ed94f3fa..7b24587129 100644
--- a/interface/src/ScriptsModel.cpp
+++ b/interface/src/ScriptsModel.cpp
@@ -11,14 +11,15 @@
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
 //
 
-#include <QNetworkAccessManager>
 #include <QUrl>
 #include <QUrlQuery>
 #include <QXmlStreamReader>
 
-#include "ScriptsModel.h"
+#include <NetworkAccessManager.h>
+
 #include "Menu.h"
 
+#include "ScriptsModel.h"
 
 static const QString S3_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com";
 static const QString PUBLIC_URL = "http://public.highfidelity.io";
@@ -30,8 +31,6 @@ static const QString IS_TRUNCATED_NAME = "IsTruncated";
 static const QString CONTAINER_NAME = "Contents";
 static const QString KEY_NAME = "Key";
 
-static const int SCRIPT_PATH = Qt::UserRole;
-
 ScriptItem::ScriptItem(const QString& filename, const QString& fullPath) :
     _filename(filename),
     _fullPath(fullPath) {
@@ -113,14 +112,15 @@ void ScriptsModel::requestRemoteFiles(QString marker) {
     }
     url.setQuery(query);
 
-    QNetworkAccessManager* accessManager = new QNetworkAccessManager(this);
-    connect(accessManager, SIGNAL(finished(QNetworkReply*)), SLOT(downloadFinished(QNetworkReply*)));
-
+    NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
     QNetworkRequest request(url);
-    accessManager->get(request);
+    QNetworkReply* reply = networkAccessManager.get(request);
+    connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
+
 }
 
-void ScriptsModel::downloadFinished(QNetworkReply* reply) {
+void ScriptsModel::downloadFinished() {
+    QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
     bool finished = true;
 
     if (reply->error() == QNetworkReply::NoError) {
diff --git a/interface/src/ScriptsModel.h b/interface/src/ScriptsModel.h
index 250c7eb9a8..ca72a8d8f4 100644
--- a/interface/src/ScriptsModel.h
+++ b/interface/src/ScriptsModel.h
@@ -43,7 +43,7 @@ public:
 
 protected slots:
     void updateScriptsLocation(const QString& newPath);
-    void downloadFinished(QNetworkReply* reply);
+    void downloadFinished();
     void reloadLocalFiles();
     void reloadRemoteFiles();
 
diff --git a/interface/src/UserLocationsModel.cpp b/interface/src/UserLocationsModel.cpp
new file mode 100644
index 0000000000..e84cae8f95
--- /dev/null
+++ b/interface/src/UserLocationsModel.cpp
@@ -0,0 +1,246 @@
+//
+//  UserLocationsModel.cpp
+//  interface/src
+//
+//  Created by Ryan Huffman on 06/24/14.
+//  Copyright 2014 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 <QDebug>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QMessageBox>
+
+#include "AccountManager.h"
+#include "Application.h"
+#include "UserLocationsModel.h"
+
+static const QString PLACES_GET = "/api/v1/places";
+static const QString PLACES_UPDATE = "/api/v1/places/%1";
+static const QString PLACES_DELETE= "/api/v1/places/%1";
+
+UserLocation::UserLocation(QString id, QString name, QString location) :
+    _id(id),
+    _name(name),
+    _location(location),
+    _previousName(name),
+    _updating(false) {
+}
+
+void UserLocation::requestRename(const QString& newName) {
+    if (!_updating && newName.toLower() != _name) {
+        _updating = true;
+
+        JSONCallbackParameters callbackParams(this, "handleRenameResponse", this, "handleRenameError");
+        QJsonObject jsonNameObject;
+        jsonNameObject.insert("name", QJsonValue(newName));
+        QJsonDocument jsonDocument(jsonNameObject);
+        AccountManager::getInstance().authenticatedRequest(PLACES_UPDATE.arg(_id),
+                                                           QNetworkAccessManager::PutOperation,
+                                                           callbackParams,
+                                                           jsonDocument.toJson());
+        _previousName = _name;
+        _name = newName;
+
+        emit updated(_name);
+    }
+}
+
+void UserLocation::handleRenameResponse(const QJsonObject& responseData) {
+    _updating = false;
+
+    QJsonValue status = responseData["status"];
+    if (!status.isUndefined() && status.toString() == "success") {
+        QString updatedName = responseData["data"].toObject()["name"].toString();
+        _name = updatedName;
+    } else {
+        _name = _previousName;
+
+        QString msg = "There was an error renaming location '" + _name + "'";
+
+        QJsonValue data = responseData["data"];
+        if (!data.isUndefined()) {
+            QJsonValue nameError = data.toObject()["name"];
+            if (!nameError.isUndefined()) {
+                msg += ": " + nameError.toString();
+            }
+        }
+        qDebug() << msg;
+        QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
+    }
+
+    emit updated(_name);
+}
+
+void UserLocation::handleRenameError(QNetworkReply::NetworkError error, const QString& errorString) {
+    _updating = false;
+
+    QString msg = "There was an error renaming location '" + _name + "': " + errorString;
+    qDebug() << msg;
+    QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
+
+    emit updated(_name);
+}
+
+void UserLocation::requestDelete() {
+    if (!_updating) {
+        _updating = true;
+
+        JSONCallbackParameters callbackParams(this, "handleDeleteResponse", this, "handleDeleteError");
+        AccountManager::getInstance().authenticatedRequest(PLACES_DELETE.arg(_id),
+                                                           QNetworkAccessManager::DeleteOperation,
+                                                           callbackParams);
+    }
+}
+
+void UserLocation::handleDeleteResponse(const QJsonObject& responseData) {
+    _updating = false;
+
+    QJsonValue status = responseData["status"];
+    if (!status.isUndefined() && status.toString() == "success") {
+        emit deleted(_name);
+    } else {
+        QString msg = "There was an error deleting location '" + _name + "'";
+        qDebug() << msg;
+        QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
+    }
+}
+
+void UserLocation::handleDeleteError(QNetworkReply::NetworkError error, const QString& errorString) {
+    _updating = false;
+
+    QString msg = "There was an error deleting location '" + _name + "': " + errorString;
+    qDebug() << msg;
+    QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
+}
+
+UserLocationsModel::UserLocationsModel(QObject* parent) :
+    QAbstractListModel(parent),
+    _updating(false) {
+
+    refresh();
+}
+
+UserLocationsModel::~UserLocationsModel() {
+    qDeleteAll(_locations);
+    _locations.clear();
+}
+
+void UserLocationsModel::update() {
+    beginResetModel();
+    endResetModel();
+}
+
+void UserLocationsModel::deleteLocation(const QModelIndex& index) {
+    UserLocation* location = _locations[index.row()];
+    location->requestDelete();
+}
+
+void UserLocationsModel::renameLocation(const QModelIndex& index, const QString& newName) {
+    UserLocation* location = _locations[index.row()];
+    location->requestRename(newName);
+}
+
+void UserLocationsModel::refresh() {
+    if (!_updating) {
+        beginResetModel();
+        qDeleteAll(_locations);
+        _locations.clear();
+        _updating = true;
+        endResetModel();
+
+        JSONCallbackParameters callbackParams(this, "handleLocationsResponse");
+        AccountManager::getInstance().authenticatedRequest(PLACES_GET,
+                                                           QNetworkAccessManager::GetOperation,
+                                                           callbackParams);
+    }
+}
+
+void UserLocationsModel::handleLocationsResponse(const QJsonObject& responseData) {
+    _updating = false;
+
+    QJsonValue status = responseData["status"];
+    if (!status.isUndefined() && status.toString() == "success") {
+        beginResetModel();
+        QJsonArray locations = responseData["data"].toObject()["places"].toArray();
+        for (QJsonArray::const_iterator it = locations.constBegin(); it != locations.constEnd(); it++) {
+            QJsonObject location = (*it).toObject();
+            QJsonObject address = location["address"].toObject();
+            UserLocation* userLocation = new UserLocation(location["id"].toString(), location["name"].toString(),
+                              "hifi://" + address["domain"].toString()
+                              + "/" + address["position"].toString()
+                              + "/" + address["orientation"].toString());
+            _locations.append(userLocation);
+            connect(userLocation, &UserLocation::deleted, this, &UserLocationsModel::removeLocation);
+            connect(userLocation, &UserLocation::updated, this, &UserLocationsModel::update);
+        }
+        endResetModel();
+    } else {
+        qDebug() << "Error loading location data";
+    }
+}
+
+void UserLocationsModel::removeLocation(const QString& name) {
+    beginResetModel();
+    for (QList<UserLocation*>::iterator it = _locations.begin(); it != _locations.end(); it++) {
+        if ((*it)->name() == name) {
+            _locations.erase(it);
+            break;
+        }
+    }
+    endResetModel();
+}
+
+int UserLocationsModel::rowCount(const QModelIndex& parent) const {
+    if (parent.isValid()) {
+        return 0;
+    }
+
+    if (_updating) {
+        return 1;
+    }
+
+    return _locations.length();
+}
+
+QVariant UserLocationsModel::data(const QModelIndex& index, int role) const {
+    if (role == Qt::DisplayRole) {
+        if (_updating) {
+            return QVariant("Updating...");
+        } else if (index.row() > _locations.length()) {
+            return QVariant();
+        } else if (index.column() == NameColumn) {
+            return _locations[index.row()]->name();
+        } else if (index.column() == LocationColumn) {
+            return QVariant(_locations[index.row()]->location());
+        }
+    }
+
+    return QVariant();
+
+}
+QVariant UserLocationsModel::headerData(int section, Qt::Orientation orientation, int role) const {
+    if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+        switch (section) {
+            case NameColumn: return "Name";
+            case LocationColumn: return "Location";
+            default: return QVariant();
+        }
+    }
+
+    return QVariant();
+}
+
+Qt::ItemFlags UserLocationsModel::flags(const QModelIndex& index) const {
+    if (index.row() < _locations.length()) {
+        UserLocation* ul = _locations[index.row()];
+        if (ul->isUpdating()) {
+            return Qt::NoItemFlags;
+        }
+    }
+
+    return QAbstractListModel::flags(index);
+}
diff --git a/interface/src/UserLocationsModel.h b/interface/src/UserLocationsModel.h
new file mode 100644
index 0000000000..d3f86faa5a
--- /dev/null
+++ b/interface/src/UserLocationsModel.h
@@ -0,0 +1,82 @@
+//
+//  UserLocationsModel.h
+//  interface/src
+//
+//  Created by Ryan Huffman on 06/24/14.
+//  Copyright 2014 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#ifndef hifi_UserLocationsModel_h
+#define hifi_UserLocationsModel_h
+
+#include <QAbstractListModel>
+#include <QModelIndex>
+#include <QVariant>
+
+
+class UserLocation : public QObject {
+    Q_OBJECT
+public:
+    UserLocation(QString id, QString name, QString location);
+    bool isUpdating() { return _updating; }
+    void requestRename(const QString& newName);
+    void requestDelete();
+
+    QString id() { return _id; }
+    QString name() { return _name; }
+    QString location() { return _location; }
+
+public slots:
+    void handleRenameResponse(const QJsonObject& responseData);
+    void handleRenameError(QNetworkReply::NetworkError error, const QString& errorString);
+    void handleDeleteResponse(const QJsonObject& responseData);
+    void handleDeleteError(QNetworkReply::NetworkError error, const QString& errorString);
+
+signals:
+    void updated(const QString& name);
+    void deleted(const QString& name);
+
+private:
+    QString _id;
+    QString _name;
+    QString _location;
+    QString _previousName;
+    bool _updating;
+
+};
+
+class UserLocationsModel : public QAbstractListModel {
+    Q_OBJECT
+public:
+    UserLocationsModel(QObject* parent = NULL);
+    ~UserLocationsModel();
+    
+    virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
+    virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
+    virtual int columnCount(const QModelIndex& parent = QModelIndex()) const { return 2; };
+    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+    virtual Qt::ItemFlags flags(const QModelIndex& index) const;
+
+    void deleteLocation(const QModelIndex& index);
+    void renameLocation(const QModelIndex& index, const QString& newName);
+
+    enum Columns {
+        NameColumn = 0,
+        LocationColumn
+    };
+
+public slots:
+    void refresh();
+    void update();
+    void handleLocationsResponse(const QJsonObject& responseData);
+    void removeLocation(const QString& name);
+
+private:
+    bool _updating;
+    QList<UserLocation*> _locations;
+};
+
+#endif // hifi_UserLocationsModel_h
diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp
index c3f31ff6e7..59e5b08cc0 100644
--- a/interface/src/avatar/FaceModel.cpp
+++ b/interface/src/avatar/FaceModel.cpp
@@ -51,10 +51,10 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX
     glm::mat3 axes = glm::mat3_cast(glm::quat());
     glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) *
         joint.preTransform * glm::mat4_cast(joint.preRotation)));
-    state._rotationInParentFrame = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2])) 
+    state.setRotationInParentFrame(glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2])) 
         * glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1])) 
         * glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalPitch(), glm::normalize(inverse * axes[0])) 
-        * joint.rotation;
+        * joint.rotation);
 }
 
 void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
@@ -68,8 +68,8 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ
         _owningHead->getSaccade() - _translation, 1.0f));
     glm::quat between = rotationBetween(front, lookAt);
     const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
-    state._rotationInParentFrame = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
-        joint.rotation;
+    state.setRotationInParentFrame(glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
+        joint.rotation);
 }
 
 void FaceModel::updateJointState(int index) {
diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp
index 3b09a1a2ba..2f35b96181 100644
--- a/interface/src/avatar/SkeletonModel.cpp
+++ b/interface/src/avatar/SkeletonModel.cpp
@@ -219,10 +219,9 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
         JointState& parentState = _jointStates[parentJointIndex];
         parentState.setRotationFromBindFrame(palmRotation, PALM_PRIORITY);
         // lock hand to forearm by slamming its rotation (in parent-frame) to identity
-        _jointStates[jointIndex]._rotationInParentFrame = glm::quat();
+        _jointStates[jointIndex].setRotationInParentFrame(glm::quat());
     } else {
-        setJointPosition(jointIndex, palmPosition, palmRotation, 
-                true, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY);
+        inverseKinematics(jointIndex, palmPosition, palmRotation, PALM_PRIORITY);
     }
 }
 
@@ -258,9 +257,9 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const
     glm::mat3 axes = glm::mat3_cast(glm::quat());
     glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) *
         joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)));
-    state._rotationInParentFrame = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), 
+    state.setRotationInParentFrame(glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), 
         glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(), 
-        glm::normalize(inverse * axes[0])) * joint.rotation;
+        glm::normalize(inverse * axes[0])) * joint.rotation);
 }
 
 void SkeletonModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
@@ -537,6 +536,11 @@ void SkeletonModel::buildRagdollConstraints() {
     }
 }
 
+void SkeletonModel::updateVisibleJointStates() {
+    Model::updateVisibleJointStates();
+    // TODO: implement this to move visible joints to agree with joint shape positions
+}
+
 // virtual 
 void SkeletonModel::stepRagdollForward(float deltaTime) {
     const float RAGDOLL_FOLLOWS_JOINTS_TIMESCALE = 0.03f;
@@ -644,7 +648,6 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
             _ragdollPoints[i]._lastPosition = _ragdollPoints[i]._position;
             continue;
         }
-        assert(parentIndex != -1);
         
         glm::quat modifiedRotation = joint.preRotation * joint.rotation * joint.postRotation;    
         transforms[i] = transforms[parentIndex] * glm::translate(joint.translation) 
@@ -700,7 +703,7 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
     _boundingRadius = 0.5f * glm::length(diagonal);
 }
 
-void SkeletonModel::resetShapePositions() {
+void SkeletonModel::resetShapePositionsToDefaultPose() {
     // DEBUG method.
     // Moves shapes to the joint default locations for debug visibility into
     // how the bounding shape is computed.
diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h
index b91c112b6a..76d0d45efa 100644
--- a/interface/src/avatar/SkeletonModel.h
+++ b/interface/src/avatar/SkeletonModel.h
@@ -93,6 +93,8 @@ public:
     /// Retrieve the positions of up to two eye meshes.
     /// \return whether or not both eye meshes were found
     bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
+
+    virtual void updateVisibleJointStates();
     
     // virtual overrride from Ragdoll
     virtual void stepRagdollForward(float deltaTime);
@@ -104,7 +106,7 @@ public:
     float getBoundingShapeRadius() const { return _boundingShape.getRadius(); }
     const CapsuleShape& getBoundingShape() const { return _boundingShape; }
 
-    void resetShapePositions(); // DEBUG method
+    void resetShapePositionsToDefaultPose(); // DEBUG method
 
     void renderRagdoll();
 protected:
diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp
index dbe444bf9b..199c313119 100644
--- a/interface/src/devices/OculusManager.cpp
+++ b/interface/src/devices/OculusManager.cpp
@@ -266,7 +266,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
 
     ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay();
 
-    // We only need to render the overlays to a texture once, then we just render the texture as a quad
+    // We only need to render the overlays to a texture once, then we just render the texture on the hemisphere
     // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() 
     applicationOverlay.renderOverlay(true);
     const bool displayOverlays = Menu::getInstance()->isOptionChecked(MenuOption::DisplayOculusOverlays);
diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp
index b5cc28b07f..25d3ff892a 100644
--- a/interface/src/devices/TV3DManager.cpp
+++ b/interface/src/devices/TV3DManager.cpp
@@ -93,6 +93,18 @@ void TV3DManager::display(Camera& whichCamera) {
     int portalW = Application::getInstance()->getGLWidget()->width() / 2;
     int portalH = Application::getInstance()->getGLWidget()->height();
 
+    const bool glowEnabled = Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect);
+
+    ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay();
+
+    // We only need to render the overlays to a texture once, then we just render the texture as a quad
+    // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() 
+    applicationOverlay.renderOverlay(true);
+
+    if (glowEnabled) {
+        Application::getInstance()->getGlowEffect()->prepare();
+    }
+
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
     glEnable(GL_SCISSOR_TEST);
@@ -102,13 +114,21 @@ void TV3DManager::display(Camera& whichCamera) {
 
     glPushMatrix();
     {
+        
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity(); // reset projection matrix
         glFrustum(_leftEye.left, _leftEye.right, _leftEye.bottom, _leftEye.top, nearZ, farZ); // set left view frustum
+        GLfloat p[4][4];
+        glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0]));
+        GLfloat cotangent = p[1][1];
+        GLfloat fov = atan(1.0f / cotangent);
         glTranslatef(_leftEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
+
         glMatrixMode(GL_MODELVIEW);
         glLoadIdentity();
         Application::getInstance()->displaySide(whichCamera);
+
+        applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
     }
     glPopMatrix();
     glDisable(GL_SCISSOR_TEST);
@@ -124,14 +144,25 @@ void TV3DManager::display(Camera& whichCamera) {
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity(); // reset projection matrix
         glFrustum(_rightEye.left, _rightEye.right, _rightEye.bottom, _rightEye.top, nearZ, farZ); // set left view frustum
+        GLfloat p[4][4];
+        glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0]));
+        GLfloat cotangent = p[1][1];
+        GLfloat fov = atan(1.0f / cotangent);
         glTranslatef(_rightEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
+
         glMatrixMode(GL_MODELVIEW);
         glLoadIdentity();
         Application::getInstance()->displaySide(whichCamera);
+
+        applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
     }
     glPopMatrix();
     glDisable(GL_SCISSOR_TEST);
 
     // reset the viewport to how we started
     glViewport(0, 0, Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height());
+
+    if (glowEnabled) {
+        Application::getInstance()->getGlowEffect()->render();
+    }
 }
diff --git a/interface/src/renderer/JointState.cpp b/interface/src/renderer/JointState.cpp
index e66a2f44e9..8e4aecdf51 100644
--- a/interface/src/renderer/JointState.cpp
+++ b/interface/src/renderer/JointState.cpp
@@ -11,14 +11,26 @@
 
 #include <glm/gtx/norm.hpp>
 
-//#include <GeometryUtil.h>
 #include <SharedUtil.h>
 
 #include "JointState.h"
 
 JointState::JointState() :
     _animationPriority(0.0f),
-    _fbxJoint(NULL) {
+    _fbxJoint(NULL),
+    _isConstrained(false) {
+}
+
+void JointState::copyState(const JointState& state) {
+    _animationPriority = state._animationPriority;
+    _transform = state._transform;
+    _rotation = extractRotation(_transform);
+    _rotationInParentFrame = state._rotationInParentFrame;
+
+    _visibleTransform = state._visibleTransform;
+    _visibleRotation = extractRotation(_visibleTransform);
+    _visibleRotationInParentFrame = state._visibleRotationInParentFrame;
+    // DO NOT copy _fbxJoint
 }
 
 void JointState::setFBXJoint(const FBXJoint* joint) {
@@ -26,14 +38,10 @@ void JointState::setFBXJoint(const FBXJoint* joint) {
     _rotationInParentFrame = joint->rotation;
     // NOTE: JointState does not own the FBXJoint to which it points.
     _fbxJoint = joint;
-}
-
-void JointState::copyState(const JointState& state) {
-    _rotationInParentFrame = state._rotationInParentFrame;
-    _transform = state._transform;
-    _rotation = extractRotation(_transform);
-    _animationPriority = state._animationPriority;
-    // DO NOT copy _fbxJoint
+    // precompute whether there are any constraints or not
+    float distanceMin = glm::distance(_fbxJoint->rotationMin, glm::vec3(-PI));
+    float distanceMax = glm::distance(_fbxJoint->rotationMax, glm::vec3(PI));
+    _isConstrained = distanceMin > EPSILON || distanceMax > EPSILON;
 }
 
 void JointState::computeTransform(const glm::mat4& parentTransform) {
@@ -43,6 +51,13 @@ void JointState::computeTransform(const glm::mat4& parentTransform) {
     _rotation = extractRotation(_transform);
 }
 
+void JointState::computeVisibleTransform(const glm::mat4& parentTransform) {
+    glm::quat modifiedRotation = _fbxJoint->preRotation * _visibleRotationInParentFrame * _fbxJoint->postRotation;
+    glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform;
+    _visibleTransform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform;
+    _visibleRotation = extractRotation(_visibleTransform);
+}
+
 glm::quat JointState::getRotationFromBindToModelFrame() const {
     return _rotation * _fbxJoint->inverseBindRotation;
 }
@@ -50,16 +65,16 @@ glm::quat JointState::getRotationFromBindToModelFrame() const {
 void JointState::restoreRotation(float fraction, float priority) {
     assert(_fbxJoint != NULL);
     if (priority == _animationPriority || _animationPriority == 0.0f) {
-        _rotationInParentFrame = safeMix(_rotationInParentFrame, _fbxJoint->rotation, fraction);
+        setRotationInParentFrame(safeMix(_rotationInParentFrame, _fbxJoint->rotation, fraction));
         _animationPriority = 0.0f;
     }
 }
 
 void JointState::setRotationFromBindFrame(const glm::quat& rotation, float priority) {
+    // rotation is from bind- to model-frame
     assert(_fbxJoint != NULL);
     if (priority >= _animationPriority) {
-        // rotation is from bind- to model-frame
-        _rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation);
+        setRotationInParentFrame(_rotationInParentFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation));
         _animationPriority = priority;
     }
 }
@@ -68,6 +83,9 @@ void JointState::clearTransformTranslation() {
     _transform[3][0] = 0.0f;
     _transform[3][1] = 0.0f;
     _transform[3][2] = 0.0f;
+    _visibleTransform[3][0] = 0.0f;
+    _visibleTransform[3][1] = 0.0f;
+    _visibleTransform[3][2] = 0.0f;
 }
 
 void JointState::setRotation(const glm::quat& rotation, bool constrain, float priority) {
@@ -75,27 +93,59 @@ void JointState::setRotation(const glm::quat& rotation, bool constrain, float pr
 }
 
 void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) {
-    // NOTE: delta is in jointParent-frame
+    // NOTE: delta is in model-frame
     assert(_fbxJoint != NULL);
     if (priority < _animationPriority) {
         return;
     }
     _animationPriority = priority;
-    if (!constrain || (_fbxJoint->rotationMin == glm::vec3(-PI, -PI, -PI) &&
-            _fbxJoint->rotationMax == glm::vec3(PI, PI, PI))) {
+    if (!constrain || !_isConstrained) {
         // no constraints
         _rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation;
         _rotation = delta * _rotation;
         return;
     }
-    glm::quat targetRotation = delta * _rotation;
-    glm::vec3 eulers = safeEulerAngles(_rotationInParentFrame * glm::inverse(_rotation) * targetRotation);
-    glm::quat newRotation = glm::quat(glm::clamp(eulers, _fbxJoint->rotationMin, _fbxJoint->rotationMax));
-    _rotation = _rotation * glm::inverse(_rotationInParentFrame) * newRotation;
-    _rotationInParentFrame = newRotation;
+    glm::quat targetRotation = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation;
+    setRotationInParentFrame(targetRotation);
+}
+
+/// Applies delta rotation to joint but mixes a little bit of the default pose as well.
+/// This helps keep an IK solution stable.
+void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float priority) {
+    // NOTE: delta is in model-frame
+    assert(_fbxJoint != NULL);
+    if (priority < _animationPriority) {
+        return;
+    }
+    _animationPriority = priority;
+    glm::quat targetRotation = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation;
+    if (mixFactor > 0.0f && mixFactor <= 1.0f) {
+        targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor);
+    }
+    setRotationInParentFrame(targetRotation);
+}
+
+
+glm::quat JointState::computeParentRotation() const {
+    // R = Rp * Rpre * r * Rpost
+    // Rp = R * (Rpre * r * Rpost)^
+    return _rotation * glm::inverse(_fbxJoint->preRotation * _rotationInParentFrame * _fbxJoint->postRotation);
+}
+
+void JointState::setRotationInParentFrame(const glm::quat& targetRotation) {
+    glm::quat parentRotation = computeParentRotation();
+    _rotationInParentFrame = targetRotation;
+    // R' = Rp * Rpre * r' * Rpost
+    _rotation = parentRotation * _fbxJoint->preRotation * _rotationInParentFrame * _fbxJoint->postRotation;
 }
 
 const glm::vec3& JointState::getDefaultTranslationInParentFrame() const {
     assert(_fbxJoint != NULL);
     return _fbxJoint->translation;
 }
+
+void JointState::slaveVisibleTransform() {
+    _visibleTransform = _transform;
+    _visibleRotation = _rotation;
+    _visibleRotationInParentFrame = _rotationInParentFrame;
+}
diff --git a/interface/src/renderer/JointState.h b/interface/src/renderer/JointState.h
index b1a584d4ec..8412cfd0cb 100644
--- a/interface/src/renderer/JointState.h
+++ b/interface/src/renderer/JointState.h
@@ -22,12 +22,19 @@ class JointState {
 public:
     JointState();
 
+    void copyState(const JointState& state);
+
     void setFBXJoint(const FBXJoint* joint); 
     const FBXJoint& getFBXJoint() const { return *_fbxJoint; }
 
-    void copyState(const JointState& state);
 
     void computeTransform(const glm::mat4& parentTransform);
+
+    void computeVisibleTransform(const glm::mat4& parentTransform);
+    const glm::mat4& getVisibleTransform() const { return _visibleTransform; }
+    glm::quat getVisibleRotation() const { return _visibleRotation; }
+    glm::vec3 getVisiblePosition() const { return extractTranslation(_visibleTransform); }
+
     const glm::mat4& getTransform() const { return _transform; }
 
     glm::quat getRotation() const { return _rotation; }
@@ -39,11 +46,19 @@ public:
     /// \param rotation rotation of joint in model-frame
     void setRotation(const glm::quat& rotation, bool constrain, float priority);
 
-    /// \param delta is in the jointParent-frame
+    /// \param delta is in the model-frame
     void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f);
 
-    const glm::vec3& getDefaultTranslationInParentFrame() const;
+    /// Applies delta rotation to joint but mixes a little bit of the default pose as well.
+    /// This helps keep an IK solution stable.
+    /// \param delta rotation change in model-frame
+    /// \param mixFactor fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all)
+    /// \param priority priority level of this animation blend
+    void mixRotationDelta(const glm::quat& delta, float mixFactor, float priority = 1.0f);
 
+    /// Blends a fraciton of default pose into joint rotation.
+    /// \param fraction fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all)
+    /// \param priority priority level of this animation blend
     void restoreRotation(float fraction, float priority);
 
     /// \param rotation is from bind- to model-frame
@@ -51,16 +66,36 @@ public:
     /// NOTE: the JointState's model-frame transform/rotation are NOT updated!
     void setRotationFromBindFrame(const glm::quat& rotation, float priority);
 
+    void setRotationInParentFrame(const glm::quat& targetRotation);
+    const glm::quat& getRotationInParentFrame() const { return _rotationInParentFrame; }
+
+    const glm::vec3& getDefaultTranslationInParentFrame() const;
+
+
     void clearTransformTranslation();
 
-    glm::quat _rotationInParentFrame; // joint- to parentJoint-frame
+    void slaveVisibleTransform();
+
     float _animationPriority; // the priority of the animation affecting this joint
 
 private:
+    /// \return parent model-frame rotation 
+    // (used to keep _rotation consistent when modifying _rotationInWorldFrame directly)
+    glm::quat computeParentRotation() const;
+
+    /// debug helper function
+    void loadBindRotation();
+
     glm::mat4 _transform; // joint- to model-frame
     glm::quat _rotation;  // joint- to model-frame
+    glm::quat _rotationInParentFrame; // joint- to parentJoint-frame
+
+    glm::mat4 _visibleTransform;
+    glm::quat _visibleRotation;
+    glm::quat _visibleRotationInParentFrame;
 
     const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint
+    bool _isConstrained;
 };
 
 #endif // hifi_JointState_h
diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp
index 3b5cda4fd2..ffca2c8ea6 100644
--- a/interface/src/renderer/Model.cpp
+++ b/interface/src/renderer/Model.cpp
@@ -39,8 +39,8 @@ Model::Model(QObject* parent) :
     _scaledToFit(false),
     _snapModelToCenter(false),
     _snappedToCenter(false),
+    _showTrueJointTransforms(false),
     _rootIndex(-1),
-    //_enableCollisionShapes(false),
     _lodDistance(0.0f),
     _pupilDilation(0.0f),
     _url("http://invalid.com") {
@@ -460,7 +460,7 @@ void Model::reset() {
     }
     const FBXGeometry& geometry = _geometry->getFBXGeometry();
     for (int i = 0; i < _jointStates.size(); i++) {
-        _jointStates[i]._rotationInParentFrame = geometry.joints.at(i).rotation;
+        _jointStates[i].setRotationInParentFrame(geometry.joints.at(i).rotation);
     }
 }
 
@@ -571,6 +571,9 @@ void Model::setJointStates(QVector<JointState> states) {
             radius = distance;
         }
     }
+    for (int i = 0; i < _jointStates.size(); i++) {
+        _jointStates[i].slaveVisibleTransform();
+    }
     _boundingRadius = radius;
 }
 
@@ -686,7 +689,7 @@ bool Model::getJointState(int index, glm::quat& rotation) const {
     if (index == -1 || index >= _jointStates.size()) {
         return false;
     }
-    rotation = _jointStates.at(index)._rotationInParentFrame;
+    rotation = _jointStates.at(index).getRotationInParentFrame();
     const glm::quat& defaultRotation = _geometry->getFBXGeometry().joints.at(index).rotation;
     return glm::abs(rotation.x - defaultRotation.x) >= EPSILON ||
         glm::abs(rotation.y - defaultRotation.y) >= EPSILON ||
@@ -699,7 +702,7 @@ void Model::setJointState(int index, bool valid, const glm::quat& rotation, floa
         JointState& state = _jointStates[index];
         if (priority >= state._animationPriority) {
             if (valid) {
-                state._rotationInParentFrame = rotation;
+                state.setRotationInParentFrame(rotation);
                 state._animationPriority = priority;
             } else {
                 state.restoreRotation(1.0f, priority);
@@ -765,6 +768,23 @@ bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const
     return true;
 }
 
+bool Model::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const {
+    if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
+        return false;
+    }
+    // position is in world-frame
+    position = _translation + _rotation * _jointStates[jointIndex].getVisiblePosition();
+    return true;
+}
+
+bool Model::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const {
+    if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
+        return false;
+    }
+    rotation = _rotation * _jointStates[jointIndex].getVisibleRotation();
+    return true;
+}
+
 QStringList Model::getJointNames() const {
     if (QThread::currentThread() != thread()) {
         QStringList result;
@@ -918,6 +938,8 @@ void Model::simulateInternal(float deltaTime) {
     for (int i = 0; i < _jointStates.size(); i++) {
         updateJointState(i);
     }
+    updateVisibleJointStates();
+
     _shapesAreDirty = ! _shapes.isEmpty();
     
     // update the attachment transforms and simulate them
@@ -928,8 +950,13 @@ void Model::simulateInternal(float deltaTime) {
         
         glm::vec3 jointTranslation = _translation;
         glm::quat jointRotation = _rotation;
-        getJointPositionInWorldFrame(attachment.jointIndex, jointTranslation);
-        getJointRotationInWorldFrame(attachment.jointIndex, jointRotation);
+        if (_showTrueJointTransforms) {
+            getJointPositionInWorldFrame(attachment.jointIndex, jointTranslation);
+            getJointRotationInWorldFrame(attachment.jointIndex, jointRotation);
+        } else {
+            getVisibleJointPositionInWorldFrame(attachment.jointIndex, jointTranslation);
+            getVisibleJointRotationInWorldFrame(attachment.jointIndex, jointRotation);
+        }
         
         model->setTranslation(jointTranslation + jointRotation * attachment.translation * _scale);
         model->setRotation(jointRotation * attachment.rotation);
@@ -944,9 +971,16 @@ void Model::simulateInternal(float deltaTime) {
     for (int i = 0; i < _meshStates.size(); i++) {
         MeshState& state = _meshStates[i];
         const FBXMesh& mesh = geometry.meshes.at(i);
-        for (int j = 0; j < mesh.clusters.size(); j++) {
-            const FBXCluster& cluster = mesh.clusters.at(j);
-            state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix;
+        if (_showTrueJointTransforms) {
+            for (int j = 0; j < mesh.clusters.size(); j++) {
+                const FBXCluster& cluster = mesh.clusters.at(j);
+                state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix;
+            }
+        } else {
+            for (int j = 0; j < mesh.clusters.size(); j++) {
+                const FBXCluster& cluster = mesh.clusters.at(j);
+                state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getVisibleTransform() * cluster.inverseBindMatrix;
+            }
         }
     }
     
@@ -972,6 +1006,14 @@ void Model::updateJointState(int index) {
     }
 }
 
+void Model::updateVisibleJointStates() {
+    if (!_showTrueJointTransforms) {
+        for (int i = 0; i < _jointStates.size(); i++) {
+            _jointStates[i].slaveVisibleTransform();
+        }
+    }
+}
+
 bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation,
        int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) {
     if (jointIndex == -1 || _jointStates.isEmpty()) {
@@ -1058,6 +1100,128 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const gl
     return true;
 }
 
+void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority) {
+    // NOTE: targetRotation is from bind- to model-frame
+
+    if (endIndex == -1 || _jointStates.isEmpty()) {
+        return;
+    }
+
+    const FBXGeometry& geometry = _geometry->getFBXGeometry();
+    const QVector<int>& freeLineage = geometry.joints.at(endIndex).freeLineage;
+    if (freeLineage.isEmpty()) {
+        return;
+    }
+    int numFree = freeLineage.size();
+
+    // store and remember topmost parent transform
+    glm::mat4 topParentTransform;
+    {
+        int index = freeLineage.last();
+        const JointState& state = _jointStates.at(index);
+        const FBXJoint& joint = state.getFBXJoint();
+        int parentIndex = joint.parentIndex;
+        if (parentIndex == -1) {
+            const FBXGeometry& geometry = _geometry->getFBXGeometry();
+            topParentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
+        } else {
+            topParentTransform = _jointStates[parentIndex].getTransform();
+        }
+    }
+
+    // this is a cyclic coordinate descent algorithm: see
+    // http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d
+
+    // keep track of the position of the end-effector
+    JointState& endState = _jointStates[endIndex];
+    glm::vec3 endPosition = endState.getPosition();
+    float distanceToGo = glm::distance(targetPosition, endPosition);
+
+    const int MAX_ITERATION_COUNT = 2;
+    const float ACCEPTABLE_IK_ERROR = 0.005f; // 5mm
+    int numIterations = 0;
+    do {
+        ++numIterations;
+        // moving up, rotate each free joint to get endPosition closer to target
+        for (int j = 1; j < numFree; j++) {
+            int nextIndex = freeLineage.at(j);
+            JointState& nextState = _jointStates[nextIndex];
+            FBXJoint nextJoint = nextState.getFBXJoint();
+            if (! nextJoint.isFree) {
+                continue;
+            }
+
+            glm::vec3 pivot = nextState.getPosition();
+            glm::vec3 leverArm = endPosition - pivot;
+            float leverLength = glm::length(leverArm);
+            if (leverLength < EPSILON) {
+                continue;
+            }
+            glm::quat deltaRotation = rotationBetween(leverArm, targetPosition - pivot);
+
+            /* DON'T REMOVE! This code provides the gravitational effect on the IK solution.
+            * It is commented out for the moment because we're blending the IK solution with 
+            * the default pose which provides similar stability, but we might want to use
+            * gravity again later.
+            
+            // We want to mix the shortest rotation with one that will pull the system down with gravity.
+            // So we compute a simplified center of mass, where each joint has a mass of 1.0 and we don't 
+            // bother averaging it because we only need direction.
+            if (j > 1) {
+
+                glm::vec3 centerOfMass(0.0f);
+                for (int k = 0; k < j; ++k) {
+                    int massIndex = freeLineage.at(k);
+                    centerOfMass += _jointStates[massIndex].getPosition() - pivot;
+                }
+                // the gravitational effect is a rotation that tends to align the two cross products
+                const glm::vec3 worldAlignment = glm::vec3(0.0f, -1.f, 0.0f);
+                glm::quat gravityDelta = rotationBetween(glm::cross(centerOfMass, leverArm),
+                    glm::cross(worldAlignment, leverArm));
+
+                float gravityAngle = glm::angle(gravityDelta);
+                const float MIN_GRAVITY_ANGLE = 0.1f;
+                float mixFactor = 0.5f;
+                if (gravityAngle < MIN_GRAVITY_ANGLE) {
+                    // the final rotation is a mix of the two
+                    mixFactor = 0.5f * gravityAngle / MIN_GRAVITY_ANGLE;
+                }
+                deltaRotation = safeMix(deltaRotation, gravityDelta, mixFactor);
+            }
+            */
+
+            // Apply the rotation, but use mixRotationDelta() which blends a bit of the default pose
+            // at in the process.  This provides stability to the IK solution and removes the necessity
+            // for the gravity effect.
+            glm::quat oldNextRotation = nextState.getRotation();
+            float mixFactor = 0.03f;
+            nextState.mixRotationDelta(deltaRotation, mixFactor, priority);
+
+            // measure the result of the rotation which may have been modified by
+            // blending and constraints
+            glm::quat actualDelta = nextState.getRotation() * glm::inverse(oldNextRotation);
+            endPosition = pivot + actualDelta * leverArm;
+        }
+
+        // recompute transforms from the top down
+        glm::mat4 parentTransform = topParentTransform;
+        for (int j = numFree - 1; j >= 0; --j) {
+            JointState& freeState = _jointStates[freeLineage.at(j)];
+            freeState.computeTransform(parentTransform);
+            parentTransform = freeState.getTransform();
+        }
+
+        // measure our success
+        endPosition = endState.getPosition();
+        distanceToGo = glm::distance(targetPosition, endPosition);
+    } while (numIterations < MAX_ITERATION_COUNT && distanceToGo < ACCEPTABLE_IK_ERROR);
+
+    // set final rotation of the end joint
+    endState.setRotationFromBindFrame(targetRotation, priority);
+     
+    _shapesAreDirty = !_shapes.isEmpty();
+}
+
 bool Model::restoreJointPosition(int jointIndex, float fraction, float priority) {
     if (jointIndex == -1 || _jointStates.isEmpty()) {
         return false;
@@ -1605,7 +1769,7 @@ void AnimationHandle::applyFrame(float frameIndex) {
         if (mapping != -1) {
             JointState& state = _model->_jointStates[mapping];
             if (_priority >= state._animationPriority) {
-                state._rotationInParentFrame = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
+                state.setRotationInParentFrame(safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction));
                 state._animationPriority = _priority;
             }
         }
diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h
index 2045a0c9b5..835207b7eb 100644
--- a/interface/src/renderer/Model.h
+++ b/interface/src/renderer/Model.h
@@ -120,6 +120,9 @@ public:
     bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const;
     bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const;
 
+    bool getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const;
+    bool getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const;
+
     /// \param jointIndex index of joint in model structure
     /// \param position[out] position of joint in model-frame
     /// \return true if joint exists
@@ -152,6 +155,7 @@ protected:
 
     bool _snapModelToCenter; /// is the model's offset automatically adjusted to center around 0,0,0 in model space
     bool _snappedToCenter; /// are we currently snapped to center
+    bool _showTrueJointTransforms;
     int _rootIndex;
     
     QVector<JointState> _jointStates;
@@ -176,6 +180,8 @@ protected:
 
     /// Updates the state of the joint at the specified index.
     virtual void updateJointState(int index);
+
+    virtual void updateVisibleJointStates();
     
     /// \param jointIndex index of joint in model structure
     /// \param position position of joint in model-frame
@@ -188,6 +194,8 @@ protected:
     bool setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation = glm::quat(),
         bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false,
         const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f);
+
+    void inverseKinematics(int jointIndex, glm::vec3 position, const glm::quat& rotation, float priority);
     
     /// Restores the indexed joint to its default position.
     /// \param fraction the fraction of the default position to apply (i.e., 0.25f to slerp one fourth of the way to
diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp
index 55a67ce854..01c3dc1cc1 100644
--- a/interface/src/renderer/TextureCache.cpp
+++ b/interface/src/renderer/TextureCache.cpp
@@ -85,6 +85,33 @@ void TextureCache::setFrameBufferSize(QSize frameBufferSize) {
     }
 }
 
+// use fixed table of permutations. Could also make ordered list programmatically
+// and then shuffle algorithm. For testing, this ensures consistent behavior in each run.
+// this list taken from Ken Perlin's Improved Noise reference implementation (orig. in Java) at
+// http://mrl.nyu.edu/~perlin/noise/
+
+const int permutation[256] = 
+{
+    151, 160, 137,  91,  90,  15, 131,  13, 201,  95,  96,  53, 194, 233,   7, 225,
+    140,  36, 103,  30,  69, 142,   8,  99,  37, 240,  21,  10,  23, 190,   6, 148,
+    247, 120, 234,  75,   0,  26, 197,  62,  94, 252, 219, 203, 117,  35,  11,  32,
+     57, 177,  33,  88, 237, 149,  56,  87, 174,  20, 125, 136, 171, 168,  68, 175,
+     74, 165,  71, 134, 139,  48,  27, 166,  77, 146, 158, 231,  83, 111, 229, 122,
+     60, 211, 133, 230, 220, 105,  92,  41,  55,  46, 245,  40, 244, 102, 143,  54,
+     65,  25,  63, 161,   1, 216,  80,  73, 209,  76, 132, 187, 208,  89,  18, 169,
+     200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186,   3,  64,
+     52, 217, 226, 250, 124, 123,   5, 202,  38, 147, 118, 126, 255,  82,  85, 212,
+    207, 206,  59, 227,  47,  16,  58,  17, 182, 189,  28,  42, 223, 183, 170, 213,
+    119, 248, 152,   2,  44, 154, 163,  70, 221, 153, 101, 155, 167,  43, 172,   9,
+    129,  22,  39, 253,  19,  98, 108, 110,  79, 113, 224, 232, 178, 185, 112, 104,
+    218, 246,  97, 228, 251,  34, 242, 193, 238, 210, 144,  12, 191, 179, 162, 241,
+     81,  51, 145, 235, 249,  14, 239, 107,  49, 192, 214,  31, 181, 199, 106, 157,
+    184,  84, 204, 176, 115, 121,  50,  45, 127,   4, 150, 254, 138, 236, 205,  93,
+    222, 114,  67,  29,  24,  72, 243, 141, 128, 195,  78,  66, 215,  61, 156, 180
+};
+
+#define USE_CHRIS_NOISE 1
+
 GLuint TextureCache::getPermutationNormalTextureID() {
     if (_permutationNormalTextureID == 0) {
         glGenTextures(1, &_permutationNormalTextureID);
@@ -92,10 +119,17 @@ GLuint TextureCache::getPermutationNormalTextureID() {
         
         // the first line consists of random permutation offsets
         unsigned char data[256 * 2 * 3];
+#if (USE_CHRIS_NOISE==1)
+        for (int i = 0; i < 256; i++) {
+            data[3*i+0] = permutation[i];
+            data[3*i+1] = permutation[i];
+            data[3*i+2] = permutation[i];
+#else
         for (int i = 0; i < 256 * 3; i++) {
             data[i] = rand() % 256;
+#endif
         }
-        // the next, random unit normals
+
         for (int i = 256 * 3; i < 256 * 3 * 2; i += 3) {
             glm::vec3 randvec = glm::sphericalRand(1.0f);
             data[i] = ((randvec.x + 1.0f) / 2.0f) * 255.0f;
@@ -105,7 +139,6 @@ GLuint TextureCache::getPermutationNormalTextureID() {
         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        
         glBindTexture(GL_TEXTURE_2D, 0);
     }
     return _permutationNormalTextureID;
diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp
index 77e8986297..4c445958ec 100644
--- a/interface/src/ui/ApplicationOverlay.cpp
+++ b/interface/src/ui/ApplicationOverlay.cpp
@@ -41,8 +41,7 @@ ApplicationOverlay::ApplicationOverlay() :
     _textureFov(DEFAULT_OCULUS_UI_ANGULAR_SIZE * RADIANS_PER_DEGREE),
     _alpha(1.0f),
     _active(true),
-    _crosshairTexture(0)
-{
+    _crosshairTexture(0) {
 
     memset(_reticleActive, 0, sizeof(_reticleActive));
     memset(_magActive, 0, sizeof(_reticleActive));
@@ -206,7 +205,7 @@ void ApplicationOverlay::getClickLocation(int &x, int &y) const {
     }
 }
 
-// Draws the FBO texture for Oculus rift. TODO: Draw a curved texture instead of plane.
+// Draws the FBO texture for Oculus rift.
 void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
 
     if (_alpha == 0.0f) {
@@ -293,6 +292,107 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
 
 }
 
+// Draws the FBO texture for 3DTV.
+void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov) {
+
+    if (_alpha == 0.0f) {
+        return;
+    }
+
+    Application* application = Application::getInstance();
+
+    MyAvatar* myAvatar = application->getAvatar();
+    const glm::vec3& viewMatrixTranslation = application->getViewMatrixTranslation();
+
+    glActiveTexture(GL_TEXTURE0);
+
+    glEnable(GL_BLEND);
+    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
+    glBindTexture(GL_TEXTURE_2D, getFramebufferObject()->texture());
+    glEnable(GL_DEPTH_TEST);
+    glDisable(GL_LIGHTING);
+    glEnable(GL_TEXTURE_2D);
+
+    glMatrixMode(GL_MODELVIEW);
+
+    glPushMatrix();
+    glLoadIdentity();
+    // Transform to world space
+    glm::quat rotation = whichCamera.getRotation();
+    glm::vec3 axis2 = glm::axis(rotation);
+    glRotatef(-glm::degrees(glm::angle(rotation)), axis2.x, axis2.y, axis2.z);
+    glTranslatef(viewMatrixTranslation.x, viewMatrixTranslation.y, viewMatrixTranslation.z);
+
+    // Translate to the front of the camera
+    glm::vec3 pos = whichCamera.getPosition();
+    glm::quat rot = myAvatar->getOrientation();
+    glm::vec3 axis = glm::axis(rot);
+
+    glTranslatef(pos.x, pos.y, pos.z);
+    glRotatef(glm::degrees(glm::angle(rot)), axis.x, axis.y, axis.z);
+
+    glColor4f(1.0f, 1.0f, 1.0f, _alpha);
+
+    //Render
+ //   fov -= RADIANS_PER_DEGREE * 2.5f; //reduce by 5 degrees so it fits in the view
+    const GLfloat distance = 1.0f;
+
+    const GLfloat halfQuadHeight = distance * tan(fov);
+    const GLfloat halfQuadWidth = halfQuadHeight * aspectRatio;
+    const GLfloat quadWidth = halfQuadWidth * 2.0f;
+    const GLfloat quadHeight = halfQuadHeight * 2.0f;
+
+    GLfloat x = -halfQuadWidth;
+    GLfloat y = -halfQuadHeight;
+    glDisable(GL_DEPTH_TEST);
+
+    glBegin(GL_QUADS);
+
+    glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + quadHeight, -distance);
+    glTexCoord2f(1.0f, 1.0f); glVertex3f(x + quadWidth, y + quadHeight, -distance);
+    glTexCoord2f(1.0f, 0.0f); glVertex3f(x + quadWidth, y, -distance);
+    glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, -distance);
+
+    glEnd();
+
+    if (_crosshairTexture == 0) {
+        _crosshairTexture = Application::getInstance()->getGLWidget()->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png"));
+    }
+
+    //draw the mouse pointer
+    glBindTexture(GL_TEXTURE_2D, _crosshairTexture);
+
+    const float reticleSize = 40.0f / application->getGLWidget()->width() * quadWidth;
+    x -= reticleSize / 2.0f;
+    y += reticleSize / 2.0f;
+    const float mouseX = (application->getMouseX() / (float)application->getGLWidget()->width()) * quadWidth;
+    const float mouseY = (1.0 - (application->getMouseY() / (float)application->getGLWidget()->height())) * quadHeight;
+
+    glBegin(GL_QUADS);
+
+    glColor3f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2]);
+
+    glTexCoord2d(0.0f, 0.0f); glVertex3f(x + mouseX, y + mouseY, -distance);
+    glTexCoord2d(1.0f, 0.0f); glVertex3f(x + mouseX + reticleSize, y + mouseY, -distance);
+    glTexCoord2d(1.0f, 1.0f); glVertex3f(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance);
+    glTexCoord2d(0.0f, 1.0f); glVertex3f(x + mouseX, y + mouseY - reticleSize, -distance);
+
+    glEnd();
+
+    glEnable(GL_DEPTH_TEST);
+
+    glPopMatrix();
+
+    glDepthMask(GL_TRUE);
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glDisable(GL_TEXTURE_2D);
+
+    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
+    glEnable(GL_LIGHTING);
+
+    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+}
+
 //Renders optional pointers
 void ApplicationOverlay::renderPointers() {
     Application* application = Application::getInstance();
diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h
index b9f9596ccf..7c1f87d575 100644
--- a/interface/src/ui/ApplicationOverlay.h
+++ b/interface/src/ui/ApplicationOverlay.h
@@ -29,6 +29,7 @@ public:
     void renderOverlay(bool renderToTexture = false);
     void displayOverlayTexture();
     void displayOverlayTextureOculus(Camera& whichCamera);
+    void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov);
     void computeOculusPickRay(float x, float y, glm::vec3& direction) const;
     void getClickLocation(int &x, int &y) const;
 
diff --git a/interface/src/ui/ModelsBrowser.cpp b/interface/src/ui/ModelsBrowser.cpp
index 203c54d97a..ec583a14f7 100644
--- a/interface/src/ui/ModelsBrowser.cpp
+++ b/interface/src/ui/ModelsBrowser.cpp
@@ -14,10 +14,11 @@
 #include <QGridLayout>
 #include <QHeaderView>
 #include <QMessageBox>
-#include <QNetworkAccessManager>
 #include <QUrl>
 #include <QXmlStreamReader>
 
+#include <NetworkAccessManager.h>
+
 #include "Application.h"
 
 #include "ModelsBrowser.h"
@@ -210,10 +211,10 @@ void ModelHandler::update() {
     }
     for (int i = 0; i < _model.rowCount(); ++i) {
         QUrl url(_model.item(i,0)->data(Qt::UserRole).toString());
-        QNetworkAccessManager* accessManager = new QNetworkAccessManager(this);
+        NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
         QNetworkRequest request(url);
-        accessManager->head(request);
-        connect(accessManager, SIGNAL(finished(QNetworkReply*)), SLOT(downloadFinished(QNetworkReply*)));
+        QNetworkReply* reply = networkAccessManager.head(request);
+        connect(reply, SIGNAL(finished()), SLOT(processCheck()));
     }
     _lock.unlock();
 }
@@ -233,7 +234,8 @@ void ModelHandler::exit() {
     _lock.unlock();
 }
 
-void ModelHandler::downloadFinished(QNetworkReply* reply) {
+void ModelHandler::downloadFinished() {
+    QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
     QByteArray data = reply->readAll();
     
     if (!data.isEmpty()) {
@@ -261,10 +263,10 @@ void ModelHandler::queryNewFiles(QString marker) {
     
     // Download
     url.setQuery(query);
-    QNetworkAccessManager* accessManager = new QNetworkAccessManager(this);
+    NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
     QNetworkRequest request(url);
-    accessManager->get(request);
-    connect(accessManager, SIGNAL(finished(QNetworkReply*)), SLOT(downloadFinished(QNetworkReply*)));
+    QNetworkReply* reply = networkAccessManager.get(request);
+    connect(reply, SIGNAL(finished()), SLOT(processCheck()));
             
 }
 
diff --git a/interface/src/ui/ModelsBrowser.h b/interface/src/ui/ModelsBrowser.h
index 3e832c9dbe..8063fd8eeb 100644
--- a/interface/src/ui/ModelsBrowser.h
+++ b/interface/src/ui/ModelsBrowser.h
@@ -43,7 +43,7 @@ public slots:
     void exit();
     
 private slots:
-    void downloadFinished(QNetworkReply* reply);
+    void downloadFinished();
     
 private:
     bool _initiateExit;
diff --git a/interface/src/ui/ScriptEditorWidget.cpp b/interface/src/ui/ScriptEditorWidget.cpp
index 513bbd899a..d25408e568 100644
--- a/interface/src/ui/ScriptEditorWidget.cpp
+++ b/interface/src/ui/ScriptEditorWidget.cpp
@@ -148,8 +148,8 @@ void ScriptEditorWidget::loadFile(const QString& scriptPath) {
             disconnect(_scriptEngine, &ScriptEngine::finished, this, &ScriptEditorWidget::onScriptFinished);
         }
     } else {
-        QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
-        QNetworkReply* reply = networkManager->get(QNetworkRequest(url));
+        NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+        QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
         qDebug() << "Downloading included script at" << scriptPath;
         QEventLoop loop;
         QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
diff --git a/interface/src/ui/SnapshotShareDialog.cpp b/interface/src/ui/SnapshotShareDialog.cpp
index 617d5e7101..046aa4d12c 100644
--- a/interface/src/ui/SnapshotShareDialog.cpp
+++ b/interface/src/ui/SnapshotShareDialog.cpp
@@ -40,8 +40,7 @@ Q_DECLARE_METATYPE(QNetworkAccessManager::Operation)
 
 SnapshotShareDialog::SnapshotShareDialog(QString fileName, QWidget* parent) :
     QDialog(parent),
-    _fileName(fileName),
-    _networkAccessManager(NULL)
+    _fileName(fileName)
 {
 
     setAttribute(Qt::WA_DeleteOnClose);
@@ -92,10 +91,6 @@ void SnapshotShareDialog::uploadSnapshot() {
         return;
     }
 
-    if (!_networkAccessManager) {
-        _networkAccessManager = new QNetworkAccessManager(this);
-    }
-
     QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
 
     QHttpPart apiKeyPart;
@@ -118,9 +113,7 @@ void SnapshotShareDialog::uploadSnapshot() {
     QUrl url(FORUM_UPLOADS_URL);
     QNetworkRequest request(url);
 
-    QNetworkReply* reply = _networkAccessManager->post(request, multiPart);
-
-
+    QNetworkReply* reply = NetworkAccessManager::getInstance().post(request, multiPart);
     connect(reply, &QNetworkReply::finished, this, &SnapshotShareDialog::uploadRequestFinished);
 
     QEventLoop loop;
@@ -129,11 +122,6 @@ void SnapshotShareDialog::uploadSnapshot() {
 }
 
 void SnapshotShareDialog::sendForumPost(QString snapshotPath) {
-
-    if (!_networkAccessManager) {
-        _networkAccessManager = new QNetworkAccessManager(this);
-    }
-
     // post to Discourse forum
     QNetworkRequest request;
     QUrl forumUrl(FORUM_POST_URL);
@@ -148,7 +136,7 @@ void SnapshotShareDialog::sendForumPost(QString snapshotPath) {
     request.setUrl(forumUrl);
     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
 
-    QNetworkReply* requestReply = _networkAccessManager->post(request, postData);
+    QNetworkReply* requestReply = NetworkAccessManager::getInstance().post(request, postData);
     connect(requestReply, &QNetworkReply::finished, this, &SnapshotShareDialog::postRequestFinished);
 
     QEventLoop loop;
diff --git a/interface/src/ui/SnapshotShareDialog.h b/interface/src/ui/SnapshotShareDialog.h
index a8795d578a..ced9f2d951 100644
--- a/interface/src/ui/SnapshotShareDialog.h
+++ b/interface/src/ui/SnapshotShareDialog.h
@@ -14,7 +14,6 @@
 
 #include "ui_shareSnapshot.h"
 
-#include <QNetworkAccessManager>
 #include <QNetworkReply>
 #include <QUrl>
 
@@ -26,7 +25,6 @@ public:
 
 private:
     QString _fileName;
-    QNetworkAccessManager* _networkAccessManager;
     Ui_SnapshotShareDialog _ui;
 
     void uploadSnapshot();
diff --git a/interface/src/ui/UserLocationsDialog.cpp b/interface/src/ui/UserLocationsDialog.cpp
new file mode 100644
index 0000000000..f72e66ce77
--- /dev/null
+++ b/interface/src/ui/UserLocationsDialog.cpp
@@ -0,0 +1,77 @@
+//
+//  UserLocationsDialog.cpp
+//  interface/src/ui
+//
+//  Created by Ryan Huffman on 06/24/14.
+//  Copyright 2014 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 <QDebug>
+#include <QInputDialog>
+#include <QPushButton>
+
+#include "Menu.h"
+#include "UserLocationsDialog.h"
+
+UserLocationsDialog::UserLocationsDialog(QWidget* parent) :
+    QDialog(parent),
+    _ui(),
+    _proxyModel(this),
+    _userLocationsModel(this) {
+
+    _ui.setupUi(this);
+
+    _proxyModel.setSourceModel(&_userLocationsModel);
+    _proxyModel.setDynamicSortFilter(true);
+
+    _ui.locationsTreeView->setModel(&_proxyModel);
+    _ui.locationsTreeView->setSortingEnabled(true);
+    _ui.locationsTreeView->sortByColumn(UserLocationsModel::NameColumn, Qt::AscendingOrder);
+
+    connect(_ui.locationsTreeView->selectionModel(), &QItemSelectionModel::selectionChanged,
+            this, &UserLocationsDialog::updateEnabled);
+    connect(&_userLocationsModel, &UserLocationsModel::modelReset, this, &UserLocationsDialog::updateEnabled);
+    connect(&_userLocationsModel, &UserLocationsModel::modelReset, &_proxyModel, &QSortFilterProxyModel::invalidate);
+    connect(_ui.locationsTreeView, &QTreeView::doubleClicked, this, &UserLocationsDialog::goToModelIndex);
+
+    connect(_ui.deleteButton, &QPushButton::clicked, this, &UserLocationsDialog::deleteSelection);
+    connect(_ui.renameButton, &QPushButton::clicked, this, &UserLocationsDialog::renameSelection);
+    connect(_ui.refreshButton, &QPushButton::clicked, &_userLocationsModel, &UserLocationsModel::refresh);
+
+    this->setWindowTitle("My Locations");
+}
+
+void UserLocationsDialog::updateEnabled() {
+    bool enabled = _ui.locationsTreeView->selectionModel()->hasSelection();
+    _ui.renameButton->setEnabled(enabled);
+    _ui.deleteButton->setEnabled(enabled);
+}
+
+void UserLocationsDialog::goToModelIndex(const QModelIndex& index) {
+    QVariant location = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::LocationColumn));
+    Menu::getInstance()->goToURL(location.toString());
+}
+
+void UserLocationsDialog::deleteSelection() {
+    QModelIndex selection = _ui.locationsTreeView->selectionModel()->currentIndex();
+    selection = _proxyModel.mapToSource(selection);
+    if (selection.isValid()) {
+        _userLocationsModel.deleteLocation(selection);
+    }
+}
+
+void UserLocationsDialog::renameSelection() {
+    QModelIndex selection = _ui.locationsTreeView->selectionModel()->currentIndex();
+    selection = _proxyModel.mapToSource(selection);
+    if (selection.isValid()) {
+        bool ok;
+        QString name = _userLocationsModel.data(selection.sibling(selection.row(), UserLocationsModel::NameColumn)).toString();
+        QString newName = QInputDialog::getText(this, "Rename '" + name + "'", "Set name to:", QLineEdit::Normal, name, &ok);
+        if (ok && !newName.isEmpty()) {
+            _userLocationsModel.renameLocation(selection, newName);
+        }
+    }
+}
diff --git a/interface/src/ui/UserLocationsDialog.h b/interface/src/ui/UserLocationsDialog.h
new file mode 100644
index 0000000000..0e596ece87
--- /dev/null
+++ b/interface/src/ui/UserLocationsDialog.h
@@ -0,0 +1,35 @@
+//
+//  UserLocationsDialog.h
+//  interface/src/ui
+//
+//  Created by Ryan Huffman on 06/24/14.
+//  Copyright 2014 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#ifndef hifi_UserLocationsDialog_h
+#define hifi_UserLocationsDialog_h
+
+#include "ui_userLocationsDialog.h"
+#include "UserLocationsModel.h"
+
+class UserLocationsDialog : public QDialog {
+    Q_OBJECT
+public:
+    UserLocationsDialog(QWidget* parent = NULL);
+
+protected slots:
+    void updateEnabled();
+    void goToModelIndex(const QModelIndex& index);
+    void deleteSelection();
+    void renameSelection();
+
+private:
+    Ui::UserLocationsDialog _ui;
+    QSortFilterProxyModel _proxyModel;
+    UserLocationsModel _userLocationsModel;
+};
+
+#endif // hifi_UserLocationsDialog_h
diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp
index 40de565155..8742f19c3d 100644
--- a/interface/src/ui/overlays/BillboardOverlay.cpp
+++ b/interface/src/ui/overlays/BillboardOverlay.cpp
@@ -14,8 +14,7 @@
 #include "BillboardOverlay.h"
 
 BillboardOverlay::BillboardOverlay()
-: _manager(NULL),
-  _scale(1.0f),
+: _scale(1.0f),
   _isFacingAvatar(true) {
 }
 
@@ -119,18 +118,13 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) {
     }
 }
 
-// TODO: handle setting image multiple times, how do we manage releasing the bound texture?
 void BillboardOverlay::setBillboardURL(const QUrl url) {
-    // TODO: are we creating too many QNetworkAccessManager() when multiple calls to setImageURL are made?
-    _manager->deleteLater();
-    _manager = new QNetworkAccessManager();
-    connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
-    _manager->get(QNetworkRequest(url));
+    QNetworkReply* reply = NetworkAccessManager::getInstance().get(QNetworkRequest(url));
+    connect(reply, &QNetworkReply::finished, this, &BillboardOverlay::replyFinished);
 }
 
-void BillboardOverlay::replyFinished(QNetworkReply* reply) {
+void BillboardOverlay::replyFinished() {
     // replace our byte array with the downloaded data
+    QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
     _billboard = reply->readAll();
-    _manager->deleteLater();
-    _manager = NULL;
 }
diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h
index 473e8a066f..0037d1a4f7 100644
--- a/interface/src/ui/overlays/BillboardOverlay.h
+++ b/interface/src/ui/overlays/BillboardOverlay.h
@@ -27,12 +27,11 @@ public:
     virtual void setProperties(const QScriptValue& properties);
 
 private slots:
-    void replyFinished(QNetworkReply* reply);
+    void replyFinished();
 
 private:
     void setBillboardURL(const QUrl url);
     
-    QNetworkAccessManager* _manager;
     QUrl _url;
     QByteArray _billboard;
     QSize _size;
diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp
index 79b1b23de5..aeea781eb6 100644
--- a/interface/src/ui/overlays/ImageOverlay.cpp
+++ b/interface/src/ui/overlays/ImageOverlay.cpp
@@ -19,7 +19,6 @@
 #include "ImageOverlay.h"
 
 ImageOverlay::ImageOverlay() :
-    _manager(NULL),
     _textureID(0),
     _renderImage(false),
     _textureBound(false),
@@ -36,21 +35,18 @@ ImageOverlay::~ImageOverlay() {
 
 // TODO: handle setting image multiple times, how do we manage releasing the bound texture?
 void ImageOverlay::setImageURL(const QUrl& url) {
-    // TODO: are we creating too many QNetworkAccessManager() when multiple calls to setImageURL are made?
-    _manager->deleteLater();
-    _manager = new QNetworkAccessManager();
-    connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
-    _manager->get(QNetworkRequest(url));
+    NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+    QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
+    connect(reply, &QNetworkReply::finished, this, &ImageOverlay::replyFinished);
 }
 
-void ImageOverlay::replyFinished(QNetworkReply* reply) {
-
+void ImageOverlay::replyFinished() {
+    QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
+    
     // replace our byte array with the downloaded data
     QByteArray rawData = reply->readAll();
     _textureImage.loadFromData(rawData);
     _renderImage = true;
-    _manager->deleteLater();
-    _manager = NULL;
 }
 
 void ImageOverlay::render() {
diff --git a/interface/src/ui/overlays/ImageOverlay.h b/interface/src/ui/overlays/ImageOverlay.h
index 613cd95989..633567287d 100644
--- a/interface/src/ui/overlays/ImageOverlay.h
+++ b/interface/src/ui/overlays/ImageOverlay.h
@@ -16,13 +16,13 @@
 
 #include <QGLWidget>
 #include <QImage>
-#include <QNetworkAccessManager>
 #include <QNetworkReply>
 #include <QRect>
 #include <QScriptValue>
 #include <QString>
 #include <QUrl>
 
+#include <NetworkAccessManager.h>
 #include <SharedUtil.h>
 
 #include "Overlay.h"
@@ -46,13 +46,12 @@ public:
     virtual void setProperties(const QScriptValue& properties);
 
 private slots:
-    void replyFinished(QNetworkReply* reply); // we actually want to hide this...
+    void replyFinished(); // we actually want to hide this...
 
 private:
 
     QUrl _imageURL;
     QImage _textureImage;
-    QNetworkAccessManager* _manager;
 
     GLuint _textureID;
     QRect _fromImage; // where from in the image to sample
diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp
index dd483da27a..581947c074 100644
--- a/interface/src/ui/overlays/Overlays.cpp
+++ b/interface/src/ui/overlays/Overlays.cpp
@@ -84,13 +84,13 @@ void Overlays::render3D() {
         return;
     }
     bool myAvatarComputed = false;
-    MyAvatar* avatar;
+    MyAvatar* avatar = NULL;
     glm::quat myAvatarRotation;
-    glm::vec3 myAvatarPosition;
-    float angle;
-    glm::vec3 axis;
-    float myAvatarScale;
-    
+    glm::vec3 myAvatarPosition(0.0f);
+    float angle = 0.0f;
+    glm::vec3 axis(0.0f, 1.0f, 0.0f);
+    float myAvatarScale = 1.0f;
+
     foreach(Overlay* thisOverlay, _overlays3D) {
         glPushMatrix();
         switch (thisOverlay->getAnchor()) {
diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h
index 78a037762e..c2aafb24e8 100644
--- a/interface/src/ui/overlays/TextOverlay.h
+++ b/interface/src/ui/overlays/TextOverlay.h
@@ -16,7 +16,6 @@
 
 #include <QGLWidget>
 #include <QImage>
-#include <QNetworkAccessManager>
 #include <QNetworkReply>
 #include <QRect>
 #include <QScriptValue>
diff --git a/interface/ui/userLocationsDialog.ui b/interface/ui/userLocationsDialog.ui
new file mode 100644
index 0000000000..609ce1c8ab
--- /dev/null
+++ b/interface/ui/userLocationsDialog.ui
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UserLocationsDialog</class>
+ <widget class="QWidget" name="UserLocationsDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>929</width>
+    <height>633</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="spacing">
+    <number>-1</number>
+   </property>
+   <property name="leftMargin">
+    <number>12</number>
+   </property>
+   <property name="topMargin">
+    <number>12</number>
+   </property>
+   <property name="rightMargin">
+    <number>12</number>
+   </property>
+   <property name="bottomMargin">
+    <number>12</number>
+   </property>
+   <item>
+    <widget class="QWidget" name="widget_2" native="true">
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLabel" name="label">
+        <property name="styleSheet">
+         <string notr="true">font-size: 16px</string>
+        </property>
+        <property name="text">
+         <string>My Locations</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="refreshButton">
+        <property name="text">
+         <string>Refresh</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QTreeView" name="locationsTreeView">
+     <property name="indentation">
+      <number>0</number>
+     </property>
+     <property name="rootIsDecorated">
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QWidget" name="widget" native="true">
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <property name="spacing">
+       <number>-1</number>
+      </property>
+      <property name="leftMargin">
+       <number>12</number>
+      </property>
+      <property name="topMargin">
+       <number>12</number>
+      </property>
+      <property name="rightMargin">
+       <number>12</number>
+      </property>
+      <property name="bottomMargin">
+       <number>12</number>
+      </property>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="renameButton">
+        <property name="text">
+         <string>Rename</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="deleteButton">
+        <property name="text">
+         <string>Delete</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/libraries/audio/CMakeLists.txt b/libraries/audio/CMakeLists.txt
index 60636ba051..fafdfc7e6c 100644
--- a/libraries/audio/CMakeLists.txt
+++ b/libraries/audio/CMakeLists.txt
@@ -12,6 +12,9 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cm
 
 set(TARGET_NAME audio)
 
+find_package(Qt5 COMPONENTS Script)
+include_directories(SYSTEM "${Qt5Script_INCLUDE_DIRS}")
+
 # set up the external glm library
 include(${MACRO_DIR}/SetupHifiLibrary.cmake)
 setup_hifi_library(${TARGET_NAME})
@@ -26,4 +29,4 @@ link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
 # add a definition for ssize_t so that windows doesn't bail
 if (WIN32)
   add_definitions(-Dssize_t=long)
-endif ()
\ No newline at end of file
+endif ()
diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp
index 6ae3b19541..7937a925a8 100644
--- a/libraries/audio/src/AudioRingBuffer.cpp
+++ b/libraries/audio/src/AudioRingBuffer.cpp
@@ -53,7 +53,7 @@ void AudioRingBuffer::reset() {
     _isStarved = true;
 }
 
-void AudioRingBuffer::resizeForFrameSize(qint64 numFrameSamples) {
+void AudioRingBuffer::resizeForFrameSize(int numFrameSamples) {
     delete[] _buffer;
     _sampleCapacity = numFrameSamples * RING_BUFFER_LENGTH_FRAMES;
     _buffer = new int16_t[_sampleCapacity];
@@ -70,14 +70,14 @@ int AudioRingBuffer::parseData(const QByteArray& packet) {
     return writeData(packet.data() + numBytesBeforeAudioData, packet.size() - numBytesBeforeAudioData);
 }
 
-qint64 AudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) {
+int AudioRingBuffer::readSamples(int16_t* destination, int maxSamples) {
     return readData((char*) destination, maxSamples * sizeof(int16_t));
 }
 
-qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) {
+int AudioRingBuffer::readData(char *data, int maxSize) {
 
     // only copy up to the number of samples we have available
-    int numReadSamples = std::min((unsigned) (maxSize / sizeof(int16_t)), samplesAvailable());
+    int numReadSamples = std::min((int) (maxSize / sizeof(int16_t)), samplesAvailable());
 
     // If we're in random access mode, then we consider our number of available read samples slightly
     // differently. Namely, if anything has been written, we say we have as many samples as they ask for
@@ -118,14 +118,14 @@ qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) {
     return numReadSamples * sizeof(int16_t);
 }
 
-qint64 AudioRingBuffer::writeSamples(const int16_t* source, qint64 maxSamples) {    
+int AudioRingBuffer::writeSamples(const int16_t* source, int maxSamples) {    
     return writeData((const char*) source, maxSamples * sizeof(int16_t));
 }
 
-qint64 AudioRingBuffer::writeData(const char* data, qint64 maxSize) {
+int AudioRingBuffer::writeData(const char* data, int maxSize) {
     // make sure we have enough bytes left for this to be the right amount of audio
     // otherwise we should not copy that data, and leave the buffer pointers where they are
-    int samplesToCopy = std::min((quint64)(maxSize / sizeof(int16_t)), (quint64)_sampleCapacity);
+    int samplesToCopy = std::min((int)(maxSize / sizeof(int16_t)), _sampleCapacity);
     
     int samplesRoomFor = _sampleCapacity - samplesAvailable();
     if (samplesToCopy > samplesRoomFor) {
@@ -167,7 +167,7 @@ void AudioRingBuffer::shiftReadPosition(unsigned int numSamples) {
     }
 }
 
-unsigned int AudioRingBuffer::samplesAvailable() const {
+int AudioRingBuffer::samplesAvailable() const {
     if (!_endOfLastWrite) {
         return 0;
     }
@@ -208,7 +208,7 @@ int AudioRingBuffer::addSilentFrame(int numSilentSamples) {
     return numSilentSamples * sizeof(int16_t);
 }
 
-bool AudioRingBuffer::isNotStarvedOrHasMinimumSamples(unsigned int numRequiredSamples) const {
+bool AudioRingBuffer::isNotStarvedOrHasMinimumSamples(int numRequiredSamples) const {
     if (!_isStarved) {
         return true;
     } else {
diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h
index 8d19f9c0bb..80a2abeba4 100644
--- a/libraries/audio/src/AudioRingBuffer.h
+++ b/libraries/audio/src/AudioRingBuffer.h
@@ -43,7 +43,7 @@ public:
     ~AudioRingBuffer();
 
     void reset();
-    void resizeForFrameSize(qint64 numFrameSamples);
+    void resizeForFrameSize(int numFrameSamples);
     
     int getSampleCapacity() const { return _sampleCapacity; }
     
@@ -53,20 +53,20 @@ public:
     const int16_t* getNextOutput() const { return _nextOutput; }
     const int16_t* getBuffer() const { return _buffer; }
 
-    qint64 readSamples(int16_t* destination, qint64 maxSamples);
-    qint64 writeSamples(const int16_t* source, qint64 maxSamples);
+    int readSamples(int16_t* destination, int maxSamples);
+    int writeSamples(const int16_t* source, int maxSamples);
     
-    qint64 readData(char* data, qint64 maxSize);
-    qint64 writeData(const char* data, qint64 maxSize);
+    int readData(char* data, int maxSize);
+    int writeData(const char* data, int maxSize);
     
     int16_t& operator[](const int index);
     const int16_t& operator[] (const int index) const;
     
     void shiftReadPosition(unsigned int numSamples);
     
-    unsigned int samplesAvailable() const;
+    int samplesAvailable() const;
     
-    bool isNotStarvedOrHasMinimumSamples(unsigned int numRequiredSamples) const;
+    bool isNotStarvedOrHasMinimumSamples(int numRequiredSamples) const;
     
     bool isStarved() const { return _isStarved; }
     void setIsStarved(bool isStarved) { _isStarved = isStarved; }
diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp
index 546ed97fe2..e11d73358c 100644
--- a/libraries/audio/src/PositionalAudioRingBuffer.cpp
+++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp
@@ -212,7 +212,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
         }
 
         return  false;
-    } else if (samplesAvailable() < (unsigned int)samplesPerFrame) { 
+    } else if (samplesAvailable() < samplesPerFrame) { 
         // if the buffer doesn't have a full frame of samples to take for mixing, it is starved
         _isStarved = true;
         
diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp
index 7ef3afdf29..03c9f6b8ee 100644
--- a/libraries/audio/src/Sound.cpp
+++ b/libraries/audio/src/Sound.cpp
@@ -15,12 +15,12 @@
 
 #include <QDataStream>
 #include <QtCore/QDebug>
-#include <QtNetwork/QNetworkAccessManager>
 #include <QtNetwork/QNetworkRequest>
 #include <QtNetwork/QNetworkReply>
 #include <qendian.h>
 
 #include <LimitedNodeList.h>
+#include <NetworkAccessManager.h>
 #include <SharedUtil.h>
 
 #include "AudioRingBuffer.h"
@@ -73,11 +73,11 @@ Sound::Sound(const QUrl& sampleURL, QObject* parent) :
     // assume we have a QApplication or QCoreApplication instance and use the
     // QNetworkAccess manager to grab the raw audio file at the given URL
 
-    QNetworkAccessManager *manager = new QNetworkAccessManager(this);
+    NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
 
     qDebug() << "Requesting audio file" << sampleURL.toDisplayString();
     
-    QNetworkReply* soundDownload = manager->get(QNetworkRequest(sampleURL));
+    QNetworkReply* soundDownload = networkAccessManager.get(QNetworkRequest(sampleURL));
     connect(soundDownload, &QNetworkReply::finished, this, &Sound::replyFinished);
     connect(soundDownload, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyError(QNetworkReply::NetworkError)));
 }
diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp
index 94066d9a1c..3f3e71c5e8 100644
--- a/libraries/avatars/src/AvatarData.cpp
+++ b/libraries/avatars/src/AvatarData.cpp
@@ -16,10 +16,10 @@
 #include <QtCore/QDataStream>
 #include <QtCore/QThread>
 #include <QtCore/QUuid>
-#include <QtNetwork/QNetworkAccessManager>
 #include <QtNetwork/QNetworkReply>
 #include <QtNetwork/QNetworkRequest>
 
+#include <NetworkAccessManager.h>
 #include <NodeList.h>
 #include <PacketHeaders.h>
 #include <SharedUtil.h>
@@ -33,8 +33,6 @@ quint64 DEFAULT_FILTERED_LOG_EXPIRY = 2 * USECS_PER_SECOND;
 
 using namespace std;
 
-QNetworkAccessManager* AvatarData::networkAccessManager = NULL;
-
 AvatarData::AvatarData() :
     _sessionUUID(),
     _handPosition(0,0,0),
@@ -751,18 +749,15 @@ void AvatarData::setBillboard(const QByteArray& billboard) {
 void AvatarData::setBillboardFromURL(const QString &billboardURL) {
     _billboardURL = billboardURL;
     
-    if (AvatarData::networkAccessManager) {
-        qDebug() << "Changing billboard for avatar to PNG at" << qPrintable(billboardURL);
-        
-        QNetworkRequest billboardRequest;
-        billboardRequest.setUrl(QUrl(billboardURL));
-        
-        QNetworkReply* networkReply = AvatarData::networkAccessManager->get(billboardRequest);
-        connect(networkReply, SIGNAL(finished()), this, SLOT(setBillboardFromNetworkReply()));
-        
-    } else {
-        qDebug() << "Billboard PNG download requested but no network access manager is available.";
-    }
+    
+    qDebug() << "Changing billboard for avatar to PNG at" << qPrintable(billboardURL);
+    
+    QNetworkRequest billboardRequest;
+    billboardRequest.setUrl(QUrl(billboardURL));
+    
+    NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+    QNetworkReply* networkReply = networkAccessManager.get(billboardRequest);
+    connect(networkReply, SIGNAL(finished()), this, SLOT(setBillboardFromNetworkReply()));
 }
 
 void AvatarData::setBillboardFromNetworkReply() {
@@ -839,8 +834,9 @@ void AvatarData::updateJointMappings() {
     _jointIndices.clear();
     _jointNames.clear();
     
-    if (networkAccessManager && _skeletonModelURL.fileName().toLower().endsWith(".fst")) {
-        QNetworkReply* networkReply = networkAccessManager->get(QNetworkRequest(_skeletonModelURL));
+    if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) {
+        NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+        QNetworkReply* networkReply = networkAccessManager.get(QNetworkRequest(_skeletonModelURL));
         connect(networkReply, SIGNAL(finished()), this, SLOT(setJointMappingsFromNetworkReply()));
     }
 }
diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h
index 4c7136fd0a..1b8f6e6007 100755
--- a/libraries/avatars/src/AvatarData.h
+++ b/libraries/avatars/src/AvatarData.h
@@ -102,7 +102,6 @@ enum KeyState {
 const glm::vec3 vec3Zero(0.0f);
 
 class QDataStream;
-class QNetworkAccessManager;
 
 class AttachmentData;
 class JointData;
@@ -269,8 +268,6 @@ public:
     QElapsedTimer& getLastUpdateTimer() { return _lastUpdateTimer; }
      
     virtual float getBoundingRadius() const { return 1.f; }
-    
-    static void setNetworkAccessManager(QNetworkAccessManager* sharedAccessManager) { networkAccessManager = sharedAccessManager; }
 
 public slots:
     void sendIdentityPacket();
@@ -323,8 +320,6 @@ protected:
     
     QHash<QString, int> _jointIndices; ///< 1-based, since zero is returned for missing keys
     QStringList _jointNames; ///< in order of depth-first traversal
-    
-    static QNetworkAccessManager* networkAccessManager;
 
     quint64 _errorLogExpiry; ///< time in future when to log an error
     
diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp
index 918261a953..563d735790 100644
--- a/libraries/networking/src/AccountManager.cpp
+++ b/libraries/networking/src/AccountManager.cpp
@@ -37,19 +37,20 @@ Q_DECLARE_METATYPE(JSONCallbackParameters)
 
 const QString ACCOUNTS_GROUP = "accounts";
 
-JSONCallbackParameters::JSONCallbackParameters() :
-    jsonCallbackReceiver(NULL),
-    jsonCallbackMethod(),
-    errorCallbackReceiver(NULL),
-    errorCallbackMethod(),
-    updateReciever(NULL),
-    updateSlot()
+JSONCallbackParameters::JSONCallbackParameters(QObject* jsonCallbackReceiver, const QString& jsonCallbackMethod,
+                                               QObject* errorCallbackReceiver, const QString& errorCallbackMethod,
+                                               QObject* updateReceiver, const QString& updateSlot) :
+    jsonCallbackReceiver(jsonCallbackReceiver),
+    jsonCallbackMethod(jsonCallbackMethod),
+    errorCallbackReceiver(errorCallbackReceiver),
+    errorCallbackMethod(errorCallbackMethod),
+    updateReciever(updateReceiver),
+    updateSlot(updateSlot)
 {
 }
 
 AccountManager::AccountManager() :
     _authURL(),
-    _networkAccessManager(NULL),
     _pendingCallbackMap(),
     _accountInfo()
 {
@@ -153,9 +154,7 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::
                                     const JSONCallbackParameters& callbackParams,
                                     const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart) {
 
-    if (!_networkAccessManager) {
-        _networkAccessManager = new QNetworkAccessManager(this);
-    }
+    NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
 
     if (hasValidAccessToken()) {
         QNetworkRequest authenticatedRequest;
@@ -184,26 +183,29 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::
 
         switch (operation) {
             case QNetworkAccessManager::GetOperation:
-                networkReply = _networkAccessManager->get(authenticatedRequest);
+                networkReply = networkAccessManager.get(authenticatedRequest);
                 break;
             case QNetworkAccessManager::PostOperation:
             case QNetworkAccessManager::PutOperation:
                 if (dataMultiPart) {
                     if (operation == QNetworkAccessManager::PostOperation) {
-                        networkReply = _networkAccessManager->post(authenticatedRequest, dataMultiPart);
+                        networkReply = networkAccessManager.post(authenticatedRequest, dataMultiPart);
                     } else {
-                        networkReply = _networkAccessManager->put(authenticatedRequest, dataMultiPart);
+                        networkReply = networkAccessManager.put(authenticatedRequest, dataMultiPart);
                     }
                     dataMultiPart->setParent(networkReply);
                 } else {
                     authenticatedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
                     if (operation == QNetworkAccessManager::PostOperation) {
-                        networkReply = _networkAccessManager->post(authenticatedRequest, dataByteArray);
+                        networkReply = networkAccessManager.post(authenticatedRequest, dataByteArray);
                     } else {
-                        networkReply = _networkAccessManager->put(authenticatedRequest, dataByteArray);
+                        networkReply = networkAccessManager.put(authenticatedRequest, dataByteArray);
                     }
                 }
 
+                break;
+            case QNetworkAccessManager::DeleteOperation:
+                networkReply = networkAccessManager.sendCustomRequest(authenticatedRequest, "DELETE");
                 break;
             default:
                 // other methods not yet handled
@@ -304,9 +306,7 @@ bool AccountManager::checkAndSignalForAccessToken() {
 
 void AccountManager::requestAccessToken(const QString& login, const QString& password) {
 
-    if (!_networkAccessManager) {
-        _networkAccessManager = new QNetworkAccessManager(this);
-    }
+    NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
 
     QNetworkRequest request;
 
@@ -324,7 +324,7 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas
     request.setUrl(grantURL);
     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
 
-    QNetworkReply* requestReply = _networkAccessManager->post(request, postData);
+    QNetworkReply* requestReply = networkAccessManager.post(request, postData);
     connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestAccessTokenFinished);
     connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError)));
 }
@@ -376,15 +376,13 @@ void AccountManager::requestAccessTokenError(QNetworkReply::NetworkError error)
 }
 
 void AccountManager::requestProfile() {
-    if (!_networkAccessManager) {
-        _networkAccessManager = new QNetworkAccessManager(this);
-    }
+    NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
 
     QUrl profileURL = _authURL;
     profileURL.setPath("/api/v1/users/profile");
     profileURL.setQuery("access_token=" + _accountInfo.getAccessToken().token);
 
-    QNetworkReply* profileReply = _networkAccessManager->get(QNetworkRequest(profileURL));
+    QNetworkReply* profileReply = networkAccessManager.get(QNetworkRequest(profileURL));
     connect(profileReply, &QNetworkReply::finished, this, &AccountManager::requestProfileFinished);
     connect(profileReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestProfileError(QNetworkReply::NetworkError)));
 }
diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h
index c18836ca54..49a39c1a22 100644
--- a/libraries/networking/src/AccountManager.h
+++ b/libraries/networking/src/AccountManager.h
@@ -15,14 +15,17 @@
 #include <QtCore/QByteArray>
 #include <QtCore/QObject>
 #include <QtCore/QUrl>
-#include <QtNetwork/QNetworkAccessManager>
 #include <QtNetwork/QNetworkReply>
 
+#include "NetworkAccessManager.h"
+
 #include "DataServerAccountInfo.h"
 
 class JSONCallbackParameters {
 public:
-    JSONCallbackParameters();
+    JSONCallbackParameters(QObject* jsonCallbackReceiver = NULL, const QString& jsonCallbackMethod = QString(),
+                           QObject* errorCallbackReceiver = NULL, const QString& errorCallbackMethod = QString(),
+                           QObject* updateReceiver = NULL, const QString& updateSlot = QString());
 
     bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; }
 
@@ -58,8 +61,6 @@ public:
 
     const DataServerAccountInfo& getAccountInfo() const { return _accountInfo; }
 
-    void destroy() { delete _networkAccessManager; }
-
 public slots:
     void requestAccessTokenFinished();
     void requestProfileFinished();
@@ -93,7 +94,6 @@ private:
                                     QHttpMultiPart* dataMultiPart);
 
     QUrl _authURL;
-    QNetworkAccessManager* _networkAccessManager;
     QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;
 
     DataServerAccountInfo _accountInfo;
diff --git a/libraries/networking/src/NetworkAccessManager.cpp b/libraries/networking/src/NetworkAccessManager.cpp
new file mode 100644
index 0000000000..b9eda27947
--- /dev/null
+++ b/libraries/networking/src/NetworkAccessManager.cpp
@@ -0,0 +1,149 @@
+//
+//  NetworkAccessManager.cpp
+//
+//
+//  Created by Clement on 7/1/14.
+//  Copyright 2014 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 <QMetaObject>
+#include <QThread>
+
+#include "NetworkAccessManager.h"
+
+NetworkAccessManager& NetworkAccessManager::getInstance() {
+    static NetworkAccessManager sharedInstance;
+    return sharedInstance;
+}
+
+NetworkAccessManager::NetworkAccessManager() {
+}
+
+QNetworkReply* NetworkAccessManager::get(const QNetworkRequest& request) {
+    if (QThread::currentThread() != thread()) {
+        QNetworkReply* result;
+        QMetaObject::invokeMethod(this,
+                                  "get",
+                                  Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(QNetworkReply*, result),
+                                  Q_ARG(const QNetworkRequest, request));
+        return result;
+    }
+    return QNetworkAccessManager::get(request);
+}
+
+QNetworkReply* NetworkAccessManager::head(const QNetworkRequest& request) {
+    if (QThread::currentThread() != thread()) {
+        QNetworkReply* result;
+        QMetaObject::invokeMethod(this,
+                                  "head",
+                                  Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(QNetworkReply*, result),
+                                  Q_ARG(const QNetworkRequest, request));
+        return result;
+    }
+    return QNetworkAccessManager::head(request);
+}
+
+QNetworkReply* NetworkAccessManager::post(const QNetworkRequest& request, QIODevice* data) {
+    if (QThread::currentThread() != thread()) {
+        QNetworkReply* result;
+        QMetaObject::invokeMethod(this,
+                                  "post",
+                                  Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(QNetworkReply*, result),
+                                  Q_ARG(const QNetworkRequest, request),
+                                  Q_ARG(QIODevice*, data));
+        return result;
+    }
+    return QNetworkAccessManager::post(request, data);
+}
+
+QNetworkReply* NetworkAccessManager::post(const QNetworkRequest& request, const QByteArray& data) {
+    if (QThread::currentThread() != thread()) {
+        QNetworkReply* result;
+        QMetaObject::invokeMethod(this,
+                                  "post",
+                                  Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(QNetworkReply*, result),
+                                  Q_ARG(const QNetworkRequest, request),
+                                  Q_ARG(const QByteArray, data));
+        return result;
+    }
+    return QNetworkAccessManager::post(request, data);
+}
+
+QNetworkReply* NetworkAccessManager::post(const QNetworkRequest& request, QHttpMultiPart* multiPart) {
+    if (QThread::currentThread() != thread()) {
+        QNetworkReply* result;
+        QMetaObject::invokeMethod(this,
+                                  "post",
+                                  Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(QNetworkReply*, result),
+                                  Q_ARG(const QNetworkRequest, request),
+                                  Q_ARG(QHttpMultiPart*, multiPart));
+        return result;
+    }
+    return QNetworkAccessManager::post(request, multiPart);
+}
+
+QNetworkReply* NetworkAccessManager::put(const QNetworkRequest& request, QIODevice* data) {
+    if (QThread::currentThread() != thread()) {
+        QNetworkReply* result;
+        QMetaObject::invokeMethod(this,
+                                  "put",
+                                  Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(QNetworkReply*, result),
+                                  Q_ARG(const QNetworkRequest, request),
+                                  Q_ARG(QIODevice*, data));
+        return result;
+    }
+    return QNetworkAccessManager::put(request, data);
+}
+
+QNetworkReply* NetworkAccessManager::put(const QNetworkRequest& request, QHttpMultiPart* multiPart) {
+    if (QThread::currentThread() != thread()) {
+        QNetworkReply* result;
+        QMetaObject::invokeMethod(this,
+                                  "put",
+                                  Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(QNetworkReply*, result),
+                                  Q_ARG(const QNetworkRequest, request),
+                                  Q_ARG(QHttpMultiPart*, multiPart));
+        return result;
+    }
+    return QNetworkAccessManager::put(request, multiPart);
+}
+
+QNetworkReply* NetworkAccessManager::put(const QNetworkRequest & request, const QByteArray & data) {
+    if (QThread::currentThread() != thread()) {
+        QNetworkReply* result;
+        QMetaObject::invokeMethod(this,
+                                  "put",
+                                  Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(QNetworkReply*, result),
+                                  Q_ARG(const QNetworkRequest, request),
+                                  Q_ARG(const QByteArray, data));
+        return result;
+    }
+    return QNetworkAccessManager::put(request, data);
+}
+
+
+QNetworkReply* NetworkAccessManager::sendCustomRequest(const QNetworkRequest& request, const QByteArray& verb, QIODevice* data) {
+    if (QThread::currentThread() != thread()) {
+        QNetworkReply* result;
+        QMetaObject::invokeMethod(this,
+                                  "sendCustomRequest",
+                                  Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(QNetworkReply*, result),
+                                  Q_ARG(const QNetworkRequest, request),
+                                  Q_ARG(const QByteArray, verb),
+                                  Q_ARG(QIODevice*, data));
+        return result;
+    }
+    return QNetworkAccessManager::sendCustomRequest(request, verb, data);
+}
\ No newline at end of file
diff --git a/libraries/networking/src/NetworkAccessManager.h b/libraries/networking/src/NetworkAccessManager.h
new file mode 100644
index 0000000000..ba97f12552
--- /dev/null
+++ b/libraries/networking/src/NetworkAccessManager.h
@@ -0,0 +1,41 @@
+//
+//  NetworkAccessManager.h
+//
+//
+//  Created by Clement on 7/1/14.
+//  Copyright 2014 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#ifndef hifi_NetworkAccessManager_h
+#define hifi_NetworkAccessManager_h
+
+#include <QNetworkAccessManager>
+#include <QNetworkConfiguration>
+#include <QNetworkProxy>
+
+/// Wrapper around QNetworkAccessManager wo that we only use one instance
+/// For any other method you should need, make sure to be on the right thread
+/// or call the method using QMetaObject::invokeMethod()
+class NetworkAccessManager : public QNetworkAccessManager {
+    Q_OBJECT
+public:
+    static NetworkAccessManager& getInstance();
+    
+    Q_INVOKABLE QNetworkReply* get(const QNetworkRequest& request);
+    Q_INVOKABLE QNetworkReply* head(const QNetworkRequest& request);
+    Q_INVOKABLE QNetworkReply* post(const QNetworkRequest& request, QIODevice* data);
+    Q_INVOKABLE QNetworkReply* post(const QNetworkRequest& request, const QByteArray& data);
+    Q_INVOKABLE QNetworkReply* post(const QNetworkRequest& request, QHttpMultiPart* multiPart);
+    Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, QIODevice* data);
+    Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, QHttpMultiPart* multiPart);
+    Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, const QByteArray& data);
+    Q_INVOKABLE QNetworkReply* sendCustomRequest(const QNetworkRequest& request, const QByteArray& verb, QIODevice* data = 0);
+    
+private:
+    NetworkAccessManager();
+};
+
+#endif // hifi_NetworkAccessManager_h
\ No newline at end of file
diff --git a/libraries/shared/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp
similarity index 97%
rename from libraries/shared/src/ResourceCache.cpp
rename to libraries/networking/src/ResourceCache.cpp
index 14998232d6..a183e2f9a1 100644
--- a/libraries/shared/src/ResourceCache.cpp
+++ b/libraries/networking/src/ResourceCache.cpp
@@ -16,6 +16,8 @@
 #include <QTimer>
 #include <QtDebug>
 
+#include "NetworkAccessManager.h"
+
 #include "ResourceCache.h"
 
 ResourceCache::ResourceCache(QObject* parent) :
@@ -103,8 +105,6 @@ void ResourceCache::requestCompleted(Resource* resource) {
     }
 }
 
-QNetworkAccessManager* ResourceCache::_networkAccessManager = NULL;
-
 const int DEFAULT_REQUEST_LIMIT = 10;
 int ResourceCache::_requestLimit = DEFAULT_REQUEST_LIMIT;
 
@@ -219,7 +219,7 @@ void Resource::init() {
     if (_url.isEmpty()) {
         _startedLoading = _loaded = true;
         
-    } else if (!(_url.isValid() && ResourceCache::getNetworkAccessManager())) {
+    } else if (!(_url.isValid())) {
         _startedLoading = _failedToLoad = true;
     }
 }
@@ -272,7 +272,7 @@ void Resource::handleReplyTimeout() {
 }
 
 void Resource::makeRequest() {
-    _reply = ResourceCache::getNetworkAccessManager()->get(_request);
+    _reply = NetworkAccessManager::getInstance().get(_request);
     
     connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64)));
     connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError()));
diff --git a/libraries/shared/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h
similarity index 94%
rename from libraries/shared/src/ResourceCache.h
rename to libraries/networking/src/ResourceCache.h
index 2404485c46..1593ad45fc 100644
--- a/libraries/shared/src/ResourceCache.h
+++ b/libraries/networking/src/ResourceCache.h
@@ -22,7 +22,6 @@
 #include <QUrl>
 #include <QWeakPointer>
 
-class QNetworkAccessManager;
 class QNetworkReply;
 class QTimer;
 
@@ -33,10 +32,6 @@ class ResourceCache : public QObject {
     Q_OBJECT
     
 public:
-
-    static void setNetworkAccessManager(QNetworkAccessManager* manager) { _networkAccessManager = manager; }
-    static QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
-
     static void setRequestLimit(int limit) { _requestLimit = limit; }
     static int getRequestLimit() { return _requestLimit; }
 
@@ -76,7 +71,6 @@ private:
     QHash<QUrl, QWeakPointer<Resource> > _resources;
     int _lastLRUKey;
     
-    static QNetworkAccessManager* _networkAccessManager;
     static int _requestLimit;
     static QList<QPointer<Resource> > _pendingRequests;
     static QList<Resource*> _loadingRequests;
diff --git a/libraries/networking/src/UserActivityLogger.cpp b/libraries/networking/src/UserActivityLogger.cpp
index aa18cb43ee..5b20c82263 100644
--- a/libraries/networking/src/UserActivityLogger.cpp
+++ b/libraries/networking/src/UserActivityLogger.cpp
@@ -83,17 +83,10 @@ void UserActivityLogger::close(int delayTime) {
     
     // In order to get the end of the session, we need to give the account manager enough time to send the packet.
     QEventLoop loop;
-    // Here we connect the callbacks to stop the event loop
-    JSONCallbackParameters params;
-    params.jsonCallbackReceiver = &loop;
-    params.errorCallbackReceiver = &loop;
-    params.jsonCallbackMethod = "quit";
-    params.errorCallbackMethod = "quit";
-    // In case something goes wrong, we also setup a timer so that the delai is not greater than delayTime
     QTimer timer;
     connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
     // Now we can log it
-    logAction(ACTION_NAME, QJsonObject(), params);
+    logAction(ACTION_NAME, QJsonObject());
     timer.start(delayTime);
     loop.exec();
 }
diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp
index d8d5887d97..0291690c3d 100644
--- a/libraries/particles/src/ParticleCollisionSystem.cpp
+++ b/libraries/particles/src/ParticleCollisionSystem.cpp
@@ -183,7 +183,6 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA)
 
 // MIN_VALID_SPEED is obtained by computing speed gained at one gravity after the shortest expected frame
 const float MIN_EXPECTED_FRAME_PERIOD = 0.0167f;  // 1/60th of a second
-const float HALTING_SPEED = 9.8 * MIN_EXPECTED_FRAME_PERIOD / (float)(TREE_SCALE);
 
 void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
     // particles that are in hand, don't collide with avatars
diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp
index 04e970d68d..63ae58b924 100644
--- a/libraries/script-engine/src/ScriptEngine.cpp
+++ b/libraries/script-engine/src/ScriptEngine.cpp
@@ -13,7 +13,6 @@
 #include <QtCore/QEventLoop>
 #include <QtCore/QTimer>
 #include <QtCore/QThread>
-#include <QtNetwork/QNetworkAccessManager>
 #include <QtNetwork/QNetworkRequest>
 #include <QtNetwork/QNetworkReply>
 #include <QScriptEngine>
@@ -23,6 +22,7 @@
 #include <AvatarData.h>
 #include <CollisionInfo.h>
 #include <ModelsScriptingInterface.h>
+#include <NetworkAccessManager.h>
 #include <NodeList.h>
 #include <PacketHeaders.h>
 #include <ParticlesScriptingInterface.h>
@@ -142,8 +142,8 @@ ScriptEngine::ScriptEngine(const QUrl& scriptURL,
                 emit errorMessage("ERROR Loading file:" + fileName);
             }
         } else {
-            QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
-            QNetworkReply* reply = networkManager->get(QNetworkRequest(url));
+            NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+            QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
             qDebug() << "Downloading included script at" << url;
             QEventLoop loop;
             QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
@@ -648,8 +648,8 @@ void ScriptEngine::include(const QString& includeFile) {
     QString includeContents;
 
     if (url.scheme() == "http" || url.scheme() == "ftp") {
-        QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
-        QNetworkReply* reply = networkManager->get(QNetworkRequest(url));
+        NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+        QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
         qDebug() << "Downloading included script at" << includeFile;
         QEventLoop loop;
         QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
diff --git a/libraries/script-engine/src/XMLHttpRequestClass.cpp b/libraries/script-engine/src/XMLHttpRequestClass.cpp
index a81f8950fa..d9b7312bf4 100644
--- a/libraries/script-engine/src/XMLHttpRequestClass.cpp
+++ b/libraries/script-engine/src/XMLHttpRequestClass.cpp
@@ -14,6 +14,8 @@
 
 #include <QEventLoop>
 
+#include <NetworkAccessManager.h>
+
 #include "XMLHttpRequestClass.h"
 
 XMLHttpRequestClass::XMLHttpRequestClass(QScriptEngine* engine) :
@@ -22,7 +24,6 @@ XMLHttpRequestClass::XMLHttpRequestClass(QScriptEngine* engine) :
     _url(),
     _method(""),
     _responseType(""),
-    _manager(this),
     _request(),
     _reply(NULL),
     _sendData(NULL),
@@ -161,7 +162,7 @@ void XMLHttpRequestClass::send(const QString& data) {
 }
 
 void XMLHttpRequestClass::doSend() {
-    _reply = _manager.sendCustomRequest(_request, _method.toLatin1(), _sendData);
+    _reply = NetworkAccessManager::getInstance().sendCustomRequest(_request, _method.toLatin1(), _sendData);
 
     connectToReply(_reply);
 
diff --git a/libraries/script-engine/src/XMLHttpRequestClass.h b/libraries/script-engine/src/XMLHttpRequestClass.h
index 49a952e638..48f1a596e1 100644
--- a/libraries/script-engine/src/XMLHttpRequestClass.h
+++ b/libraries/script-engine/src/XMLHttpRequestClass.h
@@ -13,7 +13,6 @@
 #define hifi_XMLHttpRequestClass_h
 
 #include <QBuffer>
-#include <QNetworkAccessManager>
 #include <QNetworkReply>
 #include <QNetworkRequest>
 #include <QObject>
@@ -104,7 +103,6 @@ private:
     QUrl _url;
     QString _method;
     QString _responseType;
-    QNetworkAccessManager _manager;
     QNetworkRequest _request;
     QNetworkReply* _reply;
     QBuffer* _sendData;
diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt
index 7f9a34492d..560546473c 100644
--- a/libraries/shared/CMakeLists.txt
+++ b/libraries/shared/CMakeLists.txt
@@ -10,7 +10,7 @@ set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
 set(TARGET_NAME shared)
 project(${TARGET_NAME})
 
-find_package(Qt5 COMPONENTS Network Widgets Xml)
+find_package(Qt5 COMPONENTS Network Widgets Xml Script)
 
 include(${MACRO_DIR}/SetupHifiLibrary.cmake)
 setup_hifi_library(${TARGET_NAME})
@@ -32,4 +32,8 @@ if (UNIX AND NOT APPLE)
     target_link_libraries(${TARGET_NAME} "${CMAKE_THREAD_LIBS_INIT}")
 endif (UNIX AND NOT APPLE)
 
-target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets)
\ No newline at end of file
+# There is something special (bug) about Qt5Scripts, that we have to explicitly add its include
+# directory when Qt5 (5.2.1) is compiled from source and is not in a standard place.
+include_directories(SYSTEM "${Qt5Script_INCLUDE_DIRS}")
+
+target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets)
diff --git a/libraries/shared/src/PhysicsSimulation.cpp b/libraries/shared/src/PhysicsSimulation.cpp
index 637a5e955c..e2f95a213c 100644
--- a/libraries/shared/src/PhysicsSimulation.cpp
+++ b/libraries/shared/src/PhysicsSimulation.cpp
@@ -24,9 +24,6 @@ int MAX_ENTITIES_PER_SIMULATION = 64;
 int MAX_COLLISIONS_PER_SIMULATION = 256;
 
 
-const int NUM_SHAPE_BITS = 6;
-const int SHAPE_INDEX_MASK = (1 << (NUM_SHAPE_BITS + 1)) - 1;
-
 PhysicsSimulation::PhysicsSimulation() : _collisionList(MAX_COLLISIONS_PER_SIMULATION), 
         _numIterations(0), _numCollisions(0), _constraintError(0.0f), _stepTime(0) {
 }
diff --git a/tests/networking/src/SequenceNumberStatsTests.cpp b/tests/networking/src/SequenceNumberStatsTests.cpp
index 89a14deb20..62651eaa6f 100644
--- a/tests/networking/src/SequenceNumberStatsTests.cpp
+++ b/tests/networking/src/SequenceNumberStatsTests.cpp
@@ -23,7 +23,7 @@ void SequenceNumberStatsTests::runAllTests() {
     pruneTest();
 }
 
-const int UINT16_RANGE = std::numeric_limits<quint16>::max() + 1;
+const quint32 UINT16_RANGE = std::numeric_limits<quint16>::max() + 1;
 
 
 void SequenceNumberStatsTests::rolloverTest() {
@@ -34,7 +34,7 @@ void SequenceNumberStatsTests::rolloverTest() {
     quint16 seq = 79;   // start on some random number
 
     for (int R = 0; R < 2; R++) {
-        for (int i = 0; i < 3 * UINT16_RANGE; i++) {
+        for (quint32 i = 0; i < 3 * UINT16_RANGE; i++) {
             stats.sequenceNumberReceived(seq);
             seq = seq + (quint16)1;
 
@@ -53,12 +53,12 @@ void SequenceNumberStatsTests::earlyLateTest() {
 
     SequenceNumberStats stats;
     quint16 seq = 65530;
-    int numSent = 0;
+    quint32 numSent = 0;
 
-    int numEarly = 0;
-    int numLate = 0;
-    int numLost = 0;
-    int numRecovered = 0;
+    quint32 numEarly = 0;
+    quint32 numLate = 0;
+    quint32 numLost = 0;
+    quint32 numRecovered = 0;
 
     for (int R = 0; R < 2; R++) {
         for (int T = 0; T < 10000; T++) {
@@ -122,12 +122,12 @@ void SequenceNumberStatsTests::duplicateTest() {
 
     SequenceNumberStats stats;
     quint16 seq = 12345;
-    int numSent = 0;
+    quint32 numSent = 0;
 
-    int numDuplicate = 0;
-    int numEarly = 0;
-    int numLate = 0;
-    int numLost = 0;
+    quint32 numDuplicate = 0;
+    quint32 numEarly = 0;
+    quint32 numLate = 0;
+    quint32 numLost = 0;
 
     for (int R = 0; R < 2; R++) {
         for (int T = 0; T < 10000; T++) {
@@ -210,10 +210,10 @@ void SequenceNumberStatsTests::pruneTest() {
     
     SequenceNumberStats stats;
     quint16 seq = 54321;
-    int numSent = 0;
+    quint32 numSent = 0;
 
-    int numEarly = 0;
-    int numLost = 0;
+    quint32 numEarly = 0;
+    quint32 numLost = 0;
 
     for (int R = 0; R < 2; R++) {
         for (int T = 0; T < 1000; T++) {