Просмотр исходного кода

Easing functions
Web audio pre-alpha

David Catuhe 10 лет назад
Родитель
Сommit
1d8a6d719e

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

@@ -14,6 +14,37 @@
             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;
@@ -23,6 +54,14 @@
             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;
         };
@@ -65,11 +104,19 @@
             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) {
@@ -143,16 +190,11 @@
                 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);
             }
 
@@ -167,6 +209,8 @@
             // 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) {
@@ -175,6 +219,7 @@
             } 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]) {

+ 63 - 6
Babylon/Animations/babylon.animation.ts

@@ -5,10 +5,47 @@
         private _highLimitsCache = {};
         private _stopped = false;
         public _target;
+        private _easingFunction: BABYLON.IEasingFunction;
 
         public targetPropertyPath: string[];
         public currentFrame: number;
 
+        public static CreateAndStartAnimation(name: string, mesh: BABYLON.AbstractMesh, tartgetProperty: string,
+            framePerSecond: number, totalFrame: number,
+            from: any, to: any, loopMode?: number) {
+
+            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));
+
+        }
+
+
         constructor(public name: string, public targetProperty: string, public framePerSecond: number, public dataType: number, public loopMode?: number) {
             this.targetPropertyPath = targetProperty.split(".");
             this.dataType = dataType;
@@ -24,6 +61,14 @@
             return this._keys;
         }
 
+        public getEasingFunction() {
+            return this._easingFunction;
+        }
+
+        public setEasingFunction(easingFunction: BABYLON.EasingFunction) {
+            this._easingFunction = easingFunction;
+        }
+
         public floatInterpolateFunction(startValue: number, endValue: number, gradient: number): number {
             return startValue + (endValue - startValue) * gradient;
         }
@@ -58,6 +103,7 @@
             this._highLimitsCache = {};
         }
 
+
         private _interpolate(currentFrame: number, repeatCount: number, loopMode: number, offsetValue?, highLimitValue?) {
             if (loopMode === Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) {
                 return highLimitValue.clone ? highLimitValue.clone() : highLimitValue;
@@ -66,11 +112,20 @@
             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) {
                         // Float
                         case Animation.ANIMATIONTYPE_FLOAT:
@@ -140,20 +195,17 @@
             return this._keys[this._keys.length - 1].value;
         }
 
+
         public animate(delay: number, from: number, to: number, loop: boolean, speedRatio: number): boolean {
             if (!this.targetPropertyPath || this.targetPropertyPath.length < 1) {
                 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);
             }
 
@@ -168,6 +220,7 @@
             // 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) { // If we are out of range and not looping get back to caller
@@ -176,7 +229,9 @@
             } 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]) {
                         var fromValue = this._interpolate(from, 0, Animation.ANIMATIONLOOPMODE_CYCLE);
@@ -264,6 +319,8 @@
             return returnValue;
         }
 
+
+
         // Statics
         private static _ANIMATIONTYPE_FLOAT = 0;
         private static _ANIMATIONTYPE_VECTOR3 = 1;

+ 270 - 0
Babylon/Animations/babylon.easing.js

