From 74a7150cffd3a48d99e558c480fa6af4e5f71237 Mon Sep 17 00:00:00 2001
From: Gustl22 <user.rebo@gmx.de>
Date: Thu, 30 Aug 2018 10:21:35 +0200
Subject: [PATCH] Replace SharedModel with ModelInstance

---
 .../oscim/test/gdx/poi3d/GdxModelLayer.java   |  25 +-
 .../test/gdx/poi3d/GdxModelRenderer.java      |   5 +-
 .../oscim/test/gdx/poi3d/GdxRenderer3D.java   |   5 +-
 .../oscim/test/gdx/poi3d/GdxRenderer3D2.java  |   5 +-
 .../org/oscim/test/gdx/poi3d/Poi3DLayer.java  |  23 +-
 .../org/oscim/test/gdx/poi3d/SharedModel.java | 555 ------------------
 6 files changed, 34 insertions(+), 584 deletions(-)
 delete mode 100644 vtm-playground/src/org/oscim/test/gdx/poi3d/SharedModel.java

diff --git a/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxModelLayer.java b/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxModelLayer.java
index ba332093..738aef5b 100644
--- a/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxModelLayer.java
+++ b/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxModelLayer.java
@@ -2,6 +2,7 @@ package org.oscim.test.gdx.poi3d;
 
 import com.badlogic.gdx.assets.AssetManager;
 import com.badlogic.gdx.graphics.g3d.Model;
+import com.badlogic.gdx.graphics.g3d.ModelInstance;
 import com.badlogic.gdx.graphics.g3d.model.Node;
 
 import org.oscim.core.MapPosition;
