瀏覽代碼

Merge pull request #842 from RaananW/pasring-functions

Pasring functions
David Catuhe 9 年之前
父節點
當前提交
7eea90d666
共有 47 個文件被更改,包括 2397 次插入2270 次删除
  1. 151 0
      src/Actions/babylon.actionManager.js
  2. 180 0
      src/Actions/babylon.actionManager.ts
  3. 32 0
      src/Audio/babylon.sound.js
  4. 42 5
      src/Audio/babylon.sound.ts
  5. 15 0
      src/Bones/babylon.skeleton.js
  6. 21 0
      src/Bones/babylon.skeleton.ts
  7. 107 0
      src/Cameras/babylon.camera.js
  8. 119 0
      src/Cameras/babylon.camera.ts
  9. 1 1
      src/Collisions/babylon.collider.ts
  10. 1 1
      src/LensFlare/babylon.lensFlare.ts
  11. 10 0
      src/LensFlare/babylon.lensFlareSystem.js
  12. 14 0
      src/LensFlare/babylon.lensFlareSystem.ts
  13. 28 0
      src/Lights/Shadows/babylon.shadowGenerator.js
  14. 38 4
      src/Lights/Shadows/babylon.shadowGenerator.ts
  15. 50 0
      src/Lights/babylon.light.js
  16. 64 0
      src/Lights/babylon.light.ts
  17. 33 987
      src/Loading/Plugins/babylon.babylonFileLoader.js
  18. 33 1214
      src/Loading/Plugins/babylon.babylonFileLoader.ts
  19. 11 0
      src/Materials/Textures/babylon.cubeTexture.js
  20. 12 0
      src/Materials/Textures/babylon.cubeTexture.ts
  21. 49 0
      src/Materials/Textures/babylon.texture.js
  22. 56 0
      src/Materials/Textures/babylon.texture.ts
  23. 7 0
      src/Materials/babylon.material.js
  24. 17 8
      src/Materials/babylon.material.ts
  25. 15 0
      src/Materials/babylon.multiMaterial.js
  26. 20 0
      src/Materials/babylon.multiMaterial.ts
  27. 8 8
      src/Materials/babylon.standardMaterial.js
  28. 8 8
      src/Materials/babylon.standardMaterial.ts
  29. 15 0
      src/Math/babylon.math.js
  30. 19 1
      src/Math/babylon.math.ts
  31. 1 1
      src/Mesh/babylon.abstractMesh.ts
  32. 268 0
      src/Mesh/babylon.geometry.js
  33. 354 6
      src/Mesh/babylon.geometry.ts
  34. 1 1
      src/Mesh/babylon.instancedMesh.ts
  35. 163 4
      src/Mesh/babylon.mesh.js
  36. 213 9
      src/Mesh/babylon.mesh.ts
  37. 65 0
      src/Mesh/babylon.mesh.vertexData.js
  38. 84 5
      src/Mesh/babylon.mesh.vertexData.ts
  39. 1 0
      src/Mesh/babylon.meshBuilder.js
  40. 2 1
      src/Mesh/babylon.meshBuilder.ts
  41. 1 1
      src/Mesh/babylon.meshSimplification.ts
  42. 2 2
      src/Mesh/babylon.subMesh.ts
  43. 30 0
      src/Particles/babylon.particleSystem.js
  44. 33 0
      src/Particles/babylon.particleSystem.ts
  45. 1 1
      src/Physics/Plugins/babylon.cannonJSPlugin.ts
  46. 1 1
      src/Tools/babylon.tools.ts
  47. 1 1
      src/babylon.engine.ts

+ 151 - 0
src/Actions/babylon.actionManager.js

@@ -281,6 +281,157 @@ var BABYLON;
             var properties = propertyPath.split(".");
             return properties[properties.length - 1];
         };
+        ActionManager.ParseActions = function (parsedActions, object, scene) {
+            var actionManager = new BABYLON.ActionManager(scene);
+            if (object === null)
+                scene.actionManager = actionManager;
+            else
+                object.actionManager = actionManager;
+            // instanciate a new object
+            var instanciate = function (name, params) {
+                var newInstance = Object.create(BABYLON[name].prototype);
+                newInstance.constructor.apply(newInstance, params);
+                return newInstance;
+            };
+            var parseParameter = function (name, value, target, propertyPath) {
+                if (propertyPath === null) {
+                    // String, boolean or float
+                    var floatValue = parseFloat(value);
+                    if (value === "true" || value === "false")
+                        return value === "true";
+                    else
+                        return isNaN(floatValue) ? value : floatValue;
+                }
+                var effectiveTarget = propertyPath.split(".");
+                var values = value.split(",");
+                // Get effective Target
+                for (var i = 0; i < effectiveTarget.length; i++) {
+                    target = target[effectiveTarget[i]];
+                }
+                // Return appropriate value with its type
+                if (typeof (target) === "boolean")
+                    return values[0] === "true";
+                if (typeof (target) === "string")
+                    return values[0];
+                // Parameters with multiple values such as Vector3 etc.
+                var split = new Array();
+                for (var i = 0; i < values.length; i++)
+                    split.push(parseFloat(values[i]));
+                if (target instanceof BABYLON.Vector3)
+                    return BABYLON.Vector3.FromArray(split);
+                if (target instanceof BABYLON.Vector4)
+                    return BABYLON.Vector4.FromArray(split);
+                if (target instanceof BABYLON.Color3)
+                    return BABYLON.Color3.FromArray(split);
+                if (target instanceof BABYLON.Color4)
+                    return BABYLON.Color4.FromArray(split);
+                return parseFloat(values[0]);
+            };
+            // traverse graph per trigger
+            var traverse = function (parsedAction, trigger, condition, action, combineArray) {
+                if (combineArray === void 0) { combineArray = null; }
+                if (parsedAction.detached)
+                    return;
+                var parameters = new Array();
+                var target = null;
+                var propertyPath = null;
+                var combine = parsedAction.combine && parsedAction.combine.length > 0;
+                // Parameters
+                if (parsedAction.type === 2)
+                    parameters.push(actionManager);
+                else
+                    parameters.push(trigger);
+                if (combine) {
+                    var actions = new Array();
+                    for (var j = 0; j < parsedAction.combine.length; j++) {
+                        traverse(parsedAction.combine[j], ActionManager.NothingTrigger, condition, action, actions);
+                    }
+                    parameters.push(actions);
+                }
+                else {
+                    for (var i = 0; i < parsedAction.properties.length; i++) {
+                        var value = parsedAction.properties[i].value;
+                        var name = parsedAction.properties[i].name;
+                        var targetType = parsedAction.properties[i].targetType;
+                        if (name === "target")
+                            if (targetType !== null && targetType === "SceneProperties")
+                                value = target = scene;
+                            else
+                                value = target = scene.getNodeByName(value);
+                        else if (name === "parent")
+                            value = scene.getNodeByName(value);
+                        else if (name === "sound")
+                            value = scene.getSoundByName(value);
+                        else if (name !== "propertyPath") {
+                            if (parsedAction.type === 2 && name === "operator")
+                                value = BABYLON.ValueCondition[value];
+                            else
+                                value = parseParameter(name, value, target, name === "value" ? propertyPath : null);
+                        }
+                        else {
+                            propertyPath = value;
+                        }
+                        parameters.push(value);
+                    }
+                }
+                if (combineArray === null) {
+                    parameters.push(condition);
+                }
+                else {
+                    parameters.push(null);
+                }
+                // If interpolate value action
+                if (parsedAction.name === "InterpolateValueAction") {
+                    var param = parameters[parameters.length - 2];
+                    parameters[parameters.length - 1] = param;
+                    parameters[parameters.length - 2] = condition;
+                }
+                // Action or condition(s) and not CombineAction
+                var newAction = instanciate(parsedAction.name, parameters);
+                if (newAction instanceof BABYLON.Condition && condition !== null) {
+                    var nothing = new BABYLON.DoNothingAction(trigger, condition);
+                    if (action)
+                        action.then(nothing);
+                    else
+                        actionManager.registerAction(nothing);
+                    action = nothing;
+                }
+                if (combineArray === null) {
+                    if (newAction instanceof BABYLON.Condition) {
+                        condition = newAction;
+                        newAction = action;
+                    }
+                    else {
+                        condition = null;
+                        if (action)
+                            action.then(newAction);
+                        else
+                            actionManager.registerAction(newAction);
+                    }
+                }
+                else {
+                    combineArray.push(newAction);
+                }
+                for (var i = 0; i < parsedAction.children.length; i++)
+                    traverse(parsedAction.children[i], trigger, condition, newAction, null);
+            };
+            // triggers
+            for (var i = 0; i < parsedActions.children.length; i++) {
+                var triggerParams;
+                var trigger = parsedActions.children[i];
+                if (trigger.properties.length > 0) {
+                    var param = trigger.properties[0].value;
+                    var value = trigger.properties[0].targetType === null ? param : scene.getMeshByName(param);
+                    triggerParams = { trigger: BABYLON.ActionManager[trigger.name], parameter: value };
+                }
+                else
+                    triggerParams = BABYLON.ActionManager[trigger.name];
+                for (var j = 0; j < trigger.children.length; j++) {
+                    if (!trigger.detached)
+                        traverse(trigger.children[j], triggerParams, null, null);
+                }
+            }
+        };
         // Statics
         ActionManager._NothingTrigger = 0;
         ActionManager._OnPickTrigger = 1;

+ 180 - 0
src/Actions/babylon.actionManager.ts

@@ -277,5 +277,185 @@
 
             return properties[properties.length - 1];
         }
+
+        public static ParseActions(parsedActions: any, object: AbstractMesh, scene: Scene) {
+            var actionManager = new BABYLON.ActionManager(scene);
+            if (object === null)
+                scene.actionManager = actionManager;
+            else
+                object.actionManager = actionManager;
+
+            // instanciate a new object
+            var instanciate = (name: any, params: Array<any>): any => {
+                var newInstance: Object = Object.create(BABYLON[name].prototype);
+                newInstance.constructor.apply(newInstance, params);
+                return newInstance;
+            };
+
+            var parseParameter = (name: string, value: string, target: any, propertyPath: string): any => {
+                if (propertyPath === null) {
+                    // String, boolean or float
+                    var floatValue = parseFloat(value);
+
+                    if (value === "true" || value === "false")
+                        return value === "true";
+                    else
+                        return isNaN(floatValue) ? value : floatValue;
+                }
+
+                var effectiveTarget = propertyPath.split(".");
+                var values = value.split(",");
+
+                // Get effective Target
+                for (var i = 0; i < effectiveTarget.length; i++) {
+                    target = target[effectiveTarget[i]];
+                }
+
+                // Return appropriate value with its type
+                if (typeof (target) === "boolean")
+                    return values[0] === "true";
+
+                if (typeof (target) === "string")
+                    return values[0];
+
+                // Parameters with multiple values such as Vector3 etc.
+                var split = new Array<number>();
+                for (var i = 0; i < values.length; i++)
+                    split.push(parseFloat(values[i]));
+
+                if (target instanceof Vector3)
+                    return Vector3.FromArray(split);
+
+                if (target instanceof Vector4)
+                    return Vector4.FromArray(split);
+
+                if (target instanceof Color3)
+                    return Color3.FromArray(split);
+
+                if (target instanceof Color4)
+                    return Color4.FromArray(split);
+
+                return parseFloat(values[0]);
+            };
+
+            // traverse graph per trigger
+            var traverse = (parsedAction: any, trigger: any, condition: Condition, action: Action, combineArray: Array<Action> = null) => {
+                if (parsedAction.detached)
+                    return;
+
+                var parameters = new Array<any>();
+                var target: any = null;
+                var propertyPath: string = null;
+                var combine = parsedAction.combine && parsedAction.combine.length > 0;
+
+                // Parameters
+                if (parsedAction.type === 2)
+                    parameters.push(actionManager);
+                else
+                    parameters.push(trigger);
+
+                if (combine) {
+                    var actions = new Array<Action>();
+                    for (var j = 0; j < parsedAction.combine.length; j++) {
+                        traverse(parsedAction.combine[j], ActionManager.NothingTrigger, condition, action, actions);
+                    }
+                    parameters.push(actions);
+                }
+                else {
+                    for (var i = 0; i < parsedAction.properties.length; i++) {
+                        var value = parsedAction.properties[i].value;
+                        var name = parsedAction.properties[i].name;
+                        var targetType = parsedAction.properties[i].targetType;
+
+                        if (name === "target")
+                            if (targetType !== null && targetType === "SceneProperties")
+                                value = target = scene;
+                            else
+                                value = target = scene.getNodeByName(value);
+                        else if (name === "parent")
+                            value = scene.getNodeByName(value);
+                        else if (name === "sound")
+                            value = scene.getSoundByName(value);
+                        else if (name !== "propertyPath") {
+                            if (parsedAction.type === 2 && name === "operator")
+                                value = ValueCondition[value];
+                            else
+                                value = parseParameter(name, value, target, name === "value" ? propertyPath : null);
+                        } else {
+                            propertyPath = value;
+                        }
+
+                        parameters.push(value);
+                    }
+                }
+
+                if (combineArray === null) {
+                    parameters.push(condition);
+                }
+                else {
+                    parameters.push(null);
+                }
+
+                // If interpolate value action
+                if (parsedAction.name === "InterpolateValueAction") {
+                    var param = parameters[parameters.length - 2];
+                    parameters[parameters.length - 1] = param;
+                    parameters[parameters.length - 2] = condition;
+                }
+
+                // Action or condition(s) and not CombineAction
+                var newAction = instanciate(parsedAction.name, parameters);
+
+                if (newAction instanceof Condition && condition !== null) {
+                    var nothing = new DoNothingAction(trigger, condition);
+
+                    if (action)
+                        action.then(nothing);
+                    else
+                        actionManager.registerAction(nothing);
+
+                    action = nothing;
+                }
+
+                if (combineArray === null) {
+                    if (newAction instanceof Condition) {
+                        condition = newAction;
+                        newAction = action;
+                    } else {
+                        condition = null;
+                        if (action)
+                            action.then(newAction);
+                        else
+                            actionManager.registerAction(newAction);
+                    }
+                }
+                else {
+                    combineArray.push(newAction);
+                }
+
+                for (var i = 0; i < parsedAction.children.length; i++)
+                    traverse(parsedAction.children[i], trigger, condition, newAction, null);
+            };
+
+            // triggers
+            for (var i = 0; i < parsedActions.children.length; i++) {
+                var triggerParams: any;
+                var trigger = parsedActions.children[i];
+
+                if (trigger.properties.length > 0) {
+                    var param = trigger.properties[0].value;
+                    var value = trigger.properties[0].targetType === null ? param : scene.getMeshByName(param);
+                    triggerParams = { trigger: BABYLON.ActionManager[trigger.name], parameter: value };
+                }
+                else
+                    triggerParams = BABYLON.ActionManager[trigger.name];
+
+                for (var j = 0; j < trigger.children.length; j++) {
+                    if (!trigger.detached)
+                        traverse(trigger.children[j], triggerParams, null, null);
+                }
+            }
+        }
+
     }
 } 

+ 32 - 0
src/Audio/babylon.sound.js

@@ -439,6 +439,38 @@ var BABYLON;
                 this._updateDirection();
             }
         };
+        Sound.ParseSound = function (parsedSound, scene, rootUrl) {
+            var soundName = parsedSound.name;
+            var soundUrl = rootUrl + soundName;
+            var options = {
+                autoplay: parsedSound.autoplay, loop: parsedSound.loop, volume: parsedSound.volume,
+                spatialSound: parsedSound.spatialSound, maxDistance: parsedSound.maxDistance,
+                rolloffFactor: parsedSound.rolloffFactor,
+                refDistance: parsedSound.refDistance,
+                distanceModel: parsedSound.distanceModel,
+                playbackRate: parsedSound.playbackRate
+            };
+            var newSound = new Sound(soundName, soundUrl, scene, function () { scene._removePendingData(newSound); }, options);
+            scene._addPendingData(newSound);
+            if (parsedSound.position) {
+                var soundPosition = BABYLON.Vector3.FromArray(parsedSound.position);
+                newSound.setPosition(soundPosition);
+            }
+            if (parsedSound.isDirectional) {
+                newSound.setDirectionalCone(parsedSound.coneInnerAngle || 360, parsedSound.coneOuterAngle || 360, parsedSound.coneOuterGain || 0);
+                if (parsedSound.localDirectionToMesh) {
+                    var localDirectionToMesh = BABYLON.Vector3.FromArray(parsedSound.localDirectionToMesh);
+                    newSound.setLocalDirectionToMesh(localDirectionToMesh);
+                }
+            }
+            if (parsedSound.connectedMeshId) {
+                var connectedMesh = scene.getMeshByID(parsedSound.connectedMeshId);
+                if (connectedMesh) {
+                    newSound.attachToMesh(connectedMesh);
+                }
+            }
+            return newSound;
+        };
         return Sound;
     })();
     BABYLON.Sound = Sound;

+ 42 - 5
src/Audio/babylon.sound.ts

@@ -104,7 +104,7 @@
                             this._htmlAudioElement.src = urlOrArrayBuffer;
                             this._htmlAudioElement.controls = false;
                             this._htmlAudioElement.loop = this.loop;
-                            this._htmlAudioElement.crossOrigin = "anonymous"; 
+                            this._htmlAudioElement.crossOrigin = "anonymous";
                             this._isReadyToPlay = true;
                             document.body.appendChild(this._htmlAudioElement);
                             // Simulating a ready to play event for consistent behavior with non streamed audio source
@@ -173,7 +173,7 @@
                     this._htmlAudioElement.src = "";
                     document.body.removeChild(this._htmlAudioElement);
                 }
