From e4cba1433393ca903ac5db5b511935a9a70a713d Mon Sep 17 00:00:00 2001
From: Zach Pomerantz <zach@highfidelity.io>
Date: Wed, 30 Mar 2016 18:54:25 -0700
Subject: [PATCH] Avoid recreating model items when adding to scene

---
 .../src/RenderableModelEntityItem.cpp         |  2 -
 libraries/render-utils/src/Model.cpp          | 97 ++++++++-----------
 libraries/render-utils/src/Model.h            |  5 +-
 3 files changed, 44 insertions(+), 60 deletions(-)

diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
index b510f58b12..a9dcb3883c 100644
--- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
@@ -434,8 +434,6 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
                 _showCollisionHull = shouldShowCollisionHull;
                 render::PendingChanges pendingChanges;
 
-                _model->removeFromScene(scene, pendingChanges);
-
                 render::Item::Status::Getters statusGetters;
                 makeEntityItemStatusGetters(getThisPointer(), statusGetters);
                 _model->addToScene(scene, pendingChanges, statusGetters, _showCollisionHull);
diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp
index 39ffc9dd9a..3a5928f3d1 100644
--- a/libraries/render-utils/src/Model.cpp
+++ b/libraries/render-utils/src/Model.cpp
@@ -541,43 +541,6 @@ void Model::setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scen
     }
 }
 
-
-bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges, bool showCollisionHull) {
-
-    if ((!_meshGroupsKnown || showCollisionHull != _showCollisionHull) && isLoaded()) {
-        _showCollisionHull = showCollisionHull;
-        segregateMeshGroups();
-    }
-
-    bool somethingAdded = false;
-
-    foreach (auto renderItem, _modelMeshRenderItemsSet) {
-        auto item = scene->allocateID();
-        auto renderPayload = std::make_shared<ModelMeshPartPayload::Payload>(renderItem);
-        pendingChanges.resetItem(item, renderPayload);
-        pendingChanges.updateItem<ModelMeshPartPayload>(item, [](ModelMeshPartPayload& data) {
-            data.notifyLocationChanged();
-        });
-        _modelMeshRenderItems.insert(item, renderPayload);
-        somethingAdded = true;
-    }
-
-    foreach (auto renderItem, _collisionRenderItemsSet) {
-        auto item = scene->allocateID();
-        auto renderPayload = std::make_shared<MeshPartPayload::Payload>(renderItem);
-        pendingChanges.resetItem(item, renderPayload);
-        pendingChanges.updateItem<MeshPartPayload>(item, [](MeshPartPayload& data) {
-            data.notifyLocationChanged();
-        });
-        _collisionRenderItems.insert(item, renderPayload);
-        somethingAdded = true;
-    }
-
-    _readyWhenAdded = readyToAddToScene();
-
-    return somethingAdded;
-}
-
 bool Model::addToScene(std::shared_ptr<render::Scene> scene,
                        render::PendingChanges& pendingChanges,
                        render::Item::Status::Getters& statusGetters,
@@ -589,28 +552,48 @@ bool Model::addToScene(std::shared_ptr<render::Scene> scene,
 
     bool somethingAdded = false;
 
-    foreach (auto renderItem, _modelMeshRenderItemsSet) {
-        auto item = scene->allocateID();
-        auto renderPayload = std::make_shared<ModelMeshPartPayload::Payload>(renderItem);
-        renderPayload->addStatusGetters(statusGetters);
-        pendingChanges.resetItem(item, renderPayload);
-        pendingChanges.updateItem<ModelMeshPartPayload>(item, [](ModelMeshPartPayload& data) {
-            data.notifyLocationChanged();
-        });
-        _modelMeshRenderItems.insert(item, renderPayload);
-        somethingAdded = true;
+    if (_modelMeshRenderItems.size()) {
+        for (auto item : _modelMeshRenderItems.keys()) {
+            pendingChanges.updateItem<ModelMeshPartPayload>(item, [](ModelMeshPartPayload& data) {
+                data.notifyLocationChanged();
+            });
+        }
+    } else {
+        for (auto renderItem : _modelMeshRenderItemsSet) {
+            auto item = scene->allocateID();
+            auto renderPayload = std::make_shared<ModelMeshPartPayload::Payload>(renderItem);
+            if (statusGetters.size()) {
+                renderPayload->addStatusGetters(statusGetters);
+            }
+            pendingChanges.resetItem(item, renderPayload);
+            pendingChanges.updateItem<ModelMeshPartPayload>(item, [](ModelMeshPartPayload& data) {
+                data.notifyLocationChanged();
+            });
+            _modelMeshRenderItems.insert(item, renderPayload);
+            somethingAdded = true;
+        }
     }
 
-    foreach (auto renderItem, _collisionRenderItemsSet) {
-        auto item = scene->allocateID();
-        auto renderPayload = std::make_shared<MeshPartPayload::Payload>(renderItem);
-        renderPayload->addStatusGetters(statusGetters);
-        pendingChanges.resetItem(item, renderPayload);
-        pendingChanges.updateItem<MeshPartPayload>(item, [](MeshPartPayload& data) {
-            data.notifyLocationChanged();
-        });
-        _collisionRenderItems.insert(item, renderPayload);
-        somethingAdded = true;
+    if (_collisionRenderItems.size()) {
+        for (auto item : _collisionRenderItems.keys()) {
+            pendingChanges.updateItem<MeshPartPayload>(item, [](MeshPartPayload& data) {
+                data.notifyLocationChanged();
+            });
+        }
+    } else {
+        for (auto renderItem : _collisionRenderItemsSet) {
+            auto item = scene->allocateID();
+            auto renderPayload = std::make_shared<MeshPartPayload::Payload>(renderItem);
+            if (statusGetters.size()) {
+                renderPayload->addStatusGetters(statusGetters);
+            }
+            pendingChanges.resetItem(item, renderPayload);
+            pendingChanges.updateItem<MeshPartPayload>(item, [](MeshPartPayload& data) {
+                data.notifyLocationChanged();
+            });
+            _collisionRenderItems.insert(item, renderPayload);
+            somethingAdded = true;
+        }
     }
 
     _readyWhenAdded = readyToAddToScene();
diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h
index 03760378f0..239d0e7c28 100644
--- a/libraries/render-utils/src/Model.h
+++ b/libraries/render-utils/src/Model.h
@@ -87,7 +87,10 @@ public:
     bool initWhenReady(render::ScenePointer scene);
     bool addToScene(std::shared_ptr<render::Scene> scene,
                     render::PendingChanges& pendingChanges,
-                    bool showCollisionHull = false);
+                    bool showCollisionHull = false) {
+        auto getters = render::Item::Status::Getters(0);
+        return addToScene(scene, pendingChanges, getters, showCollisionHull);
+    }
     bool addToScene(std::shared_ptr<render::Scene> scene,
                     render::PendingChanges& pendingChanges,
                     render::Item::Status::Getters& statusGetters,