From f0c4aef93291471aaf1bb00c717bee9abce2ab6d Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Mon, 30 Mar 2015 17:26:33 -0700
Subject: [PATCH 01/19] download and make tbb for OS X

---
 cmake/externals/tbb/CMakeLists.txt            | 34 +++++++++++--------
 .../tbb/OSXTBBInstallNameChange.cmake         | 18 ++--------
 ...droidTBBLibCopy.cmake => TBBLibCopy.cmake} |  4 +--
 3 files changed, 25 insertions(+), 31 deletions(-)
 rename cmake/externals/tbb/{AndroidTBBLibCopy.cmake => TBBLibCopy.cmake} (94%)

diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt
index ad46196b95..b9b2b65010 100644
--- a/cmake/externals/tbb/CMakeLists.txt
+++ b/cmake/externals/tbb/CMakeLists.txt
@@ -13,16 +13,28 @@ if (ANDROID)
     BUILD_COMMAND ${NDK_BUILD_COMMAND} --directory=jni target=android tbb tbbmalloc arch=arm
     BUILD_IN_SOURCE 1
     CONFIGURE_COMMAND ""
-    INSTALL_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/AndroidTBBLibCopy.cmake
+    INSTALL_COMMAND ${CMAKE_COMMAND} -DTBB_LIBS_SUFFIX=so -P ${CMAKE_CURRENT_SOURCE_DIR}/TBBLibCopy.cmake
+    LOG_DOWNLOAD 1
+    LOG_CONFIGURE 1
+    LOG_BUILD 1
+  )
+elseif (APPLE)
+  find_program(MAKE_COMMAND NAMES make DOC "Path to the make command")
+  
+  ExternalProject_Add(
+    ${EXTERNAL_NAME}
+    URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150316oss_src.tgz
+    URL_MD5 bf090eaa86cf89ea014b7b462786a440
+    BUILD_COMMAND ${MAKE_COMMAND} tbb_os=macos
+    BUILD_IN_SOURCE 1
+    CONFIGURE_COMMAND ""
+    INSTALL_COMMAND ${CMAKE_COMMAND} -DTBB_LIBS_SUFFIX=dylib -P ${CMAKE_CURRENT_SOURCE_DIR}/TBBLibCopy.cmake
     LOG_DOWNLOAD 1
     LOG_CONFIGURE 1
     LOG_BUILD 1
   )
 else ()
-  if (APPLE)
-    set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150316oss_osx.tgz)
-    set(DOWNLOAD_MD5 25a36ebff070ff801760ec658079f6aa)
-  elseif (WIN32)
+  if (WIN32)
     set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150316oss_win.zip)
     set(DOWNLOAD_MD5 d250d40bb93b255f75bcbb19e976a440)
   else () 
@@ -46,7 +58,7 @@ ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
 string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
 
 if (APPLE) 
-  set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/libc++")
+  set(_TBB_LIB_DIR "${SOURCE_DIR}/lib")
   set(_LIB_PREFIX "lib")
   set(_LIB_EXT "dylib")
   
@@ -95,14 +107,8 @@ elseif (UNIX)
 endif () 
 
 if (DEFINED _TBB_LIB_DIR)
-  if (NOT APPLE)
-    set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb_debug.${_LIB_EXT} CACHE FILEPATH "TBB debug library location")
-    set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc_debug.${_LIB_EXT} CACHE FILEPATH "TBB malloc debug library location")
-  else ()
-    set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "TBB debug library location")
-    set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG "" CACHE FILEPATH "TBB malloc debug library location")
-  endif ()
-  
+  set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb_debug.${_LIB_EXT} CACHE FILEPATH "TBB debug library location")
+  set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc_debug.${_LIB_EXT} CACHE FILEPATH "TBB malloc debug library location")
   set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb.${_LIB_EXT} CACHE FILEPATH "TBB release library location")
   set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc.${_LIB_EXT} CACHE FILEPATH "TBB malloc release library location")
 endif ()
diff --git a/cmake/externals/tbb/OSXTBBInstallNameChange.cmake b/cmake/externals/tbb/OSXTBBInstallNameChange.cmake
index c263ed7d2e..cc4df46812 100644
--- a/cmake/externals/tbb/OSXTBBInstallNameChange.cmake
+++ b/cmake/externals/tbb/OSXTBBInstallNameChange.cmake
@@ -10,9 +10,11 @@
 #
 
 # first find the so files in the source dir
-set(_TBB_LIBRARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/libc++)
+set(_TBB_LIBRARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib)
 file(GLOB_RECURSE _TBB_LIBRARIES "${_TBB_LIBRARY_DIR}/*.dylib")
 
+message(${_TBB_LIBRARIES})
+
 # raise an error if we found none
 if (NOT _TBB_LIBRARIES)
   message(FATAL_ERROR "Did not find any TBB libraries")
@@ -28,20 +30,6 @@ find_program(LIPO_COMMAND NAMES lipo DOC "Path to the lipo command")
 foreach(_TBB_LIBRARY ${_TBB_LIBRARIES})
   get_filename_component(_TBB_LIBRARY_FILENAME ${_TBB_LIBRARY} NAME)
   
-  set(_LIPO_ARGS -remove i386 ${_TBB_LIBRARY_FILENAME} -output ${_TBB_LIBRARY_FILENAME})
-  message(STATUS "${LIPO_COMMAND} ${_LIPO_ARGS}")
-   
-  # first we use lipo to remove i386 from each dylib
-  execute_process(
-    COMMAND ${LIPO_COMMAND} ${_LIPO_ARGS}
-    WORKING_DIRECTORY ${_TBB_LIBRARY_DIR}
-    ERROR_VARIABLE _LIPO_ERROR
-  )
-  
-  if (_LIPO_ERROR)
-    message(FATAL_ERROR "There was an error removing i386 for ${_TBB_LIBRARY_FILENAME} - ${_LIPO_ERROR}")
-  endif ()
-  
   set(_INSTALL_NAME_ARGS ${INSTALL_NAME_TOOL_COMMAND} -id ${_TBB_LIBRARY} ${_TBB_LIBRARY_FILENAME})
   
   message(STATUS "${INSTALL_NAME_COMMAND} ${_INSTALL_NAME_ARGS}")
diff --git a/cmake/externals/tbb/AndroidTBBLibCopy.cmake b/cmake/externals/tbb/TBBLibCopy.cmake
similarity index 94%
rename from cmake/externals/tbb/AndroidTBBLibCopy.cmake
rename to cmake/externals/tbb/TBBLibCopy.cmake
index 1c7697ab54..8f5423750b 100644
--- a/cmake/externals/tbb/AndroidTBBLibCopy.cmake
+++ b/cmake/externals/tbb/TBBLibCopy.cmake
@@ -1,5 +1,5 @@
 # 