-                
+
                 if (this._connectedMesh) {
                     this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
                     this._connectedMesh = null;
@@ -188,7 +188,7 @@
                 this._isReadyToPlay = true;
                 if (this.autoplay) { this.play(); }
                 if (this._readyToPlayCallback) { this._readyToPlayCallback(); }
-            },() => { Tools.Error("Error while decoding audio data for: " + this.name); });
+            }, () => { Tools.Error("Error while decoding audio data for: " + this.name); });
         }
 
         public setAudioBuffer(audioBuffer: AudioBuffer): void {
@@ -253,7 +253,7 @@
 
         public switchPanningModelToHRTF() {
             this._panningModel = "HRTF";
-            this._switchPanningModel();    
+            this._switchPanningModel();
         }
 
         public switchPanningModelToEqualPower() {
@@ -423,7 +423,7 @@
                     this.stop(0);
                     this._startOffset += Engine.audioEngine.audioContext.currentTime - this._startTime;
                 }
-                this.isPaused = true;  
+                this.isPaused = true;
             }
         }
 
@@ -477,5 +477,42 @@
                 this._updateDirection();
             }
         }
+
+        public static ParseSound(parsedSound: any, scene: Scene, rootUrl: string): Sound {
+            var soundName = parsedSound.name;
+            var soundUrl = rootUrl + soundName;
+
+            var options = {
+                autoplay: parsedSound.autoplay, loop: parsedSound.loop, volume: parsedSound.volume,
+                spatialSound: parsedSound.spatialSound, maxDistance: parsedSound.maxDistance,
+                rolloffFactor: parsedSound.rolloffFactor,
+                refDistance: parsedSound.refDistance,
+                distanceModel: parsedSound.distanceModel,
+                playbackRate: parsedSound.playbackRate
+            };
+
+            var newSound = new Sound(soundName, soundUrl, scene, () => { scene._removePendingData(newSound); }, options);
+            scene._addPendingData(newSound);
+
+            if (parsedSound.position) {
+                var soundPosition = Vector3.FromArray(parsedSound.position);
+                newSound.setPosition(soundPosition);
+            }
+            if (parsedSound.isDirectional) {
+                newSound.setDirectionalCone(parsedSound.coneInnerAngle || 360, parsedSound.coneOuterAngle || 360, parsedSound.coneOuterGain || 0);
+                if (parsedSound.localDirectionToMesh) {
+                    var localDirectionToMesh = Vector3.FromArray(parsedSound.localDirectionToMesh);
+                    newSound.setLocalDirectionToMesh(localDirectionToMesh);
+                }
+            }
+            if (parsedSound.connectedMeshId) {
+                var connectedMesh = scene.getMeshByID(parsedSound.connectedMeshId);
+                if (connectedMesh) {
+                    newSound.attachToMesh(connectedMesh);
+                }
+            }
+            
+            return newSound;
+        }
     }
 }

+ 15 - 0
src/Bones/babylon.skeleton.js

@@ -103,6 +103,21 @@ var BABYLON;
             // Remove from scene
             this.getScene().removeSkeleton(this);
         };
+        Skeleton.ParseSkeleton = function (parsedSkeleton, scene) {
+            var skeleton = new BABYLON.Skeleton(parsedSkeleton.name, parsedSkeleton.id, scene);
+            for (var index = 0; index < parsedSkeleton.bones.length; index++) {
+                var parsedBone = parsedSkeleton.bones[index];
+                var parentBone = null;
+                if (parsedBone.parentBoneIndex > -1) {
+                    parentBone = skeleton.bones[parsedBone.parentBoneIndex];
+                }
+                var bone = new BABYLON.Bone(parsedBone.name, skeleton, parentBone, BABYLON.Matrix.FromArray(parsedBone.matrix));
+                if (parsedBone.animation) {
+                    bone.animations.push(BABYLON.Animation.ParseAnimation(parsedBone.animation));
+                }
+            }
+            return skeleton;
+        };
         return Skeleton;
     })();
     BABYLON.Skeleton = Skeleton;

+ 21 - 0
src/Bones/babylon.skeleton.ts

@@ -136,5 +136,26 @@
             // Remove from scene
             this.getScene().removeSkeleton(this);
         }
+        
+        public static ParseSkeleton(parsedSkeleton: any, scene: BABYLON.Scene) : BABYLON.Skeleton {
+            var skeleton = new BABYLON.Skeleton(parsedSkeleton.name, parsedSkeleton.id, scene);
+
+            for (var index = 0; index < parsedSkeleton.bones.length; index++) {
+                var parsedBone = parsedSkeleton.bones[index];
+    
+                var parentBone = null;
+                if (parsedBone.parentBoneIndex > -1) {
+                    parentBone = skeleton.bones[parsedBone.parentBoneIndex];
+                }
+    
+                var bone = new BABYLON.Bone(parsedBone.name, skeleton, parentBone, BABYLON.Matrix.FromArray(parsedBone.matrix));
+    
+                if (parsedBone.animation) {
+                    bone.animations.push(Animation.ParseAnimation(parsedBone.animation));
+                }
+            }
+    
+            return skeleton;
+        }
     }
 }

+ 107 - 0
src/Cameras/babylon.camera.js

@@ -516,6 +516,113 @@ var BABYLON;
                 this._rigCameras[0].viewport = this._rigCameras[1].viewport = this.viewport;
             }
         };
+        Camera.ParseCamera = function (parsedCamera, scene) {
+            var camera;
+            var position = BABYLON.Vector3.FromArray(parsedCamera.position);
+            var lockedTargetMesh = (parsedCamera.lockedTargetId) ? scene.getLastMeshByID(parsedCamera.lockedTargetId) : null;
+            if (parsedCamera.type === "AnaglyphArcRotateCamera" || parsedCamera.type === "ArcRotateCamera") {
+                var alpha = parsedCamera.alpha;
+                var beta = parsedCamera.beta;
+                var radius = parsedCamera.radius;
+                if (parsedCamera.type === "AnaglyphArcRotateCamera") {
+                    var interaxial_distance = parsedCamera.interaxial_distance;
+                    camera = new BABYLON.AnaglyphArcRotateCamera(parsedCamera.name, alpha, beta, radius, lockedTargetMesh, interaxial_distance, scene);
+                }
+                else {
+                    camera = new BABYLON.ArcRotateCamera(parsedCamera.name, alpha, beta, radius, lockedTargetMesh, scene);
+                }
+            }
+            else if (parsedCamera.type === "AnaglyphFreeCamera") {
+                interaxial_distance = parsedCamera.interaxial_distance;
+                camera = new BABYLON.AnaglyphFreeCamera(parsedCamera.name, position, interaxial_distance, scene);
+            }
+            else if (parsedCamera.type === "DeviceOrientationCamera") {
+                camera = new BABYLON.DeviceOrientationCamera(parsedCamera.name, position, scene);
+            }
+            else if (parsedCamera.type === "FollowCamera") {
+                camera = new BABYLON.FollowCamera(parsedCamera.name, position, scene);
+                camera.heightOffset = parsedCamera.heightOffset;
+                camera.radius = parsedCamera.radius;
+                camera.rotationOffset = parsedCamera.rotationOffset;
+                if (lockedTargetMesh)
+                    camera.target = lockedTargetMesh;
+            }
+            else if (parsedCamera.type === "GamepadCamera") {
+                camera = new BABYLON.GamepadCamera(parsedCamera.name, position, scene);
+            }
+            else if (parsedCamera.type === "TouchCamera") {
+                camera = new BABYLON.TouchCamera(parsedCamera.name, position, scene);
+            }
+            else if (parsedCamera.type === "VirtualJoysticksCamera") {
+                camera = new BABYLON.VirtualJoysticksCamera(parsedCamera.name, position, scene);
+            }
+            else if (parsedCamera.type === "WebVRFreeCamera") {
+                camera = new BABYLON.WebVRFreeCamera(parsedCamera.name, position, scene);
+            }
+            else if (parsedCamera.type === "VRDeviceOrientationFreeCamera") {
+                camera = new BABYLON.VRDeviceOrientationFreeCamera(parsedCamera.name, position, scene);
+            }
+            else {
+                // Free Camera is the default value
+                camera = new BABYLON.FreeCamera(parsedCamera.name, position, scene);
+            }
+            // apply 3d rig, when found
+            if (parsedCamera.cameraRigMode) {
+                var rigParams = (parsedCamera.interaxial_distance) ? { interaxialDistance: parsedCamera.interaxial_distance } : {};
+                camera.setCameraRigMode(parsedCamera.cameraRigMode, rigParams);
+            }
+            // Test for lockedTargetMesh & FreeCamera outside of if-else-if nest, since things like GamepadCamera extend FreeCamera
+            if (lockedTargetMesh && camera instanceof BABYLON.FreeCamera) {
+                camera.lockedTarget = lockedTargetMesh;
+            }
+            camera.id = parsedCamera.id;
+            BABYLON.Tags.AddTagsTo(camera, parsedCamera.tags);
+            // Parent
+            if (parsedCamera.parentId) {
+                camera._waitingParentId = parsedCamera.parentId;
+            }
+            // Target
+            if (parsedCamera.target) {
+                if (camera.setTarget) {
+                    camera.setTarget(BABYLON.Vector3.FromArray(parsedCamera.target));
+                }
+                else {
+                    //For ArcRotate
+                    camera.target = BABYLON.Vector3.FromArray(parsedCamera.target);
+                }
+            }
+            else {
+                camera.rotation = BABYLON.Vector3.FromArray(parsedCamera.rotation);
+            }
+            camera.fov = parsedCamera.fov;
+            camera.minZ = parsedCamera.minZ;
+            camera.maxZ = parsedCamera.maxZ;
+            camera.speed = parsedCamera.speed;
+            camera.inertia = parsedCamera.inertia;
+            camera.checkCollisions = parsedCamera.checkCollisions;
+            camera.applyGravity = parsedCamera.applyGravity;
+            if (parsedCamera.ellipsoid) {
+                camera.ellipsoid = BABYLON.Vector3.FromArray(parsedCamera.ellipsoid);
+            }
+            // Animations
+            if (parsedCamera.animations) {
+                for (var animationIndex = 0; animationIndex < parsedCamera.animations.length; animationIndex++) {
+                    var parsedAnimation = parsedCamera.animations[animationIndex];
+                    camera.animations.push(BABYLON.Animation.ParseAnimation(parsedAnimation));
+                }
+            }
+            if (parsedCamera.autoAnimate) {
+                scene.beginAnimation(camera, parsedCamera.autoAnimateFrom, parsedCamera.autoAnimateTo, parsedCamera.autoAnimateLoop, 1.0);
+            }
+            // Layer Mask
+            if (parsedCamera.layerMask && (!isNaN(parsedCamera.layerMask))) {
+                camera.layerMask = Math.abs(parseInt(parsedCamera.layerMask));
+            }
+            else {
+                camera.layerMask = 0x0FFFFFFF;
+            }
+            return camera;
+        };
         // Statics
         Camera._PERSPECTIVE_CAMERA = 0;
         Camera._ORTHOGRAPHIC_CAMERA = 1;

+ 119 - 0
src/Cameras/babylon.camera.ts

@@ -584,6 +584,125 @@
                 this._rigCameras[0].viewport = this._rigCameras[1].viewport = this.viewport;
             }
         }
+
+        public static ParseCamera(parsedCamera: any, scene: Scene): Camera {
+            var camera;
+            var position = Vector3.FromArray(parsedCamera.position);
+            var lockedTargetMesh = (parsedCamera.lockedTargetId) ? scene.getLastMeshByID(parsedCamera.lockedTargetId) : null;
+
+            if (parsedCamera.type === "AnaglyphArcRotateCamera" || parsedCamera.type === "ArcRotateCamera") {
+                var alpha = parsedCamera.alpha;
+                var beta = parsedCamera.beta;
+                var radius = parsedCamera.radius;
+                if (parsedCamera.type === "AnaglyphArcRotateCamera") {
+                    var interaxial_distance = parsedCamera.interaxial_distance;
+                    camera = new AnaglyphArcRotateCamera(parsedCamera.name, alpha, beta, radius, lockedTargetMesh, interaxial_distance, scene);
+                } else {
+                    camera = new ArcRotateCamera(parsedCamera.name, alpha, beta, radius, lockedTargetMesh, scene);
+                }
+
+            } else if (parsedCamera.type === "AnaglyphFreeCamera") {
+                interaxial_distance = parsedCamera.interaxial_distance;
+                camera = new AnaglyphFreeCamera(parsedCamera.name, position, interaxial_distance, scene);
+
+            } else if (parsedCamera.type === "DeviceOrientationCamera") {
+                camera = new DeviceOrientationCamera(parsedCamera.name, position, scene);
+
+            } else if (parsedCamera.type === "FollowCamera") {
+                camera = new FollowCamera(parsedCamera.name, position, scene);
+                camera.heightOffset = parsedCamera.heightOffset;
+                camera.radius = parsedCamera.radius;
+                camera.rotationOffset = parsedCamera.rotationOffset;
+                if (lockedTargetMesh)
+                    (<FollowCamera>camera).target = lockedTargetMesh;
+
+            } else if (parsedCamera.type === "GamepadCamera") {
+                camera = new GamepadCamera(parsedCamera.name, position, scene);
+
+            } else if (parsedCamera.type === "TouchCamera") {
+                camera = new TouchCamera(parsedCamera.name, position, scene);
+
+            } else if (parsedCamera.type === "VirtualJoysticksCamera") {
+                camera = new VirtualJoysticksCamera(parsedCamera.name, position, scene);
+
+            } else if (parsedCamera.type === "WebVRFreeCamera") {
+                camera = new WebVRFreeCamera(parsedCamera.name, position, scene);
+
+            } else if (parsedCamera.type === "VRDeviceOrientationFreeCamera") {
+                camera = new VRDeviceOrientationFreeCamera(parsedCamera.name, position, scene);
+
+            } else {
+                // Free Camera is the default value
+                camera = new FreeCamera(parsedCamera.name, position, scene);
+            }
+
+            // apply 3d rig, when found
+            if (parsedCamera.cameraRigMode) {
+                var rigParams = (parsedCamera.interaxial_distance) ? { interaxialDistance: parsedCamera.interaxial_distance } : {};
+                camera.setCameraRigMode(parsedCamera.cameraRigMode, rigParams);
+            }
+
+            // Test for lockedTargetMesh & FreeCamera outside of if-else-if nest, since things like GamepadCamera extend FreeCamera
+            if (lockedTargetMesh && camera instanceof FreeCamera) {
+                (<FreeCamera>camera).lockedTarget = lockedTargetMesh;
+            }
+
+            camera.id = parsedCamera.id;
+
+            Tags.AddTagsTo(camera, parsedCamera.tags);
+
+            // Parent
+            if (parsedCamera.parentId) {
+                camera._waitingParentId = parsedCamera.parentId;
+            }
+
+            // Target
+            if (parsedCamera.target) {
+                if (camera.setTarget) {
+                    camera.setTarget(Vector3.FromArray(parsedCamera.target));
+                } else {
+                    //For ArcRotate
+                    camera.target = Vector3.FromArray(parsedCamera.target);
+                }
+            } else {
+                camera.rotation = Vector3.FromArray(parsedCamera.rotation);
+            }
+
+            camera.fov = parsedCamera.fov;
+            camera.minZ = parsedCamera.minZ;
+            camera.maxZ = parsedCamera.maxZ;
+
+            camera.speed = parsedCamera.speed;
+            camera.inertia = parsedCamera.inertia;
+
+            camera.checkCollisions = parsedCamera.checkCollisions;
+            camera.applyGravity = parsedCamera.applyGravity;
+            if (parsedCamera.ellipsoid) {
+                camera.ellipsoid = Vector3.FromArray(parsedCamera.ellipsoid);
+            }
+
+            // Animations
+            if (parsedCamera.animations) {
+                for (var animationIndex = 0; animationIndex < parsedCamera.animations.length; animationIndex++) {
+                    var parsedAnimation = parsedCamera.animations[animationIndex];
+
+                    camera.animations.push(Animation.ParseAnimation(parsedAnimation));
+                }
+            }
+
+            if (parsedCamera.autoAnimate) {
+                scene.beginAnimation(camera, parsedCamera.autoAnimateFrom, parsedCamera.autoAnimateTo, parsedCamera.autoAnimateLoop, 1.0);
+            }
+
+            // Layer Mask
+            if (parsedCamera.layerMask && (!isNaN(parsedCamera.layerMask))) {
+                camera.layerMask = Math.abs(parseInt(parsedCamera.layerMask));
+            } else {
+                camera.layerMask = 0x0FFFFFFF;
+            }
+
+            return camera;
+        }
     }
 }
 

+ 1 - 1
src/Collisions/babylon.collider.ts

@@ -315,7 +315,7 @@
             }
         }
 
-        public _collide(trianglePlaneArray: Array<Plane>, pts: Vector3[], indices: number[], indexStart: number, indexEnd: number, decal: number, hasMaterial: boolean): void {
+        public _collide(trianglePlaneArray: Array<Plane>, pts: Vector3[], indices: number[] | Int32Array, indexStart: number, indexEnd: number, decal: number, hasMaterial: boolean): void {
             for (var i = indexStart; i < indexEnd; i += 3) {
                 var p1 = pts[indices[i] - decal];
                 var p2 = pts[indices[i + 1] - decal];

+ 1 - 1
src/LensFlare/babylon.lensFlare.ts

@@ -13,7 +13,7 @@
             system.lensFlares.push(this);
         }
 
-        public dispose = function (): void {
+        public dispose = function(): void {
             if (this.texture) {
                 this.texture.dispose();
             }

+ 10 - 0
src/LensFlare/babylon.lensFlareSystem.js

@@ -176,6 +176,16 @@ var BABYLON;
             var index = this._scene.lensFlareSystems.indexOf(this);
             this._scene.lensFlareSystems.splice(index, 1);
         };
+        LensFlareSystem.ParseLensFlareSystem = function (parsedLensFlareSystem, scene, rootUrl) {
+            var emitter = scene.getLastEntryByID(parsedLensFlareSystem.emitterId);
+            var lensFlareSystem = new LensFlareSystem("lensFlareSystem#" + parsedLensFlareSystem.emitterId, emitter, scene);
+            lensFlareSystem.borderLimit = parsedLensFlareSystem.borderLimit;
+            for (var index = 0; index < parsedLensFlareSystem.flares.length; index++) {
+                var parsedFlare = parsedLensFlareSystem.flares[index];
+                var flare = new BABYLON.LensFlare(parsedFlare.size, parsedFlare.position, BABYLON.Color3.FromArray(parsedFlare.color), rootUrl + parsedFlare.textureName, lensFlareSystem);
+            }
+            return lensFlareSystem;
+        };
         return LensFlareSystem;
     })();
     BABYLON.LensFlareSystem = LensFlareSystem;

+ 14 - 0
src/LensFlare/babylon.lensFlareSystem.ts

@@ -233,5 +233,19 @@
             var index = this._scene.lensFlareSystems.indexOf(this);
             this._scene.lensFlareSystems.splice(index, 1);
         }
