Pārlūkot izejas kodu

Merge pull request #335 from simonferquel/master

Max2Babylon : support for bone based animations + leverage of the IGame* interfaces for easier exports
David Catuhe 10 gadi atpakaļ
vecāks
revīzija
120fc07286
49 mainītis faili ar 1365 papildinājumiem un 1451 dzēšanām
  1. 3 0
      .gitignore
  2. 1 1
      Babylon/Actions/babylon.actionManager.js
  3. 6 51
      Babylon/Animations/babylon.animation.js
  4. 2 3
      Babylon/Lights/Shadows/babylon.shadowGenerator.js
  5. 0 8
      Babylon/Loading/Plugins/babylon.babylonFileLoader.js
  6. 2 2
      Babylon/Loading/babylon.sceneLoader.js
  7. 14 13
      Babylon/Materials/babylon.effect.js
  8. 0 5
      Babylon/Materials/babylon.material.js
  9. 37 65
      Babylon/Materials/babylon.shaderMaterial.js
  10. 113 136
      Babylon/Materials/babylon.standardMaterial.js
  11. 51 69
      Babylon/Materials/textures/Procedurals/babylon.customProceduralTexture.js
  12. 6 43
      Babylon/Materials/textures/Procedurals/babylon.proceduralTexture.js
  13. 80 166
      Babylon/Materials/textures/Procedurals/babylon.standardProceduralTexture.js
  14. 1 1
      Babylon/Materials/textures/babylon.baseTexture.js
  15. 1 1
      Babylon/Materials/textures/babylon.renderTargetTexture.js
  16. 0 2
      Babylon/Materials/textures/babylon.texture.js
  17. 0 54
      Babylon/Math/babylon.math.js
  18. 2 12
      Babylon/Mesh/babylon.InstancedMesh.js
  19. 3 44
      Babylon/Mesh/babylon.abstractMesh.js
  20. 5 10
      Babylon/Mesh/babylon.geometry.js
  21. 34 45
      Babylon/Mesh/babylon.mesh.js
  22. 2 2
      Babylon/Mesh/babylon.vertexBuffer.js
  23. 6 7
      Babylon/Particles/babylon.particleSystem.js
  24. 0 2
      Babylon/Physics/Plugins/babylon.oimoJSPlugin.js
  25. 1 3
      Babylon/Rendering/babylon.boundingBoxRenderer.js
  26. 5 6
      Babylon/Rendering/babylon.outlineRenderer.js
  27. 6 11
      Babylon/Rendering/babylon.renderingGroup.js
  28. 3 2
      Babylon/Rendering/babylon.renderingManager.js
  29. 2 2
      Babylon/Sprites/babylon.spriteManager.js
  30. 4 44
      Babylon/Tools/babylon.tools.js
  31. 9 39
      Babylon/babylon.engine.js
  32. 24 129
      Babylon/babylon.scene.js
  33. 14 1
      Exporters/3ds Max/BabylonExport.Entities/BabylonExport.Entities.csproj
  34. 4 0
      Exporters/3ds Max/BabylonExport.Entities/packages.config
  35. 16 4
      Exporters/3ds Max/Max2Babylon/2015/Max2Babylon2015.csproj
  36. 5 0
      Exporters/3ds Max/Max2Babylon/2015/packages.config
  37. 5 0
      Exporters/3ds Max/Max2Babylon/BabylonExportActionItem.cs
  38. 55 4
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Animation.cs
  39. 43 28
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Camera.cs
  40. 62 44
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Light.cs
  41. 17 17
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Material.cs
  42. 284 202
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Mesh.cs
  43. 261 98
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Skeleton.cs
  44. 8 17
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Texture.cs
  45. 39 31
      Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.cs
  46. 17 5
      Exporters/3ds Max/Max2Babylon/Max2Babylon.csproj
  47. 92 19
      Exporters/3ds Max/Max2Babylon/Tools/Tools.cs
  48. 15 3
      Exporters/3ds Max/Max2Babylon/Tools/WebServer.cs
  49. 5 0
      Exporters/3ds Max/Max2Babylon/packages.config

+ 3 - 0
.gitignore

@@ -113,3 +113,6 @@ UpgradeLog*.XML
 .settings/
 .pydevproject
 
+/Exporters/3ds Max/Max2Babylon.sln.ide
+/Exporters/3ds Max/Max2Babylon.sln.ide
+/Exporters/ExportToBabylon.sln.ide

+ 1 - 1
Babylon/Actions/babylon.actionManager.js

@@ -202,7 +202,7 @@
                 var action = this.actions[index];
 
                 if (action.trigger === trigger) {
-                    if (trigger === ActionManager.OnKeyUpTrigger || trigger === ActionManager.OnKeyDownTrigger) {
+                    if (trigger == ActionManager.OnKeyUpTrigger || trigger == ActionManager.OnKeyDownTrigger) {
                         var parameter = action.getTriggerParameter();
 
                         if (parameter) {

+ 6 - 51
Babylon/Animations/babylon.animation.js

@@ -14,37 +14,6 @@
             this.dataType = dataType;
             this.loopMode = loopMode === undefined ? Animation.ANIMATIONLOOPMODE_CYCLE : loopMode;
         }
-        Animation.CreateAndStartAnimation = function (name, mesh, tartgetProperty, framePerSecond, totalFrame, from, to, loopMode) {
-            var dataType = undefined;
-
-            if (!isNaN(parseFloat(from)) && isFinite(from)) {
-                dataType = Animation.ANIMATIONTYPE_FLOAT;
-            } else if (from instanceof BABYLON.Quaternion) {
-                dataType = Animation.ANIMATIONTYPE_QUATERNION;
-            } else if (from instanceof BABYLON.Vector3) {
-                dataType = Animation.ANIMATIONTYPE_VECTOR3;
-            } else if (from instanceof BABYLON.Vector2) {
-                dataType = Animation.ANIMATIONTYPE_VECTOR2;
-            } else if (from instanceof BABYLON.Color3) {
-                dataType = Animation.ANIMATIONTYPE_COLOR3;
-            }
-
-            if (dataType == undefined) {
-                return;
-            }
-
-            var animation = new Animation(name, tartgetProperty, framePerSecond, dataType, loopMode);
-
-            var keys = [];
-            keys.push({ frame: 0, value: from });
-            keys.push({ frame: totalFrame, value: to });
-            animation.setKeys(keys);
-
-            mesh.animations.push(animation);
-
-            mesh.getScene().beginAnimation(mesh, 0, totalFrame, (animation.loopMode == 1));
-        };
-
         // Methods
         Animation.prototype.isStopped = function () {
             return this._stopped;
@@ -54,14 +23,6 @@
             return this._keys;
         };
 
-        Animation.prototype.getEasingFunction = function () {
-            return this._easingFunction;
-        };
-
-        Animation.prototype.setEasingFunction = function (easingFunction) {
-            this._easingFunction = easingFunction;
-        };
-
         Animation.prototype.floatInterpolateFunction = function (startValue, endValue, gradient) {
             return startValue + (endValue - startValue) * gradient;
         };
@@ -104,19 +65,11 @@
             this.currentFrame = currentFrame;
 
             for (var key = 0; key < this._keys.length; key++) {
-                // for each frame, we need the key just before the frame superior
                 if (this._keys[key + 1].frame >= currentFrame) {
                     var startValue = this._keys[key].value;
                     var endValue = this._keys[key + 1].value;
-
-                    // gradient : percent of currentFrame between the frame inf and the frame sup
                     var gradient = (currentFrame - this._keys[key].frame) / (this._keys[key + 1].frame - this._keys[key].frame);
 
-                    // check for easingFunction and correction of gradient
-                    if (this._easingFunction != null) {
-                        gradient = this._easingFunction.ease(gradient);
-                    }
-
                     switch (this.dataType) {
                         case Animation.ANIMATIONTYPE_FLOAT:
                             switch (loopMode) {
@@ -190,11 +143,16 @@
                 this._stopped = true;
                 return false;
             }
+
             var returnValue = true;
 
             // Adding a start key at frame 0 if missing
             if (this._keys[0].frame != 0) {
-                var newKey = { frame: 0, value: this._keys[0].value };
+                var newKey = {
+                    frame: 0,
+                    value: this._keys[0].value
+                };
+
                 this._keys.splice(0, 0, newKey);
             }
 
@@ -209,8 +167,6 @@
             // Compute ratio
             var range = to - from;
             var offsetValue;
-
-            // ratio represents the frame delta between from and to
             var ratio = delay * (this.framePerSecond * speedRatio) / 1000.0;
 
             if (ratio > range && !loop) {
@@ -219,7 +175,6 @@
             } else {
                 // Get max value if required
                 var highLimitValue = 0;
-
                 if (this.loopMode != Animation.ANIMATIONLOOPMODE_CYCLE) {
                     var keyOffset = to.toString() + from.toString();
                     if (!this._offsetsCache[keyOffset]) {

+ 2 - 3
Babylon/Lights/Shadows/babylon.shadowGenerator.js

@@ -55,7 +55,7 @@
                     }
 
                     // Bones
-                    var useBones = mesh.skeleton && scene.skeletonsEnabled && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
+                    var useBones = mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
 
                     if (useBones) {
                         _this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
@@ -163,7 +163,6 @@
             var attribs = [BABYLON.VertexBuffer.PositionKind];
 
             var mesh = subMesh.getMesh();
-            var scene = mesh.getScene();
             var material = subMesh.getMaterial();
 
             // Alpha test
@@ -180,7 +179,7 @@
             }
 
             // Bones
-            if (mesh.skeleton && scene.skeletonsEnabled && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
+            if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
                 attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
                 attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
                 defines.push("#define BONES");

+ 0 - 8
Babylon/Loading/Plugins/babylon.babylonFileLoader.js

@@ -647,18 +647,10 @@
             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;

+ 2 - 2
Babylon/Loading/babylon.sceneLoader.js

@@ -64,14 +64,14 @@
                     try  {
                         if (!plugin.importMesh(meshesNames, scene, data, rootUrl, meshes, particleSystems, skeletons)) {
                             if (onerror) {
-                                onerror(scene, 'unable to load the scene');
+                                onerror(scene);
                             }
 
                             return;
                         }
                     } catch (e) {
                         if (onerror) {
-                            onerror(scene, e);
+                            onerror(scene);
                         }
 
                         return;

+ 14 - 13
Babylon/Materials/babylon.effect.js

@@ -143,8 +143,8 @@
             }
 
             // Is in local store ?
-            if (Effect.ShadersStore[vertex + "VertexShader"]) {
-                callback(Effect.ShadersStore[vertex + "VertexShader"]);
+            if (BABYLON.Effect.ShadersStore[vertex + "VertexShader"]) {
+                callback(BABYLON.Effect.ShadersStore[vertex + "VertexShader"]);
                 return;
             }
 
@@ -169,13 +169,13 @@
             }
 
             // Is in local store ?
-            if (Effect.ShadersStore[fragment + "PixelShader"]) {
-                callback(Effect.ShadersStore[fragment + "PixelShader"]);
+            if (BABYLON.Effect.ShadersStore[fragment + "PixelShader"]) {
+                callback(BABYLON.Effect.ShadersStore[fragment + "PixelShader"]);
                 return;
             }
 
-            if (Effect.ShadersStore[fragment + "FragmentShader"]) {
-                callback(Effect.ShadersStore[fragment + "FragmentShader"]);
+            if (BABYLON.Effect.ShadersStore[fragment + "FragmentShader"]) {
+                callback(BABYLON.Effect.ShadersStore[fragment + "FragmentShader"]);
                 return;
             }
 
@@ -208,6 +208,7 @@
                         index--;
                     }
                 }
+
                 engine.bindSamplers(this);
 
                 this._isReady = true;
@@ -339,7 +340,7 @@
         };
 
         Effect.prototype.setVector2 = function (uniformName, vector2) {
-            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] === vector2.x && this._valueCache[uniformName][1] === vector2.y)
+            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == vector2.x && this._valueCache[uniformName][1] == vector2.y)
                 return this;
 
             this._cacheFloat2(uniformName, vector2.x, vector2.y);
@@ -349,7 +350,7 @@
         };
 
         Effect.prototype.setFloat2 = function (uniformName, x, y) {
-            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] === x && this._valueCache[uniformName][1] === y)
+            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == x && this._valueCache[uniformName][1] == y)
                 return this;
 
             this._cacheFloat2(uniformName, x, y);
@@ -359,7 +360,7 @@
         };
 
         Effect.prototype.setVector3 = function (uniformName, vector3) {
-            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] === vector3.x && this._valueCache[uniformName][1] === vector3.y && this._valueCache[uniformName][2] === vector3.z)
+            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == vector3.x && this._valueCache[uniformName][1] == vector3.y && this._valueCache[uniformName][2] == vector3.z)
                 return this;
 
             this._cacheFloat3(uniformName, vector3.x, vector3.y, vector3.z);
@@ -370,7 +371,7 @@
         };
 
         Effect.prototype.setFloat3 = function (uniformName, x, y, z) {
-            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] === x && this._valueCache[uniformName][1] === y && this._valueCache[uniformName][2] === z)
+            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == x && this._valueCache[uniformName][1] == y && this._valueCache[uniformName][2] == z)
                 return this;
 
             this._cacheFloat3(uniformName, x, y, z);
@@ -380,7 +381,7 @@
         };
 
         Effect.prototype.setFloat4 = function (uniformName, x, y, z, w) {
-            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] === x && this._valueCache[uniformName][1] === y && this._valueCache[uniformName][2] === z && this._valueCache[uniformName][3] === w)
+            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == x && this._valueCache[uniformName][1] == y && this._valueCache[uniformName][2] == z && this._valueCache[uniformName][3] == w)
                 return this;
 
             this._cacheFloat4(uniformName, x, y, z, w);
@@ -390,7 +391,7 @@
         };
 
         Effect.prototype.setColor3 = function (uniformName, color3) {
-            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] === color3.r && this._valueCache[uniformName][1] === color3.g && this._valueCache[uniformName][2] === color3.b)
+            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == color3.r && this._valueCache[uniformName][1] == color3.g && this._valueCache[uniformName][2] == color3.b)
                 return this;
 
             this._cacheFloat3(uniformName, color3.r, color3.g, color3.b);
@@ -400,7 +401,7 @@
         };
 
         Effect.prototype.setColor4 = function (uniformName, color3, alpha) {
-            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] === color3.r && this._valueCache[uniformName][1] === color3.g && this._valueCache[uniformName][2] === color3.b && this._valueCache[uniformName][3] === alpha)
+            if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == color3.r && this._valueCache[uniformName][1] == color3.g && this._valueCache[uniformName][2] == color3.b && this._valueCache[uniformName][3] == alpha)
                 return this;
 
             this._cacheFloat4(uniformName, color3.r, color3.g, color3.b, alpha);

+ 0 - 5
Babylon/Materials/babylon.material.js

@@ -114,11 +114,6 @@
         };
 
         Material.prototype.bind = function (world, mesh) {
-            this._scene._cachedMaterial = this;
-
-            if (this.onBind) {
-                this.onBind(this);
-            }
         };
 
         Material.prototype.bindOnlyWorldMatrix = function (world) {

+ 37 - 65
Babylon/Materials/babylon.shaderMaterial.js

@@ -102,100 +102,72 @@ var BABYLON;
         };
 
         ShaderMaterial.prototype.isReady = function () {
-            var scene = this.getScene();
-            var engine = scene.getEngine();
+            var engine = this.getScene().getEngine();
 
-            if (!this.checkReadyOnEveryCall) {
-                if (this._renderId === scene.getRenderId()) {
-                    return true;
-                }
-            }
-
-            var previousEffect = this._effect;
             this._effect = engine.createEffect(this._shaderPath, this._options.attributes, this._options.uniforms, this._options.samplers, "", null, this.onCompiled, this.onError);
 
             if (!this._effect.isReady()) {
                 return false;
             }
 
-            if (previousEffect !== this._effect) {
-                scene.resetCachedMaterial();
-            }
-
-            this._renderId = scene.getRenderId();
-
             return true;
         };
 
-        ShaderMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            var scene = this.getScene();
-
+        ShaderMaterial.prototype.bind = function (world) {
+            // Std values
             if (this._options.uniforms.indexOf("world") !== -1) {
                 this._effect.setMatrix("world", world);
             }
 
+            if (this._options.uniforms.indexOf("view") !== -1) {
+                this._effect.setMatrix("view", this.getScene().getViewMatrix());
+            }
+
             if (this._options.uniforms.indexOf("worldView") !== -1) {
-                world.multiplyToRef(scene.getViewMatrix(), this._cachedWorldViewMatrix);
+                world.multiplyToRef(this.getScene().getViewMatrix(), this._cachedWorldViewMatrix);
                 this._effect.setMatrix("worldView", this._cachedWorldViewMatrix);
             }
 
-            if (this._options.uniforms.indexOf("worldViewProjection") !== -1) {
-                this._effect.setMatrix("worldViewProjection", world.multiply(scene.getTransformMatrix()));
+            if (this._options.uniforms.indexOf("projection") !== -1) {
+                this._effect.setMatrix("projection", this.getScene().getProjectionMatrix());
             }
-        };
-
-        ShaderMaterial.prototype.bind = function (world) {
-            // Std values
-            this.bindOnlyWorldMatrix(world);
-
-            if (this.getScene().getCachedMaterial() !== this) {
-                if (this._options.uniforms.indexOf("view") !== -1) {
-                    this._effect.setMatrix("view", this.getScene().getViewMatrix());
-                }
-
-                if (this._options.uniforms.indexOf("projection") !== -1) {
-                    this._effect.setMatrix("projection", this.getScene().getProjectionMatrix());
-                }
-
-                if (this._options.uniforms.indexOf("viewProjection") !== -1) {
-                    this._effect.setMatrix("viewProjection", this.getScene().getTransformMatrix());
-                }
 
-                for (var name in this._textures) {
-                    this._effect.setTexture(name, this._textures[name]);
-                }
+            if (this._options.uniforms.indexOf("worldViewProjection") !== -1) {
+                this._effect.setMatrix("worldViewProjection", world.multiply(this.getScene().getTransformMatrix()));
+            }
 
-                for (name in this._floats) {
-                    this._effect.setFloat(name, this._floats[name]);
-                }
+            for (var name in this._textures) {
+                this._effect.setTexture(name, this._textures[name]);
+            }
 
-                for (name in this._floatsArrays) {
-                    this._effect.setArray(name, this._floatsArrays[name]);
-                }
+            for (name in this._floats) {
+                this._effect.setFloat(name, this._floats[name]);
+            }
 
-                for (name in this._colors3) {
-                    this._effect.setColor3(name, this._colors3[name]);
-                }
+            for (name in this._floatsArrays) {
+                this._effect.setArray(name, this._floatsArrays[name]);
+            }
 
-                for (name in this._colors4) {
-                    var color = this._colors4[name];
-                    this._effect.setFloat4(name, color.r, color.g, color.b, color.a);
-                }
+            for (name in this._colors3) {
+                this._effect.setColor3(name, this._colors3[name]);
+            }
 
-                for (name in this._vectors2) {
-                    this._effect.setVector2(name, this._vectors2[name]);
-                }
+            for (name in this._colors4) {
+                var color = this._colors4[name];
+                this._effect.setFloat4(name, color.r, color.g, color.b, color.a);
+            }
 
-                for (name in this._vectors3) {
-                    this._effect.setVector3(name, this._vectors3[name]);
-                }
+            for (name in this._vectors2) {
+                this._effect.setVector2(name, this._vectors2[name]);
+            }
 
-                for (name in this._matrices) {
-                    this._effect.setMatrix(name, this._matrices[name]);
-                }
+            for (name in this._vectors3) {
+                this._effect.setVector3(name, this._vectors3[name]);
             }
 
-            _super.prototype.bind.call(this, world, null);
+            for (name in this._matrices) {
+                this._effect.setMatrix(name, this._matrices[name]);
+            }
         };
 
         ShaderMaterial.prototype.dispose = function (forceDisposeEffect) {

+ 113 - 136
Babylon/Materials/babylon.standardMaterial.js

@@ -88,7 +88,7 @@ var BABYLON;
 
             // Textures
             if (scene.texturesEnabled) {
-                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                if (this.diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
                     if (!this.diffuseTexture.isReady()) {
                         return false;
                     } else {
@@ -96,7 +96,7 @@ var BABYLON;
                     }
                 }
 
-                if (this.ambientTexture && StandardMaterial.AmbientTextureEnabled) {
+                if (this.ambientTexture && BABYLON.StandardMaterial.AmbientTextureEnabled) {
                     if (!this.ambientTexture.isReady()) {
                         return false;
                     } else {
@@ -104,7 +104,7 @@ var BABYLON;
                     }
                 }
 
-                if (this.opacityTexture && StandardMaterial.OpacityTextureEnabled) {
+                if (this.opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
                     if (!this.opacityTexture.isReady()) {
                         return false;
                     } else {
@@ -116,7 +116,7 @@ var BABYLON;
                     }
                 }
 
-                if (this.reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
+                if (this.reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
                     if (!this.reflectionTexture.isReady()) {
                         return false;
                     } else {
@@ -125,7 +125,7 @@ var BABYLON;
                     }
                 }
 
-                if (this.emissiveTexture && StandardMaterial.EmissiveTextureEnabled) {
+                if (this.emissiveTexture && BABYLON.StandardMaterial.EmissiveTextureEnabled) {
                     if (!this.emissiveTexture.isReady()) {
                         return false;
                     } else {
@@ -133,7 +133,7 @@ var BABYLON;
                     }
                 }
 
-                if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
+                if (this.specularTexture && BABYLON.StandardMaterial.SpecularTextureEnabled) {
                     if (!this.specularTexture.isReady()) {
                         return false;
                     } else {
@@ -143,7 +143,7 @@ var BABYLON;
                 }
             }
 
-            if (scene.getEngine().getCaps().standardDerivatives && this.bumpTexture && StandardMaterial.BumpTextureEnabled) {
+            if (scene.getEngine().getCaps().standardDerivatives && this.bumpTexture && BABYLON.StandardMaterial.BumpTextureEnabled) {
                 if (!this.bumpTexture.isReady()) {
                     return false;
                 } else {
@@ -171,12 +171,12 @@ var BABYLON;
             }
 
             // Point size
-            if (this.pointsCloud || scene.forcePointsCloud) {
+            if (this.pointsCloud) {
                 defines.push("#define POINTSIZE");
             }
 
             // Fog
-            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
+            if (scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
                 defines.push("#define FOG");
                 fallbacks.addFallback(1, "FOG");
             }
@@ -270,43 +270,41 @@ var BABYLON;
                     }
 
                     lightIndex++;
-                    if (lightIndex === maxSimultaneousLights)
+                    if (lightIndex == maxSimultaneousLights)
                         break;
                 }
             }
 
-            if (StandardMaterial.FresnelEnabled) {
-                // Fresnel
-                if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled || this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled || this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
-                    var fresnelRank = 1;
+            // Fresnel
+            if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled || this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled || this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                var fresnelRank = 1;
 
-                    if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
-                        defines.push("#define DIFFUSEFRESNEL");
-                        fallbacks.addFallback(fresnelRank, "DIFFUSEFRESNEL");
-                        fresnelRank++;
-                    }
-
-                    if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
-                        defines.push("#define OPACITYFRESNEL");
-                        fallbacks.addFallback(fresnelRank, "OPACITYFRESNEL");
-                        fresnelRank++;
-                    }
+                if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+                    defines.push("#define DIFFUSEFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "DIFFUSEFRESNEL");
+                    fresnelRank++;
+                }
 
-                    if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
-                        defines.push("#define REFLECTIONFRESNEL");
-                        fallbacks.addFallback(fresnelRank, "REFLECTIONFRESNEL");
-                        fresnelRank++;
-                    }
+                if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                    defines.push("#define OPACITYFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "OPACITYFRESNEL");
+                    fresnelRank++;
+                }
 
-                    if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
-                        defines.push("#define EMISSIVEFRESNEL");
-                        fallbacks.addFallback(fresnelRank, "EMISSIVEFRESNEL");
-                        fresnelRank++;
-                    }
+                if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                    defines.push("#define REFLECTIONFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "REFLECTIONFRESNEL");
+                    fresnelRank++;
+                }
 
-                    defines.push("#define FRESNEL");
-                    fallbacks.addFallback(fresnelRank - 1, "FRESNEL");
+                if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                    defines.push("#define EMISSIVEFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "EMISSIVEFRESNEL");
+                    fresnelRank++;
                 }
+
+                defines.push("#define FRESNEL");
+                fallbacks.addFallback(fresnelRank - 1, "FRESNEL");
             }
 
             // Attribs
@@ -320,7 +318,7 @@ var BABYLON;
                     attribs.push(BABYLON.VertexBuffer.UV2Kind);
                     defines.push("#define UV2");
                 }
-                if (mesh.useVertexColors && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
+                if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
                     attribs.push(BABYLON.VertexBuffer.ColorKind);
                     defines.push("#define VERTEXCOLOR");
 
@@ -328,7 +326,7 @@ var BABYLON;
                         defines.push("#define VERTEXALPHA");
                     }
                 }
-                if (mesh.skeleton && scene.skeletonsEnabled && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
+                if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
                     attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
                     attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
                     defines.push("#define BONES");
@@ -349,11 +347,9 @@ var BABYLON;
 
             // Get correct effect
             var join = defines.join("\n");
-            if (this._cachedDefines !== join) {
+            if (this._cachedDefines != join) {
                 this._cachedDefines = join;
 
-                scene.resetCachedMaterial();
-
                 // Legacy browser patch
                 var shaderName = "default";
                 if (!scene.getEngine().getCaps().standardDerivatives) {
@@ -404,118 +400,92 @@ var BABYLON;
             this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
 
             // Bones
-            if (mesh.skeleton && scene.skeletonsEnabled && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
+            if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
                 this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
             }
 
-            if (scene.getCachedMaterial() !== this) {
-                if (StandardMaterial.FresnelEnabled) {
-                    // Fresnel
-                    if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
-                        this._effect.setColor4("diffuseLeftColor", this.diffuseFresnelParameters.leftColor, this.diffuseFresnelParameters.power);
-                        this._effect.setColor4("diffuseRightColor", this.diffuseFresnelParameters.rightColor, this.diffuseFresnelParameters.bias);
-                    }
-
-                    if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
-                        this._effect.setColor4("opacityParts", new BABYLON.Color3(this.opacityFresnelParameters.leftColor.toLuminance(), this.opacityFresnelParameters.rightColor.toLuminance(), this.opacityFresnelParameters.bias), this.opacityFresnelParameters.power);
-                    }
-
-                    if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
-                        this._effect.setColor4("reflectionLeftColor", this.reflectionFresnelParameters.leftColor, this.reflectionFresnelParameters.power);
-                        this._effect.setColor4("reflectionRightColor", this.reflectionFresnelParameters.rightColor, this.reflectionFresnelParameters.bias);
-                    }
-
-                    if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
-                        this._effect.setColor4("emissiveLeftColor", this.emissiveFresnelParameters.leftColor, this.emissiveFresnelParameters.power);
-                        this._effect.setColor4("emissiveRightColor", this.emissiveFresnelParameters.rightColor, this.emissiveFresnelParameters.bias);
-                    }
-                }
-
-                // Textures
-                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
-                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
-
-                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
-                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
-                }
+            // Fresnel
+            if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+                this._effect.setColor4("diffuseLeftColor", this.diffuseFresnelParameters.leftColor, this.diffuseFresnelParameters.power);
+                this._effect.setColor4("diffuseRightColor", this.diffuseFresnelParameters.rightColor, this.diffuseFresnelParameters.bias);
+            }
 
-                if (this.ambientTexture && StandardMaterial.AmbientTextureEnabled) {
-                    this._effect.setTexture("ambientSampler", this.ambientTexture);
+            if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                this._effect.setColor4("opacityParts", new BABYLON.Color3(this.opacityFresnelParameters.leftColor.toLuminance(), this.opacityFresnelParameters.rightColor.toLuminance(), this.opacityFresnelParameters.bias), this.opacityFresnelParameters.power);
+            }
 
-                    this._effect.setFloat2("vAmbientInfos", this.ambientTexture.coordinatesIndex, this.ambientTexture.level);
-                    this._effect.setMatrix("ambientMatrix", this.ambientTexture.getTextureMatrix());
-                }
+            if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                this._effect.setColor4("reflectionLeftColor", this.reflectionFresnelParameters.leftColor, this.reflectionFresnelParameters.power);
+                this._effect.setColor4("reflectionRightColor", this.reflectionFresnelParameters.rightColor, this.reflectionFresnelParameters.bias);
+            }
 