@@ -0,0 +1,270 @@
+var __extends = this.__extends || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    __.prototype = b.prototype;
+    d.prototype = new __();
+};
+var BABYLON;
+(function (BABYLON) {
+    var EasingFunction = (function () {
+        function EasingFunction() {
+            // Properties
+            this._easingMode = EasingFunction.EASINGMODE_EASEIN;
+        }
+        Object.defineProperty(EasingFunction, "EASINGMODE_EASEIN", {
+            get: function () {
+                return EasingFunction._EASINGMODE_EASEIN;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(EasingFunction, "EASINGMODE_EASEOUT", {
+            get: function () {
+                return EasingFunction._EASINGMODE_EASEOUT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(EasingFunction, "EASINGMODE_EASEINOUT", {
+            get: function () {
+                return EasingFunction._EASINGMODE_EASEINOUT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        EasingFunction.prototype.setEasingMode = function (easingMode) {
+            var n = Math.min(Math.max(easingMode, 0), 2);
+            this._easingMode = n;
+        };
+        EasingFunction.prototype.getEasingMode = function () {
+            return this._easingMode;
+        };
+
+        EasingFunction.prototype.easeInCore = function (gradient) {
+            throw new Error('You must implement this method');
+        };
+
+        EasingFunction.prototype.ease = function (gradient) {
+            switch (this._easingMode) {
+                case EasingFunction.EASINGMODE_EASEIN:
+                    return this.easeInCore(gradient);
+                case EasingFunction.EASINGMODE_EASEOUT:
+                    return (1 - this.easeInCore(1 - gradient));
+            }
+
+            if (gradient >= 0.5) {
+                return (((1 - this.easeInCore((1 - gradient) * 2)) * 0.5) + 0.5);
+            }
+
+            return (this.easeInCore(gradient * 2) * 0.5);
+        };
+        EasingFunction._EASINGMODE_EASEIN = 0;
+        EasingFunction._EASINGMODE_EASEOUT = 1;
+        EasingFunction._EASINGMODE_EASEINOUT = 2;
+        return EasingFunction;
+    })();
+    BABYLON.EasingFunction = EasingFunction;
+
+    var CircleEase = (function (_super) {
+        __extends(CircleEase, _super);
+        function CircleEase() {
+            _super.apply(this, arguments);
+        }
+        CircleEase.prototype.easeInCore = function (gradient) {
+            gradient = Math.max(0, Math.min(1, gradient));
+            return (1.0 - Math.sqrt(1.0 - (gradient * gradient)));
+        };
+        return CircleEase;
+    })(EasingFunction);
+    BABYLON.CircleEase = CircleEase;
+
+    var BackEase = (function (_super) {
+        __extends(BackEase, _super);
+        function BackEase(amplitude) {
+            if (typeof amplitude === "undefined") { amplitude = 1; }
+            _super.call(this);
+            this.amplitude = amplitude;
+        }
+        BackEase.prototype.easeInCore = function (gradient) {
+            var num = Math.max(0, this.amplitude);
+            return (Math.pow(gradient, 3.0) - ((gradient * num) * Math.sin(3.1415926535897931 * gradient)));
+        };
+        return BackEase;
+    })(EasingFunction);
+    BABYLON.BackEase = BackEase;
+
+    var BounceEase = (function (_super) {
+        __extends(BounceEase, _super);
+        function BounceEase(bounces, bounciness) {
+            if (typeof bounces === "undefined") { bounces = 3; }
+            if (typeof bounciness === "undefined") { bounciness = 2; }
+            _super.call(this);
+            this.bounces = bounces;
+            this.bounciness = bounciness;
+        }
+        BounceEase.prototype.easeInCore = function (gradient) {
+            var y = Math.max(0.0, this.bounces);
+            var bounciness = this.bounciness;
+            if (bounciness <= 1.0) {
+                bounciness = 1.001;
+            }
+            var num9 = Math.pow(bounciness, y);
+            var num5 = 1.0 - bounciness;
+            var num4 = ((1.0 - num9) / num5) + (num9 * 0.5);
+            var num15 = gradient * num4;
+            var num65 = Math.log((-num15 * (1.0 - bounciness)) + 1.0) / Math.log(bounciness);
+            var num3 = Math.floor(num65);
+            var num13 = num3 + 1.0;
+            var num8 = (1.0 - Math.pow(bounciness, num3)) / (num5 * num4);
+            var num12 = (1.0 - Math.pow(bounciness, num13)) / (num5 * num4);
+            var num7 = (num8 + num12) * 0.5;
+            var num6 = gradient - num7;
+            var num2 = num7 - num8;
+            return (((-Math.pow(1.0 / bounciness, y - num3) / (num2 * num2)) * (num6 - num2)) * (num6 + num2));
+        };
+        return BounceEase;
+    })(EasingFunction);
+    BABYLON.BounceEase = BounceEase;
+
+    var CubicEase = (function (_super) {
+        __extends(CubicEase, _super);
+        function CubicEase() {
+            _super.apply(this, arguments);
+        }
+        CubicEase.prototype.easeInCore = function (gradient) {
+            return (gradient * gradient * gradient);
+        };
+        return CubicEase;
+    })(EasingFunction);
+    BABYLON.CubicEase = CubicEase;
+
+    var ElasticEase = (function (_super) {
+        __extends(ElasticEase, _super);
+        function ElasticEase(oscillations, springiness) {
+            if (typeof oscillations === "undefined") { oscillations = 3; }
+            if (typeof springiness === "undefined") { springiness = 3; }
+            _super.call(this);
+            this.oscillations = oscillations;
+            this.springiness = springiness;
+        }
+        ElasticEase.prototype.easeInCore = function (gradient) {
+            var num2;
+            var num3 = Math.max(0.0, this.oscillations);
+            var num = Math.max(0.0, this.springiness);
+
+            if (num == 0) {
+                num2 = gradient;
+            } else {
+                num2 = (Math.exp(num * gradient) - 1.0) / (Math.exp(num) - 1.0);
+            }
+            return (num2 * Math.sin(((6.2831853071795862 * num3) + 1.5707963267948966) * gradient));
+        };
+        return ElasticEase;
+    })(EasingFunction);
+    BABYLON.ElasticEase = ElasticEase;
+
+    var ExponentialEase = (function (_super) {
+        __extends(ExponentialEase, _super);
+        function ExponentialEase(exponent) {
+            if (typeof exponent === "undefined") { exponent = 2; }
+            _super.call(this);
+            this.exponent = exponent;
+        }
+        ExponentialEase.prototype.easeInCore = function (gradient) {
+            if (this.exponent <= 0) {
+                return gradient;
+            }
+
+            return ((Math.exp(this.exponent * gradient) - 1.0) / (Math.exp(this.exponent) - 1.0));
+        };
+        return ExponentialEase;
+    })(EasingFunction);
+    BABYLON.ExponentialEase = ExponentialEase;
+
+    var PowerEase = (function (_super) {
+        __extends(PowerEase, _super);
+        function PowerEase(power) {
+            if (typeof power === "undefined") { power = 2; }
+            _super.call(this);
+            this.power = power;
+        }
+        PowerEase.prototype.easeInCore = function (gradient) {
+            var y = Math.max(0.0, this.power);
+            return Math.pow(gradient, y);
+        };
+        return PowerEase;
+    })(EasingFunction);
+    BABYLON.PowerEase = PowerEase;
+
+    var QuadraticEase = (function (_super) {
+        __extends(QuadraticEase, _super);
+        function QuadraticEase() {
+            _super.apply(this, arguments);
+        }
+        QuadraticEase.prototype.easeInCore = function (gradient) {
+            return (gradient * gradient);
+        };
+        return QuadraticEase;
+    })(EasingFunction);
+    BABYLON.QuadraticEase = QuadraticEase;
+
+    var QuarticEase = (function (_super) {
+        __extends(QuarticEase, _super);
+        function QuarticEase() {
+            _super.apply(this, arguments);
+        }
+        QuarticEase.prototype.easeInCore = function (gradient) {
+            return (gradient * gradient * gradient * gradient);
+        };
+        return QuarticEase;
+    })(EasingFunction);
+    BABYLON.QuarticEase = QuarticEase;
+
+    var QuinticEase = (function (_super) {
+        __extends(QuinticEase, _super);
+        function QuinticEase() {
+            _super.apply(this, arguments);
+        }
+        QuinticEase.prototype.easeInCore = function (gradient) {
+            return (gradient * gradient * gradient * gradient * gradient);
+        };
+        return QuinticEase;
+    })(EasingFunction);
+    BABYLON.QuinticEase = QuinticEase;
+
+    var SineEase = (function (_super) {
+        __extends(SineEase, _super);
+        function SineEase() {
+            _super.apply(this, arguments);
+        }
+        SineEase.prototype.easeInCore = function (gradient) {
+            return (1.0 - Math.sin(1.5707963267948966 * (1.0 - gradient)));
+        };
+        return SineEase;
+    })(EasingFunction);
+    BABYLON.SineEase = SineEase;
+
+    var BezierCurveEase = (function (_super) {
+        __extends(BezierCurveEase, _super);
+        function BezierCurveEase(x1, y1, x2, y2) {
+            if (typeof x1 === "undefined") { x1 = 0; }
+            if (typeof y1 === "undefined") { y1 = 0; }
+            if (typeof x2 === "undefined") { x2 = 1; }
+            if (typeof y2 === "undefined") { y2 = 1; }
+            _super.call(this);
+            this.x1 = x1;
+            this.y1 = y1;
+            this.x2 = x2;
+            this.y2 = y2;
+        }
+        BezierCurveEase.prototype.easeInCore = function (gradient) {
+            return BABYLON.BezierCurve.interpolate(gradient, this.x1, this.y1, this.x2, this.y2);
+        };
+        return BezierCurveEase;
+    })(EasingFunction);
+    BABYLON.BezierCurveEase = BezierCurveEase;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.easing.js.map

+ 188 - 0
Babylon/Animations/babylon.easing.ts

@@ -0,0 +1,188 @@
+module BABYLON {
+
+    export interface IEasingFunction {
+        ease(gradient: number): number;
+    }
+
+    export class EasingFunction implements IEasingFunction {
+        //Statics
+        private static _EASINGMODE_EASEIN = 0;
+        private static _EASINGMODE_EASEOUT = 1;
+        private static _EASINGMODE_EASEINOUT = 2;
+
+        public static get EASINGMODE_EASEIN(): number {
+            return EasingFunction._EASINGMODE_EASEIN;
+        }
+
+        public static get EASINGMODE_EASEOUT(): number {
+            return EasingFunction._EASINGMODE_EASEOUT;
+        }
+
+        public static get EASINGMODE_EASEINOUT(): number {
+            return EasingFunction._EASINGMODE_EASEINOUT;
+        }
+
+        // Properties
+        private _easingMode = EasingFunction.EASINGMODE_EASEIN;
+
+        public setEasingMode(easingMode: number) {
+            var n = Math.min(Math.max(easingMode, 0), 2);
+            this._easingMode = n;
+        }
+        public getEasingMode(): number {
+            return this._easingMode;
+        }
+
+        public easeInCore(gradient: number): number {
+            throw new Error('You must implement this method');
+        }
+
+        public ease(gradient: number): number {
+            switch (this._easingMode) {
+                case EasingFunction.EASINGMODE_EASEIN:
+                    return this.easeInCore(gradient);
+                case EasingFunction.EASINGMODE_EASEOUT:
+                    return (1 - this.easeInCore(1 - gradient));
+            }
+
+            if (gradient >= 0.5) {
+                return (((1 - this.easeInCore((1 - gradient) * 2)) * 0.5) + 0.5);
+            }
+
+            return (this.easeInCore(gradient * 2) * 0.5);
+        }
+
+    }
+
+    export class CircleEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number {
+            gradient = Math.max(0, Math.min(1, gradient));
+            return (1.0 - Math.sqrt(1.0 - (gradient * gradient)));
+        }
+    }
+
+    export class BackEase extends EasingFunction implements IEasingFunction {
+        constructor(public amplitude: number = 1) {
+            super();
+        }
+
+        public easeInCore(gradient: number): number {
+            var num = Math.max(0, this.amplitude);
+            return (Math.pow(gradient, 3.0) - ((gradient * num) * Math.sin(3.1415926535897931 * gradient)));
+        }
+    }
+
+    export class BounceEase extends EasingFunction implements IEasingFunction {
+        constructor(public bounces: number= 3, public bounciness: number= 2) {
+            super();
+        }
+
+        public easeInCore(gradient: number): number {
+            var y = Math.max(0.0, this.bounces);
+            var bounciness = this.bounciness;
+            if (bounciness <= 1.0) {
+                bounciness = 1.001;
+            }
+            var num9 = Math.pow(bounciness, y);
+            var num5 = 1.0 - bounciness;
+            var num4 = ((1.0 - num9) / num5) + (num9 * 0.5);
+            var num15 = gradient * num4;
+            var num65 = Math.log((-num15 * (1.0 - bounciness)) + 1.0) / Math.log(bounciness);
+            var num3 = Math.floor(num65);
+            var num13 = num3 + 1.0;
+            var num8 = (1.0 - Math.pow(bounciness, num3)) / (num5 * num4);
+            var num12 = (1.0 - Math.pow(bounciness, num13)) / (num5 * num4);
+            var num7 = (num8 + num12) * 0.5;
+            var num6 = gradient - num7;
+            var num2 = num7 - num8;
+            return (((-Math.pow(1.0 / bounciness, y - num3) / (num2 * num2)) * (num6 - num2)) * (num6 + num2));
+        }
+    }
+
+    export class CubicEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number {
+            return (gradient * gradient * gradient);
+        }
+    }
+
+    export class ElasticEase extends EasingFunction implements IEasingFunction {
+        constructor(public oscillations: number= 3, public springiness: number= 3) {
+            super();
+        }
+
+        public easeInCore(gradient: number): number {
+            var num2;
+            var num3 = Math.max(0.0, this.oscillations);
+            var num = Math.max(0.0, this.springiness);
+
+            if (num == 0) {
+                num2 = gradient;
+            }else {
+                num2 = (Math.exp(num * gradient) - 1.0) / (Math.exp(num) - 1.0);
+            }
+            return (num2 * Math.sin(((6.2831853071795862 * num3) + 1.5707963267948966) * gradient));
+        }
+    }
+
+    export class ExponentialEase  extends EasingFunction implements IEasingFunction {
+        constructor(public exponent: number= 2) {
+            super();
+        }
+
+        public easeInCore(gradient: number): number {
+            if (this.exponent <= 0) {
+                return gradient;
+            }
+
+            return ((Math.exp(this.exponent * gradient) - 1.0) / (Math.exp(this.exponent) - 1.0));
+        }
+    }
+
+    export class PowerEase  extends EasingFunction implements IEasingFunction {
+        constructor(public power: number= 2) {
+            super();
+        }
+
+        public easeInCore(gradient: number): number {
+            var y = Math.max(0.0, this.power);
+            return Math.pow(gradient, y);
+        }
+    }
+
+    export class QuadraticEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number {
+            return (gradient * gradient);
+
+           
+
+        }
+    }
+
+    export class QuarticEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number {
+            return (gradient * gradient * gradient * gradient);
+        }
+    }
+
+    export class QuinticEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number {
+            return (gradient * gradient * gradient * gradient * gradient);
+        }
+    }
+
+    export class SineEase  extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number {
+            return (1.0 - Math.sin(1.5707963267948966 * (1.0 - gradient)));
+        }
+    }
+
+    export class BezierCurveEase extends EasingFunction implements IEasingFunction {
+        constructor(public x1: number= 0, public y1: number= 0, public x2: number= 1, public y2: number= 1) {
+            super();
+        }
+
+        public easeInCore(gradient: number): number {
+            return BezierCurve.interpolate(gradient, this.x1, this.y1, this.x2, this.y2);
+        }
+    }
+}

+ 25 - 0
Babylon/Audio/babylon.audioengine.js

@@ -0,0 +1,25 @@
+var BABYLON;
+(function (BABYLON) {
+    // We're mainly based on the logic defined into the FreeCamera code
+    var AudioEngine = (function () {
+        function AudioEngine() {
+            this.audioContext = null;
+            this.canUseWebAudio = true;
+            try  {
+                if (typeof AudioContext !== 'undefined') {
+                    this.audioContext = new AudioContext();
+                } else if (typeof webkitAudioContext !== 'undefined') {
+                    this.audioContext = new webkitAudioContext();
+                } else {
+                    this.canUseWebAudio = false;
+                }
+            } catch (e) {
+                // Web
+                this.canUseWebAudio = false;
+            }
+        }
+        return AudioEngine;
+    })();
+    BABYLON.AudioEngine = AudioEngine;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.audioengine.js.map

+ 46 - 0
Babylon/Audio/babylon.audioengine.ts

@@ -0,0 +1,46 @@
+module BABYLON {
+    export class AudioEngine {
+        public audioContext: AudioContext = null;
+        public canUseWebAudio: boolean = false;
+        public masterGain: GainNode;
+
+        constructor() {
+             // creating the audio context 
+            try {
+                if (typeof AudioContext !== 'undefined') {
+                    this.audioContext = new AudioContext();
+                    this.canUseWebAudio = true;
+                } else if (typeof webkitAudioContext !== 'undefined') {
+                    this.audioContext = new webkitAudioContext();
+                    this.canUseWebAudio = true;
+                } 
+            } catch (e) {
+                this.canUseWebAudio = false;
+            }
+
+            // create a global volume gain node 
+            if (this.canUseWebAudio) {
+                this.masterGain = this.audioContext.createGain();
+                this.masterGain.gain.value = 1;
+                this.masterGain.connect(this.audioContext.destination);
+            }
+        }
+
+        public getGlobalVolume(): number {
+            if (this.canUseWebAudio) {
+                return this.masterGain.gain.value;
+            }
+            else {
+                return -1;
+            }
+        }
+
+        public setGlobalVolume(newVolume: number) {
+            if (this.canUseWebAudio) {
+                this.masterGain.gain.value = newVolume;
+            }
+        }
+    }
+}
+
+

+ 68 - 0
Babylon/Audio/babylon.sound.js

@@ -0,0 +1,68 @@
+var BABYLON;
+(function (BABYLON) {
+    var Sound = (function () {
+        function Sound(url, audioEngine, readyToPlayCallback, distanceMax, autoplay, loop) {
+            var _this = this;
+            this.distanceMax = 10;
+            this.autoplay = false;
+            this.loop = false;
+            this._position = BABYLON.Vector3.Zero();
+            this._isLoaded = false;
+            this._isReadyToPlay = false;
+            this._audioEngine = audioEngine;
+            this._readyToPlayCallback = readyToPlayCallback;
+            if (distanceMax)
+                this.distanceMax = distanceMax;
+            if (autoplay)
+                this.autoplay = autoplay;
+            if (loop)
+                this.loop = loop;
+            if (audioEngine.canUseWebAudio) {
+                BABYLON.Tools.LoadFile(url, function (data) {
+                    _this._soundLoaded(data);
+                }, null, null, true);
+            }
+        }
+        Sound.prototype.setPosition = function (newPosition) {
+            if (this._isReadyToPlay) {
+                this._position = newPosition;
+                this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
+            }
+        };
+
+        Sound.prototype.play = function () {
+            if (this._isReadyToPlay) {
+                this._soundSource = this._audioEngine.audioContext.createBufferSource();
+                this._soundSource.buffer = this._audioBuffer;
+                this._soundPanner = this._audioEngine.audioContext.createPanner();
+                this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
+                this._soundPanner.connect(this._audioEngine.audioContext.destination);
+                this._soundSource.connect(this._soundPanner);
+                this._soundSource.loop = this.loop;
+                this._soundSource.start(0);
+            }
+        };
+
+        Sound.prototype.stop = function () {
+        };
+
+        Sound.prototype.pause = function () {
+        };
+
+        Sound.prototype._soundLoaded = function (audioData) {
+            var _this = this;
+            this._isLoaded = true;
+            this._audioEngine.audioContext.decodeAudioData(audioData, function (buffer) {
+                _this._audioBuffer = buffer;
+                _this._isReadyToPlay = true;
+                if (_this.autoplay)
+                    _this.play();
+                if (_this._readyToPlayCallback)
+                    _this._readyToPlayCallback();
+            }, null);
+        };
+        return Sound;
+    })();
+    BABYLON.Sound = Sound;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.sound.js.map

+ 84 - 0
Babylon/Audio/babylon.sound.ts

@@ -0,0 +1,84 @@
+module BABYLON {
+    export class Sound {
+        private _audioBuffer;
+        public distanceMax: number = 10;
+        public autoplay: boolean = false;
+        public loop: boolean = false;
+        private _position: Vector3 = Vector3.Zero();
+        private _orientation: Vector3 = Vector3.Zero();
+        private _volume: number;
+        private _currentVolume: number;
+        private _isLoaded: boolean = false;
+        private _isReadyToPlay: boolean = false;
+        private _audioEngine: BABYLON.AudioEngine;
+        private _readyToPlayCallback;
+        private _soundSource: AudioBufferSourceNode;
+        private _soundPanner: PannerNode;
+
+        constructor(url: string, engine: BABYLON.Engine, readyToPlayCallback, distanceMax?: number, autoplay?: boolean, loop?: boolean) {
+            this._audioEngine = engine.getAudioEngine();;
+            this._readyToPlayCallback = readyToPlayCallback;
+            if (distanceMax) this.distanceMax = distanceMax;
+            if (autoplay) this.autoplay = autoplay;
+            if (loop) this.loop = loop;
+            if (this._audioEngine.canUseWebAudio) {
+                BABYLON.Tools.LoadFile(url, (data) => { this._soundLoaded(data); }, null, null, true);
+            }
+        }
+
+        public setPosition(newPosition: Vector3) {
+            this._position = newPosition;
+
+            if (this._isReadyToPlay) {    
+                this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
+            }
+        }
+
+        public setOrientiation(newOrientation: Vector3) {
+            this._orientation = newOrientation;
+
+            if (this._isReadyToPlay) {
+                this._soundPanner.setOrientation(this._orientation.x, this._orientation.y, this._orientation.z);
+            }
+        }
+
+        public play() {
+            if (this._isReadyToPlay) {
+                this._soundSource = this._audioEngine.audioContext.createBufferSource();
+                this._soundSource.buffer = this._audioBuffer;
+                this._soundPanner = this._audioEngine.audioContext.createPanner();
+                this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
+                this._soundPanner.connect(this._audioEngine.masterGain);
+                this._soundSource.connect(this._soundPanner);
+                this._soundSource.loop = this.loop;
+                this._soundSource.start(0);
+            }
+        }
+        
+        public stop() {
+        }   
+
+        public pause() {
+        }
+
+        public attachToMesh(meshToConnectTo: BABYLON.AbstractMesh) {
+            meshToConnectTo.registerAfterWorldMatrixUpdate((connectedMesh: BABYLON.AbstractMesh) => this._onRegisterAfterWorldMatrixUpdate(connectedMesh));
+        }
+
+        private _onRegisterAfterWorldMatrixUpdate(connectedMesh: BABYLON.AbstractMesh) {
+            this.setPosition(connectedMesh.position);
+        }
+
+        private _soundLoaded(audioData: ArrayBuffer) {
+            this._isLoaded = true;
+            this._audioEngine.audioContext.decodeAudioData(audioData, (buffer) => {
+                this._audioBuffer = buffer;
+                this._isReadyToPlay = true;
+                if (this.autoplay) this.play();
+                if (this._readyToPlayCallback) this._readyToPlayCallback();
+            }, function (error) {
+                BABYLON.Tools.Error("Error while decoding audio data: " + error.err);
+            });
+        }
+    }
+}

+ 3 - 3
Babylon/Loading/babylon.sceneLoader.ts

@@ -52,7 +52,7 @@
             SceneLoader._registeredPlugins.push(plugin);
         }
 
-        public static ImportMesh(meshesNames: any, rootUrl: string, sceneFilename: string, scene: Scene, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, progressCallBack?: () => void, onerror?: (scene: Scene) => void): void {
+        public static ImportMesh(meshesNames: any, rootUrl: string, sceneFilename: string, scene: Scene, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, progressCallBack?: () => void, onerror?: (scene: Scene, e:any) => void): void {
             var manifestChecked = success => {
                 scene.database = database;
 
@@ -66,14 +66,14 @@
                     try {
                         if (!plugin.importMesh(meshesNames, scene, data, rootUrl, meshes, particleSystems, skeletons)) {
                             if (onerror) {
-                                onerror(scene);
+                                onerror(scene, 'unable to load the scene');
                             }
 
                             return;
                         }
                     } catch (e) {
                         if (onerror) {
-                            onerror(scene);
+                            onerror(scene, e);
                         }
 
                         return;

+ 25 - 16
Babylon/Materials/textures/Procedurals/babylon.customProceduralTexture.js

@@ -10,9 +10,10 @@ var BABYLON;
         __extends(CustomProceduralTexture, _super);
         function CustomProceduralTexture(name, texturePath, size, scene, fallbackTexture, generateMipMaps) {
             _super.call(this, name, size, "empty", scene, fallbackTexture, generateMipMaps);
-            this._generateTime = true;
+            this._animate = true;
             this._time = 0;
             this._shaderLoaded = false;
+            this._updateTexture = false;
 
             this._texturePath = texturePath;
 
@@ -20,17 +21,15 @@ var BABYLON;
             this.loadJson(texturePath);
 
             // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
-            this.refreshRate = 0;
+            this.refreshRate = 1;
         }
         CustomProceduralTexture.prototype.loadJson = function (jsonUrl) {
-            var _this = this;
             function noConfigFile() {
                 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);
@@ -38,13 +37,8 @@ var BABYLON;
                 if (xhr.status === 200 || BABYLON.Tools.ValidateXHRData(xhr, 1)) {
                     try  {
                         that._config = JSON.parse(xhr.response);
-                        that.updateShaderUniforms();
-                        that.setFragment(jsonUrl + "/custom");
-                        that._generateTime = that._config.generateTime;
-                        if (that._generateTime)
-                            _this.refreshRate = 1;
+                        that._updateTexture = true;
                         that._shaderLoaded = true;
-                        that.render();
                     } catch (ex) {
                         noConfigFile();
                     }
@@ -69,7 +63,20 @@ var BABYLON;
             if (!this._shaderLoaded)
                 return;
 
-            if (this._generateTime) {
+            if (this._updateTexture) {
+                this.reset();
+                this.setFragment(this._texturePath + "/custom");
+                this.updateTextures();
+                this.updateShaderUniforms();
+                this._shaderLoaded = true;
+                this._animate = this._config.animate;
+                this.refreshRate = this._config.refreshrate;
+                this.isReady();
+                this._updateTexture = false;
+                return;
+            }
+
+            if (this._animate) {
                 this._time += this.getScene().getAnimationRatio() * 0.03;
                 this.updateShaderUniforms();
             }
@@ -77,11 +84,13 @@ var BABYLON;
             _super.prototype.render.call(this, useCameraPostProcess);
         };
 
-        CustomProceduralTexture.prototype.updateShaderUniforms = function () {
+        CustomProceduralTexture.prototype.updateTextures = 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()));
+                this.setTexture(this._config.texture2Ds[i].textureName, new BABYLON.Texture(this._texturePath + "/" + this._config.texture2Ds[i].textureRelativeUrl, this.getScene(), false, false, BABYLON.Texture.TRILINEAR_SAMPLINGMODE, null, null, null, true));
             }
+        };
 
+        CustomProceduralTexture.prototype.updateShaderUniforms = function () {
             for (var j = 0; j < this._config.uniforms.length; j++) {
                 var uniform = this._config.uniforms[j];
 
@@ -105,12 +114,12 @@ var BABYLON;
             }
         };
 
-        Object.defineProperty(CustomProceduralTexture.prototype, "generateTime", {
+        Object.defineProperty(CustomProceduralTexture.prototype, "animate", {
             get: function () {
-                return this.generateTime;
+                return this._animate;
             },
             set: function (value) {
-                this.generateTime = value;
+                this._animate = value;
                 this.updateShaderUniforms();
             },
             enumerable: true,

+ 26 - 22
Babylon/Materials/textures/Procedurals/babylon.customProceduralTexture.ts

@@ -1,11 +1,12 @@
 module BABYLON {
     export class CustomProceduralTexture extends ProceduralTexture {
 
-        private _generateTime: boolean = true;
+        private _animate: boolean = true;
         private _time: number = 0;
         private _shaderLoaded: boolean = false;
         private _config: any;
         private _texturePath: string;
+        private _updateTexture: boolean = false;
 
         constructor(name: string, texturePath: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {
             super(name, size, "empty", scene, fallbackTexture, generateMipMaps);
@@ -16,33 +17,25 @@
             this.loadJson(texturePath);
 
             // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
-            this.refreshRate = 0;
-
+            this.refreshRate = 1;
         }
 
         private loadJson(jsonUrl: string) {
-
             function noConfigFile() {
                 BABYLON.Tools.Log("No config file found in " + jsonUrl);
             }
 
             var that = this;
             var configFileUrl = jsonUrl + "/config.json";
-
             var xhr: XMLHttpRequest = new XMLHttpRequest();
 
             xhr.open("GET", configFileUrl, true);
-            xhr.addEventListener("load", () => {
+            xhr.addEventListener("load", function () {
                 if (xhr.status === 200 || BABYLON.Tools.ValidateXHRData(xhr, 1)) {
                     try {
                         that._config = JSON.parse(xhr.response);
-                        that.updateShaderUniforms();
-                        that.setFragment(jsonUrl + "/custom");
-                        that._generateTime = that._config.generateTime;
-                        if (that._generateTime)
-                            this.refreshRate = 1;
+                        that._updateTexture = true;
                         that._shaderLoaded = true;
-                        that.render();
                     }
                     catch (ex) {
                         noConfigFile();
@@ -66,13 +59,24 @@
         }
 
         public render(useCameraPostProcess?: boolean) {
-
             //if config and shader not loaded, do not render
             if (!this._shaderLoaded)
                 return;
 
+            if (this._updateTexture) {
+                this.reset();
+                this.setFragment(this._texturePath + "/custom")
+                this.updateTextures();
+                this.updateShaderUniforms();
+                this._shaderLoaded = true;
+                this._animate = this._config.animate;
+                this.refreshRate = this._config.refreshrate;
+                this.isReady();
+                this._updateTexture = false;
+                return;
+            }
 
-            if (this._generateTime) {
+            if (this._animate) {
                 this._time += this.getScene().getAnimationRatio() * 0.03;
                 this.updateShaderUniforms();
             }
@@ -80,12 +84,13 @@
             super.render(useCameraPostProcess);
         }
 
-        public updateShaderUniforms() {
-
+        public updateTextures() {
             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()));
+                this.setTexture(this._config.texture2Ds[i].textureName, new BABYLON.Texture(this._texturePath + "/" + this._config.texture2Ds[i].textureRelativeUrl, this.getScene(), false, false, Texture.TRILINEAR_SAMPLINGMODE, null, null, null, true));
             }
+        }
 
+        public updateShaderUniforms() {
             for (var j = 0; j < this._config.uniforms.length; j++) {
                 var uniform = this._config.uniforms[j];
 
@@ -109,14 +114,13 @@
             }
         }
 
-        public get generateTime(): boolean {
-            return this.generateTime;
+        public get animate(): boolean {
+            return this._animate;
         }
 
-        public set generateTime(value: boolean) {
-            this.generateTime = value;
+        public set animate(value: boolean) {
+            this._animate = value;
             this.updateShaderUniforms();
         }
-
     }
 }

+ 5 - 0
Babylon/Materials/textures/Procedurals/babylon.proceduralTexture.js

@@ -59,6 +59,11 @@ var BABYLON;
 
             this._indexBuffer = scene.getEngine().createIndexBuffer(indices);
         }
+        ProceduralTexture.prototype.reset = function () {
+            var engine = this.getScene().getEngine();
+            engine._releaseEffect(this._effect);
+        };
+
         ProceduralTexture.prototype.isReady = function () {
             var _this = this;
             var engine = this.getScene().getEngine();

+ 5 - 0
Babylon/Materials/textures/Procedurals/babylon.proceduralTexture.ts

@@ -66,6 +66,11 @@
             this._indexBuffer = scene.getEngine().createIndexBuffer(indices);
         }
 
+        public reset(): void {
+            var engine = this.getScene().getEngine();
+            engine._releaseEffect(this._effect);
+        }
+
       
         public isReady(): boolean {
             var engine = this.getScene().getEngine();

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

@@ -2494,5 +2494,32 @@
     })();
     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

+ 31 - 0
Babylon/Math/babylon.math.ts

@@ -403,6 +403,7 @@
             return new Vector2(x, y);
         }
 
+     
         public static Dot(left: Vector2, right: Vector2): number {
             return left.x * right.x + left.y * right.y;
         }
@@ -444,6 +445,7 @@
 
             return (x * x) + (y * y);
         }
+
     }
 
     export class Vector3 {
@@ -2484,4 +2486,33 @@
         public static Y: Vector3 = new BABYLON.Vector3(0, 1, 0);
         public static Z: Vector3 = new BABYLON.Vector3(0, 0, 1);
     };
+
+    export class BezierCurve {
+
+        public static interpolate(t: number, x1: number, y1: number, x2: number, y2: number) :number {
+
+            // 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);
+
+        }
+    }
 }

+ 25 - 0
Babylon/Mesh/babylon.abstractMesh.ts

@@ -97,6 +97,8 @@
         public _submeshesOctree: Octree<SubMesh>;
         public _intersectionsInProgress = new Array<AbstractMesh>();
 
+        private _onAfterWorldMatrixUpdate = new Array<(mesh: BABYLON.AbstractMesh) => void>();
+
         constructor(name: string, scene: Scene) {
             super(name, scene);
 
@@ -395,9 +397,30 @@
             // Absolute position
             this._absolutePosition.copyFromFloats(this._worldMatrix.m[12], this._worldMatrix.m[13], this._worldMatrix.m[14]);
 
+            // Callbacks
+            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
+        */
+        public registerAfterWorldMatrixUpdate(func: (mesh: BABYLON.AbstractMesh) => void): void {
+            this._onAfterWorldMatrixUpdate.push(func);
+        }
+
+        public unregisterAfterWorldMatrixUpdate(func: (mesh: BABYLON.AbstractMesh) => void): void {
+            var index = this._onAfterWorldMatrixUpdate.indexOf(func);
+
+            if (index > -1) {
+                this._onAfterWorldMatrixUpdate.splice(index, 1);
+            }
+        }
+
         public setPositionWithLocalVector(vector3: Vector3): void {
             this.computeWorldMatrix();
 
@@ -818,6 +841,8 @@
                 }
             }
 
+            this._onAfterWorldMatrixUpdate = [];
+
             this._isDisposed = true;
 
             // Callback

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

@@ -304,6 +304,7 @@ 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);
@@ -325,6 +326,7 @@ var BABYLON;
                             mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
                         }
                         mesh.rotationQuaternion.fromRotationMatrix(mtx);
+                        mesh.computeWorldMatrix();
                     }
                 }
             }

+ 6 - 0
Babylon/babylon.engine.js

@@ -471,6 +471,8 @@
             document.addEventListener("mspointerlockchange", this._onPointerLockChange, false);
             document.addEventListener("mozpointerlockchange", this._onPointerLockChange, false);
             document.addEventListener("webkitpointerlockchange", this._onPointerLockChange, false);
+
+            this._audioEngine = new BABYLON.AudioEngine();
         }
         Object.defineProperty(Engine, "ALPHA_DISABLE", {
             get: function () {
@@ -536,6 +538,10 @@
             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);

+ 8 - 1
Babylon/babylon.engine.ts

@@ -12,7 +12,6 @@
         private _cull: boolean;
         private _cullFace: number;
 
-
         public get isDirty(): boolean {
             return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty;
         }
@@ -355,6 +354,8 @@
         private static _DELAYLOADSTATE_LOADING = 2;
         private static _DELAYLOADSTATE_NOTLOADED = 4;
 
+        private _audioEngine: BABYLON.AudioEngine;
+
         public static get ALPHA_DISABLE(): number {
             return Engine._ALPHA_DISABLE;
         }
@@ -547,6 +548,12 @@
             document.addEventListener("mspointerlockchange", this._onPointerLockChange, false);
             document.addEventListener("mozpointerlockchange", this._onPointerLockChange, false);
             document.addEventListener("webkitpointerlockchange", this._onPointerLockChange, false);
+
+            this._audioEngine = new BABYLON.AudioEngine();
+        }
+
+        public getAudioEngine(): AudioEngine {
+            return this._audioEngine;
         }
 
         public getAspectRatio(camera: Camera): number {

+ 24 - 0
Babylon/babylon.scene.js

@@ -1089,6 +1089,9 @@
             // Intersection checks
             this._checkIntersections();
 
+            // Update the audio listener attached to the camera
+            this._updateAudioParameters();
+
             // After render
             if (this.afterRender) {
                 this.afterRender();
@@ -1105,6 +1108,25 @@
             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);
+            }
+        };
+
         Scene.prototype.dispose = function () {
             this.beforeRender = null;
             this.afterRender = null;
@@ -1118,6 +1140,8 @@
                 this.onDispose();
             }
 
+            this._onBeforeRenderCallbacks = [];
+
             this.detachControl();
 
             // Detach cameras

+ 25 - 0
Babylon/babylon.scene.ts

@@ -1167,6 +1167,9 @@
             // Intersection checks
             this._checkIntersections();
 
+            // Update the audio listener attached to the camera
+            this._updateAudioParameters();
+
             // After render
             if (this.afterRender) {
                 this.afterRender();
@@ -1185,6 +1188,26 @@
             this._lastFrameDuration = Tools.Now - startDate;
         }
 
+        private _updateAudioParameters() {
+            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);
+            }
+
+        }
+
         public dispose(): void {
             this.beforeRender = null;
             this.afterRender = null;
@@ -1198,6 +1221,8 @@
                 this.onDispose();
             }
 
+            this._onBeforeRenderCallbacks = [];
+
             this.detachControl();
 
             // Detach cameras

+ 495 - 22
babylon.2.0-alpha.debug.js

@@ -2494,6 +2494,33 @@ var BABYLON;
     })();
     BABYLON.Axis = Axis;
     ;
+
+    var BezierCurve = (function () {
+        function BezierCurve() {
+        }
+        BezierCurve.interpolate = function (t, x1, y1, x2, y2) {
+           
+            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));
+            }
+
+           
+            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 = {}));
 var BABYLON;
 (function (BABYLON) {
@@ -9879,6 +9906,7 @@ var BABYLON;
             this._isDisposed = false;
             this._renderId = 0;
             this._intersectionsInProgress = new Array();
+            this._onAfterWorldMatrixUpdate = new Array();
 
             scene.meshes.push(this);
         }
@@ -10222,9 +10250,29 @@ var BABYLON;
            
             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 or rotation 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();
 
@@ -10643,6 +10691,10 @@ var BABYLON;
                 }
             }
 
+            while (this._onAfterWorldMatrixUpdate.length > 0) {
+                this._onAfterWorldMatrixUpdate.pop();
+            }
+
             this._isDisposed = true;
 
            
@@ -13088,6 +13140,11 @@ var BABYLON;
 
             this._indexBuffer = scene.getEngine().createIndexBuffer(indices);
         }
+        ProceduralTexture.prototype.reset = function () {
+            var engine = this.getScene().getEngine();
+            engine._releaseEffect(this._effect);
+        };
+
         ProceduralTexture.prototype.isReady = function () {
             var _this = this;
             var engine = this.getScene().getEngine();
@@ -13714,9 +13771,10 @@ var BABYLON;
         __extends(CustomProceduralTexture, _super);
         function CustomProceduralTexture(name, texturePath, size, scene, fallbackTexture, generateMipMaps) {
             _super.call(this, name, size, "empty", scene, fallbackTexture, generateMipMaps);
-            this._generateTime = true;
+            this._animate = true;
             this._time = 0;
             this._shaderLoaded = false;
+            this._updateTexture = false;
 
             this._texturePath = texturePath;
 
@@ -13724,17 +13782,15 @@ var BABYLON;
             this.loadJson(texturePath);
 
            
-            this.refreshRate = 0;
+            this.refreshRate = 1;
         }
         CustomProceduralTexture.prototype.loadJson = function (jsonUrl) {
-            var _this = this;
             function noConfigFile() {
                 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);
@@ -13742,13 +13798,8 @@ var BABYLON;
                 if (xhr.status === 200 || BABYLON.Tools.ValidateXHRData(xhr, 1)) {
                     try  {
                         that._config = JSON.parse(xhr.response);
-                        that.updateShaderUniforms();
-                        that.setFragment(jsonUrl + "/custom");
-                        that._generateTime = that._config.generateTime;
-                        if (that._generateTime)
-                            _this.refreshRate = 1;
+                        that._updateTexture = true;
                         that._shaderLoaded = true;
-                        that.render();
                     } catch (ex) {
                         noConfigFile();
                     }
@@ -13773,7 +13824,20 @@ var BABYLON;
             if (!this._shaderLoaded)
                 return;
 
-            if (this._generateTime) {
+            if (this._updateTexture) {
+                this.reset();
+                this.setFragment(this._texturePath + "/custom");
+                this.updateTextures();
+                this.updateShaderUniforms();
+                this._shaderLoaded = true;
+                this._animate = this._config.animate;
+                this.refreshRate = this._config.refreshrate;
+                this.isReady();
+                this._updateTexture = false;
+                return;
+            }
+
+            if (this._animate) {
                 this._time += this.getScene().getAnimationRatio() * 0.03;
                 this.updateShaderUniforms();
             }
@@ -13781,11 +13845,13 @@ var BABYLON;
             _super.prototype.render.call(this, useCameraPostProcess);
         };
 
-        CustomProceduralTexture.prototype.updateShaderUniforms = function () {
+        CustomProceduralTexture.prototype.updateTextures = 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()));
+                this.setTexture(this._config.texture2Ds[i].textureName, new BABYLON.Texture(this._texturePath + "/" + this._config.texture2Ds[i].textureRelativeUrl, this.getScene(), false, false, BABYLON.Texture.TRILINEAR_SAMPLINGMODE, null, null, null, true));
             }
+        };
 
+        CustomProceduralTexture.prototype.updateShaderUniforms = function () {
             for (var j = 0; j < this._config.uniforms.length; j++) {
                 var uniform = this._config.uniforms[j];
 
@@ -13809,12 +13875,12 @@ var BABYLON;
             }
         };
 
-        Object.defineProperty(CustomProceduralTexture.prototype, "generateTime", {
+        Object.defineProperty(CustomProceduralTexture.prototype, "animate", {
             get: function () {
-                return this.generateTime;
+                return this._animate;
             },
             set: function (value) {
-                this.generateTime = value;
+                this._animate = value;
                 this.updateShaderUniforms();
             },
             enumerable: true,
@@ -16679,6 +16745,37 @@ var BABYLON;
             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));
+        };
+
        
         Animation.prototype.isStopped = function () {
             return this._stopped;
@@ -16688,6 +16785,14 @@ var BABYLON;
             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;
         };
@@ -16730,11 +16835,19 @@ var BABYLON;
             this.currentFrame = currentFrame;
 
             for (var key = 0; key < this._keys.length; key++) {
+               
                 if (this._keys[key + 1].frame >= currentFrame) {
                     var startValue = this._keys[key].value;
                     var endValue = this._keys[key + 1].value;
+
+                   
                     var gradient = (currentFrame - this._keys[key].frame) / (this._keys[key + 1].frame - this._keys[key].frame);
 
+                   
+                    if (this._easingFunction != null) {
+                        gradient = this._easingFunction.ease(gradient);
+                    }
+
                     switch (this.dataType) {
                         case Animation.ANIMATIONTYPE_FLOAT:
                             switch (loopMode) {
@@ -16808,16 +16921,11 @@ var BABYLON;
                 this._stopped = true;
                 return false;
             }
-
             var returnValue = true;
 
            
             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);
             }
 
@@ -16832,6 +16940,8 @@ var BABYLON;
            
             var range = to - from;
             var offsetValue;
+
+           
             var ratio = delay * (this.framePerSecond * speedRatio) / 1000.0;
 
             if (ratio > range && !loop) {
@@ -16840,6 +16950,7 @@ var BABYLON;
             } else {
                
                 var highLimitValue = 0;
+
                 if (this.loopMode != Animation.ANIMATIONLOOPMODE_CYCLE) {
                     var keyOffset = to.toString() + from.toString();
                     if (!this._offsetsCache[keyOffset]) {
@@ -17114,6 +17225,275 @@ var BABYLON;
     })();
     BABYLON.Animatable = Animatable;
 })(BABYLON || (BABYLON = {}));
+var __extends = this.__extends || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    __.prototype = b.prototype;
+    d.prototype = new __();
+};
+var BABYLON;
+(function (BABYLON) {
+    var EasingFunction = (function () {
+        function EasingFunction() {
+           
+            this._easingMode = EasingFunction.EASINGMODE_EASEIN;
+        }
+        Object.defineProperty(EasingFunction, "EASINGMODE_EASEIN", {
+            get: function () {
+                return EasingFunction._EASINGMODE_EASEIN;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(EasingFunction, "EASINGMODE_EASEOUT", {
+            get: function () {
+                return EasingFunction._EASINGMODE_EASEOUT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        Object.defineProperty(EasingFunction, "EASINGMODE_EASEINOUT", {
+            get: function () {
+                return EasingFunction._EASINGMODE_EASEINOUT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+
+        EasingFunction.prototype.setEasingMode = function (easingMode) {
+            var n = Math.min(Math.max(easingMode, 0), 2);
+            this._easingMode = n;
+        };
+        EasingFunction.prototype.getEasingMode = function () {
+            return this._easingMode;
+        };
+
+        EasingFunction.prototype.easeInCore = function (gradient) {
+            throw new Error('You must implement this method');
+        };
+
+        EasingFunction.prototype.ease = function (gradient) {
+            switch (this._easingMode) {
+                case EasingFunction.EASINGMODE_EASEIN:
+                    return this.easeInCore(gradient);
+                case EasingFunction.EASINGMODE_EASEOUT:
+                    return (1 - this.easeInCore(1 - gradient));
+            }
+
+            if (gradient >= 0.5) {
+                return (((1 - this.easeInCore((1 - gradient) * 2)) * 0.5) + 0.5);
+            }
+
+            return (this.easeInCore(gradient * 2) * 0.5);
+        };
+        EasingFunction._EASINGMODE_EASEIN = 0;
+        EasingFunction._EASINGMODE_EASEOUT = 1;
+        EasingFunction._EASINGMODE_EASEINOUT = 2;
+        return EasingFunction;
+    })();
+    BABYLON.EasingFunction = EasingFunction;
+
+    var CircleEase = (function (_super) {
+        __extends(CircleEase, _super);
+        function CircleEase() {
+            _super.apply(this, arguments);
+        }
+        CircleEase.prototype.easeInCore = function (gradient) {
+            gradient = Math.max(0, Math.min(1, gradient));
+            return (1.0 - Math.sqrt(1.0 - (gradient * gradient)));
+        };
+        return CircleEase;
+    })(EasingFunction);
+    BABYLON.CircleEase = CircleEase;
+
+    var BackEase = (function (_super) {
+        __extends(BackEase, _super);
+        function BackEase(amplitude) {
+            if (typeof amplitude === "undefined") { amplitude = 1; }
+            _super.call(this);
+            this.amplitude = amplitude;
+        }
+        BackEase.prototype.easeInCore = function (gradient) {
+            var num = Math.max(0, this.amplitude);
+            return (Math.pow(gradient, 3.0) - ((gradient * num) * Math.sin(3.1415926535897931 * gradient)));
+        };
+        return BackEase;
+    })(EasingFunction);
+    BABYLON.BackEase = BackEase;
+
+    var BounceEase = (function (_super) {
+        __extends(BounceEase, _super);
+        function BounceEase(bounces, bounciness) {
+            if (typeof bounces === "undefined") { bounces = 3; }
+            if (typeof bounciness === "undefined") { bounciness = 2; }
+            _super.call(this);
+            this.bounces = bounces;
+            this.bounciness = bounciness;
+        }
+        BounceEase.prototype.easeInCore = function (gradient) {
+            var y = Math.max(0.0, this.bounces);
+            var bounciness = this.bounciness;
+            if (bounciness <= 1.0) {
+                bounciness = 1.001;
+            }
+            var num9 = Math.pow(bounciness, y);
+            var num5 = 1.0 - bounciness;
+            var num4 = ((1.0 - num9) / num5) + (num9 * 0.5);
+            var num15 = gradient * num4;
+            var num65 = Math.log((-num15 * (1.0 - bounciness)) + 1.0) / Math.log(bounciness);
+            var num3 = Math.floor(num65);
+            var num13 = num3 + 1.0;
+            var num8 = (1.0 - Math.pow(bounciness, num3)) / (num5 * num4);
+            var num12 = (1.0 - Math.pow(bounciness, num13)) / (num5 * num4);
+            var num7 = (num8 + num12) * 0.5;
+            var num6 = gradient - num7;
+            var num2 = num7 - num8;
+            return (((-Math.pow(1.0 / bounciness, y - num3) / (num2 * num2)) * (num6 - num2)) * (num6 + num2));
+        };
+        return BounceEase;
+    })(EasingFunction);
+    BABYLON.BounceEase = BounceEase;
+
+    var CubicEase = (function (_super) {
+        __extends(CubicEase, _super);
+        function CubicEase() {
+            _super.apply(this, arguments);
+        }
+        CubicEase.prototype.easeInCore = function (gradient) {
+            return (gradient * gradient * gradient);
+        };
+        return CubicEase;
+    })(EasingFunction);
+    BABYLON.CubicEase = CubicEase;
+
+    var ElasticEase = (function (_super) {
+        __extends(ElasticEase, _super);
+        function ElasticEase(oscillations, springiness) {
+            if (typeof oscillations === "undefined") { oscillations = 3; }
+            if (typeof springiness === "undefined") { springiness = 3; }
+            _super.call(this);
+            this.oscillations = oscillations;
+            this.springiness = springiness;
+        }
+        ElasticEase.prototype.easeInCore = function (gradient) {
+            var num2;
+            var num3 = Math.max(0.0, this.oscillations);
+            var num = Math.max(0.0, this.springiness);
+
+            if (num == 0) {
+                num2 = gradient;
+            } else {
+                num2 = (Math.exp(num * gradient) - 1.0) / (Math.exp(num) - 1.0);
+            }
+            return (num2 * Math.sin(((6.2831853071795862 * num3) + 1.5707963267948966) * gradient));
+        };
+        return ElasticEase;
+    })(EasingFunction);
+    BABYLON.ElasticEase = ElasticEase;
+
+    var ExponentialEase = (function (_super) {
+        __extends(ExponentialEase, _super);
+        function ExponentialEase(exponent) {
+            if (typeof exponent === "undefined") { exponent = 2; }
+            _super.call(this);
+            this.exponent = exponent;
+        }
+        ExponentialEase.prototype.easeInCore = function (gradient) {
+            if (this.exponent <= 0) {
+                return gradient;
+            }
+
+            return ((Math.exp(this.exponent * gradient) - 1.0) / (Math.exp(this.exponent) - 1.0));
+        };
+        return ExponentialEase;
+    })(EasingFunction);
+    BABYLON.ExponentialEase = ExponentialEase;
+
+    var PowerEase = (function (_super) {
+        __extends(PowerEase, _super);
+        function PowerEase(power) {
+            if (typeof power === "undefined") { power = 2; }
+            _super.call(this);
+            this.power = power;
+        }
+        PowerEase.prototype.easeInCore = function (gradient) {
+            var y = Math.max(0.0, this.power);
+            return Math.pow(gradient, y);
+        };
+        return PowerEase;
+    })(EasingFunction);
+    BABYLON.PowerEase = PowerEase;
+
+    var QuadraticEase = (function (_super) {
+        __extends(QuadraticEase, _super);
+        function QuadraticEase() {
+            _super.apply(this, arguments);
+        }
+        QuadraticEase.prototype.easeInCore = function (gradient) {
+            return (gradient * gradient);
+        };
+        return QuadraticEase;
+    })(EasingFunction);
+    BABYLON.QuadraticEase = QuadraticEase;
+
+    var QuarticEase = (function (_super) {
+        __extends(QuarticEase, _super);
+        function QuarticEase() {
+            _super.apply(this, arguments);
+        }
+        QuarticEase.prototype.easeInCore = function (gradient) {
+            return (gradient * gradient * gradient * gradient);
+        };
+        return QuarticEase;
+    })(EasingFunction);
+    BABYLON.QuarticEase = QuarticEase;
+
+    var QuinticEase = (function (_super) {
+        __extends(QuinticEase, _super);
+        function QuinticEase() {
+            _super.apply(this, arguments);
+        }
+        QuinticEase.prototype.easeInCore = function (gradient) {
+            return (gradient * gradient * gradient * gradient * gradient);
+        };
+        return QuinticEase;
+    })(EasingFunction);
+    BABYLON.QuinticEase = QuinticEase;
+
+    var SineEase = (function (_super) {
+        __extends(SineEase, _super);
+        function SineEase() {
+            _super.apply(this, arguments);
+        }
+        SineEase.prototype.easeInCore = function (gradient) {
+            return (1.0 - Math.sin(1.5707963267948966 * (1.0 - gradient)));
+        };
+        return SineEase;
+    })(EasingFunction);
+    BABYLON.SineEase = SineEase;
+
+    var BezierCurveEase = (function (_super) {
+        __extends(BezierCurveEase, _super);
+        function BezierCurveEase(x1, y1, x2, y2) {
+            if (typeof x1 === "undefined") { x1 = 0; }
+            if (typeof y1 === "undefined") { y1 = 0; }
+            if (typeof x2 === "undefined") { x2 = 1; }
+            if (typeof y2 === "undefined") { y2 = 1; }
+            _super.call(this);
+            this.x1 = x1;
+            this.y1 = y1;
+            this.x2 = x2;
+            this.y2 = y2;
+        }
+        BezierCurveEase.prototype.easeInCore = function (gradient) {
+            return BABYLON.BezierCurve.interpolate(gradient, this.x1, this.y1, this.x2, this.y2);
+        };
+        return BezierCurveEase;
+    })(EasingFunction);
+    BABYLON.BezierCurveEase = BezierCurveEase;
+})(BABYLON || (BABYLON = {}));
 var BABYLON;
 (function (BABYLON) {
     var Octree = (function () {
@@ -18688,6 +19068,7 @@ 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);
@@ -18709,6 +19090,7 @@ var BABYLON;
                             mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
                         }
                         mesh.rotationQuaternion.fromRotationMatrix(mtx);
+                        mesh.computeWorldMatrix();
                     }
                 }
             }
@@ -28170,3 +28552,94 @@ var BABYLON;
     })(BABYLON.Internals || (BABYLON.Internals = {}));
     var Internals = BABYLON.Internals;
 })(BABYLON || (BABYLON = {}));
+var BABYLON;
+(function (BABYLON) {
+   
+    var AudioEngine = (function () {
+        function AudioEngine() {
+            this.audioContext = null;
+            this.canUseWebAudio = true;
+            try  {
+                if (typeof AudioContext !== 'undefined') {
+                    this.audioContext = new AudioContext();
+                } else if (typeof webkitAudioContext !== 'undefined') {
+                    this.audioContext = new webkitAudioContext();
+                } else {
+                    this.canUseWebAudio = false;
+                }
+            } catch (e) {
+               
+                this.canUseWebAudio = false;
+            }
+        }
+        return AudioEngine;
+    })();
+    BABYLON.AudioEngine = AudioEngine;
+})(BABYLON || (BABYLON = {}));
+var BABYLON;
+(function (BABYLON) {
+    var Sound = (function () {
+        function Sound(url, audioEngine, readyToPlayCallback, distanceMax, autoplay, loop) {
+            var _this = this;
+            this.distanceMax = 10;
+            this.autoplay = false;
+            this.loop = false;
+            this._position = BABYLON.Vector3.Zero();
+            this._isLoaded = false;
+            this._isReadyToPlay = false;
+            this._audioEngine = audioEngine;
+            this._readyToPlayCallback = readyToPlayCallback;
+            if (distanceMax)
+                this.distanceMax = distanceMax;
+            if (autoplay)
+                this.autoplay = autoplay;
+            if (loop)
+                this.loop = loop;
+            if (audioEngine.canUseWebAudio) {
+                BABYLON.Tools.LoadFile(url, function (data) {
+                    _this._soundLoaded(data);
+                }, null, null, true);
+            }
+        }
+        Sound.prototype.setPosition = function (newPosition) {
+            if (this._isReadyToPlay) {
+                this._position = newPosition;
+                this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
+            }
+        };
+
+        Sound.prototype.play = function () {
+            if (this._isReadyToPlay) {
+                this._soundSource = this._audioEngine.audioContext.createBufferSource();
+                this._soundSource.buffer = this._audioBuffer;
+                this._soundPanner = this._audioEngine.audioContext.createPanner();
+                this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
+                this._soundPanner.connect(this._audioEngine.audioContext.destination);
+                this._soundSource.connect(this._soundPanner);
+                this._soundSource.loop = this.loop;
+                this._soundSource.start(0);
+            }
+        };
+
+        Sound.prototype.stop = function () {
+        };
+
+        Sound.prototype.pause = function () {
+        };
+
+        Sound.prototype._soundLoaded = function (audioData) {
+            var _this = this;
+            this._isLoaded = true;
+            this._audioEngine.audioContext.decodeAudioData(audioData, function (buffer) {
+                _this._audioBuffer = buffer;
+                _this._isReadyToPlay = true;
+                if (_this.autoplay)
+                    _this.play();
+                if (_this._readyToPlayCallback)
+                    _this._readyToPlayCallback();
+            }, null);
+        };
+        return Sound;
+    })();
+    BABYLON.Sound = Sound;
+})(BABYLON || (BABYLON = {}));

Разница между файлами не показана из-за своего большого размера
+ 14 - 14
babylon.2.0-alpha.js


+ 173 - 2
babylon.2.0.d.ts

@@ -51,6 +51,7 @@ declare module BABYLON {
         private static _DELAYLOADSTATE_LOADED;
         private static _DELAYLOADSTATE_LOADING;
         private static _DELAYLOADSTATE_NOTLOADED;
+        private _audioEngine;
         static ALPHA_DISABLE : number;
         static ALPHA_ADD : number;
         static ALPHA_COMBINE : number;
@@ -102,6 +103,7 @@ declare module BABYLON {
         private _workingCanvas;
         private _workingContext;
         constructor(canvas: HTMLCanvasElement, antialias?: boolean, options?: any);
+        public getAudioEngine(): AudioEngine;
         public getAspectRatio(camera: Camera): number;
         public getRenderWidth(): number;
         public getRenderHeight(): number;
@@ -486,6 +488,7 @@ declare module BABYLON {
         private _processSubCameras(camera);
         private _checkIntersections();
         public render(): void;
+        private _updateAudioParameters();
         public dispose(): void;
         public _getNewPosition(position: Vector3, velocity: Vector3, collider: Collider, maximumRetry: number, finalPosition: Vector3, excludedMesh?: AbstractMesh): void;
         private _collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh?);
@@ -740,11 +743,14 @@ declare module BABYLON {
         private _highLimitsCache;
         private _stopped;
         public _target: any;
+        private _easingFunction;
         public targetPropertyPath: string[];
         public currentFrame: number;
         constructor(name: string, targetProperty: string, framePerSecond: number, dataType: number, loopMode?: number);
         public isStopped(): boolean;
         public getKeys(): any[];
+        public getEasingFunction(): IEasingFunction;
+        public setEasingFunction(easingFunction: EasingFunction): void;
         public floatInterpolateFunction(startValue: number, endValue: number, gradient: number): number;
         public quaternionInterpolateFunction(startValue: Quaternion, endValue: Quaternion, gradient: number): Quaternion;
         public vector3InterpolateFunction(startValue: Vector3, endValue: Vector3, gradient: number): Vector3;
@@ -775,6 +781,114 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    interface IEasingFunction {
+        ease(gradient: number): number;
+    }
+    class EasingFunction implements IEasingFunction {
+        private _easingMode;
+        public setEasingMode(easingMode: number): void;
+        public getEasingMode(): number;
+        public easeInCore(gradient: number): number;
+        public ease(gradient: number): number;
+        private static _EASINGMODE_EASEIN;
+        private static _EASINGMODE_EASEOUT;
+        private static _EASINGMODE_EASEINOUT;
+        static EASINGMODE_EASEIN : number;
+        static EASINGMODE_EASEOUT : number;
+        static EASINGMODE_EASEINOUT : number;
+    }
+    class CircleEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number;
+    }
+    class BackEase extends EasingFunction implements IEasingFunction {
+        public amplitude: number;
+        constructor(amplitude?: number);
+        public easeInCore(gradient: number): number;
+    }
+    class BounceEase extends EasingFunction implements IEasingFunction {
+        public bounces: number;
+        public bounciness: number;
+        constructor(bounces?: number, bounciness?: number);
+        public easeInCore(gradient: number): number;
+    }
+    class CubicEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number;
+    }
+    class ElasticEase extends EasingFunction implements IEasingFunction {
+        public oscillations: number;
+        public springiness: number;
+        constructor(oscillations?: number, springiness?: number);
+        public easeInCore(gradient: number): number;
+    }
+    class ExponentialEase extends EasingFunction implements IEasingFunction {
+        public exponent: number;
+        constructor(exponent?: number);
+        public easeInCore(gradient: number): number;
+    }
+    class PowerEase extends EasingFunction implements IEasingFunction {
+        public power: number;
+        constructor(power?: number);
+        public easeInCore(gradient: number): number;
+    }
+    class QuadraticEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number;
+    }
+    class QuarticEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number;
+    }
+    class QuinticEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number;
+    }
+    class SineEase extends EasingFunction implements IEasingFunction {
+        public easeInCore(gradient: number): number;
+    }
+    class BezierCurveEase extends EasingFunction implements IEasingFunction {
+        public x1: number;
+        public y1: number;
+        public x2: number;
+        public y2: number;
+        constructor(x1?: number, y1?: number, x2?: number, y2?: number);
+        public easeInCore(gradient: number): number;
+    }
+}
+declare module BABYLON {
+    class AudioEngine {
+        public audioContext: AudioContext;
+        public canUseWebAudio: boolean;
+        public masterGain: GainNode;
+        constructor();
+        public getGlobalVolume(): number;
+        public setGlobalVolume(newVolume: number): void;
+    }
+}
+declare module BABYLON {
+    class Sound {
+        private _audioBuffer;
+        public distanceMax: number;
+        public autoplay: boolean;
+        public loop: boolean;
+        private _position;
+        private _orientation;
+        private _volume;
+        private _currentVolume;
+        private _isLoaded;
+        private _isReadyToPlay;
+        private _audioEngine;
+        private _readyToPlayCallback;
+        private _soundSource;
+        private _soundPanner;
+        constructor(url: string, engine: Engine, readyToPlayCallback: any, distanceMax?: number, autoplay?: boolean, loop?: boolean);
+        public setPosition(newPosition: Vector3): void;
+        public setOrientiation(newOrientation: Vector3): void;
+        public play(): void;
+        public stop(): void;
+        public pause(): void;
+        public attachToMesh(meshToConnectTo: AbstractMesh): void;
+        private _onRegisterAfterWorldMatrixUpdate(connectedMesh);
+        private _soundLoaded(audioData);
+    }
+}
+declare module BABYLON {
     class Bone {
         public name: string;
         public children: Bone[];
@@ -1779,6 +1893,50 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    class ProceduralTexture extends Texture {
+        private _size;
+        public _generateMipMaps: boolean;
+        private _doNotChangeAspectRatio;
+        private _currentRefreshId;
+        private _refreshRate;
+        private _vertexBuffer;
+        private _indexBuffer;
+        private _effect;
+        private _vertexDeclaration;
+        private _vertexStrideSize;
+        private _uniforms;
+        private _samplers;
+        private _fragment;
+        private _textures;
+        private _floats;
+        private _floatsArrays;
+        private _colors3;
+        private _colors4;
+        private _vectors2;
+        private _vectors3;
+        private _matrices;
+        constructor(name: string, size: any, fragment: any, scene: Scene, generateMipMaps?: boolean);
+        public isReady(): boolean;
+        public resetRefreshCounter(): void;
+        public refreshRate : number;
+        public _shouldRender(): boolean;
+        public getRenderSize(): number;
+        public resize(size: any, generateMipMaps: any): void;
+        private _checkUniform(uniformName);
+        public setTexture(name: string, texture: Texture): ProceduralTexture;
+        public setFloat(name: string, value: number): ProceduralTexture;
+        public setFloats(name: string, value: number[]): ProceduralTexture;
+        public setColor3(name: string, value: Color3): ProceduralTexture;
+        public setColor4(name: string, value: Color4): ProceduralTexture;
+        public setVector2(name: string, value: Vector2): ProceduralTexture;
+        public setVector3(name: string, value: Vector3): ProceduralTexture;
+        public setMatrix(name: string, value: Matrix): ProceduralTexture;
+        public render(useCameraPostProcess?: boolean): void;
+        public clone(): ProceduralTexture;
+        public dispose(): void;
+    }
+}
+declare module BABYLON {
     class RenderTargetTexture extends Texture {
         public renderList: AbstractMesh[];
         public renderParticles: boolean;
@@ -1869,16 +2027,18 @@ declare module BABYLON {
 }
 declare module BABYLON {
     class CustomProceduralTexture extends ProceduralTexture {
-        private _generateTime;
+        private _animate;
         private _time;
         private _shaderLoaded;
         private _config;
         private _texturePath;
+        private _updateTexture;
         constructor(name: string, texturePath: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean);
         private loadJson(jsonUrl);
         public render(useCameraPostProcess?: boolean): void;
+        public updateTextures(): void;
         public updateShaderUniforms(): void;
-        public generateTime : boolean;
+        public animate : boolean;
     }
 }
 declare module BABYLON {
@@ -1906,6 +2066,7 @@ declare module BABYLON {
         private _matrices;
         private _fallbackTexture;
         constructor(name: string, size: any, fragment: any, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean);
+        public reset(): void;
         public isReady(): boolean;
         public resetRefreshCounter(): void;
         public setFragment(fragment: any): void;
@@ -2355,6 +2516,9 @@ declare module BABYLON {
         static Y: Vector3;
         static Z: Vector3;
     }
+    class BezierCurve {
+        static interpolate(t: number, x1: number, y1: number, x2: number, y2: number): number;
+    }
 }
 declare module BABYLON {
     class AbstractMesh extends Node implements IDisposable {
@@ -2426,6 +2590,7 @@ declare module BABYLON {
         public subMeshes: SubMesh[];
         public _submeshesOctree: Octree<SubMesh>;
         public _intersectionsInProgress: AbstractMesh[];
+        private _onAfterWorldMatrixUpdate;
         constructor(name: string, scene: Scene);
         public isBlocked : boolean;
         public getLOD(camera: Camera): AbstractMesh;
@@ -2450,6 +2615,12 @@ declare module BABYLON {
         public markAsDirty(property: string): void;
         public _updateBoundingInfo(): void;
         public computeWorldMatrix(force?: boolean): Matrix;
+        /**
+        * If you'd like to be callbacked after the mesh position, rotation or scaling has been updated
+        * @param func: callback function to add
+        */
+        public registerAfterWorldMatrixUpdate(func: (mesh: AbstractMesh) => void): void;
+        public unregisterAfterWorldMatrixUpdate(func: (mesh: AbstractMesh) => void): void;
         public setPositionWithLocalVector(vector3: Vector3): void;
         public getPositionExpressedInLocalSpace(): Vector3;
         public locallyTranslate(vector3: Vector3): void;