+        
+        public static ParseLensFlareSystem(parsedLensFlareSystem: any, scene: Scene, rootUrl: string): LensFlareSystem {
+            var emitter = scene.getLastEntryByID(parsedLensFlareSystem.emitterId);
+
+            var lensFlareSystem = new LensFlareSystem("lensFlareSystem#" + parsedLensFlareSystem.emitterId, emitter, scene);
+            lensFlareSystem.borderLimit = parsedLensFlareSystem.borderLimit;
+
+            for (var index = 0; index < parsedLensFlareSystem.flares.length; index++) {
+                var parsedFlare = parsedLensFlareSystem.flares[index];
+                var flare = new LensFlare(parsedFlare.size, parsedFlare.position, Color3.FromArray(parsedFlare.color), rootUrl + parsedFlare.textureName, lensFlareSystem);
+            }
+
+            return lensFlareSystem;
+        }
     }
 } 

+ 28 - 0
src/Lights/Shadows/babylon.shadowGenerator.js

@@ -338,6 +338,34 @@ var BABYLON;
                 this._boxBlurPostprocess.dispose();
             }
         };
+        ShadowGenerator.ParseShadowGenerator = function (parsedShadowGenerator, scene) {
+            //casting to point light, as light is missing the position attr and typescript complains.
+            var light = scene.getLightByID(parsedShadowGenerator.lightId);
+            var shadowGenerator = new ShadowGenerator(parsedShadowGenerator.mapSize, light);
+            for (var meshIndex = 0; meshIndex < parsedShadowGenerator.renderList.length; meshIndex++) {
+                var mesh = scene.getMeshByID(parsedShadowGenerator.renderList[meshIndex]);
+                shadowGenerator.getShadowMap().renderList.push(mesh);
+            }
+            if (parsedShadowGenerator.usePoissonSampling) {
+                shadowGenerator.usePoissonSampling = true;
+            }
+            else if (parsedShadowGenerator.useVarianceShadowMap) {
+                shadowGenerator.useVarianceShadowMap = true;
+            }
+            else if (parsedShadowGenerator.useBlurVarianceShadowMap) {
+                shadowGenerator.useBlurVarianceShadowMap = true;
+                if (parsedShadowGenerator.blurScale) {
+                    shadowGenerator.blurScale = parsedShadowGenerator.blurScale;
+                }
+                if (parsedShadowGenerator.blurBoxOffset) {
+                    shadowGenerator.blurBoxOffset = parsedShadowGenerator.blurBoxOffset;
+                }
+            }
+            if (parsedShadowGenerator.bias !== undefined) {
+                shadowGenerator.bias = parsedShadowGenerator.bias;
+            }
+            return shadowGenerator;
+        };
         ShadowGenerator._FILTER_NONE = 0;
         ShadowGenerator._FILTER_VARIANCESHADOWMAP = 1;
         ShadowGenerator._FILTER_POISSONSAMPLING = 2;

+ 38 - 4
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -89,7 +89,7 @@
                 (!this._light.supportsVSM() && (
                     this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP ||
                     this.filter === ShadowGenerator.FILTER_BLURVARIANCESHADOWMAP
-                    ));
+                ));
         }
         public set usePoissonSampling(value: boolean) {
             this.filter = (value ? ShadowGenerator.FILTER_POISSONSAMPLING : ShadowGenerator.FILTER_NONE);
@@ -135,11 +135,11 @@
             this._shadowMap = new RenderTargetTexture(light.name + "_shadowMap", mapSize, this._scene, false, true, Engine.TEXTURETYPE_UNSIGNED_INT, light.needCube());
             this._shadowMap.wrapU = Texture.CLAMP_ADDRESSMODE;
             this._shadowMap.wrapV = Texture.CLAMP_ADDRESSMODE;
-            this._shadowMap.anisotropicFilteringLevel = 1;        
+            this._shadowMap.anisotropicFilteringLevel = 1;
             this._shadowMap.updateSamplingMode(Texture.NEAREST_SAMPLINGMODE);
             this._shadowMap.renderParticles = false;
 
-            
+
             this._shadowMap.onBeforeRender = (faceIndex: number) => {
                 this._currentFaceIndex = faceIndex;
             }
@@ -332,7 +332,7 @@
             if (Math.abs(Vector3.Dot(this._lightDirection, Vector3.Up())) === 1.0) {
                 this._lightDirection.z = 0.0000000000001; // Need to avoid perfectly perpendicular light
             }
-                
+
             if (this._light.computeTransformedPosition()) {
                 lightPosition = this._light.transformedPosition;
             }
@@ -391,5 +391,39 @@
                 this._boxBlurPostprocess.dispose();
             }
         }
+
+        public static ParseShadowGenerator(parsedShadowGenerator: any, scene: Scene): ShadowGenerator {
+            //casting to point light, as light is missing the position attr and typescript complains.
+            var light = <PointLight> scene.getLightByID(parsedShadowGenerator.lightId);
+            var shadowGenerator = new ShadowGenerator(parsedShadowGenerator.mapSize, light);
+
+            for (var meshIndex = 0; meshIndex < parsedShadowGenerator.renderList.length; meshIndex++) {
+                var mesh = scene.getMeshByID(parsedShadowGenerator.renderList[meshIndex]);
+
+                shadowGenerator.getShadowMap().renderList.push(mesh);
+            }
+
+            if (parsedShadowGenerator.usePoissonSampling) {
+                shadowGenerator.usePoissonSampling = true;
+            } else if (parsedShadowGenerator.useVarianceShadowMap) {
+                shadowGenerator.useVarianceShadowMap = true;
+            } else if (parsedShadowGenerator.useBlurVarianceShadowMap) {
+                shadowGenerator.useBlurVarianceShadowMap = true;
+
+                if (parsedShadowGenerator.blurScale) {
+                    shadowGenerator.blurScale = parsedShadowGenerator.blurScale;
+                }
+
+                if (parsedShadowGenerator.blurBoxOffset) {
+                    shadowGenerator.blurBoxOffset = parsedShadowGenerator.blurBoxOffset;
+                }
+            }
+
+            if (parsedShadowGenerator.bias !== undefined) {
+                shadowGenerator.bias = parsedShadowGenerator.bias;
+            }
+
+            return shadowGenerator;
+        }
     }
 } 

+ 50 - 0
src/Lights/babylon.light.js

@@ -73,6 +73,56 @@ var BABYLON;
             // Remove from scene
             this.getScene().removeLight(this);
         };
+        Light.ParseLight = function (parsedLight, scene) {
+            var light;
+            switch (parsedLight.type) {
+                case 0:
+                    light = new BABYLON.PointLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.position), scene);
+                    break;
+                case 1:
+                    light = new BABYLON.DirectionalLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.direction), scene);
+                    light.position = BABYLON.Vector3.FromArray(parsedLight.position);
+                    break;
+                case 2:
+                    light = new BABYLON.SpotLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.position), BABYLON.Vector3.FromArray(parsedLight.direction), parsedLight.angle, parsedLight.exponent, scene);
+                    break;
+                case 3:
+                    light = new BABYLON.HemisphericLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.direction), scene);
+                    light.groundColor = BABYLON.Color3.FromArray(parsedLight.groundColor);
+                    break;
+            }
+            light.id = parsedLight.id;
+            BABYLON.Tags.AddTagsTo(light, parsedLight.tags);
+            if (parsedLight.intensity !== undefined) {
+                light.intensity = parsedLight.intensity;
+            }
+            if (parsedLight.range) {
+                light.range = parsedLight.range;
+            }
+            light.diffuse = BABYLON.Color3.FromArray(parsedLight.diffuse);
+            light.specular = BABYLON.Color3.FromArray(parsedLight.specular);
+            if (parsedLight.excludedMeshesIds) {
+                light._excludedMeshesIds = parsedLight.excludedMeshesIds;
+            }
+            // Parent
+            if (parsedLight.parentId) {
+                light._waitingParentId = parsedLight.parentId;
+            }
+            if (parsedLight.includedOnlyMeshesIds) {
+                light._includedOnlyMeshesIds = parsedLight.includedOnlyMeshesIds;
+            }
+            // Animations
+            if (parsedLight.animations) {
+                for (var animationIndex = 0; animationIndex < parsedLight.animations.length; animationIndex++) {
+                    var parsedAnimation = parsedLight.animations[animationIndex];
+                    light.animations.push(BABYLON.Animation.ParseAnimation(parsedAnimation));
+                }
+            }
+            if (parsedLight.autoAnimate) {
+                scene.beginAnimation(light, parsedLight.autoAnimateFrom, parsedLight.autoAnimateTo, parsedLight.autoAnimateLoop, 1.0);
+            }
+            return light;
+        };
         return Light;
     })(BABYLON.Node);
     BABYLON.Light = Light;

+ 64 - 0
src/Lights/babylon.light.ts

@@ -112,5 +112,69 @@
             // Remove from scene
             this.getScene().removeLight(this);
         }
+
+        public static ParseLight(parsedLight: any, scene: Scene): Light {
+            var light;
+
+            switch (parsedLight.type) {
+                case 0:
+                    light = new PointLight(parsedLight.name, Vector3.FromArray(parsedLight.position), scene);
+                    break;
+                case 1:
+                    light = new DirectionalLight(parsedLight.name, Vector3.FromArray(parsedLight.direction), scene);
+                    light.position = Vector3.FromArray(parsedLight.position);
+                    break;
+                case 2:
+                    light = new SpotLight(parsedLight.name, Vector3.FromArray(parsedLight.position), Vector3.FromArray(parsedLight.direction), parsedLight.angle, parsedLight.exponent, scene);
+                    break;
+                case 3:
+                    light = new HemisphericLight(parsedLight.name, Vector3.FromArray(parsedLight.direction), scene);
+                    light.groundColor = Color3.FromArray(parsedLight.groundColor);
+                    break;
+            }
+
+            light.id = parsedLight.id;
+
+            Tags.AddTagsTo(light, parsedLight.tags);
+
+            if (parsedLight.intensity !== undefined) {
+                light.intensity = parsedLight.intensity;
+            }
+
+            if (parsedLight.range) {
+                light.range = parsedLight.range;
+            }
+
+            light.diffuse = Color3.FromArray(parsedLight.diffuse);
+            light.specular = Color3.FromArray(parsedLight.specular);
+
+            if (parsedLight.excludedMeshesIds) {
+                light._excludedMeshesIds = parsedLight.excludedMeshesIds;
+            }
+
+            // Parent
+            if (parsedLight.parentId) {
+                light._waitingParentId = parsedLight.parentId;
+            }
+
+            if (parsedLight.includedOnlyMeshesIds) {
+                light._includedOnlyMeshesIds = parsedLight.includedOnlyMeshesIds;
+            }
+
+            // Animations
+            if (parsedLight.animations) {
+                for (var animationIndex = 0; animationIndex < parsedLight.animations.length; animationIndex++) {
+                    var parsedAnimation = parsedLight.animations[animationIndex];
+
+                    light.animations.push(Animation.ParseAnimation(parsedAnimation));
+                }
+            }
+
+            if (parsedLight.autoAnimate) {
+                scene.beginAnimation(light, parsedLight.autoAnimateFrom, parsedLight.autoAnimateTo, parsedLight.autoAnimateLoop, 1.0);
+            }
+            
+            return light;
+        }
     }
 } 

File diff suppressed because it is too large
+ 33 - 987
src/Loading/Plugins/babylon.babylonFileLoader.js


File diff suppressed because it is too large
+ 33 - 1214
src/Loading/Plugins/babylon.babylonFileLoader.ts


+ 11 - 0
src/Materials/Textures/babylon.cubeTexture.js

@@ -57,6 +57,17 @@ var BABYLON;
         CubeTexture.prototype.getReflectionTextureMatrix = function () {
             return this._textureMatrix;
         };
+        CubeTexture.ParseCubeTexture = function (parsedTexture, scene, rootUrl) {
+            var texture = null;
+            if ((parsedTexture.name || parsedTexture.extensions) && !parsedTexture.isRenderTarget) {
+                texture = new BABYLON.CubeTexture(rootUrl + parsedTexture.name, scene, parsedTexture.extensions);
+                texture.name = parsedTexture.name;
+                texture.hasAlpha = parsedTexture.hasAlpha;
+                texture.level = parsedTexture.level;
+                texture.coordinatesMode = parsedTexture.coordinatesMode;
+            }
+            return texture;
+        };
         CubeTexture.prototype.serialize = function () {
             if (!this.name) {
                 return null;

+ 12 - 0
src/Materials/Textures/babylon.cubeTexture.ts

@@ -70,6 +70,18 @@
         public getReflectionTextureMatrix(): Matrix {
             return this._textureMatrix;
         }
+        
+        public static ParseCubeTexture(parsedTexture: any, scene: Scene, rootUrl: string): CubeTexture {
+            var texture = null;
+            if ((parsedTexture.name || parsedTexture.extensions) && !parsedTexture.isRenderTarget) {
+                texture = new BABYLON.CubeTexture(rootUrl + parsedTexture.name, scene, parsedTexture.extensions);
+                texture.name = parsedTexture.name;
+                texture.hasAlpha = parsedTexture.hasAlpha;
+                texture.level = parsedTexture.level;
+                texture.coordinatesMode = parsedTexture.coordinatesMode;
+            }
+            return texture;
+        }
 
         public serialize(): any {
             if (!this.name) {

+ 49 - 0
src/Materials/Textures/babylon.texture.js

@@ -201,6 +201,55 @@ var BABYLON;
             if (onError === void 0) { onError = null; }
             return new Texture("data:" + name, scene, noMipmap, invertY, samplingMode, onLoad, onError, data);
         };
+        Texture.ParseTexture = function (parsedTexture, scene, rootUrl) {
+            if (parsedTexture.isCube) {
+                return BABYLON.CubeTexture.ParseCubeTexture(parsedTexture, scene, rootUrl);
+            }
+            if (!parsedTexture.name && !parsedTexture.isRenderTarget) {
+                return null;
+            }
+            var texture;
+            if (parsedTexture.mirrorPlane) {
+                texture = new BABYLON.MirrorTexture(parsedTexture.name, parsedTexture.renderTargetSize, scene);
+                texture._waitingRenderList = parsedTexture.renderList;
+                texture.mirrorPlane = BABYLON.Plane.FromArray(parsedTexture.mirrorPlane);
+            }
+            else if (parsedTexture.isRenderTarget) {
+                texture = new BABYLON.RenderTargetTexture(parsedTexture.name, parsedTexture.renderTargetSize, scene);
+                texture._waitingRenderList = parsedTexture.renderList;
+            }
+            else {
+                if (parsedTexture.base64String) {
+                    texture = Texture.CreateFromBase64String(parsedTexture.base64String, parsedTexture.name, scene);
+                }
+                else {
+                    texture = new Texture(rootUrl + parsedTexture.name, scene);
+                }
+            }
+            texture.name = parsedTexture.name;
+            texture.hasAlpha = parsedTexture.hasAlpha;
+            texture.getAlphaFromRGB = parsedTexture.getAlphaFromRGB;
+            texture.level = parsedTexture.level;
+            texture.coordinatesIndex = parsedTexture.coordinatesIndex;
+            texture.coordinatesMode = parsedTexture.coordinatesMode;
+            texture.uOffset = parsedTexture.uOffset;
+            texture.vOffset = parsedTexture.vOffset;
+            texture.uScale = parsedTexture.uScale;
+            texture.vScale = parsedTexture.vScale;
+            texture.uAng = parsedTexture.uAng;
+            texture.vAng = parsedTexture.vAng;
+            texture.wAng = parsedTexture.wAng;
+            texture.wrapU = parsedTexture.wrapU;
+            texture.wrapV = parsedTexture.wrapV;
+            // Animations
+            if (parsedTexture.animations) {
+                for (var animationIndex = 0; animationIndex < parsedTexture.animations.length; animationIndex++) {
+                    var parsedAnimation = parsedTexture.animations[animationIndex];
+                    texture.animations.push(BABYLON.Animation.ParseAnimation(parsedAnimation));
+                }
+            }
+            return texture;
+        };
         // Constants
         Texture.NEAREST_SAMPLINGMODE = 1;
         Texture.BILINEAR_SAMPLINGMODE = 2;

+ 56 - 0
src/Materials/Textures/babylon.texture.ts

@@ -259,5 +259,61 @@
         public static CreateFromBase64String(data: string, name: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null): Texture {
             return new Texture("data:" + name, scene, noMipmap, invertY, samplingMode, onLoad, onError, data);
         }
+        
+        public static ParseTexture(parsedTexture: any, scene: Scene, rootUrl: string): BaseTexture {
+            if (parsedTexture.isCube) {
+                return CubeTexture.ParseCubeTexture(parsedTexture, scene, rootUrl);
+            }
+
+            if (!parsedTexture.name && !parsedTexture.isRenderTarget) {
+                return null;
+            }
+
+            var texture;
+
+            if (parsedTexture.mirrorPlane) {
+                texture = new MirrorTexture(parsedTexture.name, parsedTexture.renderTargetSize, scene);
+                texture._waitingRenderList = parsedTexture.renderList;
+                texture.mirrorPlane = Plane.FromArray(parsedTexture.mirrorPlane);
+            } else if (parsedTexture.isRenderTarget) {
+                texture = new RenderTargetTexture(parsedTexture.name, parsedTexture.renderTargetSize, scene);
+                texture._waitingRenderList = parsedTexture.renderList;
+            } else {
+                if (parsedTexture.base64String) {
+                    texture = Texture.CreateFromBase64String(parsedTexture.base64String, parsedTexture.name, scene);
+                } else {
+                    texture = new Texture(rootUrl + parsedTexture.name, scene);
+                }
+            }
+
+            texture.name = parsedTexture.name;
+            texture.hasAlpha = parsedTexture.hasAlpha;
+            texture.getAlphaFromRGB = parsedTexture.getAlphaFromRGB;
+            texture.level = parsedTexture.level;
+
+            texture.coordinatesIndex = parsedTexture.coordinatesIndex;
+            texture.coordinatesMode = parsedTexture.coordinatesMode;
+            texture.uOffset = parsedTexture.uOffset;
+            texture.vOffset = parsedTexture.vOffset;
+            texture.uScale = parsedTexture.uScale;
+            texture.vScale = parsedTexture.vScale;
+            texture.uAng = parsedTexture.uAng;
+            texture.vAng = parsedTexture.vAng;
+            texture.wAng = parsedTexture.wAng;
+
+            texture.wrapU = parsedTexture.wrapU;
+            texture.wrapV = parsedTexture.wrapV;
+
+            // Animations
+            if (parsedTexture.animations) {
+                for (var animationIndex = 0; animationIndex < parsedTexture.animations.length; animationIndex++) {
+                    var parsedAnimation = parsedTexture.animations[animationIndex];
+
+                    texture.animations.push(Animation.ParseAnimation(parsedAnimation));
+                }
+            }
+
+            return texture;
+        }
     }
 } 

+ 7 - 0
src/Materials/babylon.material.js

@@ -241,6 +241,13 @@ var BABYLON;
             serializationObject.backFaceCulling = this.backFaceCulling;
             return serializationObject;
         };