-                if (this.opacityTexture && StandardMaterial.OpacityTextureEnabled) {
-                    this._effect.setTexture("opacitySampler", this.opacityTexture);
+            if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                this._effect.setColor4("emissiveLeftColor", this.emissiveFresnelParameters.leftColor, this.emissiveFresnelParameters.power);
+                this._effect.setColor4("emissiveRightColor", this.emissiveFresnelParameters.rightColor, this.emissiveFresnelParameters.bias);
+            }
 
-                    this._effect.setFloat2("vOpacityInfos", this.opacityTexture.coordinatesIndex, this.opacityTexture.level);
-                    this._effect.setMatrix("opacityMatrix", this.opacityTexture.getTextureMatrix());
-                }
+            // Textures
+            if (this.diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
+                this._effect.setTexture("diffuseSampler", this.diffuseTexture);
 
-                if (this.reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
-                    if (this.reflectionTexture.isCube) {
-                        this._effect.setTexture("reflectionCubeSampler", this.reflectionTexture);
-                    } else {
-                        this._effect.setTexture("reflection2DSampler", this.reflectionTexture);
-                    }
+                this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
+                this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+            }
 
-                    this._effect.setMatrix("reflectionMatrix", this.reflectionTexture.getReflectionTextureMatrix());
-                    this._effect.setFloat3("vReflectionInfos", this.reflectionTexture.coordinatesMode, this.reflectionTexture.level, this.reflectionTexture.isCube ? 1 : 0);
-                }
+            if (this.ambientTexture && BABYLON.StandardMaterial.AmbientTextureEnabled) {
+                this._effect.setTexture("ambientSampler", this.ambientTexture);
 
-                if (this.emissiveTexture && StandardMaterial.EmissiveTextureEnabled) {
-                    this._effect.setTexture("emissiveSampler", this.emissiveTexture);
+                this._effect.setFloat2("vAmbientInfos", this.ambientTexture.coordinatesIndex, this.ambientTexture.level);
+                this._effect.setMatrix("ambientMatrix", this.ambientTexture.getTextureMatrix());
+            }
 
-                    this._effect.setFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
-                    this._effect.setMatrix("emissiveMatrix", this.emissiveTexture.getTextureMatrix());
-                }
+            if (this.opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
+                this._effect.setTexture("opacitySampler", this.opacityTexture);
 
-                if (this.specularTexture && StandardMaterial.SpecularTextureEnabled) {
-                    this._effect.setTexture("specularSampler", this.specularTexture);
+                this._effect.setFloat2("vOpacityInfos", this.opacityTexture.coordinatesIndex, this.opacityTexture.level);
+                this._effect.setMatrix("opacityMatrix", this.opacityTexture.getTextureMatrix());
+            }
 
-                    this._effect.setFloat2("vSpecularInfos", this.specularTexture.coordinatesIndex, this.specularTexture.level);
-                    this._effect.setMatrix("specularMatrix", this.specularTexture.getTextureMatrix());
+            if (this.reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
+                if (this.reflectionTexture.isCube) {
+                    this._effect.setTexture("reflectionCubeSampler", this.reflectionTexture);
+                } else {
+                    this._effect.setTexture("reflection2DSampler", this.reflectionTexture);
                 }
 
-                if (this.bumpTexture && scene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled) {
-                    this._effect.setTexture("bumpSampler", this.bumpTexture);
+                this._effect.setMatrix("reflectionMatrix", this.reflectionTexture.getReflectionTextureMatrix());
+                this._effect.setFloat3("vReflectionInfos", this.reflectionTexture.coordinatesMode, this.reflectionTexture.level, this.reflectionTexture.isCube ? 1 : 0);
+            }
 
-                    this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, 1.0 / this.bumpTexture.level);
-                    this._effect.setMatrix("bumpMatrix", this.bumpTexture.getTextureMatrix());
-                }
+            if (this.emissiveTexture && BABYLON.StandardMaterial.EmissiveTextureEnabled) {
+                this._effect.setTexture("emissiveSampler", this.emissiveTexture);
 
-                // Clip plane
-                if (scene.clipPlane) {
-                    var clipPlane = scene.clipPlane;
-                    this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
-                }
+                this._effect.setFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
+                this._effect.setMatrix("emissiveMatrix", this.emissiveTexture.getTextureMatrix());
+            }
 
-                // Point size
-                if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
-                }
+            if (this.specularTexture && BABYLON.StandardMaterial.SpecularTextureEnabled) {
+                this._effect.setTexture("specularSampler", this.specularTexture);
 
-                // Colors
-                scene.ambientColor.multiplyToRef(this.ambientColor, this._globalAmbientColor);
+                this._effect.setFloat2("vSpecularInfos", this.specularTexture.coordinatesIndex, this.specularTexture.level);
+                this._effect.setMatrix("specularMatrix", this.specularTexture.getTextureMatrix());
+            }
 
-                // Scaling down color according to emissive
-                this._scaledSpecular.r = this.specularColor.r * BABYLON.Tools.Clamp(1.0 - this.emissiveColor.r);
-                this._scaledSpecular.g = this.specularColor.g * BABYLON.Tools.Clamp(1.0 - this.emissiveColor.g);
-                this._scaledSpecular.b = this.specularColor.b * BABYLON.Tools.Clamp(1.0 - this.emissiveColor.b);
+            if (this.bumpTexture && scene.getEngine().getCaps().standardDerivatives && BABYLON.StandardMaterial.BumpTextureEnabled) {
+                this._effect.setTexture("bumpSampler", this.bumpTexture);
 
-                this._effect.setVector3("vEyePosition", scene.activeCamera.position);
-                this._effect.setColor3("vAmbientColor", this._globalAmbientColor);
-                this._effect.setColor4("vSpecularColor", this._scaledSpecular, this.specularPower);
-                this._effect.setColor3("vEmissiveColor", this.emissiveColor);
+                this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
+                this._effect.setMatrix("bumpMatrix", this.bumpTexture.getTextureMatrix());
             }
 
-            // Scaling down color according to emissive
-            this._scaledDiffuse.r = this.diffuseColor.r * BABYLON.Tools.Clamp(1.0 - this.emissiveColor.r);
-            this._scaledDiffuse.g = this.diffuseColor.g * BABYLON.Tools.Clamp(1.0 - this.emissiveColor.g);
-            this._scaledDiffuse.b = this.diffuseColor.b * BABYLON.Tools.Clamp(1.0 - this.emissiveColor.b);
+            // Colors
+            scene.ambientColor.multiplyToRef(this.ambientColor, this._globalAmbientColor);
 
-            this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
+            this._effect.setVector3("vEyePosition", scene.activeCamera.position);
+            this._effect.setColor3("vAmbientColor", this._globalAmbientColor);
+            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
+            this._effect.setColor3("vEmissiveColor", this.emissiveColor);
 
             if (scene.lightsEnabled) {
                 var lightIndex = 0;
@@ -561,23 +531,31 @@ var BABYLON;
 
                     lightIndex++;
 
-                    if (lightIndex === maxSimultaneousLights)
+                    if (lightIndex == maxSimultaneousLights)
                         break;
                 }
             }
 
+            if (scene.clipPlane) {
+                var clipPlane = scene.clipPlane;
+                this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
+            }
+
             // View
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE || this.reflectionTexture) {
+            if (scene.fogMode !== BABYLON.Scene.FOGMODE_NONE || this.reflectionTexture) {
                 this._effect.setMatrix("view", scene.getViewMatrix());
             }
 
             // Fog
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
+            if (scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
                 this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
                 this._effect.setColor3("vFogColor", scene.fogColor);
             }
 
-            _super.prototype.bind.call(this, world, mesh);
+            // Point size
+            if (this.pointsCloud) {
+                this._effect.setFloat("pointSize", this.pointSize);
+            }
         };
 
         StandardMaterial.prototype.getAnimatables = function () {
@@ -647,7 +625,7 @@ var BABYLON;
         };
 
         StandardMaterial.prototype.clone = function (name) {
-            var newStandardMaterial = new StandardMaterial(name, this.getScene());
+            var newStandardMaterial = new BABYLON.StandardMaterial(name, this.getScene());
 
             // Base material
             newStandardMaterial.checkReadyOnEveryCall = this.checkReadyOnEveryCall;
@@ -694,7 +672,6 @@ var BABYLON;
         StandardMaterial.EmissiveTextureEnabled = true;
         StandardMaterial.SpecularTextureEnabled = true;
         StandardMaterial.BumpTextureEnabled = true;
-        StandardMaterial.FresnelEnabled = true;
         return StandardMaterial;
     })(BABYLON.Material);
     BABYLON.StandardMaterial = StandardMaterial;

+ 51 - 69
Babylon/Materials/textures/Procedurals/babylon.customProceduralTexture.js