-#  AndroidTBBLibCopy.cmake
+#  TBBLibCopy.cmake
 #  cmake/externals/tbb
 # 
 #  Copyright 2015 High Fidelity, Inc.
@@ -10,7 +10,7 @@
 #
 
 # first find the so files in the source dir
-file(GLOB_RECURSE _TBB_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/build/*.so")
+file(GLOB_RECURSE _TBB_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/build/*.${TBB_LIBS_SUFFIX}")
 
 # raise an error if we found none
 if (NOT _TBB_LIBRARIES)

From edf0ca2b06e4621afc82db46945d8d5c3fcee474 Mon Sep 17 00:00:00 2001
From: Sam Gateau <sam@highfidelity.io>
Date: Tue, 31 Mar 2015 10:29:03 -0700
Subject: [PATCH 02/19] Forbifd the global ambient lighting to go the simple
 global value and instead fallback to the first Spherical harmonics preset

---
 libraries/render-utils/src/DeferredLightingEffect.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp
index ffa84adbdf..6ed73c6750 100644
--- a/libraries/render-utils/src/DeferredLightingEffect.cpp
+++ b/libraries/render-utils/src/DeferredLightingEffect.cpp
@@ -535,10 +535,14 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit
 }
 
 void DeferredLightingEffect::setAmbientLightMode(int preset) {
-    if ((preset >= -1) && (preset < model::SphericalHarmonics::NUM_PRESET)) {
+    //if ((preset >= -1) && (preset < model::SphericalHarmonics::NUM_PRESET)) {
+    if ((preset >= 0) && (preset < model::SphericalHarmonics::NUM_PRESET)) {
         _ambientLightMode = preset;
         auto light = _allocatedLights.front();
         light->setAmbientSpherePreset(model::SphericalHarmonics::Preset(preset % model::SphericalHarmonics::NUM_PRESET));
+    } else {
+        // force to preset 0
+        setAmbientLightMode(0);
     }
 }
 

From 02b69f4a7009502a6fb3b3bc9db14ef1d29b188b Mon Sep 17 00:00:00 2001
From: Bradley Austin Davis <bdavis@saintandreas.org>
Date: Tue, 31 Mar 2015 13:32:13 -0700
Subject: [PATCH 03/19] Enabling the use of #ifdef DEBUG as a platform neutral
 idiom

---
 CMakeLists.txt                       | 1 +
 libraries/shared/src/StreamUtils.cpp | 4 +++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 296a566fa4..fdeb6dfd0f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -26,6 +26,7 @@ set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
 
 project(hifi)
 add_definitions(-DGLM_FORCE_RADIANS)
+set(CMAKE_CXX_FLAGS_DEBUG  "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") 
 
 if (WIN32)
   add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
diff --git a/libraries/shared/src/StreamUtils.cpp b/libraries/shared/src/StreamUtils.cpp
index f58115d288..b2ea5d95a4 100644
--- a/libraries/shared/src/StreamUtils.cpp
+++ b/libraries/shared/src/StreamUtils.cpp
@@ -66,7 +66,9 @@ QDataStream& operator>>(QDataStream& in, glm::quat& quaternion) {
 }
 
 // less common utils can be enabled with DEBUG
-#ifdef DEBUG
+// FIXME, remove the second defined clause once these compile, or remove the
+// functions.
+#if defined(DEBUG) && defined(FIXED_STREAMS)
 
 std::ostream& operator<<(std::ostream& s, const CollisionInfo& c) {
     s << "{penetration=" << c._penetration 

From 347ef3c4e1de32bca0afffa6db9ef09cd0270da3 Mon Sep 17 00:00:00 2001
From: Seth Alves <seth.alves@gmail.com>
Date: Tue, 31 Mar 2015 14:03:37 -0700
Subject: [PATCH 04/19] use scaling from visual model on collision model rather
 than using the bounds from the collision model

---
 .../src/RenderableModelEntityItem.cpp         | 40 +++++++++----------
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
index 2b65081185..2387e729ce 100644
--- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
@@ -293,7 +293,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
     }
 
     if (_model->getCollisionURL().isEmpty()) {
-        // no model url, so we're ready to compute a shape.
+        // no collision-model url, so we're ready to compute a shape (of type None).
         return true;
     }
 
@@ -312,15 +312,17 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
         info.setParams(getShapeType(), 0.5f * getDimensions());
     } else {
         const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
-        const FBXGeometry& fbxGeometry = collisionNetworkGeometry->getFBXGeometry();
+        const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry();
+
+        const QSharedPointer<NetworkGeometry> renderNetworkGeometry = _model->getGeometry();
+        const FBXGeometry& renderGeometry = renderNetworkGeometry->getFBXGeometry();
 
-        AABox aaBox;
         _points.clear();
         unsigned int i = 0;
 
         // the way OBJ files get read, each section under a "g" line is its own meshPart.  We only expect
         // to find one actual "mesh" (with one or more meshParts in it), but we loop over the meshes, just in case.
-        foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
+        foreach (const FBXMesh& mesh, collisionGeometry.meshes) {
             // each meshPart is a convex hull
             foreach (const FBXMeshPart &meshPart, mesh.parts) {
                 QVector<glm::vec3> pointsInPart;
@@ -332,15 +334,9 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
                     unsigned int p0Index = meshPart.triangleIndices[j*3];
                     unsigned int p1Index = meshPart.triangleIndices[j*3+1];
                     unsigned int p2Index = meshPart.triangleIndices[j*3+2];
-                    assert(p0Index < (unsigned int)mesh.vertices.size());
-                    assert(p1Index < (unsigned int)mesh.vertices.size());
-                    assert(p2Index < (unsigned int)mesh.vertices.size());
                     glm::vec3 p0 = mesh.vertices[p0Index];
                     glm::vec3 p1 = mesh.vertices[p1Index];
                     glm::vec3 p2 = mesh.vertices[p2Index];
-                    aaBox += p0;
-                    aaBox += p1;
-                    aaBox += p2;
                     if (!pointsInPart.contains(p0)) {
                         pointsInPart << p0;
                     }
@@ -360,18 +356,10 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
                     unsigned int p1Index = meshPart.quadIndices[j*4+1];
                     unsigned int p2Index = meshPart.quadIndices[j*4+2];
                     unsigned int p3Index = meshPart.quadIndices[j*4+3];
-                    assert(p0Index < (unsigned int)mesh.vertices.size());
-                    assert(p1Index < (unsigned int)mesh.vertices.size());
-                    assert(p2Index < (unsigned int)mesh.vertices.size());
-                    assert(p3Index < (unsigned int)mesh.vertices.size());
                     glm::vec3 p0 = mesh.vertices[p0Index];
                     glm::vec3 p1 = mesh.vertices[p1Index];
                     glm::vec3 p2 = mesh.vertices[p2Index];
                     glm::vec3 p3 = mesh.vertices[p3Index];
-                    aaBox += p0;
-                    aaBox += p1;
-                    aaBox += p2;
-                    aaBox += p3;
                     if (!pointsInPart.contains(p0)) {
                         pointsInPart << p0;
                     }
@@ -386,6 +374,11 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
                     }
                 }
 
+                if (pointsInPart.size() == 0) {
+                    qDebug() << "Warning -- meshPart has no faces";
+                    continue;
+                }
+
                 // add next convex hull
                 QVector<glm::vec3> newMeshPoints;
                 _points << newMeshPoints;
@@ -394,11 +387,14 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
             }
         }
 
-        // make sure we aren't about to divide by zero
-        glm::vec3 aaBoxDim = aaBox.getDimensions();
-        aaBoxDim = glm::clamp(aaBoxDim, glm::vec3(FLT_EPSILON), aaBoxDim);
+        // We expect that the collision model will have the same units and will be displaced
+        // from it's origin in the same way the visual model is.  The visual model has
+        // been centered and probably scaled.  We take the scaling and offset which were applied
+        // to the visual model and apply them to the collision model (without regard for the
+        // collision model's extents).
+
+        glm::vec3 scale = _dimensions / renderGeometry.getUnscaledMeshExtents().size();
 
-        glm::vec3 scale = _dimensions / aaBoxDim;
         // multiply each point by scale before handing the point-set off to the physics engine
         for (int i = 0; i < _points.size(); i++) {
             for (int j = 0; j < _points[i].size(); j++) {

From 9e0118492ebd57490be55863d74a2eedbc8fe159 Mon Sep 17 00:00:00 2001
From: Seth Alves <seth.alves@gmail.com>
Date: Tue, 31 Mar 2015 14:04:21 -0700
Subject: [PATCH 05/19] make sure to not leave in-use resources in
 UnusedResource list

---
 libraries/networking/src/ResourceCache.cpp | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp
index 739e587f5f..97ae8e1ae2 100644
--- a/libraries/networking/src/ResourceCache.cpp
+++ b/libraries/networking/src/ResourceCache.cpp
@@ -70,6 +70,7 @@ QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl&
                                                     bool delayLoad, void* extra) {
     QSharedPointer<Resource> resource = _resources.value(url);
     if (!resource.isNull()) {
+        removeUnusedResource(resource);
         return resource;
     }
 
@@ -83,16 +84,14 @@ QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl&
         return getResource(fallback, QUrl(), delayLoad);
     }
 
-    if (resource.isNull()) {
-        resource = createResource(url, fallback.isValid() ?
-            getResource(fallback, QUrl(), true) : QSharedPointer<Resource>(), delayLoad, extra);
-        resource->setSelf(resource);
-        resource->setCache(this);
-        _resources.insert(url, resource);
-        
-    } else {
-        removeUnusedResource(resource);
-    }
+    resource = createResource(url, fallback.isValid() ?
+                              getResource(fallback, QUrl(), true) : QSharedPointer<Resource>(), delayLoad, extra);
+    resource->setSelf(resource);
+    resource->setCache(this);
+    _resources.insert(url, resource);
+    removeUnusedResource(resource);
+    resource->ensureLoading();
+
     return resource;
 }
 

From ea2c5ff6226f23c83180cc4d14dadc1a4dde81a2 Mon Sep 17 00:00:00 2001
From: Seth Alves <seth.alves@gmail.com>
Date: Tue, 31 Mar 2015 14:04:33 -0700
Subject: [PATCH 06/19] formatting

---
 libraries/render-utils/src/GeometryCache.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp
index c74f714e8d..98843cc87f 100644
--- a/libraries/render-utils/src/GeometryCache.cpp
+++ b/libraries/render-utils/src/GeometryCache.cpp
@@ -1775,10 +1775,10 @@ QSharedPointer<NetworkGeometry> GeometryCache::getGeometry(const QUrl& url, cons
     return getResource(url, fallback, delayLoad, NULL).staticCast<NetworkGeometry>();
 }
 
-QSharedPointer<Resource> GeometryCache::createResource(const QUrl& url,
-        const QSharedPointer<Resource>& fallback, bool delayLoad, const void* extra) {
+QSharedPointer<Resource> GeometryCache::createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
+                                                       bool delayLoad, const void* extra) {
     QSharedPointer<NetworkGeometry> geometry(new NetworkGeometry(url, fallback.staticCast<NetworkGeometry>(), delayLoad),
-        &Resource::allReferencesCleared);
+                                             &Resource::allReferencesCleared);
     geometry->setLODParent(geometry);
     return geometry.staticCast<Resource>();
 }

From 55d506bb53c7a4f9ab1974a8cd6099954b53afd6 Mon Sep 17 00:00:00 2001
From: Seth Alves <seth.alves@gmail.com>
Date: Tue, 31 Mar 2015 14:04:49 -0700
Subject: [PATCH 07/19] formatting

---
 libraries/shared/src/Extents.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libraries/shared/src/Extents.h b/libraries/shared/src/Extents.h
index 66b33114f7..024d72013a 100644
--- a/libraries/shared/src/Extents.h
+++ b/libraries/shared/src/Extents.h
@@ -48,7 +48,7 @@ public:
     void rotate(const glm::quat& rotation);
 
     glm::vec3 size() const { return maximum - minimum; }
-    float largestDimension () const {glm::vec3 s = size(); return glm::max(s[0], s[1], s[2]); }
+    float largestDimension() const {glm::vec3 s = size(); return glm::max(s[0], s[1], s[2]); }
 
     /// \return new Extents which is original rotated around orign by rotation
     Extents getRotated(const glm::quat& rotation) const {

From f4695643e3eb2f1ab8600d10621b973470eb7373 Mon Sep 17 00:00:00 2001
From: Philip Rosedale <philip@highfidelity.io>
Date: Tue, 31 Mar 2015 14:13:19 -0700
Subject: [PATCH 08/19] Blocks fall when made, better edge colors

---
 examples/blocks.js | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/examples/blocks.js b/examples/blocks.js
index 30c2126096..7bc52824db 100644
--- a/examples/blocks.js
+++ b/examples/blocks.js
@@ -43,8 +43,8 @@ var floor = Entities.addEntity(
 var edge1 = Entities.addEntity(
 	    	{ type: "Box",
 	        position: Vec3.sum(center, { x: FLOOR_SIZE / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }), 
-			dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE }, 
-	      	color: { red: 128, green: 128, blue: 128 },
+			dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE + EDGE_THICKESS }, 
+	      	color: { red: 100, green: 100, blue: 100 },
 	      	gravity: {  x: 0, y: 0, z: 0 },
 	        ignoreCollisions: false,
 	        visible: true,
@@ -54,8 +54,8 @@ var edge1 = Entities.addEntity(
 var edge2 = Entities.addEntity(
 	    	{ type: "Box",
 	        position: Vec3.sum(center, { x: -FLOOR_SIZE / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }), 
-			dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE }, 
-	      	color: { red: 128, green: 128, blue: 128 },
+			dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE + EDGE_THICKESS }, 
+	      	color: { red: 100, green: 100, blue: 100 },
 	      	gravity: {  x: 0, y: 0, z: 0 },
 	        ignoreCollisions: false,
 	        visible: true,
@@ -65,8 +65,8 @@ var edge2 = Entities.addEntity(
 var edge3 = Entities.addEntity(
 	    	{ type: "Box",
 	        position: Vec3.sum(center, { x: 0, y: FLOOR_THICKNESS / 2.0, z: -FLOOR_SIZE / 2.0 }), 
-			dimensions: { x: FLOOR_SIZE, y: EDGE_THICKESS, z: EDGE_THICKESS }, 
-	      	color: { red: 128, green: 128, blue: 128 },
+			dimensions: { x: FLOOR_SIZE + EDGE_THICKESS, y: EDGE_THICKESS, z: EDGE_THICKESS }, 
+	      	color: { red: 100, green: 100, blue: 100 },
 	      	gravity: {  x: 0, y: 0, z: 0 },
 	        ignoreCollisions: false,
 	        visible: true,
@@ -76,8 +76,8 @@ var edge3 = Entities.addEntity(
 var edge4 = Entities.addEntity(
 	    	{ type: "Box",
 	        position: Vec3.sum(center, { x: 0, y: FLOOR_THICKNESS / 2.0, z: FLOOR_SIZE / 2.0 }), 
-			dimensions: { x: FLOOR_SIZE, y: EDGE_THICKESS, z: EDGE_THICKESS }, 
-	      	color: { red: 128, green: 128, blue: 128 },
+			dimensions: { x: FLOOR_SIZE + EDGE_THICKESS, y: EDGE_THICKESS, z: EDGE_THICKESS }, 
+	      	color: { red: 100, green: 100, blue: 100 },
 	      	gravity: {  x: 0, y: 0, z: 0 },
 	        ignoreCollisions: false,
 	        visible: true,
@@ -97,6 +97,7 @@ for (var i = 0; i < NUM_BLOCKS; i++) {
 			dimensions: { x: type.x * SCALE, y: type.y * SCALE, z: type.z * SCALE }, 
 	      	color: { red: type.red, green: type.green, blue: type.blue },
 	      	gravity: {  x: 0, y: GRAVITY, z: 0 },
+	      	velocity: { x: 0, y: 0.05, z: 0 },
 	        ignoreCollisions: false,
 	        damping: DAMPING,
 	        lifetime: LIFETIME,
@@ -104,6 +105,11 @@ for (var i = 0; i < NUM_BLOCKS; i++) {
 }
 
 function scriptEnding() {
+	Entities.editEntity(edge1, { locked: false });
+	Entities.editEntity(edge2, { locked: false });
+	Entities.editEntity(edge3, { locked: false });
+	Entities.editEntity(edge4, { locked: false });
+	Entities.editEntity(floor, { locked: false });
 	Entities.deleteEntity(edge1);
 	Entities.deleteEntity(edge2);
 	Entities.deleteEntity(edge3);

From a8891919164b72cf09e2f18715b641480eaaaabe Mon Sep 17 00:00:00 2001
From: ZappoMan <bradh@konamoxt.com>
Date: Tue, 31 Mar 2015 14:27:34 -0700
Subject: [PATCH 09/19] never cull mesh parts for avatars

---
 libraries/render-utils/src/Model.cpp | 19 ++++++-------------
 libraries/render-utils/src/Model.h   |  4 ++--
 2 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp
index 81c9f9448c..e9cfdaf345 100644
--- a/libraries/render-utils/src/Model.cpp
+++ b/libraries/render-utils/src/Model.cpp
@@ -2372,7 +2372,7 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool
 
 int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
                             bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, 
-                            bool forceRenderSomeMeshes) {
+                            bool forceRenderMeshes) {
 
     PROFILE_RANGE(__FUNCTION__);
     int meshPartsRendered = 0;
@@ -2395,7 +2395,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
     pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, 
                                 args, locations, skinLocations);
     meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, 
-                                args, locations, skinLocations, forceRenderSomeMeshes);
+                                args, locations, skinLocations, forceRenderMeshes);
     GLBATCH(glUseProgram)(0);
 
     return meshPartsRendered;
@@ -2403,7 +2403,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
 
 
 int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args,
-                                        Locations* locations, SkinLocations* skinLocations, bool forceRenderSomeMeshes) {
+                                        Locations* locations, SkinLocations* skinLocations, bool forceRenderMeshes) {
     PROFILE_RANGE(__FUNCTION__);
 
     auto textureCache = DependencyManager::get<TextureCache>();
@@ -2439,21 +2439,14 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
         // if we got here, then check to see if this mesh is in view
         if (args) {
             bool shouldRender = true;
-            bool forceRender = false;
             args->_meshesConsidered++;
 
             if (args->_viewFrustum) {
             
-                // NOTE: This is a hack to address the fact that for avatar meshes, the _calculatedMeshBoxes can be wrong
-                // for some meshes. Those meshes where the mesh's modelTransform is the identity matrix, and will have
-                // incorrectly calculated mesh boxes. In this case, we will ignore the box and assume it's visible.
-                if (forceRenderSomeMeshes && (geometry.meshes.at(i).modelTransform == glm::mat4())) {
-                    forceRender = true;
-                }
-                
-                shouldRender = forceRender || args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE;
+                shouldRender = forceRenderMeshes || 
+                                    args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE;
             
-                if (shouldRender && !forceRender) {
+                if (shouldRender && !forceRenderMeshes) {
                     float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter());
                     shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(),
                                                                             distance);
diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h
index 3b4cbdd450..299853ec9d 100644
--- a/libraries/render-utils/src/Model.h
+++ b/libraries/render-utils/src/Model.h
@@ -460,14 +460,14 @@ private:
     bool renderCore(float alpha, RenderMode mode, RenderArgs* args);
     int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, 
                         bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL, 
-                        bool forceRenderSomeMeshes = false);
+                        bool forceRenderMeshes = false);
                         
     void setupBatchTransform(gpu::Batch& batch);
     QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned);
 
     int renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
                                         RenderArgs* args, Locations* locations, SkinLocations* skinLocations, 
-                                        bool forceRenderSomeMeshes = false);
+                                        bool forceRenderMeshes = false);
 
     static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
                             bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,

From 95cc8672c016e1a78c829dc7c055212de43607ab Mon Sep 17 00:00:00 2001
From: Seth Alves <seth.alves@gmail.com>
Date: Tue, 31 Mar 2015 14:32:43 -0700
Subject: [PATCH 10/19] remove unneeded assert

---
 libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
index 2387e729ce..db742be8a1 100644
--- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
@@ -329,7 +329,6 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
 
                 // run through all the triangles and (uniquely) add each point to the hull
                 unsigned int triangleCount = meshPart.triangleIndices.size() / 3;
-                assert((unsigned int)meshPart.triangleIndices.size() == triangleCount*3);
                 for (unsigned int j = 0; j < triangleCount; j++) {
                     unsigned int p0Index = meshPart.triangleIndices[j*3];
                     unsigned int p1Index = meshPart.triangleIndices[j*3+1];

From 48144a46b1f4de9fd1c008cf6949a11095de59d0 Mon Sep 17 00:00:00 2001
From: Seth Alves <seth.alves@gmail.com>
Date: Tue, 31 Mar 2015 14:34:35 -0700
Subject: [PATCH 11/19] don't keep empty mesh-parts.  take units hint from a
 common first-line comment, if it's there.

---
 libraries/fbx/src/OBJReader.cpp | 55 +++++++++++++++++++++++----------
 1 file changed, 39 insertions(+), 16 deletions(-)

diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp
index db2733f27b..c87a942baa 100644
--- a/libraries/fbx/src/OBJReader.cpp
+++ b/libraries/fbx/src/OBJReader.cpp
@@ -27,7 +27,8 @@ public:
     enum SpecialToken {
         NO_TOKEN = -1,
         NO_PUSHBACKED_TOKEN = -1,
-        DATUM_TOKEN = 0x100
+        DATUM_TOKEN = 0x100,
+        COMMENT_TOKEN = 0x101
     };
     int nextToken();
     const QByteArray& getDatum() const { return _datum; }
@@ -35,11 +36,13 @@ public:
     void skipLine() { _device->readLine(); }
     void pushBackToken(int token) { _pushedBackToken = token; }
     void ungetChar(char ch) { _device->ungetChar(ch); }
+    const QString getComment() const { return _comment; }
 
 private:
     QIODevice* _device;
     QByteArray _datum;
     int _pushedBackToken;
+    QString _comment;
 };
 
 
@@ -56,9 +59,11 @@ int OBJTokenizer::nextToken() {
             continue; // skip whitespace
         }
         switch (ch) {
-            case '#':
-                _device->readLine(); // skip the comment
-                break;
+            case '#': {
+                _comment = _device->readLine(); // skip the comment
+                qDebug() << "COMMENT:" << _comment;
+                return COMMENT_TOKEN;
+            }
 
             case '\"':
                 _datum = "";
@@ -104,7 +109,8 @@ bool OBJTokenizer::isNextTokenFloat() {
 }
 
 bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
-                   FBXGeometry &geometry, QVector<glm::vec3>& faceNormals, QVector<int>& faceNormalIndexes) {
+                   FBXGeometry &geometry, QVector<glm::vec3>& faceNormals, QVector<int>& faceNormalIndexes,
+                   float& scaleGuess) {
     FBXMesh &mesh = geometry.meshes[0];
     mesh.parts.append(FBXMeshPart());
     FBXMeshPart &meshPart = mesh.parts.last();
@@ -128,7 +134,17 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
     meshPart._material->setEmissive(glm::vec3(0.0, 0.0, 0.0));
 
     while (true) {
-        if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
+        int tokenType = tokenizer.nextToken();
+        if (tokenType == OBJTokenizer::COMMENT_TOKEN) {
+            if (tokenizer.getComment().contains("This file uses centimeters as units")) {
+                scaleGuess = 1.0f / 100.0f;
+            }
+            if (tokenizer.getComment().contains("This file uses millimeters as units")) {
+                scaleGuess = 1.0f / 1000.0f;
+            }
+            continue;
+        }
+        if (tokenType != OBJTokenizer::DATUM_TOKEN) {
             result = false;
             break;
         }
@@ -192,6 +208,7 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
             while (true) {
                 if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
                     if (indices.count() == 0) {
+                        // nonsense, bail out.
                         goto done;
                     }
                     break;
@@ -266,22 +283,22 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
             }
         } else {
             // something we don't (yet) care about
-            qDebug() << "OBJ parser is skipping a line with" << token;
+            // qDebug() << "OBJ parser is skipping a line with" << token;
             tokenizer.skipLine();
         }
     }
 
  done:
+
+    if (meshPart.triangleIndices.size() == 0 && meshPart.quadIndices.size() == 0) {
+        // empty mesh?
+        mesh.parts.pop_back();
+    }
+
     return result;
 }
 
 
-FBXGeometry extractOBJGeometry(const FBXNode& node, const QVariantHash& mapping) {
-    FBXGeometry geometry;
-    return geometry;
-}
-
-
 FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping) {
     QBuffer buffer(const_cast<QByteArray*>(&model));
     buffer.open(QIODevice::ReadOnly);
@@ -294,24 +311,30 @@ FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping) {
     OBJTokenizer tokenizer(device);
     QVector<int> faceNormalIndexes;
     QVector<glm::vec3> faceNormals;
+    float scaleGuess = 1.0f;
 
     faceNormalIndexes.clear();
 
     geometry.meshExtents.reset();
     geometry.meshes.append(FBXMesh());
 
-
-
     try {
         // call parseOBJGroup as long as it's returning true.  Each successful call will
         // add a new meshPart to the geometry's single mesh.
         bool success = true;
         while (success) {
-            success = parseOBJGroup(tokenizer, mapping, geometry, faceNormals, faceNormalIndexes);
+            success = parseOBJGroup(tokenizer, mapping, geometry, faceNormals, faceNormalIndexes, scaleGuess);
         }
 
         FBXMesh &mesh = geometry.meshes[0];
 
+        // if we got a hint about units, scale all the points
+        if (scaleGuess != 1.0f) {
+            for (int i = 0; i < mesh.vertices.size(); i++) {
+                mesh.vertices[i] *= scaleGuess;
+            }
+        }
+
         mesh.meshExtents.reset();
         foreach (const glm::vec3& vertex, mesh.vertices) {
             mesh.meshExtents.addPoint(vertex);

From af6ce8fb07e75b8ea97697f6385e83f9793934c7 Mon Sep 17 00:00:00 2001
From: Seth Alves <seth.alves@gmail.com>
Date: Tue, 31 Mar 2015 14:37:41 -0700
Subject: [PATCH 12/19] HERE COMES AN S

---
 .../entities-renderer/src/RenderableModelEntityItem.cpp     | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
index db742be8a1..2353a20e7d 100644
--- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
@@ -61,7 +61,7 @@ void RenderableModelEntityItem::remapTextures() {
     }
     
     if (!_model->isLoadedWithTextures()) {
-        return; // nothing to do if the model has not yet loaded it's default textures
+        return; // nothing to do if the model has not yet loaded its default textures
     }
     
     if (!_originalTexturesRead && _model->isLoadedWithTextures()) {
@@ -220,7 +220,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
     // if we have a URL, then we will want to end up returning a model...
     if (!getModelURL().isEmpty()) {
     
-        // if we have a previously allocated model, but it's URL doesn't match
+        // if we have a previously allocated model, but its URL doesn't match
         // then we need to let our renderer update our model for us.
         if (_model && QUrl(getModelURL()) != _model->getURL()) {
             result = _model = _myRenderer->updateModel(_model, getModelURL(), getCollisionModelURL());
@@ -387,7 +387,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
         }
 
         // We expect that the collision model will have the same units and will be displaced
-        // from it's origin in the same way the visual model is.  The visual model has
+        // from its origin in the same way the visual model is.  The visual model has
         // been centered and probably scaled.  We take the scaling and offset which were applied
         // to the visual model and apply them to the collision model (without regard for the
         // collision model's extents).

From 74f04c0c8450fe8cff8cd406f3ab4a25ea0e12a3 Mon Sep 17 00:00:00 2001
From: Sam Gateau <sam@highfidelity.io>
Date: Tue, 31 Mar 2015 14:57:51 -0700
Subject: [PATCH 13/19] remove useless comment

---
 libraries/render-utils/src/DeferredLightingEffect.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp
index 6ed73c6750..f46bd689d4 100644
--- a/libraries/render-utils/src/DeferredLightingEffect.cpp
+++ b/libraries/render-utils/src/DeferredLightingEffect.cpp
@@ -535,7 +535,6 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit
 }
 
 void DeferredLightingEffect::setAmbientLightMode(int preset) {
-    //if ((preset >= -1) && (preset < model::SphericalHarmonics::NUM_PRESET)) {
     if ((preset >= 0) && (preset < model::SphericalHarmonics::NUM_PRESET)) {
         _ambientLightMode = preset;
         auto light = _allocatedLights.front();

From b4d11e2eb5680a8f31d8207ac1c7ec23ff271e06 Mon Sep 17 00:00:00 2001
From: Sam Gateau <sam@highfidelity.io>
Date: Tue, 31 Mar 2015 15:18:59 -0700
Subject: [PATCH 14/19] Add the needed global variable exported to enable the
 nvidia gpu on optimus platform (laptops with intel integrated) also log the
 opengl version and gpu and driver used

---
 interface/src/Application.cpp | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index eb427737e1..83e26719db 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -136,6 +136,13 @@
 #include "ui/StandAloneJSConsole.h"
 #include "ui/Stats.h"
 
+// ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
+#if defined(Q_OS_WIN)
+extern "C" {
+ _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
+}
+#endif
+
 using namespace std;
 
 //  Starfield information
@@ -646,6 +653,11 @@ void Application::initializeGL() {
     }
     #endif
 
+    qDebug() << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
+    qDebug() << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
+    qDebug() << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
+    qDebug() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
+
     #ifdef WIN32
     GLenum err = glewInit();
     if (GLEW_OK != err) {

From 740438d08dd5ab07fc86b4a4bcd64907ed022327 Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Tue, 31 Mar 2015 16:11:41 -0700
Subject: [PATCH 15/19] handle domain-server local port changes once connected

---
 libraries/networking/src/AddressManager.cpp | 10 +---------
 libraries/networking/src/AddressManager.h   |  2 --
 libraries/networking/src/DomainHandler.h    |  1 +
 libraries/networking/src/NodeList.cpp       | 17 +++++++++++++++++
 4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp
index 3c27c4644c..f8b297c025 100644
--- a/libraries/networking/src/AddressManager.cpp
+++ b/libraries/networking/src/AddressManager.cpp
@@ -33,8 +33,7 @@ AddressManager::AddressManager() :
     _rootPlaceName(),
     _rootPlaceID(),
     _positionGetter(NULL),
-    _orientationGetter(NULL),
-    _localDSPortSharedMem(NULL)
+    _orientationGetter(NULL)
 {
     connect(qApp, &QCoreApplication::aboutToQuit, this, &AddressManager::storeCurrentAddress);
 }
@@ -331,13 +330,6 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) {
         
         quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
         
-        if (domainHostname == "localhost") {
-            auto nodeList = DependencyManager::get<NodeList>();
-            nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY,
-                                                         _localDSPortSharedMem,
-                                                         domainPort);
-        }
-        
         if (!hostnameRegex.cap(2).isEmpty()) {
             domainPort = (qint16) hostnameRegex.cap(2).toInt();
         }
diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h
index a2522afcbc..db1cd6a3c8 100644
--- a/libraries/networking/src/AddressManager.h
+++ b/libraries/networking/src/AddressManager.h
@@ -95,8 +95,6 @@ private:
     QUuid _rootPlaceID;
     PositionGetter _positionGetter;
     OrientationGetter _orientationGetter;
-
-    QSharedMemory* _localDSPortSharedMem; // memory shared with domain server
 };
 
 #endif // hifi_AddressManager_h
diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h
index 0877f657e1..35ef7d8e2c 100644
--- a/libraries/networking/src/DomainHandler.h
+++ b/libraries/networking/src/DomainHandler.h
@@ -47,6 +47,7 @@ public:
     void setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname);
     
     unsigned short getPort() const { return _sockAddr.getPort(); }
+    void setPort(quint16 port) { _sockAddr.setPort(port); }
     
     const QUuid& getAssignmentUUID() const { return _assignmentUUID; }
     void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; }
diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp
index e63f230f6e..83424d7688 100644
--- a/libraries/networking/src/NodeList.cpp
+++ b/libraries/networking/src/NodeList.cpp
@@ -277,6 +277,23 @@ void NodeList::sendDomainServerCheckIn() {
         
         if (!_domainHandler.isConnected()) {
             qDebug() << "Sending connect request to domain-server at" << _domainHandler.getHostname();
+            
+            // is this our localhost domain-server?
+            // if so we need to make sure we have an up-to-date local port in case it restarted
+            
+            if (_domainHandler.getSockAddr().getAddress() == QHostAddress::LocalHost
+                || _domainHandler.getHostname() == "localhost") {
+                
+                static QSharedMemory* localDSPortSharedMem = NULL;
+                
+                quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
+                getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY,
+                                                   localDSPortSharedMem,
+                                                   domainPort);
+                qDebug() << "Local domain-server port read from shared memory (or default) is" << domainPort;
+                _domainHandler.setPort(domainPort);
+            }
+            
         }
         
         // construct the DS check in packet

From 64921c38b614262f4113dfcddcdc7ac72b2941b5 Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Tue, 31 Mar 2015 16:25:22 -0700
Subject: [PATCH 16/19] don't overlock in killNodeWithUUID

---
 libraries/networking/src/LimitedNodeList.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp
index ebd10b67a6..57977910c7 100644
--- a/libraries/networking/src/LimitedNodeList.cpp
+++ b/libraries/networking/src/LimitedNodeList.cpp
@@ -392,8 +392,9 @@ void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) {
         
         _nodeMutex.unlock();
         
-        QWriteLocker writeLocker(&_nodeMutex);
+        _nodeMutex.lockForWrite();
         _nodeHash.unsafe_erase(it);
+        _nodeMutex.unlock();
         
         handleNodeKill(matchingNode);
     } else {

From 61806935bb3118a47b04c2572b7b183a6253d6f8 Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Tue, 31 Mar 2015 16:40:21 -0700
Subject: [PATCH 17/19] add a networking constants class with metaverse URL

---
 assignment-client/src/octree/OctreeServer.cpp |  3 ++-
 domain-server/src/DomainServer.cpp            |  3 ++-
 interface/src/Application.cpp                 |  7 ++++---
 interface/src/ui/DataWebDialog.cpp            |  4 ++--
 interface/src/ui/LoginDialog.cpp              |  3 ++-
 libraries/networking/src/LimitedNodeList.cpp  |  2 --
 libraries/networking/src/LimitedNodeList.h    |  2 --
 .../networking/src/NetworkingConstants.h      | 21 +++++++++++++++++++
 .../src/OAuthNetworkAccessManager.cpp         |  4 +++-
 .../script-engine/src/XMLHttpRequestClass.cpp |  3 ++-
 10 files changed, 38 insertions(+), 14 deletions(-)
 create mode 100644 libraries/networking/src/NetworkingConstants.h

diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp
index 7cca9d3ef5..266183745f 100644
--- a/assignment-client/src/octree/OctreeServer.cpp
+++ b/assignment-client/src/octree/OctreeServer.cpp
@@ -20,6 +20,7 @@
 #include <AccountManager.h>
 #include <HTTPConnection.h>
 #include <LogHandler.h>
+#include <NetworkingConstants.h>
 #include <UUID.h>
 
 #include "../AssignmentClient.h"
@@ -252,7 +253,7 @@ OctreeServer::OctreeServer(const QByteArray& packet) :
     
     // make sure the AccountManager has an Auth URL for payment redemptions
     
-    AccountManager::getInstance().setAuthURL(DEFAULT_NODE_AUTH_URL);
+    AccountManager::getInstance().setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL);
 }
 
 OctreeServer::~OctreeServer() {
diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index 0918b85a63..263444f30a 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -27,6 +27,7 @@
 #include <HifiConfigVariantMap.h>
 #include <HTTPConnection.h>
 #include <LogUtils.h>
+#include <NetworkingConstants.h>
 #include <PacketHeaders.h>
 #include <SettingHandle.h>
 #include <SharedUtil.h>
@@ -181,7 +182,7 @@ bool DomainServer::optionallySetupOAuth() {
     
     // if we don't have an oauth provider URL then we default to the default node auth url
     if (_oauthProviderURL.isEmpty()) {
-        _oauthProviderURL = DEFAULT_NODE_AUTH_URL;
+        _oauthProviderURL = NetworkingConstants::METAVERSE_SERVER_URL;
     }
     
     AccountManager& accountManager = AccountManager::getInstance();
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index fba126309e..e1f66e1e89 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -68,6 +68,7 @@
 #include <MainWindow.h>
 #include <ModelEntityItem.h>
 #include <NetworkAccessManager.h>
+#include <NetworkingConstants.h>
 #include <OctalCode.h>
 #include <OctreeSceneStats.h>
 #include <PacketHeaders.h>
@@ -138,8 +139,8 @@
 
 // ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
 #if defined(Q_OS_WIN)
-extern "C" {
- _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
+extern "C" {
+ _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
 }
 #endif
 
@@ -425,7 +426,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
     connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
 
     // set the account manager's root URL and trigger a login request if we don't have the access token
-    accountManager.setAuthURL(DEFAULT_NODE_AUTH_URL);
+    accountManager.setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL);
     UserActivityLogger::getInstance().launch(applicationVersion());
 
     // once the event loop has started, check and signal for an access token
diff --git a/interface/src/ui/DataWebDialog.cpp b/interface/src/ui/DataWebDialog.cpp
index e28dcf8df7..f405ef50c5 100644
--- a/interface/src/ui/DataWebDialog.cpp
+++ b/interface/src/ui/DataWebDialog.cpp
@@ -13,7 +13,7 @@
 #include <qwebview.h>
 
 #include <AccountManager.h>
-#include <LimitedNodeList.h>
+#include <NetworkingConstants.h>
 
 #include "Application.h"
 #include "DataWebPage.h"
@@ -39,7 +39,7 @@ DataWebDialog* DataWebDialog::dialogForPath(const QString& path,
     connect(dialogWebView->page()->mainFrame(), &QWebFrame::javaScriptWindowObjectCleared,
             dialogWebView, &DataWebDialog::addJavascriptObjectsToWindow);
     
-    QUrl dataWebUrl(DEFAULT_NODE_AUTH_URL);
+    QUrl dataWebUrl(NetworkingConstants::METAVERSE_SERVER_URL);
     dataWebUrl.setPath(path);
     
     qDebug() << "Opening a data web dialog for" << dataWebUrl.toString();
diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp
index 4e7a4a7dc9..690489fdb2 100644
--- a/interface/src/ui/LoginDialog.cpp
+++ b/interface/src/ui/LoginDialog.cpp
@@ -14,6 +14,7 @@
 #include <QPushButton>
 #include <QPixmap>
 
+#include <NetworkingConstants.h>
 #include <PathUtils.h>
 
 #include "Application.h"
@@ -23,7 +24,7 @@
 #include "LoginDialog.h"
 #include "UIUtil.h"
 
-const QString FORGOT_PASSWORD_URL = "https://metaverse.highfidelity.com/users/password/new";
+const QString FORGOT_PASSWORD_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/users/password/new";
 
 LoginDialog::LoginDialog(QWidget* parent) :
     FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP),
diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp
index ebd10b67a6..b7ac33bba9 100644
--- a/libraries/networking/src/LimitedNodeList.cpp
+++ b/libraries/networking/src/LimitedNodeList.cpp
@@ -36,8 +36,6 @@ const char SOLO_NODE_TYPES[2] = {
     NodeType::AudioMixer
 };
 
-const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://metaverse.highfidelity.com");
-
 LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) :
     linkedDataCreateCallback(NULL),
     _sessionUUID(),
diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h
index 532e8ffcf4..be142fb036 100644
--- a/libraries/networking/src/LimitedNodeList.h
+++ b/libraries/networking/src/LimitedNodeList.h
@@ -42,8 +42,6 @@ const quint64 NODE_SILENCE_THRESHOLD_MSECS = 2 * 1000;
 
 extern const char SOLO_NODE_TYPES[2];
 
-extern const QUrl DEFAULT_NODE_AUTH_URL;
-
 const char DEFAULT_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost";
 
 const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io";
diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h
new file mode 100644
index 0000000000..00de0a7f17
--- /dev/null
+++ b/libraries/networking/src/NetworkingConstants.h
@@ -0,0 +1,21 @@
+//
+//  NetworkingConstants.h
+//  libraries/networking/src
+//
+//  Created by Stephen Birarda on 2015-03-31.
+//  Copyright 2015 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#ifndef hifi_NetworkingConstants_h
+#define hifi_NetworkingConstants_h
+
+#include <QUrl.h>
+
+namespace NetworkingConstants {
+    const QUrl METAVERSE_SERVER_URL = QUrl("https://metaverse.highfidelity.com");
+}
+
+#endif // hifi_NetworkingConstants_h
\ No newline at end of file
diff --git a/libraries/networking/src/OAuthNetworkAccessManager.cpp b/libraries/networking/src/OAuthNetworkAccessManager.cpp
index 89a73d5984..fa6f3b8340 100644
--- a/libraries/networking/src/OAuthNetworkAccessManager.cpp
+++ b/libraries/networking/src/OAuthNetworkAccessManager.cpp
@@ -15,6 +15,7 @@
 
 #include "AccountManager.h"
 #include "LimitedNodeList.h"
+#include "NetworkingConstants.h"
 #include "SharedUtil.h"
 
 #include "OAuthNetworkAccessManager.h"
@@ -33,7 +34,8 @@ QNetworkReply* OAuthNetworkAccessManager::createRequest(QNetworkAccessManager::O
                                                         QIODevice* outgoingData) {
     AccountManager& accountManager = AccountManager::getInstance();
     
-    if (accountManager.hasValidAccessToken() && req.url().host() == DEFAULT_NODE_AUTH_URL.host()) {
+    if (accountManager.hasValidAccessToken()
+        && req.url().host() == NetworkingConstants::METAVERSE_SERVER_URL.host()) {
         QNetworkRequest authenticatedRequest(req);
         authenticatedRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
         authenticatedRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER,
diff --git a/libraries/script-engine/src/XMLHttpRequestClass.cpp b/libraries/script-engine/src/XMLHttpRequestClass.cpp
index 3054472a3c..ae0486dd0c 100644
--- a/libraries/script-engine/src/XMLHttpRequestClass.cpp
+++ b/libraries/script-engine/src/XMLHttpRequestClass.cpp
@@ -17,12 +17,13 @@
 #include <qurlquery.h>
 
 #include <NetworkAccessManager.h>
+#include <NetworkingConstants.h>
 
 #include <AccountManager.h>
 #include "XMLHttpRequestClass.h"
 #include "ScriptEngine.h"
 
-const QString METAVERSE_API_URL = "https://metaverse.highfidelity.com/api/";
+const QString METAVERSE_API_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/api/";
 
 Q_DECLARE_METATYPE(QByteArray*)
 

From ef10e5734d301df5f042b761a79b43149df8ab56 Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@highfidelity.io>
Date: Tue, 31 Mar 2015 16:53:33 -0700
Subject: [PATCH 18/19] bounding box for skeleton with bad mesh weights

---
 interface/src/avatar/SkeletonModel.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp
index 3a61f69dee..dc5427ab48 100644
--- a/interface/src/avatar/SkeletonModel.cpp
+++ b/interface/src/avatar/SkeletonModel.cpp
@@ -685,6 +685,10 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
                 * joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform;
         }
 
+        // Each joint contributes its point to the bounding box
+        glm::vec3 jointPosition = extractTranslation(transforms[i]);
+        totalExtents.addPoint(jointPosition);
+
         Shape* shape = _shapes[i];
         if (!shape) {
             continue;
@@ -694,8 +698,6 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
         // that contains the sphere centered at the end of the joint with radius of the bone.
 
         // TODO: skip hand and arm shapes for bounding box calculation
-        glm::vec3 jointPosition = extractTranslation(transforms[i]);
-
         int type = shape->getType();
         if (type == CAPSULE_SHAPE) {
             // add the two furthest surface points of the capsule

From e22b33e96dd8e8c342d6d3e5f6822207f5cb236d Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Tue, 31 Mar 2015 17:00:04 -0700
Subject: [PATCH 19/19] fix QUrl include for ubuntu

---
 libraries/networking/src/NetworkingConstants.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h
index 00de0a7f17..a1940611bc 100644
--- a/libraries/networking/src/NetworkingConstants.h
+++ b/libraries/networking/src/NetworkingConstants.h
@@ -12,7 +12,7 @@
 #ifndef hifi_NetworkingConstants_h
 #define hifi_NetworkingConstants_h
 
-#include <QUrl.h>
+#include <QtCore/QUrl>
 
 namespace NetworkingConstants {
     const QUrl METAVERSE_SERVER_URL = QUrl("https://metaverse.highfidelity.com");