+        Material.ParseMaterial = function (parsedMaterial, scene, rootUrl) {
+            if (!parsedMaterial.customType) {
+                return BABYLON.StandardMaterial.Parse(parsedMaterial, scene, rootUrl);
+            }
+            //TODO this is where custom materials are inspected and parsed.
+            return null;
+        };
         Material._TriangleFillMode = 0;
         Material._WireFrameFillMode = 1;
         Material._PointFillMode = 2;

+ 17 - 8
src/Materials/babylon.material.ts

@@ -26,11 +26,11 @@
             for (var index = 0; index < this._keys.length; index++) {
                 var prop = this._keys[index];
 
-                if (typeof(this[prop]) === "number") {
+                if (typeof (this[prop]) === "number") {
                     this[prop] = 0;
-                
-                }else { 
-                    this[prop] = false; 
+
+                } else {
+                    this[prop] = false;
                 }
             }
         }
@@ -40,10 +40,10 @@
             for (var index = 0; index < this._keys.length; index++) {
                 var prop = this._keys[index];
 
-                if (typeof(this[prop]) === "number") {
-                    result += "#define "  + prop + " " + this[prop] + "\n";
-                
-                }else if (this[prop]) {
+                if (typeof (this[prop]) === "number") {
+                    result += "#define " + prop + " " + this[prop] + "\n";
+
+                } else if (this[prop]) {
                     result += "#define " + prop + "\n";
                 }
             }
@@ -279,5 +279,14 @@
 
             return serializationObject;
         }
+
+        public static ParseMaterial(parsedMaterial: any, scene: Scene, rootUrl: string) {
+            if (!parsedMaterial.customType) {
+                return StandardMaterial.Parse(parsedMaterial, scene, rootUrl);
+            }
+
+            //TODO this is where custom materials are inspected and parsed.
+            return null;
+        }
     }
 } 

+ 15 - 0
src/Materials/babylon.multiMaterial.js

@@ -39,6 +39,21 @@ var BABYLON;
             }
             return newMultiMaterial;
         };
+        MultiMaterial.ParseMultiMaterial = function (parsedMultiMaterial, scene) {
+            var multiMaterial = new BABYLON.MultiMaterial(parsedMultiMaterial.name, scene);
+            multiMaterial.id = parsedMultiMaterial.id;
+            BABYLON.Tags.AddTagsTo(multiMaterial, parsedMultiMaterial.tags);
+            for (var matIndex = 0; matIndex < parsedMultiMaterial.materials.length; matIndex++) {
+                var subMatId = parsedMultiMaterial.materials[matIndex];
+                if (subMatId) {
+                    multiMaterial.subMaterials.push(scene.getMaterialByID(subMatId));
+                }
+                else {
+                    multiMaterial.subMaterials.push(null);
+                }
+            }
+            return multiMaterial;
+        };
         return MultiMaterial;
     })(BABYLON.Material);
     BABYLON.MultiMaterial = MultiMaterial;

+ 20 - 0
src/Materials/babylon.multiMaterial.ts

@@ -41,5 +41,25 @@
 
             return newMultiMaterial;
         }
+
+        public static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial {
+            var multiMaterial = new BABYLON.MultiMaterial(parsedMultiMaterial.name, scene);
+
+            multiMaterial.id = parsedMultiMaterial.id;
+
+            Tags.AddTagsTo(multiMaterial, parsedMultiMaterial.tags);
+
+            for (var matIndex = 0; matIndex < parsedMultiMaterial.materials.length; matIndex++) {
+                var subMatId = parsedMultiMaterial.materials[matIndex];
+
+                if (subMatId) {
+                    multiMaterial.subMaterials.push(scene.getMaterialByID(subMatId));
+                } else {
+                    multiMaterial.subMaterials.push(null);
+                }
+            }
+
+            return multiMaterial;
+        }
     }
 } 

+ 8 - 8
src/Materials/babylon.standardMaterial.js

@@ -952,41 +952,41 @@ var BABYLON;
             material.backFaceCulling = source.backFaceCulling;
             material.wireframe = source.wireframe;
             if (source.diffuseTexture) {
-                material.diffuseTexture = BABYLON.BaseTexture.ParseTexture(source.diffuseTexture, scene, rootUrl);
+                material.diffuseTexture = BABYLON.Texture.ParseTexture(source.diffuseTexture, scene, rootUrl);
             }
             if (source.diffuseFresnelParameters) {
                 material.diffuseFresnelParameters = StandardMaterial.ParseFresnelParameters(source.diffuseFresnelParameters);
             }
             if (source.ambientTexture) {
-                material.ambientTexture = BABYLON.BaseTexture.ParseTexture(source.ambientTexture, scene, rootUrl);
+                material.ambientTexture = BABYLON.Texture.ParseTexture(source.ambientTexture, scene, rootUrl);
             }
             if (source.opacityTexture) {
-                material.opacityTexture = BABYLON.BaseTexture.ParseTexture(source.opacityTexture, scene, rootUrl);
+                material.opacityTexture = BABYLON.Texture.ParseTexture(source.opacityTexture, scene, rootUrl);
             }
             if (source.opacityFresnelParameters) {
                 material.opacityFresnelParameters = StandardMaterial.ParseFresnelParameters(source.opacityFresnelParameters);
             }
             if (source.reflectionTexture) {
-                material.reflectionTexture = BABYLON.BaseTexture.ParseTexture(source.reflectionTexture, scene, rootUrl);
+                material.reflectionTexture = BABYLON.Texture.ParseTexture(source.reflectionTexture, scene, rootUrl);
             }
             if (source.reflectionFresnelParameters) {
                 material.reflectionFresnelParameters = StandardMaterial.ParseFresnelParameters(source.reflectionFresnelParameters);
             }
             if (source.emissiveTexture) {
-                material.emissiveTexture = BABYLON.BaseTexture.ParseTexture(source.emissiveTexture, scene, rootUrl);
+                material.emissiveTexture = BABYLON.Texture.ParseTexture(source.emissiveTexture, scene, rootUrl);
             }
             if (source.lightmapTexture) {
-                material.lightmapTexture = BABYLON.BaseTexture.ParseTexture(source.lightmapTexture, scene, rootUrl);
+                material.lightmapTexture = BABYLON.Texture.ParseTexture(source.lightmapTexture, scene, rootUrl);
                 material.useLightmapAsShadowmap = source.useLightmapAsShadowmap;
             }
             if (source.emissiveFresnelParameters) {
                 material.emissiveFresnelParameters = StandardMaterial.ParseFresnelParameters(source.emissiveFresnelParameters);
             }
             if (source.specularTexture) {
-                material.specularTexture = BABYLON.BaseTexture.ParseTexture(source.specularTexture, scene, rootUrl);
+                material.specularTexture = BABYLON.Texture.ParseTexture(source.specularTexture, scene, rootUrl);
             }
             if (source.bumpTexture) {
-                material.bumpTexture = BABYLON.BaseTexture.ParseTexture(source.bumpTexture, scene, rootUrl);
+                material.bumpTexture = BABYLON.Texture.ParseTexture(source.bumpTexture, scene, rootUrl);
             }
             if (source.checkReadyOnlyOnce) {
                 material.checkReadyOnlyOnce = source.checkReadyOnlyOnce;

+ 8 - 8
src/Materials/babylon.standardMaterial.ts

@@ -1168,7 +1168,7 @@
             material.wireframe = source.wireframe;
 
             if (source.diffuseTexture) {
-                material.diffuseTexture = BaseTexture.ParseTexture(source.diffuseTexture, scene, rootUrl);
+                material.diffuseTexture = Texture.ParseTexture(source.diffuseTexture, scene, rootUrl);
             }
 
             if (source.diffuseFresnelParameters) {
@@ -1176,11 +1176,11 @@
             }
 
             if (source.ambientTexture) {
-                material.ambientTexture = BaseTexture.ParseTexture(source.ambientTexture, scene, rootUrl);
+                material.ambientTexture = Texture.ParseTexture(source.ambientTexture, scene, rootUrl);
             }
 
             if (source.opacityTexture) {
-                material.opacityTexture = BaseTexture.ParseTexture(source.opacityTexture, scene, rootUrl);
+                material.opacityTexture = Texture.ParseTexture(source.opacityTexture, scene, rootUrl);
             }
 
             if (source.opacityFresnelParameters) {
@@ -1188,7 +1188,7 @@
             }
 
             if (source.reflectionTexture) {
-                material.reflectionTexture = BaseTexture.ParseTexture(source.reflectionTexture, scene, rootUrl);
+                material.reflectionTexture = Texture.ParseTexture(source.reflectionTexture, scene, rootUrl);
             }
 
             if (source.reflectionFresnelParameters) {
@@ -1196,11 +1196,11 @@
             }
 
             if (source.emissiveTexture) {
-                material.emissiveTexture = BaseTexture.ParseTexture(source.emissiveTexture, scene, rootUrl);
+                material.emissiveTexture = Texture.ParseTexture(source.emissiveTexture, scene, rootUrl);
             }
 
             if (source.lightmapTexture) {
-                material.lightmapTexture = BaseTexture.ParseTexture(source.lightmapTexture, scene, rootUrl);
+                material.lightmapTexture = Texture.ParseTexture(source.lightmapTexture, scene, rootUrl);
                 material.useLightmapAsShadowmap = source.useLightmapAsShadowmap;
             }
 
@@ -1209,11 +1209,11 @@
             }
 
             if (source.specularTexture) {
-                material.specularTexture = BaseTexture.ParseTexture(source.specularTexture, scene, rootUrl);
+                material.specularTexture = Texture.ParseTexture(source.specularTexture, scene, rootUrl);
             }
 
             if (source.bumpTexture) {
-                material.bumpTexture = BaseTexture.ParseTexture(source.bumpTexture, scene, rootUrl);
+                material.bumpTexture = Texture.ParseTexture(source.bumpTexture, scene, rootUrl);
             }
 
             if (source.checkReadyOnlyOnce) {

+ 15 - 0
src/Math/babylon.math.js

@@ -260,6 +260,21 @@ var BABYLON;
         Color4.FromInts = function (r, g, b, a) {
             return new Color4(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
         };
+        Color4.CheckColors4 = function (colors, count) {
+            // Check if color3 was used
+            if (colors.length === count * 3) {
+                var colors4 = [];
+                for (var index = 0; index < colors.length; index += 3) {
+                    var newIndex = (index / 3) * 4;
+                    colors4[newIndex] = colors[index];
+                    colors4[newIndex + 1] = colors[index + 1];
+                    colors4[newIndex + 2] = colors[index + 2];
+                    colors4[newIndex + 3] = 1.0;
+                }
+                return colors4;
+            }
+            return colors;
+        };
         return Color4;
     })();
     BABYLON.Color4 = Color4;

+ 19 - 1
src/Math/babylon.math.ts

@@ -322,6 +322,24 @@
         public static FromInts(r: number, g: number, b: number, a: number): Color4 {
             return new Color4(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
         }
+
+        public static CheckColors4(colors: number[], count: number): number[] {
+            // Check if color3 was used
+            if (colors.length === count * 3) {
+                var colors4 = [];
+                for (var index = 0; index < colors.length; index += 3) {
+                    var newIndex = (index / 3) * 4;
+                    colors4[newIndex] = colors[index];
+                    colors4[newIndex + 1] = colors[index + 1];
+                    colors4[newIndex + 2] = colors[index + 2];
+                    colors4[newIndex + 3] = 1.0;
+                }
+
+                return colors4;
+            }
+
+            return colors;
+        }
     }
 
     export class Vector2 {
@@ -2429,7 +2447,7 @@
             var resultTranslation = Vector3.Lerp(startTranslation, endTranslation, gradient);
 
             return Matrix.Compose(resultScale, resultRotation, resultTranslation);
-        }    
+        }
 
         public static LookAtLH(eye: Vector3, target: Vector3, up: Vector3): Matrix {
             var result = Matrix.Zero();

+ 1 - 1
src/Mesh/babylon.abstractMesh.ts

@@ -162,7 +162,7 @@
             return 0;
         }
 
-        public getIndices(): number[] {
+        public getIndices(): number[] | Int32Array {
             return null;
         }
 

+ 268 - 0
src/Mesh/babylon.geometry.js

@@ -394,6 +394,211 @@ var BABYLON;
                 return v.toString(16);
             });
         };