@@ -9,43 +9,42 @@ var BABYLON;
     var CustomProceduralTexture = (function (_super) {
         __extends(CustomProceduralTexture, _super);
         function CustomProceduralTexture(name, texturePath, size, scene, fallbackTexture, generateMipMaps) {
-            _super.call(this, name, size, null, scene, fallbackTexture, generateMipMaps);
-            this._animate = true;
+            _super.call(this, name, size, "empty", scene, fallbackTexture, generateMipMaps);
+            this._generateTime = true;
             this._time = 0;
+            this._shaderLoaded = false;
+
             this._texturePath = texturePath;
 
-            //Try to load json
+            //readJson
             this.loadJson(texturePath);
-            this.refreshRate = 1;
+
+            // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
+            this.refreshRate = 0;
         }
         CustomProceduralTexture.prototype.loadJson = function (jsonUrl) {
             var _this = this;
-            var that = this;
-
             function noConfigFile() {
-                BABYLON.Tools.Log("No config file found in " + jsonUrl + " trying to use ShaderStore or DOM element");
-                try  {
-                    that.setFragment(that._texturePath);
-                } catch (ex) {
-                    BABYLON.Tools.Error("No json or ShaderStore or DOM element found for CustomProceduralTexture");
-                }
+                BABYLON.Tools.Log("No config file found in " + jsonUrl);
             }
 
+            var that = this;
             var configFileUrl = jsonUrl + "/config.json";
+
             var xhr = new XMLHttpRequest();
 
             xhr.open("GET", configFileUrl, true);
             xhr.addEventListener("load", function () {
                 if (xhr.status === 200 || BABYLON.Tools.ValidateXHRData(xhr, 1)) {
                     try  {
-                        _this._config = JSON.parse(xhr.response);
-
-                        _this.updateShaderUniforms();
-                        _this.updateTextures();
-                        _this.setFragment(_this._texturePath + "/custom");
-
-                        _this._animate = _this._config.animate;
-                        _this.refreshRate = _this._config.refreshrate;
+                        that._config = JSON.parse(xhr.response);
+                        that.updateShaderUniforms();
+                        that.setFragment(jsonUrl + "/custom");
+                        that._generateTime = that._config.generateTime;
+                        if (that._generateTime)
+                            _this.refreshRate = 1;
+                        that._shaderLoaded = true;
+                        that.render();
                     } catch (ex) {
                         noConfigFile();
                     }
@@ -61,28 +60,16 @@ var BABYLON;
             try  {
                 xhr.send();
             } catch (ex) {
-                BABYLON.Tools.Error("CustomProceduralTexture: Error on XHR send request.");
-            }
-        };
-
-        CustomProceduralTexture.prototype.isReady = function () {
-            if (!_super.prototype.isReady.call(this)) {
-                return false;
+                BABYLON.Tools.Error("Error on XHR send request.");
             }
-
-            for (var name in this._textures) {
-                var texture = this._textures[name];
-
-                if (!texture.isReady()) {
-                    return false;
-                }
-            }
-
-            return true;
         };
 
         CustomProceduralTexture.prototype.render = function (useCameraPostProcess) {
-            if (this._animate) {
+            //if config and shader not loaded, do not render
+            if (!this._shaderLoaded)
+                return;
+
+            if (this._generateTime) {
                 this._time += this.getScene().getAnimationRatio() * 0.03;
                 this.updateShaderUniforms();
             }
@@ -90,46 +77,41 @@ var BABYLON;
             _super.prototype.render.call(this, useCameraPostProcess);
         };
 
-        CustomProceduralTexture.prototype.updateTextures = function () {
-            for (var i = 0; i < this._config.sampler2Ds.length; i++) {
-                this.setTexture(this._config.sampler2Ds[i].sample2Dname, new BABYLON.Texture(this._texturePath + "/" + this._config.sampler2Ds[i].textureRelativeUrl, this.getScene()));
+        CustomProceduralTexture.prototype.updateShaderUniforms = function () {
+            for (var i = 0; i < this._config.texture2Ds.length; i++) {
+                this.setTexture(this._config.texture2Ds[i].textureName, new BABYLON.Texture(this._texturePath + "/" + this._config.texture2Ds[i].textureRelativeUrl, this.getScene()));
             }
-        };
 
-        CustomProceduralTexture.prototype.updateShaderUniforms = function () {
-            if (this._config) {
-                for (var j = 0; j < this._config.uniforms.length; j++) {
-                    var uniform = this._config.uniforms[j];
-
-                    switch (uniform.type) {
-                        case "float":
-                            this.setFloat(uniform.name, uniform.value);
-                            break;
-                        case "color3":
-                            this.setColor3(uniform.name, new BABYLON.Color3(uniform.r, uniform.g, uniform.b));
-                            break;
-                        case "color4":
-                            this.setColor4(uniform.name, new BABYLON.Color4(uniform.r, uniform.g, uniform.b, uniform.a));
-                            break;
-                        case "vector2":
-                            this.setVector2(uniform.name, new BABYLON.Vector2(uniform.x, uniform.y));
-                            break;
-                        case "vector3":
-                            this.setVector3(uniform.name, new BABYLON.Vector3(uniform.x, uniform.y, uniform.z));
-                            break;
-                    }
+            for (var j = 0; j < this._config.uniforms.length; j++) {
+                var uniform = this._config.uniforms[j];
+
+                switch (uniform.type) {
+                    case "float":
+                        this.setFloat(uniform.name, uniform.value);
+                        break;
+                    case "color3":
+                        this.setColor3(uniform.name, new BABYLON.Color3(uniform.r, uniform.g, uniform.b));
+                        break;
+                    case "color4":
+                        this.setColor4(uniform.name, new BABYLON.Color4(uniform.r, uniform.g, uniform.b, uniform.a));
+                        break;
+                    case "vector2":
+                        this.setVector2(uniform.name, new BABYLON.Vector2(uniform.x, uniform.y));
+                        break;
+                    case "vector3":
+                        this.setVector3(uniform.name, new BABYLON.Vector3(uniform.x, uniform.y, uniform.z));
+                        break;
                 }
             }
-
-            this.setFloat("time", this._time);
         };
 
-        Object.defineProperty(CustomProceduralTexture.prototype, "animate", {
+        Object.defineProperty(CustomProceduralTexture.prototype, "generateTime", {
             get: function () {
-                return this._animate;
+                return this.generateTime;
             },
             set: function (value) {
-                this._animate = value;
+                this.generateTime = value;
+                this.updateShaderUniforms();
             },
             enumerable: true,
             configurable: true

+ 6 - 43
Babylon/Materials/textures/Procedurals/babylon.proceduralTexture.js

@@ -9,7 +9,6 @@ var BABYLON;
     var ProceduralTexture = (function (_super) {
         __extends(ProceduralTexture, _super);
         function ProceduralTexture(name, size, fragment, scene, fallbackTexture, generateMipMaps) {
-            if (typeof generateMipMaps === "undefined") { generateMipMaps = true; }
             _super.call(this, null, scene, !generateMipMaps);
             this._currentRefreshId = -1;
             this._refreshRate = 1;
@@ -25,7 +24,6 @@ var BABYLON;
             this._vectors2 = new Array();
             this._vectors3 = new Array();
             this._matrices = new Array();
-            this._fallbackTextureUsed = false;
 
             scene._proceduralTextures.push(this);
 
@@ -34,7 +32,7 @@ var BABYLON;
             this._size = size;
             this._generateMipMaps = generateMipMaps;
 
-            this.setFragment(fragment);
+            this._fragment = fragment;
 
             this._fallbackTexture = fallbackTexture;
 
@@ -61,42 +59,15 @@ var BABYLON;
 
             this._indexBuffer = scene.getEngine().createIndexBuffer(indices);
         }
-        ProceduralTexture.prototype.reset = function () {
-            if (this._effect === undefined) {
-                return;
-            }
-            var engine = this.getScene().getEngine();
-            engine._releaseEffect(this._effect);
-        };
-
         ProceduralTexture.prototype.isReady = function () {
             var _this = this;
             var engine = this.getScene().getEngine();
-            var shaders;
 
-            if (!this._fragment) {
-                return false;
-            }
-
-            if (this._fallbackTextureUsed) {
-                return true;
-            }
-
-            if (this._fragment.fragmentElement !== undefined) {
-                shaders = { vertex: "procedural", fragmentElement: this._fragment.fragmentElement };
-            } else {
-                shaders = { vertex: "procedural", fragment: this._fragment };
-            }
-
-            this._effect = engine.createEffect(shaders, ["position"], this._uniforms, this._samplers, "", null, null, function () {
+            this._effect = engine.createEffect({ vertex: "procedural", fragment: this._fragment }, ["position"], this._uniforms, this._samplers, "", null, null, function () {
                 _this.releaseInternalTexture();
 
-                if (_this._fallbackTexture) {
-                    _this._texture = _this._fallbackTexture._texture;
-                    _this._texture.references++;
-                }
-
-                _this._fallbackTextureUsed = true;
+                _this._texture = _this._fallbackTexture._texture;
+                _this._texture.references++;
             });
 
             return this._effect.isReady();
@@ -129,16 +100,12 @@ var BABYLON;
                 return false;
             }
 
-            if (this._fallbackTextureUsed) {
-                return false;
-            }
-
             if (this._currentRefreshId === -1) {
                 this._currentRefreshId = 1;
                 return true;
             }
 
-            if (this.refreshRate === this._currentRefreshId) {
+            if (this.refreshRate == this._currentRefreshId) {
                 this._currentRefreshId = 1;
                 return true;
             }
@@ -152,10 +119,6 @@ var BABYLON;
         };
 
         ProceduralTexture.prototype.resize = function (size, generateMipMaps) {
-            if (this._fallbackTextureUsed) {
-                return;
-            }
-
             this.releaseInternalTexture();
             this._texture = this.getScene().getEngine().createRenderTargetTexture(size, generateMipMaps);
         };
@@ -282,7 +245,7 @@ var BABYLON;
 
         ProceduralTexture.prototype.clone = function () {
             var textureSize = this.getSize();
-            var newTexture = new ProceduralTexture(this.name, textureSize.width, this._fragment, this.getScene(), this._fallbackTexture, this._generateMipMaps);
+            var newTexture = new BABYLON.ProceduralTexture(this.name, textureSize.width, this._fragment, this.getScene(), this._fallbackTexture, this._generateMipMaps);
 
             // Base texture
             newTexture.hasAlpha = this.hasAlpha;

+ 80 - 166
Babylon/Materials/textures/Procedurals/babylon.standardProceduralTexture.js

@@ -12,7 +12,10 @@ var BABYLON;
             _super.call(this, name, size, "wood", scene, fallbackTexture, generateMipMaps);
             this._ampScale = 100.0;
             this._woodColor = new BABYLON.Color3(0.32, 0.17, 0.09);
+
             this.updateShaderUniforms();
+
+            // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
             this.refreshRate = 0;
         }
         WoodProceduralTexture.prototype.updateShaderUniforms = function () {
@@ -56,23 +59,27 @@ var BABYLON;
             this._time = 0.0;
             this._speed = new BABYLON.Vector2(0.5, 0.3);
             this._shift = 1.6;
+            this._alpha = 1.0;
             this._autoGenerateTime = true;
-            this._alphaThreshold = 0.5;
+
             this._fireColors = FireProceduralTexture.RedFireColors;
             this.updateShaderUniforms();
+
+            // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
             this.refreshRate = 1;
         }
         FireProceduralTexture.prototype.updateShaderUniforms = function () {
-            this.setFloat("time", this._time);
+            this.setFloat("iGlobalTime", this._time);
             this.setVector2("speed", this._speed);
             this.setFloat("shift", this._shift);
-            this.setColor3("c1", this._fireColors[0]);
-            this.setColor3("c2", this._fireColors[1]);
-            this.setColor3("c3", this._fireColors[2]);
-            this.setColor3("c4", this._fireColors[3]);
-            this.setColor3("c5", this._fireColors[4]);
-            this.setColor3("c6", this._fireColors[5]);
-            this.setFloat("alphaThreshold", this._alphaThreshold);
+            this.setFloat("alpha", this._alpha);
+
+            this.setColor3("c1", new BABYLON.Color3(this._fireColors[0][0], this._fireColors[0][1], this._fireColors[0][2]));
+            this.setColor3("c2", new BABYLON.Color3(this._fireColors[1][0], this._fireColors[1][1], this._fireColors[1][2]));
+            this.setColor3("c3", new BABYLON.Color3(this._fireColors[2][0], this._fireColors[2][1], this._fireColors[2][2]));
+            this.setColor3("c4", new BABYLON.Color3(this._fireColors[3][0], this._fireColors[3][1], this._fireColors[3][2]));
+            this.setColor3("c5", new BABYLON.Color3(this._fireColors[4][0], this._fireColors[4][1], this._fireColors[4][2]));
+            this.setColor3("c6", new BABYLON.Color3(this._fireColors[5][0], this._fireColors[5][1], this._fireColors[5][2]));
         };
 
         FireProceduralTexture.prototype.render = function (useCameraPostProcess) {
@@ -80,18 +87,19 @@ var BABYLON;
                 this._time += this.getScene().getAnimationRatio() * 0.03;
                 this.updateShaderUniforms();
             }
+
             _super.prototype.render.call(this, useCameraPostProcess);
         };
 
         Object.defineProperty(FireProceduralTexture, "PurpleFireColors", {
             get: function () {
                 return [
-                    new BABYLON.Color3(0.5, 0.0, 1.0),
-                    new BABYLON.Color3(0.9, 0.0, 1.0),
-                    new BABYLON.Color3(0.2, 0.0, 1.0),
-                    new BABYLON.Color3(1.0, 0.9, 1.0),
-                    new BABYLON.Color3(0.1, 0.1, 1.0),
-                    new BABYLON.Color3(0.9, 0.9, 1.0)
+                    [0.5, 0.0, 1.0],
+                    [0.9, 0.0, 1.0],
+                    [0.2, 0.0, 1.0],
+                    [1.0, 0.9, 1.0],
+                    [0.1, 0.1, 1.0],
+                    [0.9, 0.9, 1.0]
                 ];
             },
             enumerable: true,
@@ -101,12 +109,12 @@ var BABYLON;
         Object.defineProperty(FireProceduralTexture, "GreenFireColors", {
             get: function () {
                 return [
-                    new BABYLON.Color3(0.5, 1.0, 0.0),
-                    new BABYLON.Color3(0.5, 1.0, 0.0),
-                    new BABYLON.Color3(0.3, 0.4, 0.0),
-                    new BABYLON.Color3(0.5, 1.0, 0.0),
-                    new BABYLON.Color3(0.2, 0.0, 0.0),
-                    new BABYLON.Color3(0.5, 1.0, 0.0)
+                    [0.5, 1.0, 0.0],
+                    [0.5, 1.0, 0.0],
+                    [0.3, 0.4, 0.0],
+                    [0.5, 1.0, 0.0],
+                    [0.2, 0.0, 0.0],
+                    [0.5, 1.0, 0.0]
                 ];
             },
             enumerable: true,
@@ -116,12 +124,12 @@ var BABYLON;
         Object.defineProperty(FireProceduralTexture, "RedFireColors", {
             get: function () {
                 return [
-                    new BABYLON.Color3(0.5, 0.0, 0.1),
-                    new BABYLON.Color3(0.9, 0.0, 0.0),
-                    new BABYLON.Color3(0.2, 0.0, 0.0),
-                    new BABYLON.Color3(1.0, 0.9, 0.0),
-                    new BABYLON.Color3(0.1, 0.1, 0.1),
-                    new BABYLON.Color3(0.9, 0.9, 0.9)
+                    [0.5, 0.0, 0.1],
+                    [0.9, 0.0, 0.0],
+                    [0.2, 0.0, 0.0],
+                    [1.0, 0.9, 0.0],
+                    [0.1, 0.1, 0.1],
+                    [0.9, 0.9, 0.9]
                 ];
             },
             enumerable: true,
@@ -131,12 +139,12 @@ var BABYLON;
         Object.defineProperty(FireProceduralTexture, "BlueFireColors", {
             get: function () {
                 return [
-                    new BABYLON.Color3(0.1, 0.0, 0.5),
-                    new BABYLON.Color3(0.0, 0.0, 0.5),
-                    new BABYLON.Color3(0.1, 0.0, 0.2),
-                    new BABYLON.Color3(0.0, 0.0, 1.0),
-                    new BABYLON.Color3(0.1, 0.2, 0.3),
-                    new BABYLON.Color3(0.0, 0.2, 0.9)
+                    [0.1, 0.0, 0.5],
+                    [0.0, 0.0, 0.5],
+                    [0.1, 0.0, 0.2],
+                    [0.0, 0.0, 1.0],
+                    [0.1, 0.2, 0.3],
+                    [0.0, 0.2, 0.9]
                 ];
             },
             enumerable: true,
@@ -195,12 +203,12 @@ var BABYLON;
         });
 
 
-        Object.defineProperty(FireProceduralTexture.prototype, "alphaThreshold", {
+        Object.defineProperty(FireProceduralTexture.prototype, "alpha", {
             get: function () {
-                return this._alphaThreshold;
+                return this._alpha;
             },
             set: function (value) {
-                this._alphaThreshold = value;
+                this._alpha = value;
                 this.updateShaderUniforms();
             },
             enumerable: true,
@@ -217,8 +225,12 @@ var BABYLON;
             _super.call(this, name, size, "cloud", scene, fallbackTexture, generateMipMaps);
             this._skyColor = new BABYLON.Color3(0.15, 0.68, 1.0);
             this._cloudColor = new BABYLON.Color3(1, 1, 1);
+
             this.updateShaderUniforms();
+
+            // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
             this.refreshRate = 0;
+            // https://www.shadertoy.com/view/XsjSRt
         }
         CloudProceduralTexture.prototype.updateShaderUniforms = function () {
             this.setColor3("skyColor", this._skyColor);
@@ -258,80 +270,34 @@ var BABYLON;
         __extends(GrassProceduralTexture, _super);
         function GrassProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
             _super.call(this, name, size, "grass", scene, fallbackTexture, generateMipMaps);
-            this._herb1 = new BABYLON.Color3(0.29, 0.38, 0.02);
-            this._herb2 = new BABYLON.Color3(0.36, 0.49, 0.09);
-            this._herb3 = new BABYLON.Color3(0.51, 0.6, 0.28);
-            this._groundColor = new BABYLON.Color3(1, 1, 1);
-
-            this._grassColors = [
-                new BABYLON.Color3(0.29, 0.38, 0.02),
-                new BABYLON.Color3(0.36, 0.49, 0.09),
-                new BABYLON.Color3(0.51, 0.6, 0.28)
-            ];
 
-            this.updateShaderUniforms();
+            // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
             this.refreshRate = 0;
         }
-        GrassProceduralTexture.prototype.updateShaderUniforms = function () {
-            this.setColor3("herb1Color", this._grassColors[0]);
-            this.setColor3("herb2Color", this._grassColors[1]);
-            this.setColor3("herb3Color", this._grassColors[2]);
-            this.setColor3("groundColor", this._groundColor);
-        };
-
-        Object.defineProperty(GrassProceduralTexture.prototype, "grassColors", {
-            get: function () {
-                return this._grassColors;
-            },
-            set: function (value) {
-                this._grassColors = value;
-                this.updateShaderUniforms();
-            },
-            enumerable: true,
-            configurable: true
-        });
-
-
-        Object.defineProperty(GrassProceduralTexture.prototype, "groundColor", {
-            get: function () {
-                return this._groundColor;
-            },
-            set: function (value) {
-                this.groundColor = value;
-                this.updateShaderUniforms();
-            },
-            enumerable: true,
-            configurable: true
-        });
-
         return GrassProceduralTexture;
     })(BABYLON.ProceduralTexture);
     BABYLON.GrassProceduralTexture = GrassProceduralTexture;
 
+    var RockProceduralTexture = (function (_super) {
+        __extends(RockProceduralTexture, _super);
+        function RockProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
+            _super.call(this, name, size, "rock", scene, fallbackTexture, generateMipMaps);
+
+            // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
+            this.refreshRate = 0;
+        }
+        return RockProceduralTexture;
+    })(BABYLON.ProceduralTexture);
+    BABYLON.RockProceduralTexture = RockProceduralTexture;
+
     var RoadProceduralTexture = (function (_super) {
         __extends(RoadProceduralTexture, _super);
         function RoadProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
             _super.call(this, name, size, "road", scene, fallbackTexture, generateMipMaps);
-            this._roadColor = new BABYLON.Color3(0.53, 0.53, 0.53);
-            this.updateShaderUniforms();
+
+            // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
             this.refreshRate = 0;
         }
-        RoadProceduralTexture.prototype.updateShaderUniforms = function () {
-            this.setColor3("roadColor", this._roadColor);
-        };
-
-        Object.defineProperty(RoadProceduralTexture.prototype, "roadColor", {
-            get: function () {
-                return this._roadColor;
-            },
-            set: function (value) {
-                this._roadColor = value;
-                this.updateShaderUniforms();
-            },
-            enumerable: true,
-            configurable: true
-        });
-
         return RoadProceduralTexture;
     })(BABYLON.ProceduralTexture);
     BABYLON.RoadProceduralTexture = RoadProceduralTexture;
@@ -342,16 +308,15 @@ var BABYLON;
             _super.call(this, name, size, "brick", scene, fallbackTexture, generateMipMaps);
             this._numberOfBricksHeight = 15;
             this._numberOfBricksWidth = 5;
-            this._jointColor = new BABYLON.Color3(0.72, 0.72, 0.72);
-            this._brickColor = new BABYLON.Color3(0.77, 0.47, 0.40);
+
             this.updateShaderUniforms();
+
+            // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
             this.refreshRate = 0;
         }
         BrickProceduralTexture.prototype.updateShaderUniforms = function () {
             this.setFloat("numberOfBricksHeight", this._numberOfBricksHeight);
             this.setFloat("numberOfBricksWidth", this._numberOfBricksWidth);
-            this.setColor3("brickColor", this._brickColor);
-            this.setColor3("jointColor", this._jointColor);
         };
 
         Object.defineProperty(BrickProceduralTexture.prototype, "numberOfBricksHeight", {
@@ -383,32 +348,6 @@ var BABYLON;
             configurable: true
         });
 
-
-        Object.defineProperty(BrickProceduralTexture.prototype, "jointColor", {
-            get: function () {
-                return this._jointColor;
-            },
-            set: function (value) {
-                this._jointColor = value;
-                this.updateShaderUniforms();
-            },
-            enumerable: true,
-            configurable: true
-        });
-
-
-        Object.defineProperty(BrickProceduralTexture.prototype, "brickColor", {
-            get: function () {
-                return this._brickColor;
-            },
-            set: function (value) {
-                this._brickColor = value;
-                this.updateShaderUniforms();
-            },
-            enumerable: true,
-            configurable: true
-        });
-
         return BrickProceduralTexture;
     })(BABYLON.ProceduralTexture);
     BABYLON.BrickProceduralTexture = BrickProceduralTexture;
@@ -417,67 +356,42 @@ var BABYLON;
         __extends(MarbleProceduralTexture, _super);
         function MarbleProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
             _super.call(this, name, size, "marble", scene, fallbackTexture, generateMipMaps);
-            this._numberOfTilesHeight = 3;
-            this._numberOfTilesWidth = 3;
-            this._amplitude = 9.0;
-            this._marbleColor = new BABYLON.Color3(0.77, 0.47, 0.40);
-            this._jointColor = new BABYLON.Color3(0.72, 0.72, 0.72);
+            this._numberOfBricksHeight = 3;
+            this._numberOfBricksWidth = 3;
+
             this.updateShaderUniforms();
+
+            // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
             this.refreshRate = 0;
         }
         MarbleProceduralTexture.prototype.updateShaderUniforms = function () {
-            this.setFloat("numberOfTilesHeight", this._numberOfTilesHeight);
-            this.setFloat("numberOfTilesWidth", this._numberOfTilesWidth);
-            this.setFloat("amplitude", this._amplitude);
-            this.setColor3("marbleColor", this._marbleColor);
-            this.setColor3("jointColor", this._jointColor);
+            this.setFloat("numberOfBricksHeight", this._numberOfBricksHeight);
+            this.setFloat("numberOfBricksWidth", this._numberOfBricksWidth);
         };
 
-        Object.defineProperty(MarbleProceduralTexture.prototype, "numberOfTilesHeight", {
-            get: function () {
-                return this._numberOfTilesHeight;
-            },
-            set: function (value) {
-                this._numberOfTilesHeight = value;
-                this.updateShaderUniforms();
-            },
-            enumerable: true,
-            configurable: true
-        });
-
-
-        Object.defineProperty(MarbleProceduralTexture.prototype, "numberOfTilesWidth", {
+        Object.defineProperty(MarbleProceduralTexture.prototype, "numberOfBricksHeight", {
             get: function () {
-                return this._numberOfTilesWidth;
-            },
-            set: function (value) {
-                this._numberOfTilesWidth = value;
-                this.updateShaderUniforms();
+                return this._numberOfBricksHeight;
             },
             enumerable: true,
             configurable: true
         });
 
-
-        Object.defineProperty(MarbleProceduralTexture.prototype, "jointColor", {
-            get: function () {
-                return this._jointColor;
-            },
+        Object.defineProperty(MarbleProceduralTexture.prototype, "cloudColor", {
             set: function (value) {
-                this._jointColor = value;
+                this._numberOfBricksHeight = value;
                 this.updateShaderUniforms();
             },
             enumerable: true,
             configurable: true
         });
 
-
-        Object.defineProperty(MarbleProceduralTexture.prototype, "marbleColor", {
+        Object.defineProperty(MarbleProceduralTexture.prototype, "numberOfBricksWidth", {
             get: function () {
-                return this._marbleColor;
+                return this._numberOfBricksWidth;
             },
             set: function (value) {
-                this._marbleColor = value;
+                this._numberOfBricksHeight = value;
                 this.updateShaderUniforms();
             },
             enumerable: true,

+ 1 - 1
Babylon/Materials/textures/babylon.baseTexture.js

@@ -116,7 +116,7 @@
             this._texture.references--;
 
             // Final reference ?
-            if (this._texture.references === 0) {
+            if (this._texture.references == 0) {
                 var index = texturesCache.indexOf(this._texture);
                 texturesCache.splice(index, 1);
 

+ 1 - 1
Babylon/Materials/textures/babylon.renderTargetTexture.js

@@ -135,7 +135,7 @@ var BABYLON;
 
                         for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                             var subMesh = mesh.subMeshes[subIndex];
-                            scene._activeVertices += subMesh.indexCount;
+                            scene._activeVertices += subMesh.verticesCount;
                             this._renderingManager.dispatch(subMesh);
                         }
                     }

+ 0 - 2
Babylon/Materials/textures/babylon.texture.js

@@ -133,8 +133,6 @@ var BABYLON;
                 this._projectionModeMatrix = BABYLON.Matrix.Zero();
             }
 
-            this._cachedCoordinatesMode = this.coordinatesMode;
-
             switch (this.coordinatesMode) {
                 case BABYLON.Texture.SPHERICAL_MODE:
                     BABYLON.Matrix.IdentityToRef(this._cachedTextureMatrix);

+ 0 - 54
Babylon/Math/babylon.math.js

@@ -850,21 +850,6 @@
             return Vector3.TransformCoordinates(vector, finalMatrix);
         };
 
-        Vector3.UnprojectFromTransform = function (source, viewportWidth, viewportHeight, world, transform) {
-            var matrix = world.multiply(transform);
-            matrix.invert();
-            source.x = source.x / viewportWidth * 2 - 1;
-            source.y = -(source.y / viewportHeight * 2 - 1);
-            var vector = BABYLON.Vector3.TransformCoordinates(source, matrix);
-            var num = source.x * matrix.m[3] + source.y * matrix.m[7] + source.z * matrix.m[11] + matrix.m[15];
-
-            if (BABYLON.Tools.WithinEpsilon(num, 1.0)) {
-                vector = vector.scale(1.0 / num);
-            }
-
-            return vector;
-        };
-
         Vector3.Unproject = function (source, viewportWidth, viewportHeight, world, view, projection) {
             var matrix = world.multiply(view).multiply(projection);
             matrix.invert();
@@ -2324,10 +2309,6 @@
                 var min = (minimum.x - this.origin.x) * inv;
                 var max = (maximum.x - this.origin.x) * inv;
 
-                if (max == -Infinity) {
-                    max = Infinity;
-                }
-
                 if (min > max) {
                     var temp = min;
                     min = max;
@@ -2351,10 +2332,6 @@
                 min = (minimum.y - this.origin.y) * inv;
                 max = (maximum.y - this.origin.y) * inv;
 
-                if (max == -Infinity) {
-                    max = Infinity;
-                }
-
                 if (min > max) {
                     temp = min;
                     min = max;
@@ -2378,10 +2355,6 @@
                 min = (minimum.z - this.origin.z) * inv;
                 max = (maximum.z - this.origin.z) * inv;
 
-                if (max == -Infinity) {
-                    max = Infinity;
-                }
-
                 if (min > max) {
                     temp = min;
                     min = max;
@@ -2521,32 +2494,5 @@
     })();
     BABYLON.Axis = Axis;
     ;
-
-    var BezierCurve = (function () {
-        function BezierCurve() {
-        }
-        BezierCurve.interpolate = function (t, x1, y1, x2, y2) {
-            // Extract X (which is equal to time here)
-            var f0 = 1 - 3 * x2 + 3 * x1;
-            var f1 = 3 * x2 - 6 * x1;
-            var f2 = 3 * x1;
-
-            var refinedT = t;
-            for (var i = 0; i < 5; i++) {
-                var refinedT2 = refinedT * refinedT;
-                var refinedT3 = refinedT2 * refinedT;
-
-                var x = f0 * refinedT3 + f1 * refinedT2 + f2 * refinedT;
-                var slope = 1.0 / (3.0 * f0 * refinedT2 + 2.0 * f1 * refinedT + f2);
-                refinedT -= (x - t) * slope;
-                refinedT = Math.min(1, Math.max(0, refinedT));
-            }
-
-            // Resolve cubic bezier for the given x
-            return 3 * Math.pow(1 - refinedT, 2) * refinedT * y1 + 3 * (1 - refinedT) * Math.pow(refinedT, 2) * y2 + Math.pow(refinedT, 3);
-        };
-        return BezierCurve;
-    })();
-    BABYLON.BezierCurve = BezierCurve;
 })(BABYLON || (BABYLON = {}));
 //# sourceMappingURL=babylon.math.js.map

+ 2 - 12
Babylon/Mesh/babylon.InstancedMesh.js

@@ -107,21 +107,11 @@ var BABYLON;
         };
 
         InstancedMesh.prototype._preActivate = function () {
-            if (this._currentLOD) {
-                this._currentLOD._preActivate();
-            }
+            this.sourceMesh._preActivate();
         };
 
         InstancedMesh.prototype._activate = function (renderId) {
-            if (this._currentLOD) {
-                this._currentLOD._registerInstanceForRenderId(this, renderId);
-            }
-        };
-
-        InstancedMesh.prototype.getLOD = function (camera) {
-            this._currentLOD = this.sourceMesh.getLOD(this.getScene().activeCamera, this.getBoundingInfo().boundingSphere);
-
-            return this._currentLOD;
+            this.sourceMesh._registerInstanceForRenderId(this, renderId);
         };
 
         InstancedMesh.prototype._syncSubMeshes = function () {

+ 3 - 44
Babylon/Mesh/babylon.abstractMesh.js

@@ -14,9 +14,8 @@ var BABYLON;
             this.position = new BABYLON.Vector3(0, 0, 0);
             this.rotation = new BABYLON.Vector3(0, 0, 0);
             this.scaling = new BABYLON.Vector3(1, 1, 1);
-            this.billboardMode = AbstractMesh.BILLBOARDMODE_NONE;
+            this.billboardMode = BABYLON.AbstractMesh.BILLBOARDMODE_NONE;
             this.visibility = 1.0;
-            this.alphaIndex = Number.MAX_VALUE;
             this.infiniteDistance = false;
             this.isVisible = true;
             this.isPickable = true;
@@ -30,12 +29,7 @@ var BABYLON;
             this.renderOutline = false;
             this.outlineColor = BABYLON.Color3.Red();
             this.outlineWidth = 0.02;
-            this.renderOverlay = false;
-            this.overlayColor = BABYLON.Color3.Red();
-            this.overlayAlpha = 0.5;
             this.hasVertexAlpha = false;
-            this.useVertexColors = true;
-            this.applyFog = true;
             this.useOctreeForRenderingSelection = true;
             this.useOctreeForPicking = true;
             this.useOctreeForCollisions = true;
@@ -67,7 +61,6 @@ var BABYLON;
             this._isDisposed = false;
             this._renderId = 0;
             this._intersectionsInProgress = new Array();
-            this._onAfterWorldMatrixUpdate = new Array();
 
             scene.meshes.push(this);
         }
@@ -141,10 +134,6 @@ var BABYLON;
         };
 
         AbstractMesh.prototype.getBoundingInfo = function () {
-            if (this._masterMesh) {
-                return this._masterMesh.getBoundingInfo();
-            }
-
             if (!this._boundingInfo) {
                 this._updateBoundingInfo();
             }
@@ -159,10 +148,6 @@ var BABYLON;
         };
 
         AbstractMesh.prototype.getWorldMatrix = function () {
-            if (this._masterMesh) {
-                return this._masterMesh.getWorldMatrix();
-            }
-
             if (this._currentRenderId !== this.getScene().getRenderId()) {
                 this.computeWorldMatrix();
             }
@@ -323,10 +308,6 @@ var BABYLON;
 
             this._boundingInfo._update(this.worldMatrixFromCache);
 
-            this._updateSubMeshesBoundingInfo(this.worldMatrixFromCache);
-        };
-
-        AbstractMesh.prototype._updateSubMeshesBoundingInfo = function (matrix) {
             if (!this.subMeshes) {
                 return;
             }
@@ -334,7 +315,7 @@ var BABYLON;
             for (var subIndex = 0; subIndex < this.subMeshes.length; subIndex++) {
                 var subMesh = this.subMeshes[subIndex];
 
-                subMesh.updateBoundingInfo(matrix);
+                subMesh.updateBoundingInfo(this.worldMatrixFromCache);
             }
         };
 
@@ -423,29 +404,9 @@ var BABYLON;
             // Absolute position
             this._absolutePosition.copyFromFloats(this._worldMatrix.m[12], this._worldMatrix.m[13], this._worldMatrix.m[14]);
 
-            for (var callbackIndex = 0; callbackIndex < this._onAfterWorldMatrixUpdate.length; callbackIndex++) {
-                this._onAfterWorldMatrixUpdate[callbackIndex](this);
-            }
-
             return this._worldMatrix;
         };
 
-        /**
-        * If you'd like to be callbacked after the mesh position, rotation or scaling has been updated
-        * @param func: callback function to add
-        */
-        AbstractMesh.prototype.registerAfterWorldMatrixUpdate = function (func) {
-            this._onAfterWorldMatrixUpdate.push(func);
-        };
-
-        AbstractMesh.prototype.unregisterAfterWorldMatrixUpdate = function (func) {
-            var index = this._onAfterWorldMatrixUpdate.indexOf(func);
-
-            if (index > -1) {
-                this._onAfterWorldMatrixUpdate.splice(index, 1);
-            }
-        };
-
         AbstractMesh.prototype.setPositionWithLocalVector = function (vector3) {
             this.computeWorldMatrix();
 
@@ -600,7 +561,7 @@ var BABYLON;
                 camera = this.getScene().activeCamera;
             }
 
-            return this.absolutePosition.subtract(camera.position).length();
+            return this.absolutePosition.subtract(camera.position);
         };
 
         AbstractMesh.prototype.applyImpulse = function (force, contactPoint) {
@@ -864,8 +825,6 @@ var BABYLON;
                 }
             }
 
-            this._onAfterWorldMatrixUpdate = [];
-
             this._isDisposed = true;
 
             // Callback

+ 5 - 10
Babylon/Mesh/babylon.geometry.js

@@ -74,14 +74,14 @@ var BABYLON;
             }
         };
 
-        Geometry.prototype.updateVerticesDataDirectly = function (kind, data, offset) {
+        Geometry.prototype.updateVerticesDataDirectly = function (kind, data) {
             var vertexBuffer = this.getVertexBuffer(kind);
 
             if (!vertexBuffer) {
                 return;
             }
 
-            vertexBuffer.updateDirectly(data, offset);
+            vertexBuffer.updateDirectly(data);
         };
 
         Geometry.prototype.updateVerticesData = function (kind, data, updateExtends) {
@@ -96,10 +96,9 @@ var BABYLON;
             if (kind === BABYLON.VertexBuffer.PositionKind) {
                 var extend;
 
-                var stride = vertexBuffer.getStrideSize();
-                this._totalVertices = data.length / stride;
-
                 if (updateExtends) {
+                    var stride = vertexBuffer.getStrideSize();
+                    this._totalVertices = data.length / stride;
                     extend = BABYLON.Tools.ExtractMinAndMax(data, 0, this._totalVertices);
                 }
 
@@ -171,7 +170,7 @@ var BABYLON;
             return result;
         };
 
-        Geometry.prototype.setIndices = function (indices, totalVertices) {
+        Geometry.prototype.setIndices = function (indices) {
             if (this._indexBuffer) {
                 this._engine._releaseBuffer(this._indexBuffer);
             }
@@ -181,10 +180,6 @@ var BABYLON;
                 this._indexBuffer = this._engine.createIndexBuffer(this._indices);
             }
 
-            if (totalVertices !== undefined) {
-                this._totalVertices = totalVertices;
-            }
-
             var meshes = this._meshes;
             var numOfMeshes = meshes.length;
 

+ 34 - 45
Babylon/Mesh/babylon.mesh.js

@@ -31,15 +31,7 @@ var BABYLON;
             this._batchCache = new _InstancesBatch();
             this._instancesBufferSize = 32 * 16 * 4;
         }
-        Object.defineProperty(Mesh.prototype, "hasLODLevels", {
-            // Methods
-            get: function () {
-                return this._LODLevels.length > 0;
-            },
-            enumerable: true,
-            configurable: true
-        });
-
+        // Methods
         Mesh.prototype._sortLODLevels = function () {
             this._LODLevels.sort(function (a, b) {
                 if (a.distance < b.distance) {
@@ -54,16 +46,11 @@ var BABYLON;
         };
 
         Mesh.prototype.addLODLevel = function (distance, mesh) {
-            if (mesh && mesh._masterMesh) {
-                BABYLON.Tools.Warn("You cannot use a mesh as LOD level twice");
-                return this;
-            }
-
             var level = new BABYLON.Internals.MeshLODLevel(distance, mesh);
             this._LODLevels.push(level);
 
             if (mesh) {
-                mesh._masterMesh = this;
+                mesh._attachedLODLevel = level;
             }
 
             this._sortLODLevels();
@@ -72,25 +59,37 @@ var BABYLON;
         };
 
         Mesh.prototype.removeLODLevel = function (mesh) {
-            for (var index = 0; index < this._LODLevels.length; index++) {
-                if (this._LODLevels[index].mesh === mesh) {
-                    this._LODLevels.splice(index, 1);
-                    if (mesh) {
-                        mesh._masterMesh = null;
+            if (mesh && !mesh._attachedLODLevel) {
+                return this;
+            }
+
+            var index;
+
+            if (mesh) {
+                index = this._LODLevels.indexOf(mesh._attachedLODLevel);
+                mesh._attachedLODLevel = null;
+
+                this._LODLevels.splice(index, 1);
+
+                this._sortLODLevels();
+            } else {
+                for (index = 0; index < this._LODLevels.length; index++) {
+                    if (this._LODLevels[index].mesh === null) {
+                        this._LODLevels.splice(index, 1);
+                        break;
                     }
                 }
             }
 
-            this._sortLODLevels();
             return this;
         };
 
-        Mesh.prototype.getLOD = function (camera, boundingSphere) {
+        Mesh.prototype.getLOD = function (camera) {
             if (!this._LODLevels || this._LODLevels.length === 0) {
                 return this;
             }
 
-            var distanceToCamera = (boundingSphere ? boundingSphere : this.getBoundingInfo().boundingSphere).centerWorld.subtract(camera.position).length();
+            var distanceToCamera = this.getBoundingInfo().boundingSphere.centerWorld.subtract(camera.position).length();
 
             if (this._LODLevels[this._LODLevels.length - 1].distance > distanceToCamera) {
                 return this;
@@ -101,8 +100,7 @@ var BABYLON;
 
                 if (level.distance < distanceToCamera) {
                     if (level.mesh) {
-                        level.mesh._preActivate();
-                        level.mesh._updateSubMeshesBoundingInfo(this.worldMatrixFromCache);
+                        level.mesh._worldMatrix = this._worldMatrix;
                     }
                     return level.mesh;
                 }
@@ -179,7 +177,7 @@ var BABYLON;
 
         Object.defineProperty(Mesh.prototype, "isBlocked", {
             get: function () {
-                return this._masterMesh !== null && this._masterMesh !== undefined;
+                return this._attachedLODLevel !== null && this._attachedLODLevel !== undefined;
             },
             enumerable: true,
             configurable: true
@@ -309,15 +307,15 @@ var BABYLON;
             }
         };
 
-        Mesh.prototype.updateVerticesDataDirectly = function (kind, data, offset, makeItUnique) {
+        Mesh.prototype.updateVerticesDataDirectly = function (kind, data, makeItUnique) {
             if (!this._geometry) {
                 return;
             }
             if (!makeItUnique) {
-                this._geometry.updateVerticesDataDirectly(kind, data, offset);
+                this._geometry.updateVerticesDataDirectly(kind, data);
             } else {
                 this.makeGeometryUnique();
-                this.updateVerticesDataDirectly(kind, data, offset, false);
+                this.updateVerticesDataDirectly(kind, data, false);
             }
         };
 
@@ -329,7 +327,7 @@ var BABYLON;
             geometry.applyToMesh(this);
         };
 
-        Mesh.prototype.setIndices = function (indices, totalVertices) {
+        Mesh.prototype.setIndices = function (indices) {
             if (!this._geometry) {
                 var vertexData = new BABYLON.VertexData();
                 vertexData.indices = indices;
@@ -338,7 +336,7 @@ var BABYLON;
 
                 new BABYLON.Geometry(BABYLON.Geometry.RandomId(), scene, vertexData, false, this);
             } else {
-                this._geometry.setIndices(indices, totalVertices);
+                this._geometry.setIndices(indices);
             }
         };
 
@@ -443,8 +441,7 @@ var BABYLON;
         };
 
         Mesh.prototype._renderWithInstances = function (subMesh, fillMode, batch, effect, engine) {
-            var visibleInstances = batch.visibleInstances[subMesh._id];
-            var matricesCount = visibleInstances.length + 1;
+            var matricesCount = this.instances.length + 1;
             var bufferSize = matricesCount * 16 * 4;
 
             while (this._instancesBufferSize < bufferSize) {
@@ -470,6 +467,8 @@ var BABYLON;
                 instancesCount++;
             }
 
+            var visibleInstances = batch.visibleInstances[subMesh._id];
+
             if (visibleInstances) {
                 for (var instanceIndex = 0; instanceIndex < visibleInstances.length; instanceIndex++) {
                     var instance = visibleInstances[instanceIndex];
@@ -513,7 +512,7 @@ var BABYLON;
             }
 
             var engine = scene.getEngine();
-            var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
+            var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null);
 
             // Material
             var effectiveMaterial = subMesh.getMaterial();
@@ -527,18 +526,16 @@ var BABYLON;
             if (this.renderOutline) {
                 engine.setDepthWrite(false);
                 scene.getOutlineRenderer().render(subMesh, batch);
-                engine.setDepthWrite(savedDepthWrite);
             }
 
             effectiveMaterial._preBind();
             var effect = effectiveMaterial.getEffect();
 
             // Bind
-            var fillMode = scene.forcePointsCloud ? BABYLON.Material.PointFillMode : (scene.forceWireframe ? BABYLON.Material.WireFrameFillMode : effectiveMaterial.fillMode);
+            var fillMode = engine.forceWireframe ? BABYLON.Material.WireFrameFillMode : effectiveMaterial.fillMode;
             this._bind(subMesh, effect, fillMode);
 
             var world = this.getWorldMatrix();
-
             effectiveMaterial.bind(world, this);
 
             // Instances rendering
@@ -575,14 +572,6 @@ var BABYLON;
                 engine.setColorWrite(true);
             }
 
-            // Overlay
-            if (this.renderOverlay) {
-                var currentMode = engine.getAlphaMode();
-                engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
-                scene.getOutlineRenderer().render(subMesh, batch, true);
-                engine.setAlphaMode(currentMode);
-            }
-
             for (callbackIndex = 0; callbackIndex < this._onAfterRenderCallbacks.length; callbackIndex++) {
                 this._onAfterRenderCallbacks[callbackIndex]();
             }

+ 2 - 2
Babylon/Mesh/babylon.vertexBuffer.js

@@ -90,13 +90,13 @@
             this.create(data);
         };
 
-        VertexBuffer.prototype.updateDirectly = function (data, offset) {
+        VertexBuffer.prototype.updateDirectly = function (data) {
             if (!this._buffer) {
                 return;
             }
 
             if (this._updatable) {
-                this._engine.updateDynamicVertexBuffer(this._buffer, data, offset);
+                this._engine.updateDynamicVertexBuffer(this._buffer, data);
                 this._data = null;
             }
         };

+ 6 - 7
Babylon/Particles/babylon.particleSystem.js

@@ -1,7 +1,7 @@
 var BABYLON;
 (function (BABYLON) {
     var randomNumber = function (min, max) {
-        if (min === max) {
+        if (min == max) {
             return (min);
         }
 
@@ -29,7 +29,7 @@
             this.maxSize = 1;
             this.minAngularSpeed = 0;
             this.maxAngularSpeed = 0;
-            this.blendMode = ParticleSystem.BLENDMODE_ONEONE;
+            this.blendMode = BABYLON.ParticleSystem.BLENDMODE_ONEONE;
             this.forceDepthWrite = false;
             this.gravity = BABYLON.Vector3.Zero();
             this.direction1 = new BABYLON.Vector3(0, 1.0, 0);
@@ -173,7 +173,7 @@
             }
 
             for (index = 0; index < newParticles; index++) {
-                if (this.particles.length === this._capacity) {
+                if (this.particles.length == this._capacity) {
                     break;
                 }
 
@@ -219,7 +219,7 @@
 
             // Effect
             var join = defines.join("\n");
-            if (this._cachedDefines !== join) {
+            if (this._cachedDefines != join) {
                 this._cachedDefines = join;
 
                 this._effect = this._scene.getEngine().createEffect("particles", ["position", "color", "options"], ["invView", "view", "projection", "vClipPlane", "textureMask"], ["diffuseSampler"], join);
@@ -312,7 +312,6 @@
 
             // Render
             engine.enableEffect(effect);
-            engine.setState(false);
 
             var viewMatrix = this._scene.getViewMatrix();
             effect.setTexture("diffuseSampler", this.particleTexture);
@@ -332,7 +331,7 @@
             engine.bindBuffers(this._vertexBuffer, this._indexBuffer, this._vertexDeclaration, this._vertexStrideSize, effect);
 
             // Draw order
-            if (this.blendMode === ParticleSystem.BLENDMODE_ONEONE) {
+            if (this.blendMode === BABYLON.ParticleSystem.BLENDMODE_ONEONE) {
                 engine.setAlphaMode(BABYLON.Engine.ALPHA_ADD);
             } else {
                 engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
@@ -376,7 +375,7 @@
 
         // Clone
         ParticleSystem.prototype.clone = function (name, newEmitter) {
-            var result = new ParticleSystem(name, this._capacity, this._scene);
+            var result = new BABYLON.ParticleSystem(name, this._capacity, this._scene);
 
             BABYLON.Tools.DeepCopy(this, result, ["particles"], ["_vertexDeclaration", "_vertexStrideSize"]);
 

+ 0 - 2
Babylon/Physics/Plugins/babylon.oimoJSPlugin.js

@@ -304,7 +304,6 @@ var BABYLON;
                             mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
                         }
                         mesh.rotationQuaternion.fromRotationMatrix(mtx);
-                        mesh.computeWorldMatrix();
                     } else {
                         m = body.getMatrix();
                         mtx = BABYLON.Matrix.FromArray(m);
@@ -326,7 +325,6 @@ var BABYLON;
                             mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
                         }
                         mesh.rotationQuaternion.fromRotationMatrix(mtx);
-                        mesh.computeWorldMatrix();
                     }
                 }
             }

+ 1 - 3
Babylon/Rendering/babylon.boundingBoxRenderer.js

@@ -22,7 +22,7 @@
         };
 
         BoundingBoxRenderer.prototype.render = function () {
-            if (this.renderList.length === 0 || !this._colorShader.isReady()) {
+            if (this.renderList.length == 0 || !this._colorShader.isReady()) {
                 return;
             }
 
@@ -44,7 +44,6 @@
                 if (this.showBackLines) {
                     // Back
                     engine.setDepthFunctionToGreaterOrEqual();
-                    this._scene.resetCachedMaterial();
                     this._colorShader.setColor4("color", this.backColor.toColor4());
                     this._colorShader.bind(worldMatrix);
 
@@ -54,7 +53,6 @@
 
                 // Front
                 engine.setDepthFunctionToLess();
-                this._scene.resetCachedMaterial();
                 this._colorShader.setColor4("color", this.frontColor.toColor4());
                 this._colorShader.bind(worldMatrix);
 

+ 5 - 6
Babylon/Rendering/babylon.outlineRenderer.js

@@ -4,12 +4,11 @@
         function OutlineRenderer(scene) {
             this._scene = scene;
         }
-        OutlineRenderer.prototype.render = function (subMesh, batch, useOverlay) {
-            if (typeof useOverlay === "undefined") { useOverlay = false; }
+        OutlineRenderer.prototype.render = function (subMesh, batch) {
             var scene = this._scene;
             var engine = this._scene.getEngine();
 
-            var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
+            var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances !== null);
 
             if (!this.isReady(subMesh, hardwareInstancedRendering)) {
                 return;
@@ -19,12 +18,12 @@
             var material = subMesh.getMaterial();
 
             engine.enableEffect(this._effect);
-            this._effect.setFloat("offset", useOverlay ? 0 : mesh.outlineWidth);
-            this._effect.setColor4("color", useOverlay ? mesh.overlayColor : mesh.outlineColor, useOverlay ? mesh.overlayAlpha : 1.0);
+            this._effect.setFloat("offset", mesh.outlineWidth);
+            this._effect.setColor3("color", mesh.outlineColor);
             this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
 
             // Bones
-            var useBones = mesh.skeleton && scene.skeletonsEnabled && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
+            var useBones = mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
             if (useBones) {
                 this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
             }

+ 6 - 11
Babylon/Rendering/babylon.renderingGroup.js

@@ -25,6 +25,7 @@
 
             for (subIndex = 0; subIndex < this._opaqueSubMeshes.length; subIndex++) {
                 submesh = this._opaqueSubMeshes.data[subIndex];
+                this._activeVertices += submesh.verticesCount;
 
                 submesh.render();
             }
@@ -33,6 +34,7 @@
             engine.setAlphaTesting(true);
             for (subIndex = 0; subIndex < this._alphaTestSubMeshes.length; subIndex++) {
                 submesh = this._alphaTestSubMeshes.data[subIndex];
+                this._activeVertices += submesh.verticesCount;
 
                 submesh.render();
             }
@@ -46,22 +48,12 @@
             if (this._transparentSubMeshes.length) {
                 for (subIndex = 0; subIndex < this._transparentSubMeshes.length; subIndex++) {
                     submesh = this._transparentSubMeshes.data[subIndex];
-                    submesh._alphaIndex = submesh.getMesh().alphaIndex;
                     submesh._distanceToCamera = submesh.getBoundingInfo().boundingSphere.centerWorld.subtract(this._scene.activeCamera.position).length();
                 }
 
                 var sortedArray = this._transparentSubMeshes.data.slice(0, this._transparentSubMeshes.length);
 
                 sortedArray.sort(function (a, b) {
-                    // Alpha index first
-                    if (a._alphaIndex > b._alphaIndex) {
-                        return 1;
-                    }
-                    if (a._alphaIndex < b._alphaIndex) {
-                        return -1;
-                    }
-
-                    // Then distance to camera
                     if (a._distanceToCamera < b._distanceToCamera) {
                         return 1;
                     }
@@ -76,6 +68,7 @@
                 engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
                 for (subIndex = 0; subIndex < sortedArray.length; subIndex++) {
                     submesh = sortedArray[subIndex];
+                    this._activeVertices += submesh.verticesCount;
 
                     submesh.render();
                 }
@@ -95,7 +88,9 @@
             var mesh = subMesh.getMesh();
 
             if (material.needAlphaBlending() || mesh.visibility < 1.0 || mesh.hasVertexAlpha) {
-                this._transparentSubMeshes.push(subMesh);
+                if (material.alpha > 0 || mesh.visibility < 1.0) {
+                    this._transparentSubMeshes.push(subMesh);
+                }
             } else if (material.needAlphaTesting()) {
                 this._alphaTestSubMeshes.push(subMesh);
             } else {

+ 3 - 2
Babylon/Rendering/babylon.renderingManager.js

@@ -69,10 +69,11 @@
                         }
                     })) {
                         this._renderingGroups.splice(index, 1);
-                    } else if (renderSprites) {
-                        this._renderSprites(index);
                     }
+                } else if (renderSprites) {
+                    this._renderSprites(index);
                 }
+
                 if (renderParticles) {
                     this._renderParticles(index, activeMeshes);
                 }

+ 2 - 2
Babylon/Sprites/babylon.spriteManager.js

@@ -108,7 +108,7 @@
             // Render
             var effect = this._effectBase;
 
-            if (this._scene.fogEnabled && this._scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
+            if (this._scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
                 effect = this._effectFog;
             }
 
@@ -122,7 +122,7 @@
             effect.setFloat2("textureInfos", this.cellSize / baseSize.width, this.cellSize / baseSize.height);
 
             // Fog
-            if (this._scene.fogEnabled && this._scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
+            if (this._scene.fogMode !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
                 effect.setFloat4("vFogInfos", this._scene.fogMode, this._scene.fogStart, this._scene.fogEnd, this._scene.fogDensity);
                 effect.setColor3("vFogColor", this._scene.fogColor);
             }

+ 4 - 44
Babylon/Tools/babylon.tools.js

@@ -280,17 +280,6 @@
         };
 
         // Misc.
-        Tools.Clamp = function (value, min, max) {
-            if (typeof min === "undefined") { min = 0; }
-            if (typeof max === "undefined") { max = 1; }
-            return Math.min(max, Math.max(min, value));
-        };
-
-        Tools.Format = function (value, decimals) {
-            if (typeof decimals === "undefined") { decimals = 2; }
-            return value.toFixed(decimals);
-        };
-
         Tools.CheckExtends = function (v, min, max) {
             if (v.x < min.x)
                 min.x = v.x;
@@ -608,64 +597,36 @@
             configurable: true
         });
 
-        Tools._AddLogEntry = function (entry) {
-            Tools._LogCache = entry + Tools._LogCache;
-
-            if (Tools.OnNewCacheEntry) {
-                Tools.OnNewCacheEntry(entry);
-            }
-        };
-
         Tools._FormatMessage = function (message) {
             var padStr = function (i) {
                 return (i < 10) ? "0" + i : "" + i;
             };
 
             var date = new Date();
-            return "[" + padStr(date.getHours()) + ":" + padStr(date.getMinutes()) + ":" + padStr(date.getSeconds()) + "]: " + message;
+            return "BJS - [" + padStr(date.getHours()) + ":" + padStr(date.getMinutes()) + ":" + padStr(date.getSeconds()) + "]: " + message;
         };
 
         Tools._LogDisabled = function (message) {
             // nothing to do
         };
         Tools._LogEnabled = function (message) {
-            var formattedMessage = Tools._FormatMessage(message);
-            console.log("BJS - " + formattedMessage);
-
-            var entry = "<div style='color:white'>" + formattedMessage + "</div><br>";
-            Tools._AddLogEntry(entry);
+            console.log(Tools._FormatMessage(message));
         };
 
         Tools._WarnDisabled = function (message) {
             // nothing to do
         };
         Tools._WarnEnabled = function (message) {
-            var formattedMessage = Tools._FormatMessage(message);
-            console.warn("BJS - " + formattedMessage);
-
-            var entry = "<div style='color:orange'>" + formattedMessage + "</div><br>";
-            Tools._AddLogEntry(entry);
+            console.warn(Tools._FormatMessage(message));
         };
 
         Tools._ErrorDisabled = function (message) {
             // nothing to do
         };
         Tools._ErrorEnabled = function (message) {
-            var formattedMessage = Tools._FormatMessage(message);
-            console.error("BJS - " + formattedMessage);
-
-            var entry = "<div style='color:red'>" + formattedMessage + "</div><br>";
-            Tools._AddLogEntry(entry);
+            console.error(Tools._FormatMessage(message));
         };
 
-        Object.defineProperty(Tools, "LogCache", {
-            get: function () {
-                return Tools._LogCache;
-            },
-            enumerable: true,
-            configurable: true
-        });
-
         Object.defineProperty(Tools, "LogLevels", {
             set: function (level) {
                 if ((level & Tools.MessageLogLevel) === Tools.MessageLogLevel) {
@@ -814,7 +775,6 @@
         Tools._MessageLogLevel = 1;
         Tools._WarningLogLevel = 2;
         Tools._ErrorLogLevel = 4;
-        Tools._LogCache = "";
 
         Tools.Log = Tools._LogEnabled;
 

+ 9 - 39
Babylon/babylon.engine.js

@@ -364,17 +364,16 @@
             // Public members
             this.isFullscreen = false;
             this.isPointerLock = false;
+            this.forceWireframe = false;
             this.cullBackFaces = true;
             this.renderEvenInBackground = true;
             this.scenes = new Array();
             this._windowIsBackground = false;
             this._runningLoop = false;
             this._loadingDivBackgroundColor = "black";
-            this._drawCalls = 0;
             // States
             this._depthCullingState = new _DepthCullingState();
             this._alphaState = new _AlphaState();
-            this._alphaMode = Engine.ALPHA_DISABLE;
             // Cache
             this._loadedTexturesCache = new Array();
             this._activeTexturesCache = new Array();
@@ -472,10 +471,6 @@
             document.addEventListener("mspointerlockchange", this._onPointerLockChange, false);
             document.addEventListener("mozpointerlockchange", this._onPointerLockChange, false);
             document.addEventListener("webkitpointerlockchange", this._onPointerLockChange, false);
-
-            this._audioEngine = new BABYLON.AudioEngine();
-
-            BABYLON.Tools.Log("Babylon.js engine (v" + Engine.Version + ") launched");
         }
         Object.defineProperty(Engine, "ALPHA_DISABLE", {
             get: function () {
@@ -541,10 +536,6 @@
             configurable: true
         });
 
-        Engine.prototype.getAudioEngine = function () {
-            return this._audioEngine;
-        };
-
         Engine.prototype.getAspectRatio = function (camera) {
             var viewport = camera.viewport;
             return (this.getRenderWidth() * viewport.width) / (this.getRenderHeight() * viewport.height);
@@ -591,19 +582,7 @@
             return this._caps;
         };
 
-        Object.defineProperty(Engine.prototype, "drawCalls", {
-            get: function () {
-                return this._drawCalls;
-            },
-            enumerable: true,
-            configurable: true
-        });
-
         // Methods
-        Engine.prototype.resetDrawCalls = function () {
-            this._drawCalls = 0;
-        };
-
         Engine.prototype.setDepthFunctionToGreater = function () {
             this._depthCullingState.depthFunc = this._gl.GREATER;
         };
@@ -749,7 +728,7 @@
         };
 
         Engine.prototype.flushFramebuffer = function () {
-            //   this._gl.flush();
+            this._gl.flush();
         };
 
         Engine.prototype.restoreDefaultFramebuffer = function () {
@@ -785,19 +764,19 @@
             return vbo;
         };
 
-        Engine.prototype.updateDynamicVertexBuffer = function (vertexBuffer, vertices, offset) {
+        Engine.prototype.updateDynamicVertexBuffer = function (vertexBuffer, vertices, length) {
             this._gl.bindBuffer(this._gl.ARRAY_BUFFER, vertexBuffer);
 
-            if (offset === undefined) {
-                offset = 0;
-            }
-
+            //if (length && length != vertices.length) {
+            //    this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, new Float32Array(vertices, 0, length));
+            //} else {
             if (vertices instanceof Float32Array) {
-                this._gl.bufferSubData(this._gl.ARRAY_BUFFER, offset, vertices);
+                this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, vertices);
             } else {
-                this._gl.bufferSubData(this._gl.ARRAY_BUFFER, offset, new Float32Array(vertices));
+                this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, new Float32Array(vertices));
             }
 
+            //  }
             this._resetVertexBufferBinding();
         };
 
@@ -951,8 +930,6 @@
             }
 
             this._gl.drawElements(useTriangles ? this._gl.TRIANGLES : this._gl.LINES, indexCount, indexFormat, indexStart * 2);
-
-            this._drawCalls++;
         };
 
         Engine.prototype.drawPointClouds = function (verticesStart, verticesCount, instancesCount) {
@@ -965,7 +942,6 @@
             }
 
             this._gl.drawArrays(this._gl.POINTS, verticesStart, verticesCount);
-            this._drawCalls++;
         };
 
         // Shaders
@@ -1207,12 +1183,6 @@
                     this._alphaState.alphaBlend = true;
                     break;
             }
-
-            this._alphaMode = mode;
-        };
-
-        Engine.prototype.getAlphaMode = function () {
-            return this._alphaMode;
         };
 
         Engine.prototype.setAlphaTesting = function (enable) {

+ 24 - 129
Babylon/babylon.scene.js

@@ -8,13 +8,9 @@
             this.clearColor = new BABYLON.Color3(0.2, 0.2, 0.3);
             this.ambientColor = new BABYLON.Color3(0, 0, 0);
             this.forceWireframe = false;
-            this.forcePointsCloud = false;
-            this.forceShowBoundingBoxes = false;
-            this.animationsEnabled = true;
             this.cameraToUseForPointers = null;
             // Fog
-            this.fogEnabled = true;
-            this.fogMode = Scene.FOGMODE_NONE;
+            this.fogMode = BABYLON.Scene.FOGMODE_NONE;
             this.fogColor = new BABYLON.Color3(0.2, 0.2, 0.3);
             this.fogDensity = 0.1;
             this.fogStart = 0;
@@ -44,7 +40,6 @@
             // Layers
             this.layers = new Array();
             // Skeletons
-            this.skeletonsEnabled = true;
             this.skeletons = new Array();
             // Lens flares
             this.lensFlaresEnabled = true;
@@ -64,7 +59,6 @@
             // Procedural textures
             this.proceduralTexturesEnabled = true;
             this._proceduralTextures = new Array();
-            this.soundTracks = new Array();
             this._totalVertices = 0;
             this._activeVertices = 0;
             this._activeParticles = 0;
@@ -81,13 +75,11 @@
             this._onReadyCallbacks = new Array();
             this._pendingData = [];
             this._onBeforeRenderCallbacks = new Array();
-            this._onAfterRenderCallbacks = new Array();
             this._activeMeshes = new BABYLON.SmartArray(256);
             this._processedMaterials = new BABYLON.SmartArray(256);
             this._renderTargets = new BABYLON.SmartArray(256);
             this._activeParticleSystems = new BABYLON.SmartArray(256);
             this._activeSkeletons = new BABYLON.SmartArray(32);
-            this._activeBones = 0;
             this._activeAnimatables = new Array();
             this._transformMatrix = BABYLON.Matrix.Zero();
             this._scaledPosition = BABYLON.Vector3.Zero();
@@ -106,20 +98,9 @@
             this._outlineRenderer = new BABYLON.OutlineRenderer(this);
 
             this.attachControl();
-
-            this._debugLayer = new BABYLON.DebugLayer(this);
-            this.mainSoundTrack = new BABYLON.SoundTrack(this, { mainTrack: true });
         }
-        Object.defineProperty(Scene.prototype, "debugLayer", {
-            // Properties
-            get: function () {
-                return this._debugLayer;
-            },
-            enumerable: true,
-            configurable: true
-        });
-
         Object.defineProperty(Scene.prototype, "meshUnderPointer", {
+            // Properties
             get: function () {
                 return this._meshUnderPointer;
             },
@@ -143,10 +124,6 @@
             configurable: true
         });
 
-        Scene.prototype.getCachedMaterial = function () {
-            return this._cachedMaterial;
-        };
-
         Scene.prototype.getBoundingBoxRenderer = function () {
             return this._boundingBoxRenderer;
         };
@@ -171,10 +148,6 @@
             return this._activeParticles;
         };
 
-        Scene.prototype.getActiveBones = function () {
-            return this._activeBones;
-        };
-
         // Stats
         Scene.prototype.getLastFrameDuration = function () {
             return this._lastFrameDuration;
@@ -344,10 +317,6 @@
             return true;
         };
 
-        Scene.prototype.resetCachedMaterial = function () {
-            this._cachedMaterial = null;
-        };
-
         Scene.prototype.registerBeforeRender = function (func) {
             this._onBeforeRenderCallbacks.push(func);
         };
@@ -360,18 +329,6 @@
             }
         };
 
-        Scene.prototype.registerAfterRender = function (func) {
-            this._onAfterRenderCallbacks.push(func);
-        };
-
-        Scene.prototype.unregisterAfterRender = function (func) {
-            var index = this._onAfterRenderCallbacks.indexOf(func);
-
-            if (index > -1) {
-                this._onAfterRenderCallbacks.splice(index, 1);
-            }
-        };
-
         Scene.prototype._addPendingData = function (data) {
             this._pendingData.push(data);
         };
@@ -475,10 +432,6 @@
         };
 
         Scene.prototype._animate = function () {
-            if (!this.animationsEnabled) {
-                return;
-            }
-
             if (!this._animationStartDate) {
                 this._animationStartDate = BABYLON.Tools.Now;
             }
@@ -709,7 +662,7 @@
         };
 
         Scene.prototype._evaluateSubMesh = function (subMesh, mesh) {
-            if (mesh.subMeshes.length === 1 || subMesh.isInFrustum(this._frustumPlanes)) {
+            if (mesh.subMeshes.length == 1 || subMesh.isInFrustum(this._frustumPlanes)) {
                 var material = subMesh.getMaterial();
 
                 if (mesh.showSubMeshesBoundingBox) {
@@ -727,7 +680,7 @@
                     }
 
                     // Dispatch
-                    this._activeVertices += subMesh.indexCount;
+                    this._activeVertices += subMesh.verticesCount;
                     this._renderingManager.dispatch(subMesh);
                 }
             }
@@ -774,26 +727,18 @@
                 }
 
                 mesh.computeWorldMatrix();
+                mesh._preActivate();
 
                 // Intersections
                 if (mesh.actionManager && mesh.actionManager.hasSpecificTriggers([BABYLON.ActionManager.OnIntersectionEnterTrigger, BABYLON.ActionManager.OnIntersectionExitTrigger])) {
                     this._meshesForIntersections.pushNoDuplicate(mesh);
                 }
 
-                // Switch to current LOD
-                var meshLOD = mesh.getLOD(this.activeCamera);
-
-                if (!meshLOD) {
-                    continue;
-                }
-
-                mesh._preActivate();
-
-                if (mesh.isEnabled() && mesh.isVisible && mesh.visibility > 0 && ((mesh.layerMask & this.activeCamera.layerMask) !== 0) && mesh.isInFrustum(this._frustumPlanes)) {
+                if (mesh.isEnabled() && mesh.isVisible && mesh.visibility > 0 && ((mesh.layerMask & this.activeCamera.layerMask) != 0) && mesh.isInFrustum(this._frustumPlanes)) {
                     this._activeMeshes.push(mesh);
                     mesh._activate(this._renderId);
 
-                    this._activeMesh(meshLOD);
+                    this._activeMesh(mesh);
                 }
             }
 
@@ -819,33 +764,35 @@
         };
 
         Scene.prototype._activeMesh = function (mesh) {
-            if (mesh.skeleton && this.skeletonsEnabled) {
+            if (mesh.skeleton) {
                 this._activeSkeletons.pushNoDuplicate(mesh.skeleton);
             }
 
-            if (mesh.showBoundingBox || this.forceShowBoundingBoxes) {
+            if (mesh.showBoundingBox) {
                 this._boundingBoxRenderer.renderList.push(mesh.getBoundingInfo().boundingBox);
             }
 
-            if (mesh && mesh.subMeshes) {
+            var activeMesh = mesh.getLOD(this.activeCamera);
+
+            if (activeMesh && activeMesh.subMeshes) {
                 // Submeshes Octrees
                 var len;
                 var subMeshes;
 
-                if (mesh._submeshesOctree && mesh.useOctreeForRenderingSelection) {
-                    var intersections = mesh._submeshesOctree.select(this._frustumPlanes);
+                if (activeMesh._submeshesOctree && activeMesh.useOctreeForRenderingSelection) {
+                    var intersections = activeMesh._submeshesOctree.select(this._frustumPlanes);
 
                     len = intersections.length;
                     subMeshes = intersections.data;
                 } else {
-                    subMeshes = mesh.subMeshes;
+                    subMeshes = activeMesh.subMeshes;
                     len = subMeshes.length;
                 }
 
                 for (var subIndex = 0; subIndex < len; subIndex++) {
                     var subMesh = subMeshes[subIndex];
 
-                    this._evaluateSubMesh(subMesh, mesh);
+                    this._evaluateSubMesh(subMesh, activeMesh);
                 }
             }
         };
@@ -886,8 +833,6 @@
                 var skeleton = this._activeSkeletons.data[skeletonIndex];
 
                 skeleton.prepare();
-
-                this._activeBones += skeleton.bones.length;
             }
 
             // Render targets
@@ -977,7 +922,7 @@
         };
 
         Scene.prototype._processSubCameras = function (camera) {
-            if (camera.subCameras.length === 0) {
+            if (camera.subCameras.length == 0) {
                 this._renderForCamera(camera);
                 return;
             }
@@ -1000,17 +945,17 @@
                 for (var actionIndex = 0; actionIndex < sourceMesh.actionManager.actions.length; actionIndex++) {
                     var action = sourceMesh.actionManager.actions[actionIndex];
 
-                    if (action.trigger === BABYLON.ActionManager.OnIntersectionEnterTrigger || action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
+                    if (action.trigger == BABYLON.ActionManager.OnIntersectionEnterTrigger || action.trigger == BABYLON.ActionManager.OnIntersectionExitTrigger) {
                         var otherMesh = action.getTriggerParameter();
 
                         var areIntersecting = otherMesh.intersectsMesh(sourceMesh, false);
                         var currentIntersectionInProgress = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
 
-                        if (areIntersecting && currentIntersectionInProgress === -1 && action.trigger === BABYLON.ActionManager.OnIntersectionEnterTrigger) {
-                            action._executeCurrent(BABYLON.ActionEvent.CreateNew(sourceMesh));
+                        if (areIntersecting && currentIntersectionInProgress === -1 && action.trigger == BABYLON.ActionManager.OnIntersectionEnterTrigger) {
+                            sourceMesh.actionManager.processTrigger(BABYLON.ActionManager.OnIntersectionEnterTrigger, BABYLON.ActionEvent.CreateNew(sourceMesh));
                             sourceMesh._intersectionsInProgress.push(otherMesh);
-                        } else if (!areIntersecting && currentIntersectionInProgress > -1 && action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
-                            action._executeCurrent(BABYLON.ActionEvent.CreateNew(sourceMesh));
+                        } else if (!areIntersecting && currentIntersectionInProgress > -1 && action.trigger == BABYLON.ActionManager.OnIntersectionExitTrigger) {
+                            sourceMesh.actionManager.processTrigger(BABYLON.ActionManager.OnIntersectionExitTrigger, BABYLON.ActionEvent.CreateNew(sourceMesh));
 
                             var indexOfOther = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
 
@@ -1029,14 +974,10 @@
             this._spritesDuration = 0;
             this._activeParticles = 0;
             this._renderDuration = 0;
-            this._renderTargetsDuration = 0;
             this._evaluateActiveMeshesDuration = 0;
             this._totalVertices = 0;
             this._activeVertices = 0;
-            this._activeBones = 0;
-            this.getEngine().resetDrawCalls();
             this._meshesForIntersections.reset();
-            this.resetCachedMaterial();
 
             BABYLON.Tools.StartPerformanceCounter("Scene rendering");
 
@@ -1113,7 +1054,7 @@
             }
 
             // Clear
-            this._engine.clear(this.clearColor, this.autoClear || this.forceWireframe || this.forcePointsCloud, true);
+            this._engine.clear(this.clearColor, this.autoClear || this.forceWireframe, true);
 
             // Shadows
             if (this.shadowsEnabled) {
@@ -1148,18 +1089,11 @@
             // Intersection checks
             this._checkIntersections();
 
-            // Update the audio listener attached to the camera
-            this._updateAudioParameters();
-
             // After render
             if (this.afterRender) {
                 this.afterRender();
             }
 
-            for (callbackIndex = 0; callbackIndex < this._onAfterRenderCallbacks.length; callbackIndex++) {
-                this._onAfterRenderCallbacks[callbackIndex]();
-            }
-
             for (var index = 0; index < this._toBeDisposed.length; index++) {
                 this._toBeDisposed.data[index].dispose();
                 this._toBeDisposed[index] = null;
@@ -1171,39 +1105,6 @@
             this._lastFrameDuration = BABYLON.Tools.Now - startDate;
         };
 
-        Scene.prototype._updateAudioParameters = function () {
-            var listeningCamera;
-            var audioEngine = this._engine.getAudioEngine();
-
-            if (this.activeCameras.length > 0) {
-                listeningCamera = this.activeCameras[0];
-            } else {
-                listeningCamera = this.activeCamera;
-            }
-
-            if (listeningCamera && audioEngine.canUseWebAudio) {
-                audioEngine.audioContext.listener.setPosition(listeningCamera.position.x, listeningCamera.position.y, listeningCamera.position.z);
-                var mat = BABYLON.Matrix.Invert(listeningCamera.getViewMatrix());
-                var cameraDirection = BABYLON.Vector3.TransformNormal(new BABYLON.Vector3(0, 0, -1), mat);
-                cameraDirection.normalize();
-                audioEngine.audioContext.listener.setOrientation(cameraDirection.x, cameraDirection.y, cameraDirection.z, 0, 1, 0);
-                for (var i = 0; i < this.mainSoundTrack.soundCollection.length; i++) {
-                    var sound = this.mainSoundTrack.soundCollection[i];
-                    if (sound.useBabylonJSAttenuation) {
-                        sound.updateDistanceFromListener();
-                    }
-                }
-                for (var i = 0; i < this.soundTracks.length; i++) {
-                    for (var j = 0; i < this.soundTracks[i].soundCollection.length; j++) {
-                        var sound = this.soundTracks[i].soundCollection[j];
-                        if (sound.useBabylonJSAttenuation) {
-                            sound.updateDistanceFromListener();
-                        }
-                    }
-                }
-            }
-        };
-
         Scene.prototype.dispose = function () {
             this.beforeRender = null;
             this.afterRender = null;
@@ -1212,17 +1113,11 @@
 
             this._boundingBoxRenderer.dispose();
 
-            // Debug layer
-            this.debugLayer.hide();
-
             // Events
             if (this.onDispose) {
                 this.onDispose();
             }
 
-            this._onBeforeRenderCallbacks = [];
-            this._onAfterRenderCallbacks = [];
-
             this.detachControl();
 
             // Detach cameras
@@ -1319,7 +1214,7 @@
                 return;
             }
 
-            if (velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0) {
+            if (velocity.x != 0 || velocity.y != 0 || velocity.z != 0) {
                 collider._getResponse(position, velocity);
             }
 

+ 14 - 1
Exporters/3ds Max/BabylonExport.Entities/BabylonExport.Entities.csproj

@@ -16,6 +16,7 @@
     <SccAuxPath>SAK</SccAuxPath>
     <SccProvider>SAK</SccProvider>
     <TargetFrameworkProfile />
+    <NuGetPackageImportStamp>a3421fc4</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -36,11 +37,13 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="SharpDX">
-      <HintPath>..\BabylonExport.Core\Refs\SharpDX.dll</HintPath>
+      <HintPath>$(SharpDXPackageBinDir)\SharpDX.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
     <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="Microsoft.CSharp" />
@@ -68,7 +71,17 @@
     <Compile Include="BabylonTexture.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\packages\SharpDX.2.6.3\build\SharpDX.targets" Condition="Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SharpDX.2.6.3\build\SharpDX.targets'))" />
+  </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

+ 4 - 0
Exporters/3ds Max/BabylonExport.Entities/packages.config

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="SharpDX" version="2.6.3" targetFramework="net40" />
+</packages>

+ 16 - 4
Exporters/3ds Max/Max2Babylon/2015/Max2Babylon2015.csproj

@@ -17,6 +17,7 @@
     <SccAuxPath>SAK</SccAuxPath>
     <SccProvider>SAK</SccProvider>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+    <NuGetPackageImportStamp>847376a2</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -33,10 +34,11 @@
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>C:\Program Files\Autodesk\3ds Max 2013\bin\assemblies\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
+    <DefineConstants>TRACE;MAX2015</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <Prefer32Bit>false</Prefer32Bit>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="Autodesk.Max, Version=17.0.630.0, Culture=neutral, processorArchitecture=MSIL">
@@ -46,16 +48,17 @@
     </Reference>
     <Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\packages\Newtonsoft.Json.6.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <HintPath>..\..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="SharpDX, Version=2.4.2.0, Culture=neutral, PublicKeyToken=627a3d6d1956f55a, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\BabylonExport.Core\Refs\SharpDX.dll</HintPath>
+      <HintPath>$(SharpDXPackageBinDir)\SharpDX.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Web" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="Microsoft.CSharp" />
@@ -217,8 +220,17 @@
       <Name>BabylonExport.Entities</Name>
     </ProjectReference>
   </ItemGroup>
-  <ItemGroup />
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\..\packages\SharpDX.2.6.3\build\SharpDX.targets" Condition="Exists('..\..\packages\SharpDX.2.6.3\build\SharpDX.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\packages\SharpDX.2.6.3\build\SharpDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\SharpDX.2.6.3\build\SharpDX.targets'))" />
+  </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

+ 5 - 0
Exporters/3ds Max/Max2Babylon/2015/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" />
+  <package id="SharpDX" version="2.6.3" targetFramework="net45" />
+</packages>

+ 5 - 0
Exporters/3ds Max/Max2Babylon/BabylonExportActionItem.cs

@@ -20,6 +20,11 @@ namespace Max2Babylon
 
         public void Close()
         {
+
+            if (form == null)
+            {
+                return;
+            }
             form.Dispose();
             form = null;
         }

+ 55 - 4
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Animation.cs

@@ -185,6 +185,58 @@ namespace Max2Babylon
             ExportAnimation(property, animations, extractValueFunc, BabylonAnimation.DataType.Float);
         }
 
+        static void EliminateLinearAnimationKeys(List<BabylonAnimationKey> keys)
+        {
+            for(int ixFirst = keys.Count-3; ixFirst >=0; --ixFirst)
+            {
+                while (keys.Count - ixFirst >= 3)
+                {
+                    if(!EliminateAnimationKey(keys, ixFirst))
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+
+        static float[] weightedLerp(int frame0, int frame1, int frame2, float[] value0, float[] value2)
+        {
+            double weight2 = (double)(frame1 - frame0) / (double)(frame2 - frame0);
+            double weight0 = 1 - weight2;
+            float[] result = new float[value0.Length];
+            for(int i = 0; i < result.Length; ++i)
+            {
+                result[i] = (float)(value0[i] * weight0 + value2[i] * weight2);
+            }
+            return result;
+        }
+
+
+
+        private static bool EliminateAnimationKey(List<BabylonAnimationKey> keys, int ixFirst)
+        {
+            var first = keys[ixFirst];
+            var middle = keys[ixFirst + 1];
+            var last = keys[ixFirst + 2];
+
+            // first pass, frame equality
+            if(first.values.IsEqualTo(last.values) && first.values.IsEqualTo(middle.values))
+            {
+                keys.RemoveAt(ixFirst + 1);
+                return true;
+            }
+
+            // second pass : linear interpolation detection
+            var computedMiddleValue = weightedLerp(first.frame, middle.frame, last.frame, first.values, last.values);
+            if (computedMiddleValue.IsEqualTo(middle.values))
+            {
+                keys.RemoveAt(ixFirst + 1);
+                return true;
+            }
+            return false;
+            
+        }
+
         private static void ExportAnimation(string property, List<BabylonAnimation> animations, Func<int, float[]> extractValueFunc, BabylonAnimation.DataType dataType)
         {
             var start = Loader.Core.AnimRange.Start;
@@ -196,18 +248,17 @@ namespace Max2Babylon
             {
                 var current = extractValueFunc(key);
 
-                if (key == start || key == end || !(previous.IsEqualTo(current)))
-                {
+                
                     keys.Add(new BabylonAnimationKey()
                     {
                         frame = key / Ticks,
                         values = current
                     });
-                }
+                
 
                 previous = current;
             }
-
+            EliminateLinearAnimationKeys(keys);
             if (keys.Count > 0)
             {
                 var animationPresent = true;

+ 43 - 28
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Camera.cs

@@ -6,22 +6,24 @@ namespace Max2Babylon
 {
     partial class BabylonExporter
     {
-        private void ExportCamera(IINode cameraNode, BabylonScene babylonScene)
+        private void ExportCamera(IIGameNode cameraNode, BabylonScene babylonScene)
         {
-            if (cameraNode.GetBoolProperty("babylonjs_noexport"))
+
+            if (cameraNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
             {
                 return;
             }
-
-            var maxCamera = (cameraNode.ObjectRef as ICameraObject);
+            var gameCamera = cameraNode.IGameObject.AsGameCamera();
+            var maxCamera = gameCamera.MaxObject as ICameraObject;
+            var initialized = gameCamera.InitializeData;
             var babylonCamera = new BabylonCamera();
 
             RaiseMessage(cameraNode.Name, 1);
             babylonCamera.name = cameraNode.Name;
-            babylonCamera.id = cameraNode.GetGuid().ToString();
-            if (cameraNode.HasParent())
+            babylonCamera.id = cameraNode.MaxNode.GetGuid().ToString();
+            if (cameraNode.NodeParent != null)
             {
-                babylonCamera.parentId = cameraNode.ParentNode.GetGuid().ToString();
+                babylonCamera.parentId = cameraNode.NodeParent.MaxNode.GetGuid().ToString();
             }
 
             babylonCamera.fov = Tools.ConvertFov(maxCamera.GetFOV(0, Tools.Forever));
@@ -43,52 +45,65 @@ namespace Max2Babylon
             }
 
             // Control
-            babylonCamera.speed = cameraNode.GetFloatProperty("babylonjs_speed", 1.0f);
-            babylonCamera.inertia = cameraNode.GetFloatProperty("babylonjs_inertia", 0.9f);
+            babylonCamera.speed = cameraNode.MaxNode.GetFloatProperty("babylonjs_speed", 1.0f);
+            babylonCamera.inertia = cameraNode.MaxNode.GetFloatProperty("babylonjs_inertia", 0.9f);
 
             // Collisions
-            babylonCamera.checkCollisions = cameraNode.GetBoolProperty("babylonjs_checkcollisions");
-            babylonCamera.applyGravity = cameraNode.GetBoolProperty("babylonjs_applygravity");
-            babylonCamera.ellipsoid = cameraNode.GetVector3Property("babylonjs_ellipsoid");
+            babylonCamera.checkCollisions = cameraNode.MaxNode.GetBoolProperty("babylonjs_checkcollisions");
+            babylonCamera.applyGravity = cameraNode.MaxNode.GetBoolProperty("babylonjs_applygravity");
+            babylonCamera.ellipsoid = cameraNode.MaxNode.GetVector3Property("babylonjs_ellipsoid");
 
             // Position
-            var wm = cameraNode.GetWorldMatrix(0, cameraNode.HasParent());
-            var position = wm.Trans;
-            babylonCamera.position = position.ToArraySwitched();
+            {
+                var wm = cameraNode.GetLocalTM(0);
+                var position = wm.Translation;
+                babylonCamera.position = new float[] { position.X, position.Y, position.Z };
 
             // Target
-            var target = cameraNode.Target;
+                var target = gameCamera.CameraTarget;
             if (target != null)
             {
-                babylonCamera.lockedTargetId = target.GetGuid().ToString();
+                    babylonCamera.lockedTargetId = target.MaxNode.GetGuid().ToString();
             }
             else
             {
-                var dir = wm.GetRow(2).MultiplyBy(-1);
-                babylonCamera.target = position.Add(dir).ToArraySwitched();
+                    var dir = wm.GetRow(3);
+                    babylonCamera.target = new float[] { position.X - dir.X, position.Y - dir.Y, position.Z - dir.Z };
+                }
             }
 
             // Animations
             var animations = new List<BabylonAnimation>();
-            if (!ExportVector3Controller(cameraNode.TMController.PositionController, "position", animations))
-            {
+            //if (!ExportVector3Controller(cameraNode.TMController.PositionController, "position", animations))
+            //{
                 ExportVector3Animation("position", animations, key =>
                 {
-                    var worldMatrix = cameraNode.GetWorldMatrix(key, cameraNode.HasParent());
-                    return worldMatrix.Trans.ToArraySwitched();
+                    var wm = cameraNode.GetLocalTM(key);
+                    var position = wm.Translation;
+                    return  new float[] { position.X, position.Y, position.Z };
+                });
+            //}
+            if (gameCamera.CameraTarget == null)
+            {
+                ExportVector3Animation("target", animations, key =>
+                {
+                    var wm = cameraNode.GetLocalTM(key);
+                    var position = wm.Translation;
+                    var dir = wm.GetRow(3);
+                    return new float[] { position.X - dir.X, position.Y - dir.Y, position.Z - dir.Z };
                 });
             }
 
-            ExportFloatAnimation("fov", animations, key => new[] {Tools.ConvertFov(maxCamera.GetFOV(key, Tools.Forever))});
+            ExportFloatAnimation("fov", animations, key => new[] { Tools.ConvertFov((gameCamera.MaxObject as ICameraObject).GetFOV(key, Tools.Forever)) });
 
             babylonCamera.animations = animations.ToArray();
 
-            if (cameraNode.GetBoolProperty("babylonjs_autoanimate"))
+            if (cameraNode.MaxNode.GetBoolProperty("babylonjs_autoanimate"))
             {
                 babylonCamera.autoAnimate = true;
-                babylonCamera.autoAnimateFrom = (int)cameraNode.GetFloatProperty("babylonjs_autoanimate_from");
-                babylonCamera.autoAnimateTo = (int)cameraNode.GetFloatProperty("babylonjs_autoanimate_to");
-                babylonCamera.autoAnimateLoop = cameraNode.GetBoolProperty("babylonjs_autoanimateloop");
+                babylonCamera.autoAnimateFrom = (int)cameraNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from");
+                babylonCamera.autoAnimateTo = (int)cameraNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to");
+                babylonCamera.autoAnimateLoop = cameraNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop");
             }
 
             babylonScene.CamerasList.Add(babylonCamera);

+ 62 - 44
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Light.cs

@@ -19,28 +19,33 @@ namespace Max2Babylon
             babylonLight.intensity = 1;
 
             babylonLight.diffuse = new[] { 1.0f, 1.0f, 1.0f };
-            babylonLight.specular = new[] { 1.0f, 1.0f, 1.0f }; 
+            babylonLight.specular = new[] { 1.0f, 1.0f, 1.0f };
 
             babylonScene.LightsList.Add(babylonLight);
         }
 
-        private void ExportLight(IINode lightNode, BabylonScene babylonScene)
+        private void ExportLight(IIGameNode lightNode, BabylonScene babylonScene)
         {
-            if (lightNode.GetBoolProperty("babylonjs_noexport"))
+            if (lightNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
             {
                 return;
             }
 
-            var maxLight = (lightNode.ObjectRef as ILightObject);
+            var gameLight = lightNode.IGameObject.AsGameLight();
+            var initialized = gameLight.InitializeData;
             var babylonLight = new BabylonLight();
 
             RaiseMessage(lightNode.Name, 1);
             babylonLight.name = lightNode.Name;
-            babylonLight.id = lightNode.GetGuid().ToString();
+            babylonLight.id = lightNode.MaxNode.GetGuid().ToString();
+
 
             // Type
+
+            var maxLight = (lightNode.MaxNode.ObjectRef as ILightObject);
             var lightState = Loader.Global.LightState.Create();
             maxLight.EvalLightState(0, Tools.Forever, lightState);
+
             var directionScale = -1;
 
             switch (lightState.Type)
@@ -63,12 +68,13 @@ namespace Max2Babylon
                     break;
             }
 
-            // Shadows
+
+            // Shadows 
             if (maxLight.ShadowMethod == 1)
             {
                 if (lightState.Type == LightType.DirectLgt)
                 {
-                    ExportShadowGenerator(lightNode, babylonScene);
+                    ExportShadowGenerator(lightNode.MaxNode, babylonScene);
                 }
                 else
                 {
@@ -76,29 +82,32 @@ namespace Max2Babylon
                 }
             }
 
-            // Position
-            var wm = lightNode.GetWorldMatrix(0, false);
-            var position = wm.Trans;
-            babylonLight.position = position.ToArraySwitched();
-
-            // Direction
-            var target = lightNode.Target;
-            if (target != null)
             {
-                var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever);
-                var targetPosition = targetWm.Trans;
+                // Position
+                var wm = lightNode.GetObjectTM(0);
+                var position = wm.Translation;
+                babylonLight.position = new float[] { position.X, position.Y, position.Z };
+
+                // Direction
+                var target = gameLight.LightTarget;
+                if (target != null)
+                {
+                    var targetWm = target.GetObjectTM(0);
+                    var targetPosition = targetWm.Translation;
 
-                var direction = targetPosition.Subtract(position);
-                babylonLight.direction = direction.ToArraySwitched();
-            }
-            else
-            {
-                var dir = wm.GetRow(2).MultiplyBy(directionScale);
-                babylonLight.direction = dir.ToArraySwitched();
+                    var direction = targetPosition.Subtract(position).Normalize;
+                    babylonLight.direction = new float[] { direction.X, direction.Y, direction.Z };
+                }
+                else
+                {
+                    var vDir = Loader.Global.Point3.Create(0, -1, 0);
+                    vDir = wm.ExtractMatrix3().VectorTransform(vDir).Normalize;
+                    babylonLight.direction = new float[] { vDir.X, vDir.Y, vDir.Z };
+                }
             }
 
-            // Exclusion
             var maxScene = Loader.Core.RootNode;
+            // Exclusion
             var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE 
             var checkExclusionList = maxLight.ExclList.TestFlag(2); //NT_AFFECT_ILLUM
 
@@ -131,55 +140,64 @@ namespace Max2Babylon
                 babylonLight.excludedMeshesIds = excllist.ToArray();
             }
 
-            // Other fields
+            // Other fields 
             babylonLight.intensity = maxLight.GetIntensity(0, Tools.Forever);
 
+
             babylonLight.diffuse = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 };
             babylonLight.specular = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 };
 
+
             if (maxLight.UseAtten)
             {
                 babylonLight.range = maxLight.GetAtten(0, 1, Tools.Forever);
             }
 
+
             // Animations
             var animations = new List<BabylonAnimation>();
 
-            if (!ExportVector3Controller(lightNode.TMController.PositionController, "position", animations))
-            {
+            //if (!ExportVector3Controller(lightNode.TMController.PositionController, "position", animations))
+            //{
                 ExportVector3Animation("position", animations, key =>
                 {
-                    var worldMatrix = lightNode.GetWorldMatrix(key, lightNode.HasParent());
-                    return worldMatrix.Trans.ToArraySwitched();
+                    var mat = lightNode.GetObjectTM(key);
+                    var pos = mat.Translation;
+                    return new float[] { pos.X, pos.Y, pos.Z };
                 });
-            }
+            //}
 
             ExportVector3Animation("direction", animations, key =>
             {
-                var targetNode = lightNode.Target;
-                if (targetNode != null)
+                var wm = lightNode.GetObjectTM(key);
+                var position = wm.Translation;
+                var target = gameLight.LightTarget;
+                if (target != null)
                 {
-                    var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever);
-                    var targetPosition = targetWm.Trans;
+                    var targetWm = target.GetObjectTM(key);
+                    var targetPosition = targetWm.Translation;
 
-                    var direction = targetPosition.Subtract(position);
-                    return direction.ToArraySwitched();
+                    var direction = targetPosition.Subtract(position).Normalize;
+                    return new float[] { direction.X, direction.Y, direction.Z };
+                }
+                else
+                {
+                    var vDir = Loader.Global.Point3.Create(0, -1, 0);
+                    vDir = wm.ExtractMatrix3().VectorTransform(vDir).Normalize;
+                    return new float[] { vDir.X, vDir.Y, vDir.Z };
                 }
-                
-                var dir = wm.GetRow(2).MultiplyBy(directionScale);
-                return dir.ToArraySwitched();
             });
 
             ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Tools.Forever) });
 
             babylonLight.animations = animations.ToArray();
 
-            if (lightNode.GetBoolProperty("babylonjs_autoanimate"))
+            if (lightNode.MaxNode.GetBoolProperty("babylonjs_autoanimate"))
             {
                 babylonLight.autoAnimate = true;
-                babylonLight.autoAnimateFrom = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_from");
-                babylonLight.autoAnimateTo = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_to");
-                babylonLight.autoAnimateLoop = lightNode.GetBoolProperty("babylonjs_autoanimateloop");
+                babylonLight.autoAnimateFrom = (int)lightNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from");
+                babylonLight.autoAnimateTo = (int)lightNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to");
+                babylonLight.autoAnimateLoop = lightNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop");
             }
 
             babylonScene.LightsList.Add(babylonLight);

+ 17 - 17
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Material.cs

@@ -7,28 +7,28 @@ namespace Max2Babylon
 {
     partial class BabylonExporter
     {
-        readonly List<IMtl> referencedMaterials = new List<IMtl>();
+        readonly List<IIGameMaterial> referencedMaterials = new List<IIGameMaterial>();
 
-        private void ExportMaterial(IMtl materialNode, BabylonScene babylonScene)
+        private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene)
         {
-            var name = materialNode.Name;
-            var id = materialNode.GetGuid().ToString();
+            var name = materialNode.MaterialName;
+            var id = materialNode.MaxMaterial.GetGuid().ToString();
 
             RaiseMessage(name, 1);
 
-            if (materialNode.NumSubMtls > 0)
+            if (materialNode.SubMaterialCount > 0)
             {
                 var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id };
 
                 var guids = new List<string>();
 
-                for (var index = 0; index < materialNode.NumSubMtls; index++)
+                for (var index = 0; index < materialNode.SubMaterialCount; index++)
                 {
-                    var subMat = materialNode.GetSubMtl(index);
+                    var subMat = materialNode.GetSubMaterial(index);
 
                     if (subMat != null)
                     {
-                        guids.Add(subMat.GetGuid().ToString());
+                        guids.Add(subMat.MaxMaterial.GetGuid().ToString());
 
                         if (!referencedMaterials.Contains(subMat))
                         {
@@ -53,19 +53,19 @@ namespace Max2Babylon
             {
                 name = name,
                 id = id,
-                ambient = materialNode.GetAmbient(0, false).ToArray(),
-                diffuse = materialNode.GetDiffuse(0, false).ToArray(),
-                specular = materialNode.GetSpecular(0, false).Scale(materialNode.GetShinStr(0, false)),
-                specularPower = materialNode.GetShininess(0, false) * 256,
+                ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(),
+                diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(),
+                specular = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)),
+                specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256,
                 emissive =
-                    materialNode.GetSelfIllumColorOn(0, false)
-                        ? materialNode.GetSelfIllumColor(0, false).ToArray()
-                        : materialNode.GetDiffuse(0, false).Scale(materialNode.GetSelfIllum(0, false)),
-                alpha = 1.0f - materialNode.GetXParency(0, false)
+                    materialNode.MaxMaterial.GetSelfIllumColorOn(0, false)
+                        ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
+                        : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)),
+                alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false)
             };
 
 
-            var stdMat = materialNode.GetParamBlock(0).Owner as IStdMat2;
+            var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2;
 
             if (stdMat != null)
             {

+ 284 - 202
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Mesh.cs

@@ -10,158 +10,219 @@ namespace Max2Babylon
     partial class BabylonExporter
     {
         private int bonesCount;
-        private void ExportMesh(IINode meshNode, BabylonScene babylonScene)
+        private void ExportMesh(IIGameScene scene, IIGameNode meshNode, BabylonScene babylonScene)
         {
-            if (meshNode.IsInstance())
+            if (meshNode.MaxNode.IsInstance())
             {
                 return;
             }
 
-            if (meshNode.GetBoolProperty("babylonjs_noexport"))
+            if (meshNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
             {
                 return;
             }
 
-            if (!ExportHiddenObjects && meshNode.IsHidden(NodeHideFlags.None, false))
+            if (!ExportHiddenObjects && meshNode.MaxNode.IsHidden(NodeHideFlags.None, false))
             {
                 return;
             }
 
+            var gameMesh = meshNode.IGameObject.AsGameMesh();
+            bool initialized = gameMesh.InitializeData; //needed, the property is in fact a method initializing the exporter that has wrongly been auto 
+            // translated into a property because it has no parameters
+
             var babylonMesh = new BabylonMesh();
-            int vx1, vx2, vx3;
 
             babylonMesh.name = meshNode.Name;
-            babylonMesh.id = meshNode.GetGuid().ToString();
-            if (meshNode.HasParent())
+            babylonMesh.id = meshNode.MaxNode.GetGuid().ToString();
+            if (meshNode.NodeParent != null)
             {
-                babylonMesh.parentId = meshNode.ParentNode.GetGuid().ToString();
+                babylonMesh.parentId = meshNode.NodeParent.MaxNode.GetGuid().ToString();
             }
 
             // Misc.
-            babylonMesh.isVisible = meshNode.Renderable == 1;
-            babylonMesh.pickable = meshNode.GetBoolProperty("babylonjs_checkpickable");
-            babylonMesh.receiveShadows = meshNode.RcvShadows == 1;
-            babylonMesh.showBoundingBox = meshNode.GetBoolProperty("babylonjs_showboundingbox");
-            babylonMesh.showSubMeshesBoundingBox = meshNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox");
-            babylonMesh.applyFog = meshNode.ApplyAtmospherics == 1;
-            babylonMesh.alphaIndex = (int)meshNode.GetFloatProperty("babylonjs_alphaindex", 1000);
+            babylonMesh.isVisible = meshNode.MaxNode.Renderable == 1;
+            babylonMesh.pickable = meshNode.MaxNode.GetBoolProperty("babylonjs_checkpickable");
+            babylonMesh.receiveShadows = meshNode.MaxNode.RcvShadows == 1;
+            babylonMesh.showBoundingBox = meshNode.MaxNode.GetBoolProperty("babylonjs_showboundingbox");
+            babylonMesh.showSubMeshesBoundingBox = meshNode.MaxNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox");
+            babylonMesh.applyFog = meshNode.MaxNode.ApplyAtmospherics == 1;
+            babylonMesh.alphaIndex = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_alphaindex", 1000);
 
             // Collisions
-            babylonMesh.checkCollisions = meshNode.GetBoolProperty("babylonjs_checkcollisions");
-
-            // Skin
-            var skin = GetSkinModifier(meshNode);
+            babylonMesh.checkCollisions = meshNode.MaxNode.GetBoolProperty("babylonjs_checkcollisions");
 
-            if (skin != null)
+            bool isSkinned = gameMesh.IsObjectSkinned;
+            var skin = gameMesh.IGameSkin;
+            var unskinnedMesh = gameMesh;
+            IGMatrix skinInitPoseMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
+            if (isSkinned)
             {
+                //unskinnedMesh = skin.InitialPose;
+                bonesCount = skin.TotalSkinBoneCount;
+                skins.Add(skin);
+                skinnedNodes.Add(meshNode);
                 babylonMesh.skeletonId = skins.IndexOf(skin);
-                bonesCount = skin.NumBones;
+                skin.GetInitSkinTM(skinInitPoseMatrix);
             }
 
             // Position / rotation / scaling
-            var wm = Tools.ExtractCoordinates(meshNode, babylonMesh, exportQuaternionsInsteadOfEulers);
-
-            if (wm.Parity)
             {
-                vx1 = 2;
-                vx2 = 1;
-                vx3 = 0;
+                //var localTM = unskinnedMesh.IGameObjectTM;
+                //var worldTM = meshNode.GetWorldTM(0);
+                var localTM = meshNode.GetObjectTM(0);
+
+                var meshTrans = localTM.Translation;
+                var meshRotation = localTM.Rotation;
+                var meshScale = localTM.Scaling;
+                babylonMesh.position = new float[] { meshTrans.X, meshTrans.Y, meshTrans.Z };
+                //float rotx = 0, roty = 0, rotz = 0;
+                //unsafe
+                //{
+                //    meshRotation.GetEuler(new IntPtr(&rotx), new IntPtr(&roty), new IntPtr(&rotz));
+                //}
+                //babylonMesh.rotation = new float[] { rotx, roty, rotz };
+                babylonMesh.rotationQuaternion = new float[] { meshRotation.X, meshRotation.Y, meshRotation.Z, -meshRotation.W };
+                babylonMesh.scaling = new float[] { meshScale.X, meshScale.Y, meshScale.Z };
             }
-            else
-            {
-                vx1 = 0;
-                vx2 = 1;
-                vx3 = 2;
-            }
-
-            // Pivot
-            var pivotMatrix = Tools.Identity;
-            pivotMatrix.PreTranslate(meshNode.ObjOffsetPos);
-            Loader.Global.PreRotateMatrix(pivotMatrix, meshNode.ObjOffsetRot);
-            Loader.Global.ApplyScaling(pivotMatrix, meshNode.ObjOffsetScale);
-            babylonMesh.pivotMatrix = pivotMatrix.ToArray();
+            //// Pivot // something to do with GameMesh ?
+            //meshNode.GetObjectTM
+            //var pivotMatrix = Tools.Identity;
+            //pivotMatrix.PreTranslate(meshNode.ObjOffsetPos);
+            //Loader.Global.PreRotateMatrix(pivotMatrix, meshNode.ObjOffsetRot);
+            //Loader.Global.ApplyScaling(pivotMatrix, meshNode.ObjOffsetScale);
+            //babylonMesh.pivotMatrix = pivotMatrix.ToArray();
 
             // Mesh
-            var objectState = meshNode.EvalWorldState(0, false);
-            var triObject = objectState.Obj.GetMesh();
-            var mesh = triObject != null ? triObject.Mesh : null;
 
             RaiseMessage(meshNode.Name, 1);
 
-            if (mesh != null)
+            if (unskinnedMesh != null && unskinnedMesh.IGameType == Autodesk.Max.IGameObject.ObjectTypes.Mesh && unskinnedMesh.MaxMesh != null)
             {
-                mesh.BuildNormals();
 
-                if (mesh.NumFaces < 1)
+
+                if (unskinnedMesh.NumberOfFaces < 1)
                 {
                     RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name), 2);
                 }
 
-                if (mesh.NumVerts < 3)
+                if (unskinnedMesh.NumberOfVerts < 3)
                 {
                     RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name), 2);
                 }
 
-                if (mesh.NumVerts >= 65536)
+                if (unskinnedMesh.NumberOfVerts >= 65536)
                 {
                     RaiseWarning(string.Format("Mesh {0} has tmore than 65536 vertices which means that it will require specific WebGL extension to be rendered. This may impact portability of your scene on low end devices.", babylonMesh.name), 2);
                 }
 
                 // Material
-                var mtl = meshNode.Mtl;
+                var mtl = meshNode.NodeMaterial;
                 var multiMatsCount = 1;
 
                 if (mtl != null)
                 {
-                    babylonMesh.materialId = mtl.GetGuid().ToString();
+                    babylonMesh.materialId = mtl.MaxMaterial.GetGuid().ToString();
 
                     if (!referencedMaterials.Contains(mtl))
                     {
                         referencedMaterials.Add(mtl);
                     }
 
-                    multiMatsCount = Math.Max(mtl.NumSubMtls, 1);
+                    multiMatsCount = Math.Max(mtl.SubMaterialCount, 1);
                 }
 
-                babylonMesh.visibility = meshNode.GetVisibility(0, Tools.Forever);
+                babylonMesh.visibility = meshNode.MaxNode.GetVisibility(0, Tools.Forever);
 
                 var vertices = new List<GlobalVertex>();
                 var indices = new List<int>();
-                var matIDs = new List<int>();
+                var mappingChannels = unskinnedMesh.ActiveMapChannelNum;
+                bool hasUV = false;
+                bool hasUV2 = false;
+                for (int i = 0; i < mappingChannels.Count; ++i)
+                {
+                    IntPtr indexer = new IntPtr(i);
+                    var channelNum = mappingChannels[indexer];
+                    if (channelNum == 1)
+                {
+                        hasUV = true;
+                }
+                    else if (channelNum == 2)
+                {
+                        hasUV2 = true;
+                }
+                }
+                var hasColor = unskinnedMesh.NumberOfColorVerts > 0;
+                var hasAlpha = unskinnedMesh.GetNumberOfMapVerts(-2) > 0;
 
-                var hasUV = mesh.NumTVerts > 0;
-                var hasUV2 = mesh.GetNumMapVerts(2) > 0;
-                var hasColor = mesh.NumVertCol > 0;
-                var hasAlpha = mesh.GetNumMapVerts(-2) > 0;
+                var optimizeVertices = meshNode.MaxNode.GetBoolProperty("babylonjs_optimizevertices");
 
-                var optimizeVertices = meshNode.GetBoolProperty("babylonjs_optimizevertices");
 
-                // Skin
-                IISkinContextData skinContext = null;
-
-                if (skin != null)
-                {
-                    skinContext = skin.GetContextInterface(meshNode);
-                }
 
                 // Compute normals
-                VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices);
+                // VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices);
                 List<GlobalVertex>[] verticesAlreadyExported = null;
 
                 if (optimizeVertices)
                 {
-                    verticesAlreadyExported = new List<GlobalVertex>[mesh.NumVerts];
+                    verticesAlreadyExported = new List<GlobalVertex>[unskinnedMesh.NumberOfVerts];
                 }
 
-                for (var face = 0; face < mesh.NumFaces; face++)
+                var subMeshes = new List<BabylonSubMesh>();
+                var indexStart = 0;
+
+                
+                for (int i = 0; i < multiMatsCount; ++i)
                 {
-                    indices.Add(CreateGlobalVertex(mesh, face, vx1, vertices, hasUV, hasUV2, hasColor, hasAlpha, vnorms, verticesAlreadyExported, skinContext));
-                    indices.Add(CreateGlobalVertex(mesh, face, vx2, vertices, hasUV, hasUV2, hasColor, hasAlpha, vnorms, verticesAlreadyExported, skinContext));
-                    indices.Add(CreateGlobalVertex(mesh, face, vx3, vertices, hasUV, hasUV2, hasColor, hasAlpha, vnorms, verticesAlreadyExported, skinContext));
-                    matIDs.Add(mesh.Faces[face].MatID % multiMatsCount);
-                    CheckCancelled();
+                    int materialId = meshNode.NodeMaterial.GetMaterialID(i);
+                    ITab<IFaceEx> materialFaces = null;
+                    var indexCount = 0;
+                    var minVertexIndex = int.MaxValue;
+                    var maxVertexIndex = int.MinValue;
+                    var subMesh = new BabylonSubMesh();
+                    subMesh.indexStart = indexStart;
+                    subMesh.materialIndex = i;
+
+                    if (multiMatsCount == 1)
+                    {
+                        for(int j = 0; j < unskinnedMesh.NumberOfFaces; ++j)
+                        {
+                            var face = unskinnedMesh.GetFace(j);
+                            ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face);
+                        }
+                    }
+                    else
+                    {
+                        materialFaces = unskinnedMesh.GetFacesFromMatID(materialId);
+                        for (int j = 0; j < materialFaces.Count; ++j)
+                        {
+                            var faceIndexer = new IntPtr(j);
+                            var face = materialFaces[faceIndexer];
+
+                            Marshal.FreeHGlobal(faceIndexer);
+                            ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face);
+                        }
+                    }
+                    
+
+
+
+                   
+                    if (indexCount != 0)
+                    {
+
+                        subMesh.indexCount = indexCount;
+                        subMesh.verticesStart = minVertexIndex;
+                        subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1;
+
+                        indexStart += indexCount;
+
+                        subMeshes.Add(subMesh);
+                    }
                 }
 
+
+
                 if (vertices.Count >= 65536)
                 {
                     RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count), 2);
@@ -175,15 +236,15 @@ namespace Max2Babylon
                 RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2);
 
                 // Buffers
-                babylonMesh.positions = vertices.SelectMany(v => v.Position.ToArraySwitched()).ToArray();
-                babylonMesh.normals = vertices.SelectMany(v => v.Normal.ToArraySwitched()).ToArray();
+                babylonMesh.positions = vertices.SelectMany(v => new float[] { v.Position.X, v.Position.Y, v.Position.Z }).ToArray();
+                babylonMesh.normals = vertices.SelectMany(v => new float[] { v.Normal.X, v.Normal.Y, v.Normal.Z }).ToArray();
                 if (hasUV)
                 {
-                    babylonMesh.uvs = vertices.SelectMany(v => v.UV.ToArray()).ToArray();
+                    babylonMesh.uvs = vertices.SelectMany(v => new float[] { v.UV.X, 1 - v.UV.Y }).ToArray();
                 }
                 if (hasUV2)
                 {
-                    babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2.ToArray()).ToArray();
+                    babylonMesh.uvs2 = vertices.SelectMany(v => new float[] { v.UV2.X, 1 - v.UV2.Y }).ToArray();
                 }
 
                 if (skin != null)
@@ -198,89 +259,23 @@ namespace Max2Babylon
                     babylonMesh.hasVertexAlpha = hasAlpha;
                 }
 
-                // Submeshes
-                var sortedIndices = new List<int>();
-                var subMeshes = new List<BabylonSubMesh>();
-                var indexStart = 0;
-                for (var index = 0; index < multiMatsCount; index++)
-                {
-                    var subMesh = new BabylonSubMesh();
-                    var indexCount = 0;
-                    var minVertexIndex = int.MaxValue;
-                    var maxVertexIndex = int.MinValue;
-
-                    subMesh.indexStart = indexStart;
-                    subMesh.materialIndex = index;
-
-                    for (var face = 0; face < matIDs.Count; face++)
-                    {
-                        if (matIDs[face] == index)
-                        {
-                            var a = indices[3 * face];
-                            var b = indices[3 * face + 1];
-                            var c = indices[3 * face + 2];
-
-                            sortedIndices.Add(a);
-                            sortedIndices.Add(b);
-                            sortedIndices.Add(c);
-                            indexCount += 3;
-
-                            if (a < minVertexIndex)
-                            {
-                                minVertexIndex = a;
-                            }
-
-                            if (b < minVertexIndex)
-                            {
-                                minVertexIndex = b;
-                            }
-
-                            if (c < minVertexIndex)
-                            {
-                                minVertexIndex = c;
-                            }
-
-                            if (a > maxVertexIndex)
-                            {
-                                maxVertexIndex = a;
-                            }
-
-                            if (b > maxVertexIndex)
-                            {
-                                maxVertexIndex = b;
-                            }
-
-                            if (c > maxVertexIndex)
-                            {
-                                maxVertexIndex = c;
-                            }
-                        }
-                    }
-                    if (indexCount != 0)
-                    {
-
-                        subMesh.indexCount = indexCount;
-                        subMesh.verticesStart = minVertexIndex;
-                        subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1;
 
-                        indexStart += indexCount;
 
-                        subMeshes.Add(subMesh);
-                    }
-                    CheckCancelled();
-                }
                 babylonMesh.subMeshes = subMeshes.ToArray();
 
 
                 // Buffers - Indices
-                babylonMesh.indices = sortedIndices.ToArray();
+                babylonMesh.indices = indices.ToArray();
 
-                triObject.Dispose();
             }
 
+            // handle instances and animations
+
+
             // Instances
             var tabs = Loader.Global.NodeTab.Create();
-            Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode, tabs);
+
+            Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode.MaxNode, tabs);
             var instances = new List<BabylonAbstractMesh>();
 
             for (var index = 0; index < tabs.Count; index++)
@@ -290,18 +285,38 @@ namespace Max2Babylon
 
                 Marshal.FreeHGlobal(indexer);
 
-                if (meshNode.GetGuid() == tab.GetGuid())
+                if (meshNode.MaxNode.GetGuid() == tab.GetGuid())
+                {
+                    continue;
+                }
+                var instanceGameNode = scene.GetIGameNode(tab);
+                if (instanceGameNode == null)
                 {
                     continue;
                 }
-
                 tab.MarkAsInstance();
 
-                var instance = new BabylonAbstractMesh {name = tab.Name};
+                var instance = new BabylonAbstractMesh { name = tab.Name };
+                {
+
+                    var localTM = meshNode.GetObjectTM(0);
 
-                Tools.ExtractCoordinates(tab, instance, exportQuaternionsInsteadOfEulers);
+                    //var worldTM = meshNode.GetWorldTM(0);
+                    //var objTM = meshNode.GetObjectTM(0);
+                    var meshTrans = localTM.Translation;
+                    var meshRotation = localTM.Rotation;
+                    var meshScale = localTM.Scaling;
+                    instance.position = new float[] { meshTrans.X, meshTrans.Y, meshTrans.Z };
+                    float rotx = 0, roty = 0, rotz = 0;
+                    unsafe
+                    {
+                        meshRotation.GetEuler(new IntPtr(&rotx), new IntPtr(&roty), new IntPtr(&rotz));
+                    }
+                    instance.rotation = new float[] { rotx, roty, rotz };
+                    instance.scaling = new float[] { meshScale.X, meshScale.Y, meshScale.Z };
+                }
                 var instanceAnimations = new List<BabylonAnimation>();
-                GenerateCoordinatesAnimations(tab, instanceAnimations);
+                GenerateCoordinatesAnimations(meshNode, instanceAnimations);
                 instance.animations = instanceAnimations.ToArray();
 
                 instances.Add(instance);
@@ -314,96 +329,163 @@ namespace Max2Babylon
             GenerateCoordinatesAnimations(meshNode, animations);
             
 
-            if (!ExportFloatController(meshNode.VisController, "visibility", animations))
+            if (!ExportFloatController(meshNode.MaxNode.VisController, "visibility", animations))
             {
-                ExportFloatAnimation("visibility", animations, key => new[] { meshNode.GetVisibility(key, Tools.Forever) });
+                ExportFloatAnimation("visibility", animations, key => new[] { meshNode.MaxNode.GetVisibility(key, Tools.Forever) });
             }
 
             babylonMesh.animations = animations.ToArray();
 
-            if (meshNode.GetBoolProperty("babylonjs_autoanimate", 1))
+            if (meshNode.MaxNode.GetBoolProperty("babylonjs_autoanimate", 1))
             {
                 babylonMesh.autoAnimate = true;
-                babylonMesh.autoAnimateFrom = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_from");
-                babylonMesh.autoAnimateTo = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_to", 100);
-                babylonMesh.autoAnimateLoop = meshNode.GetBoolProperty("babylonjs_autoanimateloop", 1);
+                babylonMesh.autoAnimateFrom = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from");
+                babylonMesh.autoAnimateTo = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to", 100);
+                babylonMesh.autoAnimateLoop = meshNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop", 1);
             }
 
             babylonScene.MeshesList.Add(babylonMesh);
         }
 
-        public static void GenerateCoordinatesAnimations(IINode meshNode, List<BabylonAnimation> animations)
+        private void ExtractFace(IIGameSkin skin, IIGameMesh unskinnedMesh, List<GlobalVertex> vertices, List<int> indices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, List<GlobalVertex>[] verticesAlreadyExported, ref int indexCount, ref int minVertexIndex, ref int maxVertexIndex, IFaceEx face)
         {
-            if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations))
+            var a = CreateGlobalVertex(unskinnedMesh, face, 0, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
+            var b = CreateGlobalVertex(unskinnedMesh, face, 2, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
+            var c = CreateGlobalVertex(unskinnedMesh, face, 1, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
+            indices.Add(a);
+            indices.Add(b);
+            indices.Add(c);
+
+            if (a < minVertexIndex)
+            {
+                minVertexIndex = a;
+            }
+
+            if (b < minVertexIndex)
+            {
+                minVertexIndex = b;
+            }
+
+            if (c < minVertexIndex)
             {
+                minVertexIndex = c;
+            }
+
+            if (a > maxVertexIndex)
+            {
+                maxVertexIndex = a;
+            }
+
+            if (b > maxVertexIndex)
+            {
+                maxVertexIndex = b;
+            }
+
+            if (c > maxVertexIndex)
+            {
+                maxVertexIndex = c;
+            }
+
+
+            indexCount += 3;
+            CheckCancelled();
+        }
+
+        public static void GenerateCoordinatesAnimations(IIGameNode meshNode, List<BabylonAnimation> animations)
+            {
+            //if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations))
+            //{
                 ExportVector3Animation("position", animations, key =>
                 {
-                    var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
-                    return worldMatrix.Trans.ToArraySwitched();
+                var worldMatrix = meshNode.GetObjectTM(key);
+                var trans = worldMatrix.Translation;
+                return new float[] { trans.X, trans.Y, trans.Z };
                 });
-            }
+            //}
 
-            if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations))
-            {
+
+            //if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations))
+            //{
                 ExportQuaternionAnimation("rotationQuaternion", animations, key =>
                 {
-                    var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
+                    var worldMatrix = meshNode.GetObjectTM(key);
 
-                    var affineParts = Loader.Global.AffineParts.Create();
-                    Loader.Global.DecompAffine(worldMatrix, affineParts);
 
-                    return affineParts.Q.ToArray();
+
+                    var rot = worldMatrix.Rotation;
+                    return new float[] { rot.X, rot.Y, rot.Z, -rot.W };
                 });
-            }
+            //}
 
-            if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations))
-            {
+
+            //if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations))
+            //{
                 ExportVector3Animation("scaling", animations, key =>
                 {
-                    var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
+                    var worldMatrix = meshNode.GetObjectTM(key);
+                    var scale = worldMatrix.Scaling;
 
-                    var affineParts = Loader.Global.AffineParts.Create();
-                    Loader.Global.DecompAffine(worldMatrix, affineParts);
-
-                    return affineParts.K.ToArraySwitched();
+                    return new float[] { scale.X, scale.Y, scale.Z };
                 });
-            }
+           // }
         }
 
-        int CreateGlobalVertex(IMesh mesh, int face, int facePart, List<GlobalVertex> vertices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, VNormal[] vnorms, List<GlobalVertex>[] verticesAlreadyExported, IISkinContextData skinContextData)
+
+        int CreateGlobalVertex(IIGameMesh mesh, IFaceEx face, int facePart, List<GlobalVertex> vertices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, List<GlobalVertex>[] verticesAlreadyExported, IIGameSkin skin)
         {
-            var faceObject = mesh.Faces[face];
-            var vertexIndex = (int)faceObject.V[facePart];
+            var vertexIndex = (int)face.Vert[facePart];
 
             var vertex = new GlobalVertex
             {
                 BaseIndex = vertexIndex,
-                Position = mesh.Verts[vertexIndex],
-                Normal = vnorms[vertexIndex].GetNormal(verticesAlreadyExported != null ? 1 : faceObject.SmGroup)
+                Position = mesh.GetVertex(vertexIndex, true),
+                Normal = mesh.GetNormal((int)face.Norm[facePart], true) //vnorms[vertexIndex].GetNormal(verticesAlreadyExported != null ? 1 : faceObject.SmGroup)
             };
 
             if (hasUV)
             {
-                var tvertexIndex = (int)mesh.TvFace[face].T[facePart];
-                vertex.UV = Loader.Global.Point2.Create(mesh.TVerts[tvertexIndex].X, mesh.TVerts[tvertexIndex].Y);
+                int[] indices = new int[3];
+                unsafe
+                {
+                    fixed (int* indicesPtr = indices)
+                    {
+                        mesh.GetMapFaceIndex(1, face.MeshFaceIndex, new IntPtr(indicesPtr));
+                    }
+                }
+                var texCoord = mesh.GetMapVertex(1, indices[facePart]);
+                vertex.UV = Loader.Global.Point2.Create(texCoord.X, -texCoord.Y);
             }
 
             if (hasUV2)
             {
-                var tvertexIndex = (int)mesh.MapFaces(2)[face].T[facePart];
-                vertex.UV2 = Loader.Global.Point2.Create(mesh.MapVerts(2)[tvertexIndex].X, mesh.MapVerts(2)[tvertexIndex].Y);
+                int[] indices = new int[3];
+                unsafe
+                {
+                    fixed (int* indicesPtr = indices)
+                    {
+                        mesh.GetMapFaceIndex(2, face.MeshFaceIndex, new IntPtr(indicesPtr));
+                    }
+                }
+                var texCoord = mesh.GetMapVertex(2, indices[facePart]);
+                vertex.UV2 = Loader.Global.Point2.Create(texCoord.X, -texCoord.Y);
             }
 
             if (hasColor)
             {
-                var vertexColorIndex = (int)mesh.VcFace[face].T[facePart];
-                var vertexColor = mesh.VertCol[vertexColorIndex];
-                var alpha = hasAlpha ? mesh.MapVerts(-2)[vertexColorIndex].X : 1;
+                var vertexColorIndex = (int)face.Color[facePart];
+                var vertexColor = mesh.GetColorVertex(vertexColorIndex);
+                float alpha = 1;
+                if (hasAlpha)
+                {
+                    IPoint3 p = Loader.Global.Point3.Create();
+                    mesh.GetMapFaceIndex(-2, face.MeshFaceIndex, p.GetNativeHandle());
+                    alpha = p.X;
+                }
 
-                vertex.Color = new float[] { vertexColor.X, vertexColor.Y, vertexColor.Z, alpha};
+                vertex.Color = new float[] { vertexColor.X, vertexColor.Y, vertexColor.Z, alpha };
             }
 
-            if (skinContextData != null)
+            if (skin != null)
             {
                 float weight0 = 0;
                 float weight1 = 0;
@@ -412,29 +494,29 @@ namespace Max2Babylon
                 int bone1 = bonesCount;
                 int bone2 = bonesCount;
                 int bone3 = bonesCount;
-                int nbBones = skinContextData.GetNumAssignedBones(vertexIndex);
+                int nbBones = skin.GetNumberOfBones(vertexIndex);
 
                 if (nbBones > 0)
                 {
-                    bone0 = skinContextData.GetAssignedBone(vertexIndex, 0);
-                    weight0 = skinContextData.GetBoneWeight(vertexIndex, 0);
+                    bone0 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 0), false);
+                    weight0 = skin.GetWeight(vertexIndex, 0);
                 }
 
                 if (nbBones > 1)
                 {
-                    bone1 = skinContextData.GetAssignedBone(vertexIndex, 1);
-                    weight1 = skinContextData.GetBoneWeight(vertexIndex, 1);
+                    bone1 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 1), false);
+                    weight1 = skin.GetWeight(vertexIndex, 1);
                 }
 
                 if (nbBones > 2)
                 {
-                    bone2 = skinContextData.GetAssignedBone(vertexIndex, 2);
-                    weight2 = skinContextData.GetBoneWeight(vertexIndex, 2);
+                    bone2 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 2), false);
+                    weight2 = skin.GetWeight(vertexIndex, 2);
                 }
 
                 if (nbBones > 3)
                 {
-                    bone3 = skinContextData.GetAssignedBone(vertexIndex, 3);
+                    bone3 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 3), false);
                 }
 
                 if (nbBones == 0)

+ 261 - 98
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Skeleton.cs

@@ -1,122 +1,170 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using Autodesk.Max;
 using BabylonExport.Entities;
 using SharpDX;
 
 namespace Max2Babylon
 {
+    internal class BonePoseInfo
+    {
+        public IGMatrix AbsoluteTransform { get; set; }
+        public IGMatrix LocalTransform { get; set; }
+    }
     partial class BabylonExporter
     {
-        readonly List<IISkin> skins = new List<IISkin>();
-
-        IISkin GetSkinModifier(IINode node)
+        readonly List<IIGameSkin> skins = new List<IIGameSkin>();
+        readonly List<IIGameNode> skinnedNodes = new List<IIGameNode>();
+
+        //IISkin GetSkinModifier(IINode node, out IModifier skinModifier)
+        //{
+        //    skinModifier = null;
+        //    var obj = node.ObjectRef;
+
+        //    if (obj.SuperClassID != SClass_ID.GenDerivob)
+        //    {
+        //        return null;
+        //    }
+
+        //    var derivedObject = obj as IIDerivedObject;
+
+        //    if (derivedObject == null)
+        //    {
+        //        return null;
+        //    }
+
+        //    for (var index = 0; index < derivedObject.NumModifiers; index++)
+        //    {
+        //        var modifier = derivedObject.GetModifier(index);
+
+        //        if (modifier.ClassID.PartA == 9815843 && modifier.ClassID.PartB == 87654) // Skin
+        //        {
+        //            var skin = modifier.GetInterface((InterfaceID)0x00010000) as IISkin;
+
+        //            if (!skins.Contains(skin))
+        //            {
+        //                skins.Add(skin);
+        //            }
+        //            skinModifier = modifier;
+        //            return skin;
+        //        }
+        //    }
+
+
+        //    return null;
+        //}
+
+
+        //float[] GetBoneBindPoseLocalMatrix(IISkin skin, IINode bone, bool hasParent)
+        //{
+        //    var matrix = Loader.Global.Matrix3.Create();
+        //    var result = skin.GetBoneInitTM(bone, matrix, false);
+        //    if (!hasParent)
+        //    {
+        //        return matrix.ToArray();
+        //    }
+        //    else
+        //    {
+        //        var parentInverse = Loader.Global.Matrix3.Create();
+
+        //        result = skin.GetBoneInitTM(bone.ParentNode, matrix, false);
+        //        parentInverse.Invert();
+        //        return matrix.Multiply(parentInverse).ToArray();
+        //    }
+
+        //}
+        //float[] GetBoneMatrixForFrame(IINode bone, int frame, bool hasParent)
+        //{
+        //    //            var nodeTM2 = bone.GetNodeTM(frame, Tools.Forever);
+        //    //            var parent = bone.ParentNode;
+
+        //    //            if (!hasParent)
+        //    //            {
+        //    //                parent = bone;
+        //    //            }
+        //    //            else
+        //    //            {
+        //    //                parent = bone.ParentNode;
+        //    //            }
+        //    //            var inverseParentTM = parent.GetNodeTM(frame, Tools.Forever);
+        //    //            inverseParentTM.Invert();
+        //    //            var localTransform = nodeTM2.Multiply(inverseParentTM);
+        //    //            var vLocalPos = localTransform.Trans;
+        //    //            var parts = Loader.Global.AffineParts.Create();
+        //    //            Loader.Global.DecompAffine(localTransform, parts);
+        //    //            IPoint3 eulerAngs = Loader.Global.Point3.Create();
+        //    //#if MAX2015
+        //    //            var eulerAngsPtr = eulerAngs.NativePointer;
+        //    //#else
+        //    //            var eulerAngsPtr = eulerAngs.Handle;
+        //    //#endif
+        //    //            //Loader.Global.QuatToEuler(parts.Q, eulerAngsPtr);
+
+        //    //            return ( Matrix.RotationQuaternion(new Quaternion(parts.Q.X, parts.Q.Y, parts.Q.Z, parts.Q.W))*Matrix.Translation(vLocalPos.X, vLocalPos.Z, vLocalPos.Y)).ToArray();
+        //    return Matrix.Identity.ToArray();
+        //}
+
+        IGMatrix WithNoScale(IGMatrix mat)
         {
-            var obj = node.ObjectRef;
-
-            if (obj.SuperClassID != SClass_ID.GenDerivob)
-            {
-                return null;
-            }
-
-            var derivedObject = obj as IIDerivedObject;
-
-            if (derivedObject == null)
-            {
-                return null;
-            }
-
-            for (var index = 0; index < derivedObject.NumModifiers; index++)
-            {
-                var modifier = derivedObject.GetModifier(index);
-
-                if (modifier.ClassID.PartA == 9815843 && modifier.ClassID.PartB == 87654) // Skin
-                {
-                    var skin = modifier.GetInterface((InterfaceID)0x00010000) as IISkin;
-
-                    if (!skins.Contains(skin))
-                    {
-                        skins.Add(skin);                        
-                    }
-
-                    return skin;
-                }
-            }
-
-
-            return null;
-        }
-
-        float[] GetBoneMatrix(IISkin skin, IINode bone, int t, bool hasParent)
-        {
-            var maxMatrix = bone.GetWorldMatrix(t, hasParent);
-
-            //var initialMatrix = Loader.Global.Matrix3.Create();
-            //skin.GetBoneInitTM(bone, initialMatrix, false);
-
-            //initialMatrix.Invert();
-
-            //maxMatrix = maxMatrix.MultiplyBy(initialMatrix);
-
-            //if (!hasParent)
-            //{
-            //    initialMatrix = Loader.Global.Matrix3.Create();
-            //    skin.GetSkinInitTM(bone, initialMatrix, false);
-
-            //    initialMatrix.Invert();
-
-            //    maxMatrix = maxMatrix.MultiplyBy(initialMatrix);
-            //}
-
-            maxMatrix.NoScale();
-
-            var trans = maxMatrix.Trans;
-
-            var parts = Loader.Global.AffineParts.Create();
-            Loader.Global.DecompAffine(maxMatrix, parts);
-
-            var rotationQuaternion = new Quaternion(parts.Q.X, parts.Q.Z, parts.Q.Y, parts.Q.W);
-
-            var matrix = Matrix.RotationQuaternion(rotationQuaternion) * Matrix.Translation(trans.X, trans.Z, trans.Y);
-
-            return matrix.ToArray();
+            var mat3 = mat.ExtractMatrix3();
+            mat3.NoScale();
+            return Loader.Global.GMatrix.Create(mat3);
         }
-
-        private void ExportSkin(IISkin skin, BabylonScene babylonScene)
+        private void ExportSkin(IIGameSkin skin, BabylonScene babylonScene)
         {
-            var babylonSkeleton = new BabylonSkeleton {id = skins.IndexOf(skin)};
+            var babylonSkeleton = new BabylonSkeleton { id = skins.IndexOf(skin) };
             babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;
 
             RaiseMessage(babylonSkeleton.name, 1);
+            //IGMatrix skinInitMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
+            //skin.GetInitSkinTM(skinInitMatrix);
+            var skinIndex = skins.IndexOf(skin);
+            var meshNode = skinnedNodes[skinIndex];
+            var skinInitMatrix = meshNode.GetObjectTM(0);
 
             var bones = new List<BabylonBone>();
-
-            for (var index = 0; index < skin.NumBones; index++)
+            var gameBones = new List<IIGameNode>();
+            var boneIds = new List<int>();
+            var bindPoseInfos = new List<BonePoseInfo>();
+            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
             {
-                var bone = new BabylonBone {name = skin.GetBoneName(index), index = index};
+                var gameBone = skin.GetIGameBone(index, false);
 
-                var maxBone = skin.GetBone(index);
-                var parentNode = maxBone.ParentNode;
+                gameBones.Add(gameBone);
+                boneIds.Add(gameBone.NodeID);
+                bones.Add(new BabylonBone { index = index, name = gameBone.Name });
+                //IGMatrix boneInitMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
 
-                if (parentNode != null)
+                //skin.GetInitBoneTM(gameBone, boneInitMatrix);
+                var boneInitMatrix = gameBone.GetObjectTM(0);
+                bindPoseInfos.Add(new BonePoseInfo { AbsoluteTransform = boneInitMatrix });
+            }
+            // fix hierarchy an generate animation keys
+            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
+            {
+                var gameBone = gameBones[index];
+                var parent = gameBone.NodeParent;
+                var babBone = bones[index];
+                if (parent != null)
                 {
-                    for (var recurseIndex = 0; recurseIndex < index; recurseIndex++)
-                    {
-                        if (skin.GetBone(recurseIndex).GetGuid() == parentNode.GetGuid())
-                        {
-                            bone.parentBoneIndex = recurseIndex;
-                            break;
-                        }
-                    }
+                    babBone.parentBoneIndex = boneIds.IndexOf(parent.NodeID);
+                }
+                if (babBone.parentBoneIndex == -1)
+                {
+                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(skinInitMatrix.Inverse);
+                }
+                else
+                {
+                    var parentBindPoseInfos = bindPoseInfos[babBone.parentBoneIndex];
+                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(parentBindPoseInfos.AbsoluteTransform.Inverse);
                 }
-                var hasParent = bone.parentBoneIndex != -1;
-                bone.matrix = GetBoneMatrix(skin, maxBone, 0, hasParent);
+                babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();
 
-                // Animation
                 var babylonAnimation = new BabylonAnimation
                 {
-                    name = bone.name + "Animation", 
-                    property = "_matrix", 
-                    dataType = BabylonAnimation.DataType.Matrix, 
+                    name = gameBone.Name + "Animation",
+                    property = "_matrix",
+                    dataType = BabylonAnimation.DataType.Matrix,
                     loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
                     framePerSecond = Loader.Global.FrameRate
                 };
@@ -128,8 +176,19 @@ namespace Max2Babylon
                 var keys = new List<BabylonAnimationKey>();
                 for (var key = start; key <= end; key += Ticks)
                 {
-                    var current = GetBoneMatrix(skin, maxBone, key, hasParent);
+                    var objectTM = gameBone.GetObjectTM(key);
+                    var parentNode = gameBone.NodeParent;
+                    IGMatrix mat;
+                    if (parentNode == null || babBone.parentBoneIndex == -1)
+                    {
+                        mat = objectTM.Multiply(meshNode.GetObjectTM(key).Inverse);
+                    }
+                    else
+                    {
+                        mat = objectTM.Multiply(parentNode.GetObjectTM(key).Inverse);
+                    }
 
+                    var current = mat.ToArray();
                     if (key == start || key == end || !(previous.IsEqualTo(current)))
                     {
                         keys.Add(new BabylonAnimationKey
@@ -143,14 +202,118 @@ namespace Max2Babylon
                 }
 
                 babylonAnimation.keys = keys.ToArray();
-                bone.animation = babylonAnimation;
+                babBone.animation = babylonAnimation;
 
-                bones.Add(bone);
             }
 
+            //FixupHierarchy(Loader.Core.RootNode, skin.GetBone(0), bones);
+
             babylonSkeleton.bones = bones.ToArray();
 
             babylonScene.SkeletonsList.Add(babylonSkeleton);
         }
+
+        //private void ExportSkin(IISkin skin, BabylonScene babylonScene)
+        //{
+
+        //    var babylonSkeleton = new BabylonSkeleton { id = skins.IndexOf(skin) };
+        //    babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;
+
+        //    RaiseMessage(babylonSkeleton.name, 1);
+
+        //    var bones = new List<BabylonBone>();
+
+        //    for (var index = 0; index < skin.NumBones; index++)
+        //    {
+        //        var bone = new BabylonBone { name = skin.GetBoneName(index), index = index };
+
+        //        var maxBone = skin.GetBone(index);
+        //        var parentNode = maxBone.ParentNode;
+
+        //        if (parentNode != null)
+        //        {
+        //            for (var recurseIndex = 0; recurseIndex < index; recurseIndex++)
+        //            {
+        //                if (skin.GetBone(recurseIndex).GetGuid() == parentNode.GetGuid())
+        //                {
+        //                    bone.parentBoneIndex = recurseIndex;
+        //                    break;
+        //                }
+        //            }
+        //        }
+        //        var hasParent = bone.parentBoneIndex != -1;
+        //        var currentBoneNeutralMatrix = GetBoneBindPoseLocalMatrix(skin, maxBone, hasParent);
+        //        bone.matrix = currentBoneNeutralMatrix;
+
+        //        // Animation
+        //        var babylonAnimation = new BabylonAnimation
+        //        {
+        //            name = bone.name + "Animation",
+        //            property = "_matrix",
+        //            dataType = BabylonAnimation.DataType.Matrix,
+        //            loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
+        //            framePerSecond = Loader.Global.FrameRate
+        //        };
+
+        //        var start = Loader.Core.AnimRange.Start;
+        //        var end = Loader.Core.AnimRange.End;
+
+        //        float[] previous = null;
+        //        var keys = new List<BabylonAnimationKey>();
+        //        for (var key = start; key <= end; key += Ticks)
+        //        {
+        //            var current = GetBoneMatrixForFrame(maxBone, key, hasParent);
+
+        //            if (key == start || key == end || !(previous.IsEqualTo(current)))
+        //            {
+        //                keys.Add(new BabylonAnimationKey
+        //                {
+        //                    frame = key / Ticks,
+        //                    values = current
+        //                });
+        //            }
+
+        //            previous = current;
+        //        }
+
+        //        babylonAnimation.keys = keys.ToArray();
+        //        bone.animation = babylonAnimation;
+
+        //        bones.Add(bone);
+        //    }
+        //    //FixupHierarchy(Loader.Core.RootNode, skin.GetBone(0), bones);
+
+        //    babylonSkeleton.bones = bones.ToArray();
+
+        //    babylonScene.SkeletonsList.Add(babylonSkeleton);
+        //}
+
+        //private void FixupHierarchy(IINode sceneRoot, IINode skeletonRoot, List<BabylonBone> bones)
+        //{
+        //    var skeletonTransforms = new NodeTransforms(skeletonRoot, 0);
+        //    var sceneRootTransforms = new NodeTransforms(sceneRoot, 0);
+        //    var skelAbs = skeletonTransforms.AbsoluteTransform;
+        //    var invSceneAbs = sceneRootTransforms.AbsoluteTransform;
+        //    invSceneAbs.Invert();
+        //    var skelAbsInvSceneAbs = skelAbs.Multiply(invSceneAbs);
+        //    var invSkelLocalTransform = skeletonTransforms.LocalTransform;
+        //    invSkelLocalTransform.Invert();
+        //    var skelAbsInvSceneAbsXinvSkelLocalTransform = skelAbsInvSceneAbs.Multiply(invSkelLocalTransform);
+        //    bones[0].matrix = skelAbsInvSceneAbs.ToArray();
+        //    var matskelAbsInvSceneAbsXinvSkelLocalTransform = new Matrix(skelAbsInvSceneAbsXinvSkelLocalTransform.ToArray());
+        //    foreach (var b in bones)
+        //    {
+        //        var oldTransform = new Matrix(b.matrix);
+        //        b.matrix = (oldTransform * matskelAbsInvSceneAbsXinvSkelLocalTransform).ToArray();
+        //        foreach(var frame in b.animation.keys)
+        //        {
+
+        //            var oldTransform2 = new Matrix(frame.values);
+        //            frame.values = (oldTransform2 * matskelAbsInvSceneAbsXinvSkelLocalTransform).ToArray();
+        //        }
+        //    }
+
+
+        //}
     }
 }

+ 8 - 17
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Texture.cs

@@ -190,7 +190,7 @@ namespace Max2Babylon
             {
                 babylonTexture.wrapV = 2;
             }
-
+            
             babylonTexture.name = Path.GetFileName(texture.MapName);
 
             // Animations
@@ -204,34 +204,25 @@ namespace Max2Babylon
             ExportFloatAnimation("wAng", animations, key => new[] { uvGen.GetWAng(key) });
 
             babylonTexture.animations = animations.ToArray();
-
+            var absolutePath = texture.Map.FullFilePath;
             // Copy texture to output
             try
             {
-                if (File.Exists(texture.MapName))
-                {
-                    babylonTexture.isCube = IsTextureCube(texture.MapName);
-                    if (CopyTexturesToOutput)
+               
+                   
+                    if (File.Exists(absolutePath))
                     {
-                        File.Copy(texture.MapName, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
-                    }
-                }
-                else
-                {
-                    var texturepath = Path.Combine(Path.GetDirectoryName(Loader.Core.CurFilePath), babylonTexture.name);
-                    if (File.Exists(texturepath))
-                    {
-                        babylonTexture.isCube = IsTextureCube(texturepath);
+                        babylonTexture.isCube = IsTextureCube(absolutePath);
                         if (CopyTexturesToOutput)
                         {
-                            File.Copy(texturepath, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
+                            File.Copy(absolutePath, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
                         }
                     }
                     else
                     {
                         RaiseWarning(string.Format("Texture {0} not found.", babylonTexture.name), 2);
                     }
-                }
+                
             }
             catch
             {

+ 39 - 31
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.cs

@@ -11,6 +11,7 @@ using Autodesk.Max;
 using BabylonExport.Entities;
 using Newtonsoft.Json;
 using Color = System.Drawing.Color;
+using System.Runtime.InteropServices;
 
 namespace Max2Babylon
 {
@@ -21,6 +22,8 @@ namespace Max2Babylon
         public event Action<string, Color, int, bool> OnMessage;
         public event Action<string, int> OnError;
 
+        string maxSceneFileName;
+
         readonly List<string> alreadyExportedTextures = new List<string>();
 
         public bool AutoSave3dsMaxFile { get; set; }
@@ -79,11 +82,20 @@ namespace Max2Babylon
 
         public async Task ExportAsync(string outputFile, bool generateManifest, bool onlySelected, Form callerForm)
         {
+            var gameConversionManger = Loader.Global.ConversionManager;
+            gameConversionManger.CoordSystem = Autodesk.Max.IGameConversionManager.CoordSystem.D3d;
+
+            var gameScene = Loader.Global.IGameInterface;
+            gameScene.InitialiseIGame(onlySelected);
+            gameScene.SetStaticFrame(0);
+
+            maxSceneFileName = gameScene.SceneFileName;
+
             IsCancelled = false;
             RaiseMessage("Exportation started", Color.Blue);
             ReportProgressChanged(0);
             var babylonScene = new BabylonScene(Path.GetDirectoryName(outputFile));
-            var maxScene = Loader.Core.RootNode;
+            var rawScene = Loader.Core.RootNode;
             alreadyExportedTextures.Clear();
 
             if (!Directory.Exists(babylonScene.OutputPath))
@@ -114,31 +126,32 @@ namespace Max2Babylon
             babylonScene.clearColor = Loader.Core.GetBackGround(0, Tools.Forever).ToArray();
             babylonScene.ambientColor = Loader.Core.GetAmbient(0, Tools.Forever).ToArray();
 
-            babylonScene.gravity = maxScene.GetVector3Property("babylonjs_gravity");
-            exportQuaternionsInsteadOfEulers = maxScene.GetBoolProperty("babylonjs_exportquaternions", 1);
+            babylonScene.gravity = rawScene.GetVector3Property("babylonjs_gravity");
+            exportQuaternionsInsteadOfEulers = rawScene.GetBoolProperty("babylonjs_exportquaternions", 1);
 
             // Cameras
             BabylonCamera mainCamera = null;
             ICameraObject mainCameraNode = null;
 
             RaiseMessage("Exporting cameras");
-            foreach (var cameraNode in maxScene.NodesListBySuperClass(SClass_ID.Camera))
+            var camerasTab = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Camera);
+            for(int ix = 0; ix < camerasTab.Count; ++ix)
             {
-                if (onlySelected && !cameraNode.Selected)
-                {
-                    continue;
-                }
+                var indexer = new IntPtr(ix);
+                var cameraNode = camerasTab[indexer];
+                Marshal.FreeHGlobal(indexer);
                 ExportCamera(cameraNode, babylonScene);
 
                 if (mainCamera == null && babylonScene.CamerasList.Count > 0)
                 {
-                    mainCameraNode = (cameraNode.ObjectRef as ICameraObject);
+                    mainCameraNode = (cameraNode.MaxNode.ObjectRef as ICameraObject);
                     mainCamera = babylonScene.CamerasList[0];
                     babylonScene.activeCameraID = mainCamera.id;
                     RaiseMessage("Active camera set to " + mainCamera.name, Color.Green, 1, true);
                 }
             }
 
+
             if (mainCamera == null)
             {
                 RaiseWarning("No camera defined", 1);
@@ -157,7 +170,7 @@ namespace Max2Babylon
                 {
                     var fog = atmospheric as IStdFog;
 
-                    RaiseMessage("Exporting fog");
+                        RaiseMessage("Exporting fog");
 
                     if (fog != null)
                     {
@@ -173,8 +186,8 @@ namespace Max2Babylon
                         babylonScene.fogMode = 3;
                     }
 #endif
-                    if (mainCamera != null)
-                    {
+                        if (mainCamera != null)
+                        {
                         babylonScene.fogStart = mainCameraNode.GetEnvRange(0, 0, Tools.Forever);
                         babylonScene.fogEnd = mainCameraNode.GetEnvRange(0, 1, Tools.Forever);
                     }
@@ -184,26 +197,22 @@ namespace Max2Babylon
             // Meshes
             ReportProgressChanged(10);
             RaiseMessage("Exporting meshes");
-            var meshes = maxScene.NodesListBySuperClasses(new[] { SClass_ID.Geomobject, SClass_ID.Helper });
-            var progressionStep = 80.0f / meshes.Count();
+            var meshes = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Mesh);
+            var progressionStep = 80.0f / meshes.Count;
             var progression = 10.0f;
-            foreach (var meshNode in meshes)
-            {
-                if (onlySelected && !meshNode.Selected)
+            for (int ix = 0; ix < meshes.Count; ++ix)
                 {
-                    continue;
-                }
+                var indexer = new IntPtr(ix);
+                var meshNode = meshes[indexer];
+                Marshal.FreeHGlobal(indexer);
+                ExportMesh(gameScene, meshNode, babylonScene);
 
-                Tools.PreparePipeline(meshNode, true);
-                ExportMesh(meshNode, babylonScene);
-                Tools.PreparePipeline(meshNode, false);
 
-                progression += progressionStep;
                 ReportProgressChanged((int)progression);
 
                 CheckCancelled();
             }
-            RaiseMessage(string.Format("Total: {0}", babylonScene.MeshesList.Count), Color.Gray, 1);
+
 
             // Materials
             RaiseMessage("Exporting materials");
@@ -217,16 +226,14 @@ namespace Max2Babylon
 
             // Lights
             RaiseMessage("Exporting lights");
-            foreach (var lightNode in maxScene.NodesListBySuperClass(SClass_ID.Light))
-            {
-                if (onlySelected && !lightNode.Selected)
+            var lightNodes = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Light);
+            for(var i=0;i< lightNodes.Count; ++i)
                 {
-                    continue;
-                }
-                ExportLight(lightNode, babylonScene);
+                ExportLight(lightNodes[new IntPtr(i)], babylonScene);
                 CheckCancelled();
             }
 
+
             if (babylonScene.LightsList.Count == 0)
             {
                 RaiseWarning("No light defined", 1);
@@ -245,7 +252,6 @@ namespace Max2Babylon
                 foreach (var skin in skins)
                 {
                     ExportSkin(skin, babylonScene);
-                    skin.Dispose();
                 }
             }
 
@@ -276,5 +282,7 @@ namespace Max2Babylon
             watch.Stop();
             RaiseMessage(string.Format("Exportation done in {0:0.00}s", watch.ElapsedMilliseconds / 1000.0), Color.Blue);
         }
+
+        
     }
 }

+ 17 - 5
Exporters/3ds Max/Max2Babylon/Max2Babylon.csproj

@@ -17,6 +17,7 @@
     <SccAuxPath>SAK</SccAuxPath>
     <SccProvider>SAK</SccProvider>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+    <NuGetPackageImportStamp>eeea6a2c</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -37,6 +38,7 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <Prefer32Bit>false</Prefer32Bit>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="Autodesk.Max, Version=15.6.164.0, Culture=neutral, processorArchitecture=MSIL">
@@ -44,18 +46,18 @@
       <HintPath>Refs\Autodesk.Max.dll</HintPath>
       <Private>False</Private>
     </Reference>
-    <Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>Refs\Newtonsoft.Json.dll</HintPath>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="SharpDX, Version=2.4.2.0, Culture=neutral, PublicKeyToken=627a3d6d1956f55a, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\BabylonExport.Core\Refs\SharpDX.dll</HintPath>
+      <HintPath>$(SharpDXPackageBinDir)\SharpDX.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Web" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="Microsoft.CSharp" />
@@ -125,7 +127,7 @@
     <Compile Include="Forms\Vector3Control.Designer.cs">
       <DependentUpon>Vector3Control.cs</DependentUpon>
     </Compile>
-    <Compile Include="Tools\VNormal.cs" /> 
+    <Compile Include="Tools\VNormal.cs" />
     <Compile Include="Tools\WebServer.cs" />
   </ItemGroup>
   <ItemGroup>
@@ -161,7 +163,17 @@
       <Name>BabylonExport.Entities</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\packages\SharpDX.2.6.3\build\SharpDX.targets" Condition="Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SharpDX.2.6.3\build\SharpDX.targets'))" />
+  </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

+ 92 - 19
Exporters/3ds Max/Max2Babylon/Tools/Tools.cs

@@ -7,11 +7,61 @@ using System.Windows.Forms;
 using Autodesk.Max;
 using BabylonExport.Entities;
 using SharpDX;
+using System.Reflection;
 
 namespace Max2Babylon
 {
     public static class Tools
     {
+        public static IntPtr GetNativeHandle(this INativeObject obj)
+        {
+#if MAX2015
+            return obj.NativePointer;
+#else
+            return obj.Handle;
+#endif
+
+        }
+        static Assembly GetWrappersAssembly()
+        {
+            return Assembly.Load("Autodesk.Max.Wrappers, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
+        }
+        public static IIGameCamera AsGameCamera(this IIGameObject obj)
+        {
+            var type = GetWrappersAssembly().GetType("Autodesk.Max.Wrappers.IGameCamera");
+            var constructor = type.GetConstructors()[0];
+            // var pointerType = GetWrappersAssembly().GetType("IGameCamera");
+            unsafe
+            {
+                var voidPtr = obj.GetNativeHandle().ToPointer();
+                return (IIGameCamera)constructor.Invoke(new object[] { obj.GetNativeHandle(), false });
+            }
+        }
+
+        public static IIGameMesh AsGameMesh(this IIGameObject obj)
+        {
+            var type = GetWrappersAssembly().GetType("Autodesk.Max.Wrappers.IGameMesh");
+            var constructor = type.GetConstructors()[0];
+            // var pointerType = GetWrappersAssembly().GetType("IGameCamera");
+            unsafe
+            {
+                var voidPtr = obj.GetNativeHandle().ToPointer();
+                return (IIGameMesh)constructor.Invoke(new object[] { obj.GetNativeHandle(), false });
+            }
+        }
+
+        public static IIGameLight AsGameLight(this IIGameObject obj)
+        {
+            var type = GetWrappersAssembly().GetType("Autodesk.Max.Wrappers.IGameLight");
+            var constructor = type.GetConstructors()[0];
+            // var pointerType = GetWrappersAssembly().GetType("IGameCamera");
+            unsafe
+            {
+                var voidPtr = obj.GetNativeHandle().ToPointer();
+                return (IIGameLight)constructor.Invoke(new object[] { obj.GetNativeHandle(), false });
+            }
+        }
+
         public const float Epsilon = 0.001f;
 
         public static IPoint3 XAxis { get { return Loader.Global.Point3.Create(1, 0, 0); } }
@@ -114,7 +164,23 @@ namespace Max2Babylon
 
             return pitchYawRoll;
         }
-
+        public static float[] ToArray(this IGMatrix gmat)
+        {
+            //float eulX =0,  eulY=0,  eulZ=0;
+            //unsafe
+            //{
+            //    gmat.Rotation.GetEuler( new IntPtr(&eulX), new IntPtr(&eulY), new IntPtr(&eulZ));
+            //}
+            //return (Matrix.Scaling(gmat.Scaling.X, gmat.Scaling.Y, gmat.Scaling.Z) * Matrix.RotationYawPitchRoll(eulY, eulX, eulZ) * Matrix.Translation(gmat.Translation.X, gmat.Translation.Y, gmat.Translation.Z)).ToArray();
+            var r0 = gmat.GetRow(0);
+            var r1 = gmat.GetRow(1);
+            var r2 = gmat.GetRow(2);
+            var r3 = gmat.GetRow(3);
+            return new float[] {r0.X, r0.Y, r0.Z, r0.W,
+            r1.X, r1.Y,r1.Z, r1.W,
+            r2.X, r2.Y,r2.Z, r2.W,
+            r3.X, r3.Y,r3.Z, r3.W,};
+        }
         public static void PreparePipeline(IINode node, bool deactivate)
         {
             var obj = node.ObjectRef;
@@ -196,6 +262,7 @@ namespace Max2Babylon
 
         public static float[] ToArray(this IMatrix3 value)
         {
+
             var row0 = value.GetRow(0).ToArraySwitched();
             var row1 = value.GetRow(1).ToArraySwitched();
             var row2 = value.GetRow(2).ToArraySwitched();
@@ -407,7 +474,29 @@ namespace Max2Babylon
 
             return obj.ConvertToType(0, triObjectClassId) as ITriObject;
         }
-
+        public static bool IsAlmostEqualTo(this float[] current, float[] other, float epsilon)
+        {
+            if (current == null && other == null)
+            {
+                return true;
+            }
+            if (current == null || other == null)
+            {
+                return false;
+            }
+            if (current.Length != other.Length)
+            {
+                return false;
+            }
+            for (var i = 0; i < current.Length; ++i)
+            {
+                if (Math.Abs(current[i] - other[i]) > epsilon)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
         public static bool IsAlmostEqualTo(this IPoint4 current, IPoint4 other, float epsilon)
         {
             if (Math.Abs(current.X - other.X) > epsilon)
@@ -468,23 +557,7 @@ namespace Max2Babylon
             return true;
         }
 
-        public static bool IsAlmostEqualTo(this float[] current, float[] other, float epsilon)
-        {
-            if (current.Length != other.Length)
-            {
-                return false;
-            }
-
-            for (var index = 0; index < current.Length; index++)
-            {
-                if (Math.Abs(current[index] - other[index]) > epsilon)
-                {
-                    return false;
-                }
-            }
-
-            return true;
-        }
+     
 
         public static bool GetBoolProperty(this IINode node, string propertyName, int defaultState = 0)
         {

+ 15 - 3
Exporters/3ds Max/Max2Babylon/Tools/WebServer.cs

@@ -104,7 +104,7 @@ namespace Max2Babylon
 
         public static string SceneFilename { get; set; }
         public static string SceneFolder { get; set; }
-
+        static Random r = new Random();
         static void Listen()
         {
             try
@@ -118,14 +118,26 @@ namespace Max2Babylon
                     context.Response.AddHeader("Cache-Control", "no-cache");
                     if (string.IsNullOrEmpty(url.LocalPath) || url.LocalPath == "/")
                     {
-                        var responseText = HtmlResponseText.Replace("###SCENE###", SceneFilename);
+
+                        var responseText = HtmlResponseText.Replace("###SCENE###", SceneFilename+"?once="+r.Next());
                         WriteResponse(context, responseText);
                     }
                     else
                     {
                         try
                         {
-                            var buffer = File.ReadAllBytes(Path.Combine(SceneFolder, HttpUtility.UrlDecode(url.PathAndQuery.Substring(1))));
+                            var path = Path.Combine(SceneFolder, HttpUtility.UrlDecode(url.PathAndQuery.Substring(1)));
+                            var questionMarkIndex = path.IndexOf("?");
+                            if (questionMarkIndex != -1)
+                            {
+                                path = path.Substring(0, questionMarkIndex);
+                            }
+                            var hashIndex = path.IndexOf("#");
+                            if (hashIndex != -1)
+                            {
+                                path = path.Substring(0, hashIndex);
+                            }
+                            var buffer = File.ReadAllBytes(path);
                             WriteResponse(context, buffer);
                         }
                         catch

+ 5 - 0
Exporters/3ds Max/Max2Babylon/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" />
+  <package id="SharpDX" version="2.6.3" targetFramework="net45" />
+</packages>