@@ -60,8 +61,8 @@ public class GdxModelLayer extends Layer implements Map.UpdateListener {
     //    TileSet mTileSet = new TileSet();
     //    TileSet mPrevTiles = new TileSet();
     //
-    //    LinkedHashMap<Tile, Array<SharedModel>> mTileMap =
-    //            new LinkedHashMap<Tile, Array<SharedModel>>();
+    //    LinkedHashMap<Tile, Array<ModelInstance>> mTileMap =
+    //            new LinkedHashMap<Tile, Array<ModelInstance>>();
 
     boolean loading;
     Model mModel;
@@ -95,7 +96,7 @@ public class GdxModelLayer extends Layer implements Map.UpdateListener {
         //        if (ev == Map.CLEAR_EVENT) {
         //            mTileSet = new TileSet();
         //            mPrevTiles = new TileSet();
-        //            mTileMap = new LinkedHashMap<Tile, Array<SharedModel>>();
+        //            mTileMap = new LinkedHashMap<Tile, Array<ModelInstance>>();
         //            synchronized (g3d) {
         //                g3d.instances.clear();
         //            }
@@ -104,11 +105,11 @@ public class GdxModelLayer extends Layer implements Map.UpdateListener {
         if (loading && assets.update()) {
             doneLoading();
             // Renderable renderable = new Renderable();
-            // new SharedModel(mModel).getRenderable(renderable);
+            // new ModelInstance(mModel).getRenderable(renderable);
             // Shader shader = new DefaultShader(renderable, true, false,
             // false, false, 1, 0, 0, 0);
 
-            g3d.instances.add(new SharedModel(mModel));
+            g3d.instances.add(new ModelInstance(mModel));
 
         }
         if (loading)
@@ -133,15 +134,15 @@ public class GdxModelLayer extends Layer implements Map.UpdateListener {
         //
         //        boolean changed = false;
         //
-        //        Array<SharedModel> added = new Array<SharedModel>();
-        //        Array<SharedModel> removed = new Array<SharedModel>();
+        //        Array<ModelInstance> added = new Array<ModelInstance>();
+        //        Array<ModelInstance> removed = new Array<ModelInstance>();
 
         //        for (int i = 0; i < mTileSet.cnt; i++) {
         //            MapTile t = mTileSet.tiles[i];
         //            if (mPrevTiles.contains(t))
         //                continue;
         //
-        //            Array<SharedModel> instances = new Array<SharedModel>();
+        //            Array<ModelInstance> instances = new Array<ModelInstance>();
         //
         //            Poi3DTileData ld = (Poi3DTileData) t.getData(POI_DATA);
         //            if (ld == null)
@@ -149,7 +150,7 @@ public class GdxModelLayer extends Layer implements Map.UpdateListener {
         //
         //            for (SymbolItem it : ld.symbols) {
         //
-        //                SharedModel inst = new SharedModel(mModel);
+        //                ModelInstance inst = new ModelInstance(mModel);
         //                inst.userData = it;
         //                // float r = 0.5f + 0.5f * (float) Math.random();
         //                // float g = 0.5f + 0.5f * (float) Math.random();
@@ -178,7 +179,7 @@ public class GdxModelLayer extends Layer implements Map.UpdateListener {
         //            if (mTileSet.contains(t))
         //                continue;
         //
-        //            Array<SharedModel> instances = mTileMap.get(t);
+        //            Array<ModelInstance> instances = mTileMap.get(t);
         //            if (instances == null)
         //                continue;
         //
@@ -208,13 +209,13 @@ public class GdxModelLayer extends Layer implements Map.UpdateListener {
         //
         //        synchronized (g3d) {
         //
-        //            for (Entry<Tile, Array<SharedModel>> e : mTileMap.entrySet()) {
+        //            for (Entry<Tile, Array<ModelInstance>> e : mTileMap.entrySet()) {
         //                Tile t = e.getKey();
         //
         //                float dx = (float) (t.tileX * Tile.SIZE - tileX);
         //                float dy = (float) (t.tileY * Tile.SIZE - tileY);
         //
-        //                for (SharedModel inst : e.getValue()) {
+        //                for (ModelInstance inst : e.getValue()) {
         //                    SymbolItem it = (SymbolItem) inst.userData;
         //
         //                    // variable height
diff --git a/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxModelRenderer.java b/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxModelRenderer.java
index 7a6c7637..e1651f25 100644
--- a/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxModelRenderer.java
+++ b/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxModelRenderer.java
@@ -3,6 +3,7 @@ package org.oscim.test.gdx.poi3d;
 import com.badlogic.gdx.graphics.g3d.Environment;
 import com.badlogic.gdx.graphics.g3d.Model;
 import com.badlogic.gdx.graphics.g3d.ModelBatch;
+import com.badlogic.gdx.graphics.g3d.ModelInstance;
 import com.badlogic.gdx.graphics.g3d.Renderable;
 import com.badlogic.gdx.graphics.g3d.Shader;
 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
@@ -36,7 +37,7 @@ public class GdxModelRenderer extends LayerRenderer {
 
     public Environment lights;
 
-    public Array<SharedModel> instances = new Array<SharedModel>();
+    public Array<ModelInstance> instances = new Array<>();
 
     public Shader shader;
     public RenderContext renderContext;
@@ -151,7 +152,7 @@ public class GdxModelRenderer extends LayerRenderer {
             mBatch.begin(cam);
             //shader.begin(cam, renderContext);
 
-            for (SharedModel instance : instances) {
+            for (ModelInstance instance : instances) {
                 instance.transform.getTranslation(tempVector);
                 //instance.getRenderables(renderables, pool);
                 //    if (tempVector.x * tempVector.x + tempVector.y * tempVector.y > sqRadius)
diff --git a/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxRenderer3D.java b/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxRenderer3D.java
index 967e8af1..2c427a89 100644
--- a/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxRenderer3D.java
+++ b/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxRenderer3D.java
@@ -3,6 +3,7 @@ package org.oscim.test.gdx.poi3d;
 import com.badlogic.gdx.graphics.g3d.Environment;
 import com.badlogic.gdx.graphics.g3d.Model;
 import com.badlogic.gdx.graphics.g3d.ModelBatch;
+import com.badlogic.gdx.graphics.g3d.ModelInstance;
 import com.badlogic.gdx.graphics.g3d.Renderable;
 import com.badlogic.gdx.graphics.g3d.Shader;
 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
@@ -38,7 +39,7 @@ public class GdxRenderer3D extends LayerRenderer {
 
     public Environment lights;
 
-    public Array<SharedModel> instances = new Array<SharedModel>();
+    public Array<ModelInstance> instances = new Array<>();
 
     public Shader shader;
     public RenderContext renderContext;
@@ -160,7 +161,7 @@ public class GdxRenderer3D extends LayerRenderer {
 
             shader.begin(cam, renderContext);
 
-            for (SharedModel instance : instances) {
+            for (ModelInstance instance : instances) {
                 instance.transform.getTranslation(tempVector);
 
                 if (tempVector.x * tempVector.x + tempVector.y * tempVector.y > sqRadius)
diff --git a/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxRenderer3D2.java b/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxRenderer3D2.java
index 2e77acb0..e4b23861 100644
--- a/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxRenderer3D2.java
+++ b/vtm-playground/src/org/oscim/test/gdx/poi3d/GdxRenderer3D2.java
@@ -2,6 +2,7 @@ package org.oscim.test.gdx.poi3d;
 
 import com.badlogic.gdx.graphics.g3d.Environment;
 import com.badlogic.gdx.graphics.g3d.ModelBatch;
+import com.badlogic.gdx.graphics.g3d.ModelInstance;
 import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
 import com.badlogic.gdx.graphics.g3d.utils.DefaultShaderProvider;
 import com.badlogic.gdx.math.Vector3;
@@ -31,7 +32,7 @@ public class GdxRenderer3D2 extends LayerRenderer {
 
     public Environment lights;
 
-    public Array<SharedModel> instances = new Array<SharedModel>();
+    public Array<ModelInstance> instances = new Array<>();
 
     public GdxRenderer3D2(Map map) {
         mMap = map;
@@ -132,7 +133,7 @@ public class GdxRenderer3D2 extends LayerRenderer {
             modelBatch.begin(cam);
             cnt = instances.size;
 
-            for (SharedModel instance : instances) {
+            for (ModelInstance instance : instances) {
                 instance.transform.getTranslation(tempVector);
                 tempVector.scl(0.9f, 0.9f, 1);
                 if (!GeometryUtils.pointInPoly(tempVector.x, tempVector.y, mBox, 8, 0))
diff --git a/vtm-playground/src/org/oscim/test/gdx/poi3d/Poi3DLayer.java b/vtm-playground/src/org/oscim/test/gdx/poi3d/Poi3DLayer.java
index 22c69148..319cb768 100644
--- a/vtm-playground/src/org/oscim/test/gdx/poi3d/Poi3DLayer.java
+++ b/vtm-playground/src/org/oscim/test/gdx/poi3d/Poi3DLayer.java
@@ -2,6 +2,7 @@ package org.oscim.test.gdx.poi3d;
 
 import com.badlogic.gdx.assets.AssetManager;
 import com.badlogic.gdx.graphics.g3d.Model;
+import com.badlogic.gdx.graphics.g3d.ModelInstance;
 import com.badlogic.gdx.graphics.g3d.model.Node;
 import com.badlogic.gdx.utils.Array;
 
@@ -99,8 +100,8 @@ public class Poi3DLayer extends Layer implements Map.UpdateListener {
     TileSet mTileSet = new TileSet();
     TileSet mPrevTiles = new TileSet();
 
-    LinkedHashMap<Tile, Array<SharedModel>> mTileMap =
-            new LinkedHashMap<Tile, Array<SharedModel>>();
+    LinkedHashMap<Tile, Array<ModelInstance>> mTileMap =
+            new LinkedHashMap<>();
 
     boolean loading;
     Model mModel;
@@ -127,7 +128,7 @@ public class Poi3DLayer extends Layer implements Map.UpdateListener {
         if (ev == Map.CLEAR_EVENT) {
             mTileSet = new TileSet();
             mPrevTiles = new TileSet();
-            mTileMap = new LinkedHashMap<Tile, Array<SharedModel>>();
+            mTileMap = new LinkedHashMap<>();
             synchronized (g3d) {
                 g3d.instances.clear();
             }
@@ -136,7 +137,7 @@ public class Poi3DLayer extends Layer implements Map.UpdateListener {
         if (loading && assets.update()) {
             doneLoading();
             // Renderable renderable = new Renderable();
-            // new SharedModel(mModel).getRenderable(renderable);
+            // new ModelInstance(mModel).getRenderable(renderable);
             // Shader shader = new DefaultShader(renderable, true, false,
             // false, false, 1, 0, 0, 0);
         }
@@ -154,15 +155,15 @@ public class Poi3DLayer extends Layer implements Map.UpdateListener {
 
         boolean changed = false;
 
-        Array<SharedModel> added = new Array<SharedModel>();
-        Array<SharedModel> removed = new Array<SharedModel>();
+        Array<ModelInstance> added = new Array<>();
+        Array<ModelInstance> removed = new Array<>();
 
         for (int i = 0; i < mTileSet.cnt; i++) {
             MapTile t = mTileSet.tiles[i];
             if (mPrevTiles.contains(t))
                 continue;
 
-            Array<SharedModel> instances = new Array<SharedModel>();
+            Array<ModelInstance> instances = new Array<>();
 
             Poi3DTileData ld = (Poi3DTileData) t.getData(POI_DATA);
             if (ld == null)
@@ -170,7 +171,7 @@ public class Poi3DLayer extends Layer implements Map.UpdateListener {
 
             for (SymbolItem it : ld.symbols) {
 
-                SharedModel inst = new SharedModel(mModel);
+                ModelInstance inst = new ModelInstance(mModel);
                 inst.userData = it;
                 // float r = 0.5f + 0.5f * (float) Math.random();
                 // float g = 0.5f + 0.5f * (float) Math.random();
@@ -199,7 +200,7 @@ public class Poi3DLayer extends Layer implements Map.UpdateListener {
             if (mTileSet.contains(t))
                 continue;
 
-            Array<SharedModel> instances = mTileMap.get(t);
+            Array<ModelInstance> instances = mTileMap.get(t);
             if (instances == null)
                 continue;
 
@@ -229,13 +230,13 @@ public class Poi3DLayer extends Layer implements Map.UpdateListener {
 
         synchronized (g3d) {
 
-            for (Entry<Tile, Array<SharedModel>> e : mTileMap.entrySet()) {
+            for (Entry<Tile, Array<ModelInstance>> e : mTileMap.entrySet()) {
                 Tile t = e.getKey();
 
                 float dx = (float) (t.tileX * Tile.SIZE - tileX);
                 float dy = (float) (t.tileY * Tile.SIZE - tileY);
 
-                for (SharedModel inst : e.getValue()) {
+                for (ModelInstance inst : e.getValue()) {
                     SymbolItem it = (SymbolItem) inst.userData;
 
                     // variable height
diff --git a/vtm-playground/src/org/oscim/test/gdx/poi3d/SharedModel.java b/vtm-playground/src/org/oscim/test/gdx/poi3d/SharedModel.java
deleted file mode 100644
index 946ea1c6..00000000
--- a/vtm-playground/src/org/oscim/test/gdx/poi3d/SharedModel.java
+++ /dev/null
@@ -1,555 +0,0 @@
-package org.oscim.test.gdx.poi3d;
-
-import com.badlogic.gdx.graphics.g3d.Material;
-import com.badlogic.gdx.graphics.g3d.Model;
-import com.badlogic.gdx.graphics.g3d.ModelBatch;
-import com.badlogic.gdx.graphics.g3d.Renderable;
-import com.badlogic.gdx.graphics.g3d.RenderableProvider;
-import com.badlogic.gdx.graphics.g3d.model.Animation;
-import com.badlogic.gdx.graphics.g3d.model.MeshPart;
-import com.badlogic.gdx.graphics.g3d.model.Node;
-import com.badlogic.gdx.graphics.g3d.model.NodeAnimation;
-import com.badlogic.gdx.graphics.g3d.model.NodeKeyframe;
-import com.badlogic.gdx.graphics.g3d.model.NodePart;
-import com.badlogic.gdx.math.Matrix4;
-import com.badlogic.gdx.math.Quaternion;
-import com.badlogic.gdx.math.Vector3;
-import com.badlogic.gdx.math.collision.BoundingBox;
-import com.badlogic.gdx.utils.Array;
-import com.badlogic.gdx.utils.ArrayMap;
-import com.badlogic.gdx.utils.ObjectMap;
-import com.badlogic.gdx.utils.Pool;
-
-/**
- * An instance of a {@link Model}, allows to specify global transform and modify the materials, as it
- * has a copy of the model's materials. Multiple instances can be created from the same Model,
- * all sharing the meshes and textures of the Model. The Model owns the meshes and textures, to
- * dispose of these, the Model has to be disposed. Therefor, the Model must outlive all its ModelInstances</p>
- * <p/>
- * The ModelInstance creates a full copy of all materials, nodes and animations.
- *
- * @author badlogic, xoppa
- */
-public class SharedModel implements RenderableProvider {
-    /**
-     * the materials of the model, used by nodes that have a graphical representation FIXME not sure if superfluous, allows modification of materials without having to traverse the nodes
-     **/
-    public final Array<Material> materials = new Array<Material>();
-    /**
-     * root nodes of the model
-     **/
-    public final Array<Node> nodes = new Array<Node>();
-    /**
-     * animations of the model, modifying node transformations
-     **/
-    public final Array<Animation> animations = new Array<Animation>();
-    /**
-     * the {@link Model} this instances derives from
-     **/
-    public final Model model;
-    /**
-     * the world transform
-     **/
-    public Matrix4 transform;
-    /**
-     * user definable value, which is passed to the shader.
-     */
-    public Object userData;
-
-    /**
-     * Constructs a new ModelInstance with all nodes and materials of the given model.
-     *
-     * @param model The {@link Model} to create an instance of.
-     */
-    public SharedModel(final Model model) {
-        this(model, (String[]) null);
-    }
-
-    /**
-     * @param model          The source {@link Model}
-     * @param nodeId         The ID of the root {@link Node} of the {@link Model} for the instance to contain
-     * @param mergeTransform True to apply the source node transform to the instance transform, resetting the node transform.
-     */
-    public SharedModel(final Model model, final String nodeId, boolean mergeTransform) {
-        this(model, null, nodeId, false, false, mergeTransform);
-    }
-
-    /**
-     * @param model          The source {@link Model}
-     * @param transform      The {@link Matrix4} instance for this ModelInstance to reference or null to create a new matrix.
-     * @param nodeId         The ID of the root {@link Node} of the {@link Model} for the instance to contain
-     * @param mergeTransform True to apply the source node transform to the instance transform, resetting the node transform.
-     */
-    public SharedModel(final Model model, final Matrix4 transform, final String nodeId, boolean mergeTransform) {
-        this(model, transform, nodeId, false, false, mergeTransform);
-    }
-
-    /**
-     * Recursively searches the mode for the specified node.
-     *
-     * @param model           The source {@link Model}
-     * @param nodeId          The ID of the {@link Node} within the {@link Model} for the instance to contain
-     * @param parentTransform True to apply the parent's node transform to the instance (only applicable if recursive is true).
-     * @param mergeTransform  True to apply the source node transform to the instance transform, resetting the node transform.
-     */
-    public SharedModel(final Model model, final String nodeId, boolean parentTransform, boolean mergeTransform) {
-        this(model, null, nodeId, true, parentTransform, mergeTransform);
-    }
-
-    /**
-     * Recursively searches the mode for the specified node.
-     *
-     * @param model           The source {@link Model}
-     * @param transform       The {@link Matrix4} instance for this ModelInstance to reference or null to create a new matrix.
-     * @param nodeId          The ID of the {@link Node} within the {@link Model} for the instance to contain
-     * @param parentTransform True to apply the parent's node transform to the instance (only applicable if recursive is true).
-     * @param mergeTransform  True to apply the source node transform to the instance transform, resetting the node transform.
-     */
-    public SharedModel(final Model model, final Matrix4 transform, final String nodeId, boolean parentTransform, boolean mergeTransform) {
-        this(model, transform, nodeId, true, parentTransform, mergeTransform);
-    }
-
-    /**
-     * @param model           The source {@link Model}
-     * @param nodeId          The ID of the {@link Node} within the {@link Model} for the instance to contain
-     * @param recursive       True to recursively search the Model's node tree, false to only search for a root node
-     * @param parentTransform True to apply the parent's node transform to the instance (only applicable if recursive is true).
-     * @param mergeTransform  True to apply the source node transform to the instance transform, resetting the node transform.
-     */
-    public SharedModel(final Model model, final String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform) {
-        this(model, null, nodeId, recursive, parentTransform, mergeTransform);
-    }
-
-    /**
-     * @param model           The source {@link Model}
-     * @param transform       The {@link Matrix4} instance for this ModelInstance to reference or null to create a new matrix.
-     * @param nodeId          The ID of the {@link Node} within the {@link Model} for the instance to contain
-     * @param recursive       True to recursively search the Model's node tree, false to only search for a root node
-     * @param parentTransform True to apply the parent's node transform to the instance (only applicable if recursive is true).
-     * @param mergeTransform  True to apply the source node transform to the instance transform, resetting the node transform.
-     */
-    public SharedModel(final Model model, final Matrix4 transform, final String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform) {
-        this.model = model;
-        this.transform = transform == null ? new Matrix4() : transform;
-        nodePartBones.clear();
-        Node copy, node = model.getNode(nodeId, recursive);
-        this.nodes.add(copy = copyNode(node));
-        if (mergeTransform) {
-            this.transform.mul(parentTransform ? node.globalTransform : node.localTransform);
-            copy.translation.set(0, 0, 0);
-            copy.rotation.idt();
-            copy.scale.set(1, 1, 1);
-        } else if (parentTransform && copy.hasParent())
-            this.transform.mul(node.getParent().globalTransform);
-        setBones();
-        copyAnimations(model.animations);
-        calculateTransforms();
-    }
-
-    /**
-     * Constructs a new ModelInstance with only the specified nodes and materials of the given model.
-     */
-    public SharedModel(final Model model, final String... rootNodeIds) {
-        this(model, null, rootNodeIds);
-    }
-
-    /**
-     * Constructs a new ModelInstance with only the specified nodes and materials of the given model.
-     */
-    public SharedModel(final Model model, final Matrix4 transform, final String... rootNodeIds) {
-        this.model = model;
-        this.transform = transform == null ? new Matrix4() : transform;
-        if (rootNodeIds == null)
-            copyNodes(model.nodes);
-        else
-            copyNodes(model.nodes, rootNodeIds);
-        copyAnimations(model.animations);
-        calculateTransforms();
-    }
-
-    /**
-     * Constructs a new ModelInstance with only the specified nodes and materials of the given model.
-     */
-    public SharedModel(final Model model, final Array<String> rootNodeIds) {
-        this(model, null, rootNodeIds);
-    }
-
-    /**
-     * Constructs a new ModelInstance with only the specified nodes and materials of the given model.
-     */
-    public SharedModel(final Model model, final Matrix4 transform, final Array<String> rootNodeIds) {
-        this.model = model;
-        this.transform = transform == null ? new Matrix4() : transform;
-        copyNodes(model.nodes, rootNodeIds);
-        copyAnimations(model.animations);
-        calculateTransforms();
-    }
-
-    /**
-     * Constructs a new ModelInstance at the specified position.
-     */
-    public SharedModel(final Model model, Vector3 position) {
-        this(model);
-        this.transform.setToTranslation(position);
-    }
-
-    /**
-     * Constructs a new ModelInstance at the specified position.
-     */
-    public SharedModel(final Model model, float x, float y, float z) {
-        this(model);
-        this.transform.setToTranslation(x, y, z);
-    }
-
-    /**
-     * Constructs a new ModelInstance with the specified transform.
-     */
-    public SharedModel(final Model model, Matrix4 transform) {
-        this(model, transform, (String[]) null);
-    }
-
-    /**
-     * Constructs a new ModelInstance which is an copy of the specified ModelInstance.
-     */
-    public SharedModel(SharedModel copyFrom) {
-        this(copyFrom, copyFrom.transform.cpy());
-    }
-
-    /**
-     * Constructs a new ModelInstance which is an copy of the specified ModelInstance.
-     */
-    public SharedModel(SharedModel copyFrom, final Matrix4 transform) {
-        this.model = copyFrom.model;
-        this.transform = transform == null ? new Matrix4() : transform;
-        copyNodes(copyFrom.nodes);
-        copyAnimations(copyFrom.animations);
-        calculateTransforms();
-    }
-
-    /**
-     * @return A newly created ModelInstance which is a copy of this ModelInstance
-     */
-    public SharedModel copy() {
-        return new SharedModel(this);
-    }
-
-    private ObjectMap<NodePart, ArrayMap<Node, Matrix4>> nodePartBones = new ObjectMap<NodePart, ArrayMap<Node, Matrix4>>();
-
-    private void copyNodes(Array<Node> nodes) {
-        nodePartBones.clear();
-        for (int i = 0, n = nodes.size; i < n; ++i) {
-            final Node node = nodes.get(i);
-            this.nodes.add(copyNode(node));
-        }
-        setBones();
-    }
-
-    private void copyNodes(Array<Node> nodes, final String... nodeIds) {
-        nodePartBones.clear();
-        for (int i = 0, n = nodes.size; i < n; ++i) {
-            final Node node = nodes.get(i);
-            for (final String nodeId : nodeIds) {
-                if (nodeId.equals(node.id)) {
-                    this.nodes.add(copyNode(node));
-                    break;
-                }
-            }
-        }
-        setBones();
-    }
-
-    private void copyNodes(Array<Node> nodes, final Array<String> nodeIds) {
-        nodePartBones.clear();
-        for (int i = 0, n = nodes.size; i < n; ++i) {
-            final Node node = nodes.get(i);
-            for (final String nodeId : nodeIds) {
-                if (nodeId.equals(node.id)) {
-                    this.nodes.add(copyNode(node));
-                    break;
-                }
-            }
-        }
-        setBones();
-    }
-
-    private void setBones() {
-        for (ObjectMap.Entry<NodePart, ArrayMap<Node, Matrix4>> e : nodePartBones.entries()) {
-            if (e.key.invBoneBindTransforms == null)
-                e.key.invBoneBindTransforms = new ArrayMap<Node, Matrix4>(true, e.value.size, Node.class, Matrix4.class);
-            e.key.invBoneBindTransforms.clear();
-
-            for (final ObjectMap.Entry<Node, Matrix4> b : e.value.entries())
-                e.key.invBoneBindTransforms.put(getNode(b.key.id), b.value); // Share the inv bind matrix with the model
-
-            e.key.bones = new Matrix4[e.value.size];
-            for (int i = 0; i < e.key.bones.length; i++)
-                e.key.bones[i] = new Matrix4();
-        }
-    }
-
-    private Node copyNode(Node node) {
-        Node copy = new Node();
-        copy.id = node.id;
-        copy.inheritTransform = node.inheritTransform;
-        copy.translation.set(node.translation);
-        copy.rotation.set(node.rotation);
-        copy.scale.set(node.scale);
-        copy.localTransform.set(node.localTransform);
-        copy.globalTransform.set(node.globalTransform);
-        for (NodePart nodePart : node.parts) {
-            copy.parts.add(copyNodePart(nodePart));
-        }
-        for (Node child : node.getChildren()) {
-            copy.addChild(copyNode(child));
-        }
-        return copy;
-    }
-
-    private NodePart copyNodePart(NodePart nodePart) {
-        NodePart copy = new NodePart();
-        copy.meshPart = new MeshPart();
-        copy.meshPart.id = nodePart.meshPart.id;
-        copy.meshPart.offset = nodePart.meshPart.offset;
-        copy.meshPart.size = nodePart.meshPart.size;
-        copy.meshPart.primitiveType = nodePart.meshPart.primitiveType;
-        copy.meshPart.mesh = nodePart.meshPart.mesh;
-
-        if (nodePart.invBoneBindTransforms != null)
-            nodePartBones.put(copy, nodePart.invBoneBindTransforms);
-
-//        final int index = materials.indexOf(nodePart.material, false);
-//        if (index < 0)
-//            materials.add(copy.material = nodePart.material.copy());
-//        else
-//            copy.material = materials.get(index);
-//
-        copy.material = nodePart.material;
-
-        return copy;
-    }
-
-    private void copyAnimations(final Iterable<Animation> source) {
-        for (final Animation anim : source) {
-            Animation animation = new Animation();
-            animation.id = anim.id;
-            for (final NodeAnimation nanim : anim.nodeAnimations) {
-                final Node node = getNode(nanim.node.id);
-                if (node == null)
-                    continue;
-                NodeAnimation nodeAnim = new NodeAnimation();
-                nodeAnim.node = node;
-                if (nanim.rotation != null) {
-                    nodeAnim.rotation = new Array<NodeKeyframe<Quaternion>>();
-                    nodeAnim.rotation.ensureCapacity(nanim.rotation.size);
-                    for (final NodeKeyframe<Quaternion> kf : nanim.rotation) {
-                        if (kf.keytime > animation.duration)
-                            animation.duration = kf.keytime;
-                        nodeAnim.rotation.add(new NodeKeyframe<Quaternion>(kf.keytime, new Quaternion(kf.value == null ? node.rotation : kf.value)));
-                    }
-                }
-                if (nanim.scaling != null) {
-                    nodeAnim.scaling = new Array<NodeKeyframe<Vector3>>();
-                    nodeAnim.scaling.ensureCapacity(nanim.scaling.size);
-                    for (final NodeKeyframe<Vector3> kf : nanim.scaling) {
-                        if (kf.keytime > animation.duration)
-                            animation.duration = kf.keytime;
-                        nodeAnim.scaling.add(new NodeKeyframe<Vector3>(kf.keytime, new Vector3(kf.value == null ? node.scale : kf.value)));
-                    }
-                }
-                if (nanim.translation != null) {
-                    nodeAnim.translation = new Array<NodeKeyframe<Vector3>>();
-                    nodeAnim.translation.ensureCapacity(nanim.translation.size);
-                    for (final NodeKeyframe<Vector3> kf : nanim.translation) {
-                        if (kf.keytime > animation.duration)
-                            animation.duration = kf.keytime;
-                        nodeAnim.translation.add(new NodeKeyframe<Vector3>(kf.keytime, new Vector3(kf.value == null ? node.translation : kf.value)));
-                    }
-                }
-                if ((nodeAnim.rotation != null && nodeAnim.rotation.size > 0)
-                        || (nodeAnim.scaling != null && nodeAnim.scaling.size > 0)
-                        || (nodeAnim.translation != null && nodeAnim.translation.size > 0))
-                    animation.nodeAnimations.add(nodeAnim);
-            }
-            if (animation.nodeAnimations.size > 0)
-                animations.add(animation);
-        }
-    }
-
-
-    /**
-     * Traverses the Node hierarchy and collects {@link Renderable} instances for every
-     * node with a graphical representation. Renderables are obtained from the provided
-     * pool. The resulting array can be rendered via a {@link ModelBatch}.
-     *
-     * @param renderables the output array
-     * @param pool        the pool to obtain Renderables from
-     */
-    public void getRenderables(Array<Renderable> renderables, Pool<Renderable> pool) {
-        for (Node node : nodes) {
-            getRenderables(node, renderables, pool);
-        }
-    }
-
-    /**
-     * @return The renderable of the first node's first part.
-     */
-    public Renderable getRenderable(final Renderable out) {
-        return getRenderable(out, nodes.get(0));
-    }
-
-    /**
-     * @return The renderable of the node's first part.
-     */
-    public Renderable getRenderable(final Renderable out, final Node node) {
-        return getRenderable(out, node, node.parts.get(0));
-    }
-
-    public Renderable getRenderable(final Renderable out, final Node node, final NodePart nodePart) {
-        nodePart.setRenderable(out);
-        if (nodePart.bones == null && transform != null)
-            out.worldTransform.set(transform).mul(node.globalTransform);
-        else if (transform != null)
-            out.worldTransform.set(transform);
-        else
-            out.worldTransform.idt();
-        out.userData = userData;
-        return out;
-    }
-
-    protected void getRenderables(Node node, Array<Renderable> renderables, Pool<Renderable> pool) {
-        if (node.parts.size > 0) {
-            for (NodePart nodePart : node.parts) {
-                renderables.add(getRenderable(pool.obtain(), node, nodePart));
-            }
-        }
-
-        for (Node child : node.getChildren()) {
-            getRenderables(child, renderables, pool);
-        }
-    }
-
-    /**
-     * Calculates the local and world transform of all {@link Node} instances in this model, recursively.
-     * First each {@link Node#localTransform} transform is calculated based on the translation, rotation and
-     * scale of each Node. Then each {@link Node#calculateWorldTransform()}
-     * is calculated, based on the parent's world transform and the local transform of each Node.
-     * Finally, the animation bone matrices are updated accordingly.</p>
-     * <p/>
-     * This method can be used to recalculate all transforms if any of the Node's local properties (translation, rotation, scale)
-     * was modified.
-     */
-    public void calculateTransforms() {
-        final int n = nodes.size;
-        for (int i = 0; i < n; i++) {
-            nodes.get(i).calculateTransforms(true);
-        }
-        for (int i = 0; i < n; i++) {
-            nodes.get(i).calculateBoneTransforms(true);
-        }
-    }
-
-    /**
-     * Calculate the bounding box of this model instance.
-     * This is a potential slow operation, it is advised to cache the result.
-     *
-     * @param out the {@link BoundingBox} that will be set with the bounds.
-     * @return the out parameter for chaining
-     */
-    public BoundingBox calculateBoundingBox(final BoundingBox out) {
-        out.inf();
-        return extendBoundingBox(out);
-    }
-
-    /**
-     * Extends the bounding box with the bounds of this model instance.
-     * This is a potential slow operation, it is advised to cache the result.
-     *
-     * @param out the {@link BoundingBox} that will be extended with the bounds.
-     * @return the out parameter for chaining
-     */
-    public BoundingBox extendBoundingBox(final BoundingBox out) {
-        final int n = nodes.size;
-        for (int i = 0; i < n; i++)
-            nodes.get(i).extendBoundingBox(out);
-        return out;
-    }
-
-    /**
-     * @param id The ID of the animation to fetch (case sensitive).
-     * @return The {@link Animation} with the specified id, or null if not available.
-     */
-    public Animation getAnimation(final String id) {
-        return getAnimation(id, true);
-    }
-
-    /**
-     * @param id         The ID of the animation to fetch.
-     * @param ignoreCase whether to use case sensitivity when comparing the animation id.
-     * @return The {@link Animation} with the specified id, or null if not available.
-     */
-    public Animation getAnimation(final String id, boolean ignoreCase) {
-        final int n = animations.size;
-        Animation animation;
-        if (ignoreCase) {
-            for (int i = 0; i < n; i++)
-                if ((animation = animations.get(i)).id.equalsIgnoreCase(id))
-                    return animation;
-        } else {
-            for (int i = 0; i < n; i++)
-                if ((animation = animations.get(i)).id.equals(id))
-                    return animation;
-        }
-        return null;
-    }
-
-//    /** @param id The ID of the material to fetch.
-//     * @return The {@link Material} with the specified id, or null if not available. */
-//    public Material getMaterial(final String id) {
-//        return getMaterial(id, true);
-//    }
-//
-//    /** @param id The ID of the material to fetch.
-//     * @param ignoreCase whether to use case sensitivity when comparing the material id.
-//     * @return The {@link Material} with the specified id, or null if not available. */
-//    public Material getMaterial(final String id, boolean ignoreCase) {
-//        final int n = materials.size;
-//        Material material;
-//        if (ignoreCase) {
-//            for (int i = 0; i < n; i++)
-//                if ((material = materials.get(i)).id.equalsIgnoreCase(id))
-//                    return material;
-//        } else {
-//            for (int i = 0; i < n; i++)
-//                if ((material = materials.get(i)).id.equals(id))
-//                    return material;
-//        }
-//        return null;
-//    }
-
-    /**
-     * @param id The ID of the node to fetch.
-     * @return The {@link Node} with the specified id, or null if not found.
-     */
-    public Node getNode(final String id) {
-        return getNode(id, true);
-    }
-
-    /**
-     * @param id        The ID of the node to fetch.
-     * @param recursive false to fetch a root node only, true to search the entire node tree for the specified node.
-     * @return The {@link Node} with the specified id, or null if not found.
-     */
-    public Node getNode(final String id, boolean recursive) {
-        return getNode(id, recursive, false);
-    }
-
-    /**
-     * @param id         The ID of the node to fetch.
-     * @param recursive  false to fetch a root node only, true to search the entire node tree for the specified node.
-     * @param ignoreCase whether to use case sensitivity when comparing the node id.
-     * @return The {@link Node} with the specified id, or null if not found.
-     */
-    public Node getNode(final String id, boolean recursive, boolean ignoreCase) {
-        return Node.getNode(nodes, id, recursive, ignoreCase);
-    }
-}