+        Geometry.ImportGeometry = function (parsedGeometry, mesh) {
+            var scene = mesh.getScene();
+            // Geometry
+            var geometryId = parsedGeometry.geometryId;
+            if (geometryId) {
+                var geometry = scene.getGeometryByID(geometryId);
+                if (geometry) {
+                    geometry.applyToMesh(mesh);
+                }
+            }
+            else if (parsedGeometry instanceof ArrayBuffer) {
+                var binaryInfo = mesh._binaryInfo;
+                if (binaryInfo.positionsAttrDesc && binaryInfo.positionsAttrDesc.count > 0) {
+                    var positionsData = new Float32Array(parsedGeometry, binaryInfo.positionsAttrDesc.offset, binaryInfo.positionsAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, positionsData, false);
+                }
+                if (binaryInfo.normalsAttrDesc && binaryInfo.normalsAttrDesc.count > 0) {
+                    var normalsData = new Float32Array(parsedGeometry, binaryInfo.normalsAttrDesc.offset, binaryInfo.normalsAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, normalsData, false);
+                }
+                if (binaryInfo.uvsAttrDesc && binaryInfo.uvsAttrDesc.count > 0) {
+                    var uvsData = new Float32Array(parsedGeometry, binaryInfo.uvsAttrDesc.offset, binaryInfo.uvsAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UVKind, uvsData, false);
+                }
+                if (binaryInfo.uvs2AttrDesc && binaryInfo.uvs2AttrDesc.count > 0) {
+                    var uvs2Data = new Float32Array(parsedGeometry, binaryInfo.uvs2AttrDesc.offset, binaryInfo.uvs2AttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV2Kind, uvs2Data, false);
+                }
+                if (binaryInfo.uvs3AttrDesc && binaryInfo.uvs3AttrDesc.count > 0) {
+                    var uvs3Data = new Float32Array(parsedGeometry, binaryInfo.uvs3AttrDesc.offset, binaryInfo.uvs3AttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV3Kind, uvs3Data, false);
+                }
+                if (binaryInfo.uvs4AttrDesc && binaryInfo.uvs4AttrDesc.count > 0) {
+                    var uvs4Data = new Float32Array(parsedGeometry, binaryInfo.uvs4AttrDesc.offset, binaryInfo.uvs4AttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV4Kind, uvs4Data, false);
+                }
+                if (binaryInfo.uvs5AttrDesc && binaryInfo.uvs5AttrDesc.count > 0) {
+                    var uvs5Data = new Float32Array(parsedGeometry, binaryInfo.uvs5AttrDesc.offset, binaryInfo.uvs5AttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV5Kind, uvs5Data, false);
+                }
+                if (binaryInfo.uvs6AttrDesc && binaryInfo.uvs6AttrDesc.count > 0) {
+                    var uvs6Data = new Float32Array(parsedGeometry, binaryInfo.uvs6AttrDesc.offset, binaryInfo.uvs6AttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV6Kind, uvs6Data, false);
+                }
+                if (binaryInfo.colorsAttrDesc && binaryInfo.colorsAttrDesc.count > 0) {
+                    var colorsData = new Float32Array(parsedGeometry, binaryInfo.colorsAttrDesc.offset, binaryInfo.colorsAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.ColorKind, colorsData, false, binaryInfo.colorsAttrDesc.stride);
+                }
+                if (binaryInfo.matricesIndicesAttrDesc && binaryInfo.matricesIndicesAttrDesc.count > 0) {
+                    var matricesIndicesData = new Int32Array(parsedGeometry, binaryInfo.matricesIndicesAttrDesc.offset, binaryInfo.matricesIndicesAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, matricesIndicesData, false);
+                }
+                if (binaryInfo.matricesWeightsAttrDesc && binaryInfo.matricesWeightsAttrDesc.count > 0) {
+                    var matricesWeightsData = new Float32Array(parsedGeometry, binaryInfo.matricesWeightsAttrDesc.offset, binaryInfo.matricesWeightsAttrDesc.count);
+                    mesh.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, matricesWeightsData, false);
+                }
+                if (binaryInfo.indicesAttrDesc && binaryInfo.indicesAttrDesc.count > 0) {
+                    var indicesData = new Int32Array(parsedGeometry, binaryInfo.indicesAttrDesc.offset, binaryInfo.indicesAttrDesc.count);
+                    mesh.setIndices(indicesData);
+                }
+                if (binaryInfo.subMeshesAttrDesc && binaryInfo.subMeshesAttrDesc.count > 0) {
+                    var subMeshesData = new Int32Array(parsedGeometry, binaryInfo.subMeshesAttrDesc.offset, binaryInfo.subMeshesAttrDesc.count * 5);
+                    mesh.subMeshes = [];
+                    for (var i = 0; i < binaryInfo.subMeshesAttrDesc.count; i++) {
+                        var materialIndex = subMeshesData[(i * 5) + 0];
+                        var verticesStart = subMeshesData[(i * 5) + 1];
+                        var verticesCount = subMeshesData[(i * 5) + 2];
+                        var indexStart = subMeshesData[(i * 5) + 3];
+                        var indexCount = subMeshesData[(i * 5) + 4];
+                        var subMesh = new BABYLON.SubMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh);
+                    }
+                }
+            }
+            else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
+                mesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, parsedGeometry.positions, false);
+                mesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, parsedGeometry.normals, false);
+                if (parsedGeometry.uvs) {
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UVKind, parsedGeometry.uvs, false);
+                }
+                if (parsedGeometry.uvs2) {
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV2Kind, parsedGeometry.uvs2, false);
+                }
+                if (parsedGeometry.uvs3) {
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV3Kind, parsedGeometry.uvs3, false);
+                }
+                if (parsedGeometry.uvs4) {
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV4Kind, parsedGeometry.uvs4, false);
+                }
+                if (parsedGeometry.uvs5) {
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV5Kind, parsedGeometry.uvs5, false);
+                }
+                if (parsedGeometry.uvs6) {
+                    mesh.setVerticesData(BABYLON.VertexBuffer.UV6Kind, parsedGeometry.uvs6, false);
+                }
+                if (parsedGeometry.colors) {
+                    mesh.setVerticesData(BABYLON.VertexBuffer.ColorKind, BABYLON.Color4.CheckColors4(parsedGeometry.colors, parsedGeometry.positions.length / 3), false);
+                }
+                if (parsedGeometry.matricesIndices) {
+                    if (!parsedGeometry.matricesIndices._isExpanded) {
+                        var floatIndices = [];
+                        for (var i = 0; i < parsedGeometry.matricesIndices.length; i++) {
+                            var matricesIndex = parsedGeometry.matricesIndices[i];
+                            floatIndices.push(matricesIndex & 0x000000FF);
+                            floatIndices.push((matricesIndex & 0x0000FF00) >> 8);
+                            floatIndices.push((matricesIndex & 0x00FF0000) >> 16);
+                            floatIndices.push(matricesIndex >> 24);
+                        }
+                        mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, floatIndices, false);
+                    }
+                    else {
+                        delete parsedGeometry.matricesIndices._isExpanded;
+                        mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, parsedGeometry.matricesIndices, false);
+                    }
+                }
+                if (parsedGeometry.matricesIndicesExtra) {
+                    if (!parsedGeometry.matricesIndicesExtra._isExpanded) {
+                        var floatIndices = [];
+                        for (var i = 0; i < parsedGeometry.matricesIndicesExtra.length; i++) {
+                            var matricesIndex = parsedGeometry.matricesIndicesExtra[i];
+                            floatIndices.push(matricesIndex & 0x000000FF);
+                            floatIndices.push((matricesIndex & 0x0000FF00) >> 8);
+                            floatIndices.push((matricesIndex & 0x00FF0000) >> 16);
+                            floatIndices.push(matricesIndex >> 24);
+                        }
+                        mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesExtraKind, floatIndices, false);
+                    }
+                    else {
+                        delete parsedGeometry.matricesIndices._isExpanded;
+                        mesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesExtraKind, parsedGeometry.matricesIndicesExtra, false);
+                    }
+                }
+                if (parsedGeometry.matricesWeights) {
+                    mesh.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, parsedGeometry.matricesWeights, false);
+                }
+                if (parsedGeometry.matricesWeightsExtra) {
+                    mesh.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsExtraKind, parsedGeometry.matricesWeightsExtra, false);
+                }
+                mesh.setIndices(parsedGeometry.indices);
+            }
+            // SubMeshes
+            if (parsedGeometry.subMeshes) {
+                mesh.subMeshes = [];
+                for (var subIndex = 0; subIndex < parsedGeometry.subMeshes.length; subIndex++) {
+                    var parsedSubMesh = parsedGeometry.subMeshes[subIndex];
+                    var subMesh = new BABYLON.SubMesh(parsedSubMesh.materialIndex, parsedSubMesh.verticesStart, parsedSubMesh.verticesCount, parsedSubMesh.indexStart, parsedSubMesh.indexCount, mesh);
+                }
+            }
+            // Flat shading
+            if (mesh._shouldGenerateFlatShading) {
+                mesh.convertToFlatShadedMesh();
+                delete mesh._shouldGenerateFlatShading;
+            }
+            // Update
+            mesh.computeWorldMatrix(true);
+            // Octree
+            if (scene['_selectionOctree']) {
+                scene['_selectionOctree'].addMesh(mesh);
+            }
+        };
+        Geometry.ParseGeometry = function (parsedVertexData, scene, rootUrl) {
+            if (scene.getGeometryByID(parsedVertexData.id)) {
+                return null; // null since geometry could be something else than a box...
+            }
+            var geometry = new Geometry(parsedVertexData.id, scene);
+            BABYLON.Tags.AddTagsTo(geometry, parsedVertexData.tags);
+            if (parsedVertexData.delayLoadingFile) {
+                geometry.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
+                geometry.delayLoadingFile = rootUrl + parsedVertexData.delayLoadingFile;
+                geometry._boundingInfo = new BABYLON.BoundingInfo(BABYLON.Vector3.FromArray(parsedVertexData.boundingBoxMinimum), BABYLON.Vector3.FromArray(parsedVertexData.boundingBoxMaximum));
+                geometry._delayInfo = [];
+                if (parsedVertexData.hasUVs) {
+                    geometry._delayInfo.push(BABYLON.VertexBuffer.UVKind);
+                }
+                if (parsedVertexData.hasUVs2) {
+                    geometry._delayInfo.push(BABYLON.VertexBuffer.UV2Kind);
+                }
+                if (parsedVertexData.hasUVs3) {
+                    geometry._delayInfo.push(BABYLON.VertexBuffer.UV3Kind);
+                }
+                if (parsedVertexData.hasUVs4) {
+                    geometry._delayInfo.push(BABYLON.VertexBuffer.UV4Kind);
+                }
+                if (parsedVertexData.hasUVs5) {
+                    geometry._delayInfo.push(BABYLON.VertexBuffer.UV5Kind);
+                }
+                if (parsedVertexData.hasUVs6) {
+                    geometry._delayInfo.push(BABYLON.VertexBuffer.UV6Kind);
+                }
+                if (parsedVertexData.hasColors) {
+                    geometry._delayInfo.push(BABYLON.VertexBuffer.ColorKind);
+                }
+                if (parsedVertexData.hasMatricesIndices) {
+                    geometry._delayInfo.push(BABYLON.VertexBuffer.MatricesIndicesKind);
+                }
+                if (parsedVertexData.hasMatricesWeights) {
+                    geometry._delayInfo.push(BABYLON.VertexBuffer.MatricesWeightsKind);
+                }
+                geometry._delayLoadingFunction = BABYLON.VertexData.ImportVertexData;
+            }
+            else {
+                BABYLON.VertexData.ImportVertexData(parsedVertexData, geometry);
+            }
+            scene.pushGeometry(geometry, true);
+            return geometry;
+        };
         return Geometry;
     })();
     BABYLON.Geometry = Geometry;
@@ -483,6 +688,15 @@ var BABYLON;
                 Box.prototype.copy = function (id) {
                     return new Box(id, this.getScene(), this.size, this.canBeRegenerated(), null, this.side);
                 };
+                Box.ParseBox = function (parsedBox, scene) {
+                    if (scene.getGeometryByID(parsedBox.id)) {
+                        return null; // null since geometry could be something else than a box...
+                    }
+                    var box = new Geometry.Primitives.Box(parsedBox.id, scene, parsedBox.size, parsedBox.canBeRegenerated, null);
+                    BABYLON.Tags.AddTagsTo(box, parsedBox.tags);
+                    scene.pushGeometry(box, true);
+                    return box;
+                };
                 return Box;
             })(_Primitive);
             Primitives.Box = Box;
@@ -501,6 +715,15 @@ var BABYLON;
                 Sphere.prototype.copy = function (id) {
                     return new Sphere(id, this.getScene(), this.segments, this.diameter, this.canBeRegenerated(), null, this.side);
                 };
+                Sphere.ParseSphere = function (parsedSphere, scene) {
+                    if (scene.getGeometryByID(parsedSphere.id)) {
+                        return null; // null since geometry could be something else than a sphere...
+                    }
+                    var sphere = new Geometry.Primitives.Sphere(parsedSphere.id, scene, parsedSphere.segments, parsedSphere.diameter, parsedSphere.canBeRegenerated, null);
+                    BABYLON.Tags.AddTagsTo(sphere, parsedSphere.tags);
+                    scene.pushGeometry(sphere, true);
+                    return sphere;
+                };
                 return Sphere;
             })(_Primitive);
             Primitives.Sphere = Sphere;
@@ -541,6 +764,15 @@ var BABYLON;
                 Cylinder.prototype.copy = function (id) {
                     return new Cylinder(id, this.getScene(), this.height, this.diameterTop, this.diameterBottom, this.tessellation, this.subdivisions, this.canBeRegenerated(), null, this.side);
                 };
+                Cylinder.ParseCylinder = function (parsedCylinder, scene) {
+                    if (scene.getGeometryByID(parsedCylinder.id)) {
+                        return null; // null since geometry could be something else than a cylinder...
+                    }
+                    var cylinder = new Geometry.Primitives.Cylinder(parsedCylinder.id, scene, parsedCylinder.height, parsedCylinder.diameterTop, parsedCylinder.diameterBottom, parsedCylinder.tessellation, parsedCylinder.subdivisions, parsedCylinder.canBeRegenerated, null);
+                    BABYLON.Tags.AddTagsTo(cylinder, parsedCylinder.tags);
+                    scene.pushGeometry(cylinder, true);
+                    return cylinder;
+                };
                 return Cylinder;
             })(_Primitive);
             Primitives.Cylinder = Cylinder;
@@ -560,6 +792,15 @@ var BABYLON;
                 Torus.prototype.copy = function (id) {
                     return new Torus(id, this.getScene(), this.diameter, this.thickness, this.tessellation, this.canBeRegenerated(), null, this.side);
                 };
+                Torus.ParseTorus = function (parsedTorus, scene) {
+                    if (scene.getGeometryByID(parsedTorus.id)) {
+                        return null; // null since geometry could be something else than a torus...
+                    }
+                    var torus = new Geometry.Primitives.Torus(parsedTorus.id, scene, parsedTorus.diameter, parsedTorus.thickness, parsedTorus.tessellation, parsedTorus.canBeRegenerated, null);
+                    BABYLON.Tags.AddTagsTo(torus, parsedTorus.tags);
+                    scene.pushGeometry(torus, true);
+                    return torus;
+                };
                 return Torus;
             })(_Primitive);
             Primitives.Torus = Torus;
@@ -577,6 +818,15 @@ var BABYLON;
                 Ground.prototype.copy = function (id) {
                     return new Ground(id, this.getScene(), this.width, this.height, this.subdivisions, this.canBeRegenerated(), null);
                 };
+                Ground.ParseGround = function (parsedGround, scene) {
+                    if (scene.getGeometryByID(parsedGround.id)) {
+                        return null; // null since geometry could be something else than a ground...
+                    }
+                    var ground = new Geometry.Primitives.Ground(parsedGround.id, scene, parsedGround.width, parsedGround.height, parsedGround.subdivisions, parsedGround.canBeRegenerated, null);
+                    BABYLON.Tags.AddTagsTo(ground, parsedGround.tags);
+                    scene.pushGeometry(ground, true);
+                    return ground;
+                };
                 return Ground;
             })(_Primitive);
             Primitives.Ground = Ground;
@@ -614,6 +864,15 @@ var BABYLON;
                 Plane.prototype.copy = function (id) {
                     return new Plane(id, this.getScene(), this.size, this.canBeRegenerated(), null, this.side);
                 };
+                Plane.ParsePlane = function (parsedPlane, scene) {
+                    if (scene.getGeometryByID(parsedPlane.id)) {
+                        return null; // null since geometry could be something else than a ground...
+                    }
+                    var plane = new Geometry.Primitives.Plane(parsedPlane.id, scene, parsedPlane.size, parsedPlane.canBeRegenerated, null);
+                    BABYLON.Tags.AddTagsTo(plane, parsedPlane.tags);
+                    scene.pushGeometry(plane, true);
+                    return plane;
+                };
                 return Plane;
             })(_Primitive);
             Primitives.Plane = Plane;
@@ -636,6 +895,15 @@ var BABYLON;
                 TorusKnot.prototype.copy = function (id) {
                     return new TorusKnot(id, this.getScene(), this.radius, this.tube, this.radialSegments, this.tubularSegments, this.p, this.q, this.canBeRegenerated(), null, this.side);
                 };
+                TorusKnot.ParseTorusKnot = function (parsedTorusKnot, scene) {
+                    if (scene.getGeometryByID(parsedTorusKnot.id)) {
+                        return null; // null since geometry could be something else than a ground...
+                    }
+                    var torusKnot = new Geometry.Primitives.TorusKnot(parsedTorusKnot.id, scene, parsedTorusKnot.radius, parsedTorusKnot.tube, parsedTorusKnot.radialSegments, parsedTorusKnot.tubularSegments, parsedTorusKnot.p, parsedTorusKnot.q, parsedTorusKnot.canBeRegenerated, null);
+                    BABYLON.Tags.AddTagsTo(torusKnot, parsedTorusKnot.tags);
+                    scene.pushGeometry(torusKnot, true);
+                    return torusKnot;
+                };
                 return TorusKnot;
             })(_Primitive);
             Primitives.TorusKnot = TorusKnot;

+ 354 - 6
src/Mesh/babylon.geometry.ts

@@ -11,7 +11,7 @@
         private _engine: Engine;
         private _meshes: Mesh[];
         private _totalVertices = 0;
-        private _indices: number[];
+        private _indices: number[] | Int32Array;
         private _vertexBuffers;
         private _isDisposed = false;
         private _extend: { minimum: Vector3, maximum: Vector3 };
@@ -209,7 +209,7 @@
             return result;
         }
 
-        public setIndices(indices: number[], totalVertices?: number): void {
+        public setIndices(indices: number[] | Int32Array, totalVertices?: number): void {
             if (this._indexBuffer) {
                 this._engine._releaseBuffer(this._indexBuffer);
             }
@@ -239,7 +239,7 @@
             return this._indices.length;
         }
 
-        public getIndices(copyWhenShared?: boolean): number[] {
+        public getIndices(copyWhenShared?: boolean): number[] | Int32Array {
             if (!this.isReady()) {
                 return null;
             }
@@ -420,7 +420,7 @@
             this._delayLoadingFunction = null;
             this._delayInfo = [];
 
-            this._boundingInfo = null; 
+            this._boundingInfo = null;
 
             this._scene.removeGeometry(this);
             this._isDisposed = true;
@@ -433,7 +433,7 @@
 
             var indices = this.getIndices();
             for (var index = 0; index < indices.length; index++) {
-                vertexData.indices.push(indices[index]);
+                (<number[]>vertexData.indices).push(indices[index]);
             }
 
             var updatable = false;
@@ -490,6 +490,263 @@
                 return v.toString(16);
             });
         }
+
+        public static ImportGeometry(parsedGeometry: any, mesh: Mesh): void {
+            var scene = mesh.getScene();
+
+            // Geometry
+            var geometryId = parsedGeometry.geometryId;
+            if (geometryId) {
+                var geometry = scene.getGeometryByID(geometryId);
+                if (geometry) {
+                    geometry.applyToMesh(mesh);
+                }
+            } else if (parsedGeometry instanceof ArrayBuffer) {
+
+                var binaryInfo = mesh._binaryInfo;
+
+                if (binaryInfo.positionsAttrDesc && binaryInfo.positionsAttrDesc.count > 0) {
+                    var positionsData = new Float32Array(parsedGeometry, binaryInfo.positionsAttrDesc.offset, binaryInfo.positionsAttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.PositionKind, positionsData, false);
+                }
+
+                if (binaryInfo.normalsAttrDesc && binaryInfo.normalsAttrDesc.count > 0) {
+                    var normalsData = new Float32Array(parsedGeometry, binaryInfo.normalsAttrDesc.offset, binaryInfo.normalsAttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.NormalKind, normalsData, false);
+                }
+
+                if (binaryInfo.uvsAttrDesc && binaryInfo.uvsAttrDesc.count > 0) {
+                    var uvsData = new Float32Array(parsedGeometry, binaryInfo.uvsAttrDesc.offset, binaryInfo.uvsAttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.UVKind, uvsData, false);
+                }
+
+                if (binaryInfo.uvs2AttrDesc && binaryInfo.uvs2AttrDesc.count > 0) {
+                    var uvs2Data = new Float32Array(parsedGeometry, binaryInfo.uvs2AttrDesc.offset, binaryInfo.uvs2AttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.UV2Kind, uvs2Data, false);
+                }
+
+                if (binaryInfo.uvs3AttrDesc && binaryInfo.uvs3AttrDesc.count > 0) {
+                    var uvs3Data = new Float32Array(parsedGeometry, binaryInfo.uvs3AttrDesc.offset, binaryInfo.uvs3AttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.UV3Kind, uvs3Data, false);
+                }
+
+                if (binaryInfo.uvs4AttrDesc && binaryInfo.uvs4AttrDesc.count > 0) {
+                    var uvs4Data = new Float32Array(parsedGeometry, binaryInfo.uvs4AttrDesc.offset, binaryInfo.uvs4AttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.UV4Kind, uvs4Data, false);
+                }
+
+                if (binaryInfo.uvs5AttrDesc && binaryInfo.uvs5AttrDesc.count > 0) {
+                    var uvs5Data = new Float32Array(parsedGeometry, binaryInfo.uvs5AttrDesc.offset, binaryInfo.uvs5AttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.UV5Kind, uvs5Data, false);
+                }
+
+                if (binaryInfo.uvs6AttrDesc && binaryInfo.uvs6AttrDesc.count > 0) {
+                    var uvs6Data = new Float32Array(parsedGeometry, binaryInfo.uvs6AttrDesc.offset, binaryInfo.uvs6AttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.UV6Kind, uvs6Data, false);
+                }
+
+                if (binaryInfo.colorsAttrDesc && binaryInfo.colorsAttrDesc.count > 0) {
+                    var colorsData = new Float32Array(parsedGeometry, binaryInfo.colorsAttrDesc.offset, binaryInfo.colorsAttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.ColorKind, colorsData, false, binaryInfo.colorsAttrDesc.stride);
+                }
+
+                if (binaryInfo.matricesIndicesAttrDesc && binaryInfo.matricesIndicesAttrDesc.count > 0) {
+                    var matricesIndicesData = new Int32Array(parsedGeometry, binaryInfo.matricesIndicesAttrDesc.offset, binaryInfo.matricesIndicesAttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, matricesIndicesData, false);
+                }
+
+                if (binaryInfo.matricesWeightsAttrDesc && binaryInfo.matricesWeightsAttrDesc.count > 0) {
+                    var matricesWeightsData = new Float32Array(parsedGeometry, binaryInfo.matricesWeightsAttrDesc.offset, binaryInfo.matricesWeightsAttrDesc.count);
+                    mesh.setVerticesData(VertexBuffer.MatricesWeightsKind, matricesWeightsData, false);
+                }
+
+                if (binaryInfo.indicesAttrDesc && binaryInfo.indicesAttrDesc.count > 0) {
+                    var indicesData = new Int32Array(parsedGeometry, binaryInfo.indicesAttrDesc.offset, binaryInfo.indicesAttrDesc.count);
+                    mesh.setIndices(indicesData);
+                }
+
+                if (binaryInfo.subMeshesAttrDesc && binaryInfo.subMeshesAttrDesc.count > 0) {
+                    var subMeshesData = new Int32Array(parsedGeometry, binaryInfo.subMeshesAttrDesc.offset, binaryInfo.subMeshesAttrDesc.count * 5);
+
+                    mesh.subMeshes = [];
+                    for (var i = 0; i < binaryInfo.subMeshesAttrDesc.count; i++) {
+                        var materialIndex = subMeshesData[(i * 5) + 0];
+                        var verticesStart = subMeshesData[(i * 5) + 1];
+                        var verticesCount = subMeshesData[(i * 5) + 2];
+                        var indexStart = subMeshesData[(i * 5) + 3];
+                        var indexCount = subMeshesData[(i * 5) + 4];
+
+                        var subMesh = new SubMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh);
+                    }
+                }
+            } else if (parsedGeometry.positions && parsedGeometry.normals && parsedGeometry.indices) {
+                mesh.setVerticesData(VertexBuffer.PositionKind, parsedGeometry.positions, false);
+                mesh.setVerticesData(VertexBuffer.NormalKind, parsedGeometry.normals, false);
+
+                if (parsedGeometry.uvs) {
+                    mesh.setVerticesData(VertexBuffer.UVKind, parsedGeometry.uvs, false);
+                }
+
+                if (parsedGeometry.uvs2) {
+                    mesh.setVerticesData(VertexBuffer.UV2Kind, parsedGeometry.uvs2, false);
+                }
+
+                if (parsedGeometry.uvs3) {
+                    mesh.setVerticesData(VertexBuffer.UV3Kind, parsedGeometry.uvs3, false);
+                }
+
+                if (parsedGeometry.uvs4) {
+                    mesh.setVerticesData(VertexBuffer.UV4Kind, parsedGeometry.uvs4, false);
+                }
+
+                if (parsedGeometry.uvs5) {
+                    mesh.setVerticesData(VertexBuffer.UV5Kind, parsedGeometry.uvs5, false);
+                }
+
+                if (parsedGeometry.uvs6) {
+                    mesh.setVerticesData(VertexBuffer.UV6Kind, parsedGeometry.uvs6, false);
+                }
+
+                if (parsedGeometry.colors) {
+                    mesh.setVerticesData(VertexBuffer.ColorKind, Color4.CheckColors4(parsedGeometry.colors, parsedGeometry.positions.length / 3), false);
+                }
+
+                if (parsedGeometry.matricesIndices) {
+                    if (!parsedGeometry.matricesIndices._isExpanded) {
+                        var floatIndices = [];
+
+                        for (var i = 0; i < parsedGeometry.matricesIndices.length; i++) {
+                            var matricesIndex = parsedGeometry.matricesIndices[i];
+
+                            floatIndices.push(matricesIndex & 0x000000FF);
+                            floatIndices.push((matricesIndex & 0x0000FF00) >> 8);
+                            floatIndices.push((matricesIndex & 0x00FF0000) >> 16);
+                            floatIndices.push(matricesIndex >> 24);
+                        }
+
+                        mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, false);
+                    } else {
+                        delete parsedGeometry.matricesIndices._isExpanded;
+                        mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, parsedGeometry.matricesIndices, false);
+                    }
+                }
+
+                if (parsedGeometry.matricesIndicesExtra) {
+                    if (!parsedGeometry.matricesIndicesExtra._isExpanded) {
+                        var floatIndices = [];
+
+                        for (var i = 0; i < parsedGeometry.matricesIndicesExtra.length; i++) {
+                            var matricesIndex = parsedGeometry.matricesIndicesExtra[i];
+
+                            floatIndices.push(matricesIndex & 0x000000FF);
+                            floatIndices.push((matricesIndex & 0x0000FF00) >> 8);
+                            floatIndices.push((matricesIndex & 0x00FF0000) >> 16);
+                            floatIndices.push(matricesIndex >> 24);
+                        }
+
+                        mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, floatIndices, false);
+                    } else {
+                        delete parsedGeometry.matricesIndices._isExpanded;
+                        mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, parsedGeometry.matricesIndicesExtra, false);
+                    }
+                }
+
+                if (parsedGeometry.matricesWeights) {
+                    mesh.setVerticesData(VertexBuffer.MatricesWeightsKind, parsedGeometry.matricesWeights, false);
+                }
+
+                if (parsedGeometry.matricesWeightsExtra) {
+                    mesh.setVerticesData(VertexBuffer.MatricesWeightsExtraKind, parsedGeometry.matricesWeightsExtra, false);
+                }
+
+                mesh.setIndices(parsedGeometry.indices);
+            }
+
+            // SubMeshes
+            if (parsedGeometry.subMeshes) {
+                mesh.subMeshes = [];
+                for (var subIndex = 0; subIndex < parsedGeometry.subMeshes.length; subIndex++) {
+                    var parsedSubMesh = parsedGeometry.subMeshes[subIndex];
+
+                    var subMesh = new SubMesh(parsedSubMesh.materialIndex, parsedSubMesh.verticesStart, parsedSubMesh.verticesCount, parsedSubMesh.indexStart, parsedSubMesh.indexCount, mesh);
+                }
+            }
+
+            // Flat shading
+            if (mesh._shouldGenerateFlatShading) {
+                mesh.convertToFlatShadedMesh();
+                delete mesh._shouldGenerateFlatShading;
+            }
+
+            // Update
+            mesh.computeWorldMatrix(true);
+
+            // Octree
+            if (scene['_selectionOctree']) {
+                scene['_selectionOctree'].addMesh(mesh);
+            }
+        }
+
+        public static ParseGeometry(parsedVertexData: any, scene: Scene, rootUrl: string): Geometry {
+            if (scene.getGeometryByID(parsedVertexData.id)) {
+                return null; // null since geometry could be something else than a box...
+            }
+
+            var geometry = new Geometry(parsedVertexData.id, scene);
+
+            Tags.AddTagsTo(geometry, parsedVertexData.tags);
+
+            if (parsedVertexData.delayLoadingFile) {
+                geometry.delayLoadState = Engine.DELAYLOADSTATE_NOTLOADED;
+                geometry.delayLoadingFile = rootUrl + parsedVertexData.delayLoadingFile;
+                geometry._boundingInfo = new BoundingInfo(Vector3.FromArray(parsedVertexData.boundingBoxMinimum), Vector3.FromArray(parsedVertexData.boundingBoxMaximum));
+
+                geometry._delayInfo = [];
+                if (parsedVertexData.hasUVs) {
+                    geometry._delayInfo.push(VertexBuffer.UVKind);
+                }
+
+                if (parsedVertexData.hasUVs2) {
+                    geometry._delayInfo.push(VertexBuffer.UV2Kind);
+                }
+
+                if (parsedVertexData.hasUVs3) {
+                    geometry._delayInfo.push(VertexBuffer.UV3Kind);
+                }
+
+                if (parsedVertexData.hasUVs4) {
+                    geometry._delayInfo.push(VertexBuffer.UV4Kind);
+                }
+
+                if (parsedVertexData.hasUVs5) {
+                    geometry._delayInfo.push(VertexBuffer.UV5Kind);
+                }
+
+                if (parsedVertexData.hasUVs6) {
+                    geometry._delayInfo.push(VertexBuffer.UV6Kind);
+                }
+
+                if (parsedVertexData.hasColors) {
+                    geometry._delayInfo.push(VertexBuffer.ColorKind);
+                }
+
+                if (parsedVertexData.hasMatricesIndices) {
+                    geometry._delayInfo.push(VertexBuffer.MatricesIndicesKind);
+                }
+
+                if (parsedVertexData.hasMatricesWeights) {
+                    geometry._delayInfo.push(VertexBuffer.MatricesWeightsKind);
+                }
+
+                geometry._delayLoadingFunction = VertexData.ImportVertexData;
+            } else {
+                VertexData.ImportVertexData(parsedVertexData, geometry);
+            }
+
+            scene.pushGeometry(geometry, true);
+
+            return geometry;
+        }
     }
 
     /////// Primitives //////////////////////////////////////////////
@@ -533,7 +790,7 @@
                 super.setAllVerticesData(vertexData, false);
             }
 
-            public setVerticesData(kind: string, data: number[], updatable?: boolean): void {
+            public setVerticesData(kind: string, data: number[] | Int32Array | Float32Array, updatable?: boolean): void {
                 if (!this._beingRegenerated) {
                     return;
                 }
@@ -597,6 +854,19 @@
             public copy(id: string): Geometry {
                 return new Box(id, this.getScene(), this.size, this.canBeRegenerated(), null, this.side);
             }
+
+            public static ParseBox(parsedBox: any, scene: Scene): Geometry.Primitives.Box {
+                if (scene.getGeometryByID(parsedBox.id)) {
+                    return null; // null since geometry could be something else than a box...
+                }
+
+                var box = new Geometry.Primitives.Box(parsedBox.id, scene, parsedBox.size, parsedBox.canBeRegenerated, null);
+                Tags.AddTagsTo(box, parsedBox.tags);
+
+                scene.pushGeometry(box, true);
+
+                return box;
+            }
         }
 
         export class Sphere extends _Primitive {
@@ -620,6 +890,19 @@
             public copy(id: string): Geometry {
                 return new Sphere(id, this.getScene(), this.segments, this.diameter, this.canBeRegenerated(), null, this.side);
             }
+
+            public static ParseSphere(parsedSphere: any, scene: Scene): Geometry.Primitives.Sphere {
+                if (scene.getGeometryByID(parsedSphere.id)) {
+                    return null; // null since geometry could be something else than a sphere...
+                }
+
+                var sphere = new Geometry.Primitives.Sphere(parsedSphere.id, scene, parsedSphere.segments, parsedSphere.diameter, parsedSphere.canBeRegenerated, null);
+                Tags.AddTagsTo(sphere, parsedSphere.tags);
+
+                scene.pushGeometry(sphere, true);
+
+                return sphere;
+            }
         }
 
         export class Disc extends _Primitive {
@@ -673,6 +956,19 @@
             public copy(id: string): Geometry {
                 return new Cylinder(id, this.getScene(), this.height, this.diameterTop, this.diameterBottom, this.tessellation, this.subdivisions, this.canBeRegenerated(), null, this.side);
             }
+
+            public static ParseCylinder(parsedCylinder: any, scene: Scene): Geometry.Primitives.Cylinder {
+                if (scene.getGeometryByID(parsedCylinder.id)) {
+                    return null; // null since geometry could be something else than a cylinder...
+                }
+
+                var cylinder = new Geometry.Primitives.Cylinder(parsedCylinder.id, scene, parsedCylinder.height, parsedCylinder.diameterTop, parsedCylinder.diameterBottom, parsedCylinder.tessellation, parsedCylinder.subdivisions, parsedCylinder.canBeRegenerated, null);
+                Tags.AddTagsTo(cylinder, parsedCylinder.tags);
+
+                scene.pushGeometry(cylinder, true);
+
+                return cylinder;
+            }
         }
 
         export class Torus extends _Primitive {
@@ -698,6 +994,19 @@
             public copy(id: string): Geometry {
                 return new Torus(id, this.getScene(), this.diameter, this.thickness, this.tessellation, this.canBeRegenerated(), null, this.side);
             }
+
+            public static ParseTorus(parsedTorus: any, scene: Scene): Geometry.Primitives.Torus {
+                if (scene.getGeometryByID(parsedTorus.id)) {
+                    return null; // null since geometry could be something else than a torus...
+                }
+
+                var torus = new Geometry.Primitives.Torus(parsedTorus.id, scene, parsedTorus.diameter, parsedTorus.thickness, parsedTorus.tessellation, parsedTorus.canBeRegenerated, null);
+                Tags.AddTagsTo(torus, parsedTorus.tags);
+
+                scene.pushGeometry(torus, true);
+
+                return torus;
+            }
         }
 
         export class Ground extends _Primitive {
@@ -721,6 +1030,19 @@
             public copy(id: string): Geometry {
                 return new Ground(id, this.getScene(), this.width, this.height, this.subdivisions, this.canBeRegenerated(), null);
             }
+
+            public static ParseGround(parsedGround: any, scene: Scene): Geometry.Primitives.Ground {
+                if (scene.getGeometryByID(parsedGround.id)) {
+                    return null; // null since geometry could be something else than a ground...
+                }
+
+                var ground = new Geometry.Primitives.Ground(parsedGround.id, scene, parsedGround.width, parsedGround.height, parsedGround.subdivisions, parsedGround.canBeRegenerated, null);
+                Tags.AddTagsTo(ground, parsedGround.tags);
+
+                scene.pushGeometry(ground, true);
+
+                return ground;
+            }
         }
 
         export class TiledGround extends _Primitive {
@@ -771,6 +1093,19 @@
             public copy(id: string): Geometry {
                 return new Plane(id, this.getScene(), this.size, this.canBeRegenerated(), null, this.side);
             }
+
+            public static ParsePlane(parsedPlane: any, scene: Scene): Geometry.Primitives.Plane {
+                if (scene.getGeometryByID(parsedPlane.id)) {
+                    return null; // null since geometry could be something else than a ground...
+                }
+
+                var plane = new Geometry.Primitives.Plane(parsedPlane.id, scene, parsedPlane.size, parsedPlane.canBeRegenerated, null);
+                Tags.AddTagsTo(plane, parsedPlane.tags);
+
+                scene.pushGeometry(plane, true);
+
+                return plane;
+            }
         }
 
         export class TorusKnot extends _Primitive {
@@ -802,6 +1137,19 @@
             public copy(id: string): Geometry {
                 return new TorusKnot(id, this.getScene(), this.radius, this.tube, this.radialSegments, this.tubularSegments, this.p, this.q, this.canBeRegenerated(), null, this.side);
             }
+
+            public static ParseTorusKnot(parsedTorusKnot: any, scene: Scene): Geometry.Primitives.TorusKnot {
+                if (scene.getGeometryByID(parsedTorusKnot.id)) {
+                    return null; // null since geometry could be something else than a ground...
+                }
+
+                var torusKnot = new Geometry.Primitives.TorusKnot(parsedTorusKnot.id, scene, parsedTorusKnot.radius, parsedTorusKnot.tube, parsedTorusKnot.radialSegments, parsedTorusKnot.tubularSegments, parsedTorusKnot.p, parsedTorusKnot.q, parsedTorusKnot.canBeRegenerated, null);
+                Tags.AddTagsTo(torusKnot, parsedTorusKnot.tags);
+
+                scene.pushGeometry(torusKnot, true);
+
+                return torusKnot;
+            }
         }
     }
 }

+ 1 - 1
src/Mesh/babylon.instancedMesh.ts

@@ -63,7 +63,7 @@
             return this._sourceMesh.isVerticesDataPresent(kind);
         }
 
-        public getIndices(): number[] {
+        public getIndices(): number[] | Int32Array {
             return this._sourceMesh.getIndices();
         }
 

+ 163 - 4
src/Mesh/babylon.mesh.js

@@ -154,8 +154,8 @@ var BABYLON;
         /**
          * Add a mesh as LOD level triggered at the given distance.
          * @param {number} distance - the distance from the center of the object to show this level
-         * @param {BABYLON.Mesh} mesh - the mesh to be added as LOD level
-         * @return {BABYLON.Mesh} this mesh (for chaining)
+         * @param {Mesh} mesh - the mesh to be added as LOD level
+         * @return {Mesh} this mesh (for chaining)
          */
         Mesh.prototype.addLODLevel = function (distance, mesh) {
             if (mesh && mesh._masterMesh) {
@@ -181,8 +181,8 @@ var BABYLON;
         };
         /**
          * Remove a mesh from the LOD array
-         * @param {BABYLON.Mesh} mesh - the mesh to be removed.
-         * @return {BABYLON.Mesh} this mesh (for chaining)
+         * @param {Mesh} mesh - the mesh to be removed.
+         * @return {Mesh} this mesh (for chaining)
          */
         Mesh.prototype.removeLODLevel = function (mesh) {
             for (var index = 0; index < this._LODLevels.length; index++) {
@@ -1059,6 +1059,165 @@ var BABYLON;
             });
         };
         // Statics
+        Mesh.ParseMesh = function (parsedMesh, scene, rootUrl) {
+            var mesh = new Mesh(parsedMesh.name, scene);
+            mesh.id = parsedMesh.id;
+            BABYLON.Tags.AddTagsTo(mesh, parsedMesh.tags);
+            mesh.position = BABYLON.Vector3.FromArray(parsedMesh.position);
+            if (parsedMesh.rotationQuaternion) {
+                mesh.rotationQuaternion = BABYLON.Quaternion.FromArray(parsedMesh.rotationQuaternion);
+            }
+            else if (parsedMesh.rotation) {
+                mesh.rotation = BABYLON.Vector3.FromArray(parsedMesh.rotation);
+            }
+            mesh.scaling = BABYLON.Vector3.FromArray(parsedMesh.scaling);
+            if (parsedMesh.localMatrix) {
+                mesh.setPivotMatrix(BABYLON.Matrix.FromArray(parsedMesh.localMatrix));
+            }
+            else if (parsedMesh.pivotMatrix) {
+                mesh.setPivotMatrix(BABYLON.Matrix.FromArray(parsedMesh.pivotMatrix));
+            }
+            mesh.setEnabled(parsedMesh.isEnabled);
+            mesh.isVisible = parsedMesh.isVisible;
+            mesh.infiniteDistance = parsedMesh.infiniteDistance;
+            mesh.showBoundingBox = parsedMesh.showBoundingBox;
+            mesh.showSubMeshesBoundingBox = parsedMesh.showSubMeshesBoundingBox;
+            if (parsedMesh.applyFog !== undefined) {
+                mesh.applyFog = parsedMesh.applyFog;
+            }
+            if (parsedMesh.pickable !== undefined) {
+                mesh.isPickable = parsedMesh.pickable;
+            }
+            if (parsedMesh.alphaIndex !== undefined) {
+                mesh.alphaIndex = parsedMesh.alphaIndex;
+            }
+            mesh.receiveShadows = parsedMesh.receiveShadows;
+            mesh.billboardMode = parsedMesh.billboardMode;
+            if (parsedMesh.visibility !== undefined) {
+                mesh.visibility = parsedMesh.visibility;
+            }
+            mesh.checkCollisions = parsedMesh.checkCollisions;
+            mesh._shouldGenerateFlatShading = parsedMesh.useFlatShading;
+            // freezeWorldMatrix
+            if (parsedMesh.freezeWorldMatrix) {
+                mesh._waitingFreezeWorldMatrix = parsedMesh.freezeWorldMatrix;
+            }
+            // Parent
+            if (parsedMesh.parentId) {
+                mesh._waitingParentId = parsedMesh.parentId;
+            }
+            // Actions
+            if (parsedMesh.actions !== undefined) {
+                mesh._waitingActions = parsedMesh.actions;
+            }
+            // Geometry
+            mesh.hasVertexAlpha = parsedMesh.hasVertexAlpha;
+            if (parsedMesh.delayLoadingFile) {
+                mesh.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NOTLOADED;
+                mesh.delayLoadingFile = rootUrl + parsedMesh.delayLoadingFile;
+                mesh._boundingInfo = new BABYLON.BoundingInfo(BABYLON.Vector3.FromArray(parsedMesh.boundingBoxMinimum), BABYLON.Vector3.FromArray(parsedMesh.boundingBoxMaximum));
+                if (parsedMesh._binaryInfo) {
+                    mesh._binaryInfo = parsedMesh._binaryInfo;
+                }
+                mesh._delayInfo = [];
+                if (parsedMesh.hasUVs) {
+                    mesh._delayInfo.push(BABYLON.VertexBuffer.UVKind);
+                }
+                if (parsedMesh.hasUVs2) {
+                    mesh._delayInfo.push(BABYLON.VertexBuffer.UV2Kind);
+                }
+                if (parsedMesh.hasUVs3) {
+                    mesh._delayInfo.push(BABYLON.VertexBuffer.UV3Kind);
+                }
+                if (parsedMesh.hasUVs4) {
+                    mesh._delayInfo.push(BABYLON.VertexBuffer.UV4Kind);
+                }
+                if (parsedMesh.hasUVs5) {
+                    mesh._delayInfo.push(BABYLON.VertexBuffer.UV5Kind);
+                }
+                if (parsedMesh.hasUVs6) {
+                    mesh._delayInfo.push(BABYLON.VertexBuffer.UV6Kind);
+                }
+                if (parsedMesh.hasColors) {
+                    mesh._delayInfo.push(BABYLON.VertexBuffer.ColorKind);
+                }
+                if (parsedMesh.hasMatricesIndices) {
+                    mesh._delayInfo.push(BABYLON.VertexBuffer.MatricesIndicesKind);
+                }
+                if (parsedMesh.hasMatricesWeights) {
+                    mesh._delayInfo.push(BABYLON.VertexBuffer.MatricesWeightsKind);
+                }
+                mesh._delayLoadingFunction = BABYLON.Geometry.ImportGeometry;
+                if (BABYLON.SceneLoader.ForceFullSceneLoadingForIncremental) {
+                    mesh._checkDelayState();
+                }
+            }
+            else {
+                BABYLON.Geometry.ImportGeometry(parsedMesh, mesh);
+            }
+            // Material
+            if (parsedMesh.materialId) {
+                mesh.setMaterialByID(parsedMesh.materialId);
+            }
+            else {
+                mesh.material = null;
+            }
+            // Skeleton
+            if (parsedMesh.skeletonId > -1) {
+                mesh.skeleton = scene.getLastSkeletonByID(parsedMesh.skeletonId);
+                if (parsedMesh.numBoneInfluencers) {
+                    mesh.numBoneInfluencers = parsedMesh.numBoneInfluencers;
+                }
+            }
+            // Physics
+            if (parsedMesh.physicsImpostor) {
+                if (!scene.isPhysicsEnabled()) {
+                    scene.enablePhysics();
+                }
+                mesh.setPhysicsState({ impostor: parsedMesh.physicsImpostor, mass: parsedMesh.physicsMass, friction: parsedMesh.physicsFriction, restitution: parsedMesh.physicsRestitution });
+            }
+            // Animations
+            if (parsedMesh.animations) {
+                for (var animationIndex = 0; animationIndex < parsedMesh.animations.length; animationIndex++) {
+                    var parsedAnimation = parsedMesh.animations[animationIndex];
+                    mesh.animations.push(BABYLON.Animation.ParseAnimation(parsedAnimation));
+                }
+            }
+            if (parsedMesh.autoAnimate) {
+                scene.beginAnimation(mesh, parsedMesh.autoAnimateFrom, parsedMesh.autoAnimateTo, parsedMesh.autoAnimateLoop, 1.0);
+            }
+            // Layer Mask
+            if (parsedMesh.layerMask && (!isNaN(parsedMesh.layerMask))) {
+                mesh.layerMask = Math.abs(parseInt(parsedMesh.layerMask));
+            }
+            else {
+                mesh.layerMask = 0x0FFFFFFF;
+            }
+            // Instances
+            if (parsedMesh.instances) {
+                for (var index = 0; index < parsedMesh.instances.length; index++) {
+                    var parsedInstance = parsedMesh.instances[index];
+                    var instance = mesh.createInstance(parsedInstance.name);
+                    BABYLON.Tags.AddTagsTo(instance, parsedInstance.tags);
+                    instance.position = BABYLON.Vector3.FromArray(parsedInstance.position);
+                    if (parsedInstance.rotationQuaternion) {
+                        instance.rotationQuaternion = BABYLON.Quaternion.FromArray(parsedInstance.rotationQuaternion);
+                    }
+                    else if (parsedInstance.rotation) {
+                        instance.rotation = BABYLON.Vector3.FromArray(parsedInstance.rotation);
+                    }
+                    instance.scaling = BABYLON.Vector3.FromArray(parsedInstance.scaling);
+                    instance.checkCollisions = mesh.checkCollisions;
+                    if (parsedMesh.animations) {
+                        for (animationIndex = 0; animationIndex < parsedMesh.animations.length; animationIndex++) {
+                            parsedAnimation = parsedMesh.animations[animationIndex];
+                            instance.animations.push(BABYLON.Animation.ParseAnimation(parsedAnimation));
+                        }
+                    }
+                }
+            }
+            return mesh;
+        };
         Mesh.CreateRibbon = function (name, pathArray, closeArray, closePath, offset, scene, updatable, sideOrientation, instance) {
             return BABYLON.MeshBuilder.CreateRibbon(name, {
                 pathArray: pathArray,

+ 213 - 9
src/Mesh/babylon.mesh.ts

@@ -150,8 +150,8 @@
         /**
          * Add a mesh as LOD level triggered at the given distance.
          * @param {number} distance - the distance from the center of the object to show this level
-         * @param {BABYLON.Mesh} mesh - the mesh to be added as LOD level
-         * @return {BABYLON.Mesh} this mesh (for chaining)
+         * @param {Mesh} mesh - the mesh to be added as LOD level
+         * @return {Mesh} this mesh (for chaining)
          */
         public addLODLevel(distance: number, mesh: Mesh): Mesh {
             if (mesh && mesh._masterMesh) {
@@ -184,8 +184,8 @@
 
         /**
          * Remove a mesh from the LOD array
-         * @param {BABYLON.Mesh} mesh - the mesh to be removed.
-         * @return {BABYLON.Mesh} this mesh (for chaining)
+         * @param {Mesh} mesh - the mesh to be removed.
+         * @return {Mesh} this mesh (for chaining)
          */
         public removeLODLevel(mesh: Mesh): Mesh {
 
@@ -293,7 +293,7 @@
             return this._geometry.getTotalIndices();
         }
 
-        public getIndices(copyWhenShared?: boolean): number[] {
+        public getIndices(copyWhenShared?: boolean): number[] | Int32Array {
             if (!this._geometry) {
                 return [];
             }
@@ -485,7 +485,7 @@
             geometry.applyToMesh(this);
         }
 
-        public setIndices(indices: number[], totalVertices?: number): void {
+        public setIndices(indices: number[] | Int32Array, totalVertices?: number): void {
             if (!this._geometry) {
                 var vertexData = new VertexData();
                 vertexData.indices = indices;
@@ -1240,6 +1240,210 @@
         }
 
         // Statics
+        
+        public static ParseMesh(parsedMesh: any, scene: Scene, rootUrl: string): Mesh {
+            var mesh = new Mesh(parsedMesh.name, scene);
+            mesh.id = parsedMesh.id;
+
+            Tags.AddTagsTo(mesh, parsedMesh.tags);
+
+            mesh.position = Vector3.FromArray(parsedMesh.position);
+
+            if (parsedMesh.rotationQuaternion) {
+                mesh.rotationQuaternion = Quaternion.FromArray(parsedMesh.rotationQuaternion);
+            } else if (parsedMesh.rotation) {
+                mesh.rotation = Vector3.FromArray(parsedMesh.rotation);
+            }
+
+            mesh.scaling = Vector3.FromArray(parsedMesh.scaling);
+
+            if (parsedMesh.localMatrix) {
+                mesh.setPivotMatrix(Matrix.FromArray(parsedMesh.localMatrix));
+            } else if (parsedMesh.pivotMatrix) {
+                mesh.setPivotMatrix(Matrix.FromArray(parsedMesh.pivotMatrix));
+            }
+
+            mesh.setEnabled(parsedMesh.isEnabled);
+            mesh.isVisible = parsedMesh.isVisible;
+            mesh.infiniteDistance = parsedMesh.infiniteDistance;
+
+            mesh.showBoundingBox = parsedMesh.showBoundingBox;
+            mesh.showSubMeshesBoundingBox = parsedMesh.showSubMeshesBoundingBox;
+
+            if (parsedMesh.applyFog !== undefined) {
+                mesh.applyFog = parsedMesh.applyFog;
+            }
+
+            if (parsedMesh.pickable !== undefined) {
+                mesh.isPickable = parsedMesh.pickable;
+            }
+
+            if (parsedMesh.alphaIndex !== undefined) {
+                mesh.alphaIndex = parsedMesh.alphaIndex;
+            }
+
+            mesh.receiveShadows = parsedMesh.receiveShadows;
+
+            mesh.billboardMode = parsedMesh.billboardMode;
+
+            if (parsedMesh.visibility !== undefined) {
+                mesh.visibility = parsedMesh.visibility;
+            }
+
+            mesh.checkCollisions = parsedMesh.checkCollisions;
+            mesh._shouldGenerateFlatShading = parsedMesh.useFlatShading;
+
+            // freezeWorldMatrix
+            if (parsedMesh.freezeWorldMatrix) {
+                mesh._waitingFreezeWorldMatrix = parsedMesh.freezeWorldMatrix;
+            }
+
+            // Parent
+            if (parsedMesh.parentId) {
+                mesh._waitingParentId = parsedMesh.parentId;
+            }
+
+            // Actions
+            if (parsedMesh.actions !== undefined) {
+                mesh._waitingActions = parsedMesh.actions;
+            }
+
+            // Geometry
+            mesh.hasVertexAlpha = parsedMesh.hasVertexAlpha;
+
+            if (parsedMesh.delayLoadingFile) {
+                mesh.delayLoadState = Engine.DELAYLOADSTATE_NOTLOADED;
+                mesh.delayLoadingFile = rootUrl + parsedMesh.delayLoadingFile;
+                mesh._boundingInfo = new BoundingInfo(Vector3.FromArray(parsedMesh.boundingBoxMinimum), Vector3.FromArray(parsedMesh.boundingBoxMaximum));
+
+                if (parsedMesh._binaryInfo) {
+                    mesh._binaryInfo = parsedMesh._binaryInfo;
+                }
+
+                mesh._delayInfo = [];
+                if (parsedMesh.hasUVs) {
+                    mesh._delayInfo.push(VertexBuffer.UVKind);
+                }
+
+                if (parsedMesh.hasUVs2) {
+                    mesh._delayInfo.push(VertexBuffer.UV2Kind);
+                }
+
+                if (parsedMesh.hasUVs3) {
+                    mesh._delayInfo.push(VertexBuffer.UV3Kind);
+                }
+
+                if (parsedMesh.hasUVs4) {
+                    mesh._delayInfo.push(VertexBuffer.UV4Kind);
+                }
+
+                if (parsedMesh.hasUVs5) {
+                    mesh._delayInfo.push(VertexBuffer.UV5Kind);
+                }
+
+                if (parsedMesh.hasUVs6) {
+                    mesh._delayInfo.push(VertexBuffer.UV6Kind);
+                }
+
+                if (parsedMesh.hasColors) {
+                    mesh._delayInfo.push(VertexBuffer.ColorKind);
+                }
+
+                if (parsedMesh.hasMatricesIndices) {
+                    mesh._delayInfo.push(VertexBuffer.MatricesIndicesKind);
+                }
+
+                if (parsedMesh.hasMatricesWeights) {
+                    mesh._delayInfo.push(VertexBuffer.MatricesWeightsKind);
+                }
+
+                mesh._delayLoadingFunction = Geometry.ImportGeometry;
+
+                if (SceneLoader.ForceFullSceneLoadingForIncremental) {
+                    mesh._checkDelayState();
+                }
+
+            } else {
+                Geometry.ImportGeometry(parsedMesh, mesh);
+            }
+
+            // Material
+            if (parsedMesh.materialId) {
+                mesh.setMaterialByID(parsedMesh.materialId);
+            } else {
+                mesh.material = null;
+            }
+
+            // Skeleton
+            if (parsedMesh.skeletonId > -1) {
+                mesh.skeleton = scene.getLastSkeletonByID(parsedMesh.skeletonId);
+                if (parsedMesh.numBoneInfluencers) {
+                    mesh.numBoneInfluencers = parsedMesh.numBoneInfluencers;
+                }
+            }
+
+            // Physics
+            if (parsedMesh.physicsImpostor) {
+                if (!scene.isPhysicsEnabled()) {
+                    scene.enablePhysics();
+                }
+
+                mesh.setPhysicsState({ impostor: parsedMesh.physicsImpostor, mass: parsedMesh.physicsMass, friction: parsedMesh.physicsFriction, restitution: parsedMesh.physicsRestitution });
+            }
+
+            // Animations
+            if (parsedMesh.animations) {
+                for (var animationIndex = 0; animationIndex < parsedMesh.animations.length; animationIndex++) {
+                    var parsedAnimation = parsedMesh.animations[animationIndex];
+
+                    mesh.animations.push(Animation.ParseAnimation(parsedAnimation));
+                }
+            }
+
+            if (parsedMesh.autoAnimate) {
+                scene.beginAnimation(mesh, parsedMesh.autoAnimateFrom, parsedMesh.autoAnimateTo, parsedMesh.autoAnimateLoop, 1.0);
+            }
+
+            // Layer Mask
+            if (parsedMesh.layerMask && (!isNaN(parsedMesh.layerMask))) {
+                mesh.layerMask = Math.abs(parseInt(parsedMesh.layerMask));
+            } else {
+                mesh.layerMask = 0x0FFFFFFF;
+            }
+
+            // Instances
+            if (parsedMesh.instances) {
+                for (var index = 0; index < parsedMesh.instances.length; index++) {
+                    var parsedInstance = parsedMesh.instances[index];
+                    var instance = mesh.createInstance(parsedInstance.name);
+
+                    Tags.AddTagsTo(instance, parsedInstance.tags);
+
+                    instance.position = Vector3.FromArray(parsedInstance.position);
+
+                    if (parsedInstance.rotationQuaternion) {
+                        instance.rotationQuaternion = Quaternion.FromArray(parsedInstance.rotationQuaternion);
+                    } else if (parsedInstance.rotation) {
+                        instance.rotation = Vector3.FromArray(parsedInstance.rotation);
+                    }
+
+                    instance.scaling = Vector3.FromArray(parsedInstance.scaling);
+
+                    instance.checkCollisions = mesh.checkCollisions;
+
+                    if (parsedMesh.animations) {
+                        for (animationIndex = 0; animationIndex < parsedMesh.animations.length; animationIndex++) {
+                            parsedAnimation = parsedMesh.animations[animationIndex];
+
+                            instance.animations.push(Animation.ParseAnimation(parsedAnimation));
+                        }
+                    }
+                }
+            }
+
+            return mesh;
+        }
+
         public static CreateRibbon(name: string, pathArray: Vector3[][], closeArray: boolean, closePath: boolean, offset: number, scene: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
             return MeshBuilder.CreateRibbon(name, {
                 pathArray: pathArray,
@@ -1571,7 +1775,7 @@
             var tempMatrix = new Matrix();
 
             var matWeightIdx = 0;
-            var inf : number;
+            var inf: number;
             for (var index = 0; index < positionsData.length; index += 3, matWeightIdx += 4) {
                 var weight: number;
                 for (inf = 0; inf < 4; inf++) {
@@ -1589,10 +1793,10 @@
                             Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesExtraData[matWeightIdx + inf] * 16, weight, tempMatrix);
                             finalMatrix.addToSelf(tempMatrix);
 
-                        } else break;           
+                        } else break;
                     }
                 }
-                
+
                 Vector3.TransformCoordinatesFromFloatsToRef(this._sourcePositions[index], this._sourcePositions[index + 1], this._sourcePositions[index + 2], finalMatrix, tempVector3);
                 tempVector3.toArray(positionsData, index);
 

+ 65 - 0
src/Mesh/babylon.mesh.vertexData.js

@@ -178,6 +178,7 @@ var BABYLON;
                 }
                 var offset = this.positions ? this.positions.length / 3 : 0;
                 for (index = 0; index < other.indices.length; index++) {
+                    //TODO check type - if Int32Array!
                     this.indices.push(other.indices[index] + offset);
                 }
             }
@@ -1767,6 +1768,70 @@ var BABYLON;
                     break;
             }
         };
+        VertexData.ImportVertexData = function (parsedVertexData, geometry) {
+            var vertexData = new VertexData();
+            // positions
+            var positions = parsedVertexData.positions;
+            if (positions) {
+                vertexData.set(positions, BABYLON.VertexBuffer.PositionKind);
+            }
+            // normals
+            var normals = parsedVertexData.normals;
+            if (normals) {
+                vertexData.set(normals, BABYLON.VertexBuffer.NormalKind);
+            }
+            // uvs
+            var uvs = parsedVertexData.uvs;
+            if (uvs) {
+                vertexData.set(uvs, BABYLON.VertexBuffer.UVKind);
+            }
+            // uv2s
+            var uv2s = parsedVertexData.uv2s;
+            if (uv2s) {
+                vertexData.set(uv2s, BABYLON.VertexBuffer.UV2Kind);
+            }
+            // uv3s
+            var uv3s = parsedVertexData.uv3s;
+            if (uv3s) {
+                vertexData.set(uv3s, BABYLON.VertexBuffer.UV3Kind);
+            }
+            // uv4s
+            var uv4s = parsedVertexData.uv4s;
+            if (uv4s) {
+                vertexData.set(uv4s, BABYLON.VertexBuffer.UV4Kind);
+            }
+            // uv5s
+            var uv5s = parsedVertexData.uv5s;
+            if (uv5s) {
+                vertexData.set(uv5s, BABYLON.VertexBuffer.UV5Kind);
+            }
+            // uv6s
+            var uv6s = parsedVertexData.uv6s;
+            if (uv6s) {
+                vertexData.set(uv6s, BABYLON.VertexBuffer.UV6Kind);
+            }
+            // colors
+            var colors = parsedVertexData.colors;
+            if (colors) {
+                vertexData.set(BABYLON.Color4.CheckColors4(colors, positions.length / 3), BABYLON.VertexBuffer.ColorKind);
+            }
+            // matricesIndices
+            var matricesIndices = parsedVertexData.matricesIndices;
+            if (matricesIndices) {
+                vertexData.set(matricesIndices, BABYLON.VertexBuffer.MatricesIndicesKind);
+            }
+            // matricesWeights
+            var matricesWeights = parsedVertexData.matricesWeights;
+            if (matricesWeights) {
+                vertexData.set(matricesWeights, BABYLON.VertexBuffer.MatricesWeightsKind);
+            }
+            // indices
+            var indices = parsedVertexData.indices;
+            if (indices) {
+                vertexData.indices = indices;
+            }
+            geometry.setAllVerticesData(vertexData, parsedVertexData.updatable);
+        };
         return VertexData;
     })();
     BABYLON.VertexData = VertexData;

+ 84 - 5
src/Mesh/babylon.mesh.vertexData.ts

@@ -1,11 +1,11 @@
 module BABYLON {
     export interface IGetSetVerticesData {
         isVerticesDataPresent(kind: string): boolean;
-        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array;
-        getIndices(copyWhenShared?: boolean): number[];
+        getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Int32Array |Float32Array;
+        getIndices(copyWhenShared?: boolean): number[] | Int32Array;
         setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean): void;
         updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends?: boolean, makeItUnique?: boolean): void;
-        setIndices(indices: number[] | Float32Array): void;
+        setIndices(indices: number[] | Int32Array): void;
     }
 
     export class VertexData {
@@ -22,7 +22,7 @@
         public matricesWeights: number[] | Float32Array;
         public matricesIndicesExtra: number[] | Float32Array;
         public matricesWeightsExtra: number[] | Float32Array;
-        public indices: number[];
+        public indices: number[] | Int32Array;
 
         public set(data: number[] | Float32Array, kind: string) {
             switch (kind) {
@@ -239,7 +239,8 @@
 
                 var offset = this.positions ? this.positions.length / 3 : 0;
                 for (index = 0; index < other.indices.length; index++) {
-                    this.indices.push(other.indices[index] + offset);
+                    //TODO check type - if Int32Array!
+                    (<number[]>this.indices).push(other.indices[index] + offset);
                 }
             }
 
@@ -2098,5 +2099,83 @@
                     break;
             }
         }
+
+        public static ImportVertexData(parsedVertexData: any, geometry: Geometry) {
+            var vertexData = new VertexData();
+
+            // positions
+            var positions = parsedVertexData.positions;
+            if (positions) {
+                vertexData.set(positions, VertexBuffer.PositionKind);
+            }
+
+            // normals
+            var normals = parsedVertexData.normals;
+            if (normals) {
+                vertexData.set(normals, VertexBuffer.NormalKind);
+            }
+
+            // uvs
+            var uvs = parsedVertexData.uvs;
+            if (uvs) {
+                vertexData.set(uvs, VertexBuffer.UVKind);
+            }
+
+            // uv2s
+            var uv2s = parsedVertexData.uv2s;
+            if (uv2s) {
+                vertexData.set(uv2s, VertexBuffer.UV2Kind);
+            }
+
+            // uv3s
+            var uv3s = parsedVertexData.uv3s;
+            if (uv3s) {
+                vertexData.set(uv3s, VertexBuffer.UV3Kind);
+            }
+
+            // uv4s
+            var uv4s = parsedVertexData.uv4s;
+            if (uv4s) {
+                vertexData.set(uv4s, VertexBuffer.UV4Kind);
+            }
+
+            // uv5s
+            var uv5s = parsedVertexData.uv5s;
+            if (uv5s) {
+                vertexData.set(uv5s, VertexBuffer.UV5Kind);
+            }
+
+            // uv6s
+            var uv6s = parsedVertexData.uv6s;
+            if (uv6s) {
+                vertexData.set(uv6s, VertexBuffer.UV6Kind);
+            }
+
+            // colors
+            var colors = parsedVertexData.colors;
+            if (colors) {
+                vertexData.set(Color4.CheckColors4(colors, positions.length / 3), VertexBuffer.ColorKind);
+            }
+
+            // matricesIndices
+            var matricesIndices = parsedVertexData.matricesIndices;
+            if (matricesIndices) {
+                vertexData.set(matricesIndices, VertexBuffer.MatricesIndicesKind);
+            }
+
+            // matricesWeights
+            var matricesWeights = parsedVertexData.matricesWeights;
+            if (matricesWeights) {
+                vertexData.set(matricesWeights, VertexBuffer.MatricesWeightsKind);
+            }
+
+            // indices
+            var indices = parsedVertexData.indices;
+            if (indices) {
+                vertexData.indices = indices;
+            }
+
+            geometry.setAllVerticesData(vertexData, parsedVertexData.updatable);
+        }
     }
 }

+ 1 - 0
src/Mesh/babylon.meshBuilder.js

@@ -583,6 +583,7 @@ var BABYLON;
                 // Add UVs and get back to world
                 for (var vIndex = 0; vIndex < faceVertices.length; vIndex++) {
                     var vertex = faceVertices[vIndex];
+                    //TODO check for Int32Array
                     vertexData.indices.push(currentVertexDataIndex);
                     vertex.position.toArray(vertexData.positions, currentVertexDataIndex * 3);
                     vertex.normal.toArray(vertexData.normals, currentVertexDataIndex * 3);

+ 2 - 1
src/Mesh/babylon.meshBuilder.ts

@@ -690,7 +690,8 @@
                 for (var vIndex = 0; vIndex < faceVertices.length; vIndex++) {
                     var vertex = faceVertices[vIndex];
 
-                    vertexData.indices.push(currentVertexDataIndex);
+                    //TODO check for Int32Array
+                    (<number[]>vertexData.indices).push(currentVertexDataIndex);
                     vertex.position.toArray(vertexData.positions, currentVertexDataIndex * 3);
                     vertex.normal.toArray(vertexData.normals, currentVertexDataIndex * 3);
                     (<number[]>vertexData.uvs).push(0.5 + vertex.position.x / size.x);

+ 1 - 1
src/Mesh/babylon.meshSimplification.ts

@@ -536,7 +536,7 @@
             var submeshesArray = this._reconstructedMesh.subMeshes;
             this._reconstructedMesh.subMeshes = [];
 
-            var newIndicesArray: Array<number> = this._reconstructedMesh.getIndices(); //[];
+            var newIndicesArray: number[] = <number[]>this._reconstructedMesh.getIndices(); //[];
             var originalIndices = this._mesh.getIndices();
             for (i = 0; i < newTriangles.length; ++i) {
                 t = newTriangles[i]; //now get the new referencing point for each vertex

+ 2 - 2
src/Mesh/babylon.subMesh.ts

@@ -98,7 +98,7 @@
             this._renderingMesh.render(this, enableAlphaMode);
         }
 
-        public getLinesIndexBuffer(indices: number[], engine): WebGLBuffer {
+        public getLinesIndexBuffer(indices: number[] | Int32Array, engine): WebGLBuffer {
             if (!this._linesIndexBuffer) {
                 var linesIndices = [];
 
@@ -118,7 +118,7 @@
             return ray.intersectsBox(this._boundingInfo.boundingBox);
         }
 
-        public intersects(ray: Ray, positions: Vector3[], indices: number[], fastCheck?: boolean): IntersectionInfo {
+        public intersects(ray: Ray, positions: Vector3[], indices: number[] | Int32Array, fastCheck?: boolean): IntersectionInfo {
             var intersectInfo: IntersectionInfo = null;
 
             // Triangles test

+ 30 - 0
src/Particles/babylon.particleSystem.js

@@ -328,6 +328,36 @@ var BABYLON;
             result.start();
             return result;
         };
+        ParticleSystem.ParseParticleSystem = function (parsedParticleSystem, scene, rootUrl) {
+            var emitter = scene.getLastMeshByID(parsedParticleSystem.emitterId);
+            var particleSystem = new ParticleSystem("particles#" + emitter.name, parsedParticleSystem.capacity, scene);
+            if (parsedParticleSystem.textureName) {
+                particleSystem.particleTexture = new BABYLON.Texture(rootUrl + parsedParticleSystem.textureName, scene);
+                particleSystem.particleTexture.name = parsedParticleSystem.textureName;
+            }
+            particleSystem.minAngularSpeed = parsedParticleSystem.minAngularSpeed;
+            particleSystem.maxAngularSpeed = parsedParticleSystem.maxAngularSpeed;
+            particleSystem.minSize = parsedParticleSystem.minSize;
+            particleSystem.maxSize = parsedParticleSystem.maxSize;
+            particleSystem.minLifeTime = parsedParticleSystem.minLifeTime;
+            particleSystem.maxLifeTime = parsedParticleSystem.maxLifeTime;
+            particleSystem.emitter = emitter;
+            particleSystem.emitRate = parsedParticleSystem.emitRate;
+            particleSystem.minEmitBox = BABYLON.Vector3.FromArray(parsedParticleSystem.minEmitBox);
+            particleSystem.maxEmitBox = BABYLON.Vector3.FromArray(parsedParticleSystem.maxEmitBox);
+            particleSystem.gravity = BABYLON.Vector3.FromArray(parsedParticleSystem.gravity);
+            particleSystem.direction1 = BABYLON.Vector3.FromArray(parsedParticleSystem.direction1);
+            particleSystem.direction2 = BABYLON.Vector3.FromArray(parsedParticleSystem.direction2);
+            particleSystem.color1 = BABYLON.Color4.FromArray(parsedParticleSystem.color1);
+            particleSystem.color2 = BABYLON.Color4.FromArray(parsedParticleSystem.color2);
+            particleSystem.colorDead = BABYLON.Color4.FromArray(parsedParticleSystem.colorDead);
+            particleSystem.updateSpeed = parsedParticleSystem.updateSpeed;
+            particleSystem.targetStopDuration = parsedParticleSystem.targetStopFrame;
+            particleSystem.textureMask = BABYLON.Color4.FromArray(parsedParticleSystem.textureMask);
+            particleSystem.blendMode = parsedParticleSystem.blendMode;
+            particleSystem.start();
+            return particleSystem;
+        };
         // Statics
         ParticleSystem.BLENDMODE_ONEONE = 0;
         ParticleSystem.BLENDMODE_STANDARD = 1;

+ 33 - 0
src/Particles/babylon.particleSystem.ts

@@ -445,5 +445,38 @@
 
             return result;
         }
+
+        public static ParseParticleSystem(parsedParticleSystem: any, scene: Scene, rootUrl: string): ParticleSystem {
+            var emitter = scene.getLastMeshByID(parsedParticleSystem.emitterId);
+
+            var particleSystem = new ParticleSystem("particles#" + emitter.name, parsedParticleSystem.capacity, scene);
+            if (parsedParticleSystem.textureName) {
+                particleSystem.particleTexture = new Texture(rootUrl + parsedParticleSystem.textureName, scene);
+                particleSystem.particleTexture.name = parsedParticleSystem.textureName;
+            }
+            particleSystem.minAngularSpeed = parsedParticleSystem.minAngularSpeed;
+            particleSystem.maxAngularSpeed = parsedParticleSystem.maxAngularSpeed;
+            particleSystem.minSize = parsedParticleSystem.minSize;
+            particleSystem.maxSize = parsedParticleSystem.maxSize;
+            particleSystem.minLifeTime = parsedParticleSystem.minLifeTime;
+            particleSystem.maxLifeTime = parsedParticleSystem.maxLifeTime;
+            particleSystem.emitter = emitter;
+            particleSystem.emitRate = parsedParticleSystem.emitRate;
+            particleSystem.minEmitBox = Vector3.FromArray(parsedParticleSystem.minEmitBox);
+            particleSystem.maxEmitBox = Vector3.FromArray(parsedParticleSystem.maxEmitBox);
+            particleSystem.gravity = Vector3.FromArray(parsedParticleSystem.gravity);
+            particleSystem.direction1 = Vector3.FromArray(parsedParticleSystem.direction1);
+            particleSystem.direction2 = Vector3.FromArray(parsedParticleSystem.direction2);
+            particleSystem.color1 = Color4.FromArray(parsedParticleSystem.color1);
+            particleSystem.color2 = Color4.FromArray(parsedParticleSystem.color2);
+            particleSystem.colorDead = Color4.FromArray(parsedParticleSystem.colorDead);
+            particleSystem.updateSpeed = parsedParticleSystem.updateSpeed;
+            particleSystem.targetStopDuration = parsedParticleSystem.targetStopFrame;
+            particleSystem.textureMask = Color4.FromArray(parsedParticleSystem.textureMask);
+            particleSystem.blendMode = parsedParticleSystem.blendMode;
+            particleSystem.start();
+
+            return particleSystem;
+        }
     }
 }  

+ 1 - 1
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -145,7 +145,7 @@
             return returnValue;
         }
 
-        private _createConvexPolyhedron(rawVerts: number[] | Float32Array, rawFaces: number[], mesh: AbstractMesh): any {
+        private _createConvexPolyhedron(rawVerts: number[] | Float32Array, rawFaces: number[] | Int32Array, mesh: AbstractMesh): any {
             var verts = [], faces = [];
 
             mesh.computeWorldMatrix(true);

+ 1 - 1
src/Tools/babylon.tools.ts

@@ -131,7 +131,7 @@
             return "data:image/png;base64," + output;
         }
 
-        public static ExtractMinAndMaxIndexed(positions: number[] | Float32Array, indices: number[], indexStart: number, indexCount: number): { minimum: Vector3; maximum: Vector3 } {
+        public static ExtractMinAndMaxIndexed(positions: number[] | Float32Array, indices: number[] | Int32Array, indexStart: number, indexCount: number): { minimum: Vector3; maximum: Vector3 } {
             var minimum = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             var maximum = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 

+ 1 - 1
src/babylon.engine.ts

@@ -1070,7 +1070,7 @@
             this._cachedIndexBuffer = null;
         }
 
-        public createIndexBuffer(indices: number[]): WebGLBuffer {
+        public createIndexBuffer(indices: number[] | Int32Array): WebGLBuffer {
             var vbo = this._gl.createBuffer();
             this._gl.bindBuffer(this._gl.ELEMENT_ARRAY_BUFFER, vbo);