Browse Source

Fixing bug with instances and LOD

David Catuhe 10 năm trước cách đây
mục cha
commit
a8db5ae4c8

+ 69 - 35
Babylon/Audio/babylon.sound.js

@@ -4,11 +4,11 @@
         /**
         * Create a sound and attach it to a scene
         * @param name Name of your sound
-        * @param url Url to the sound to load async
+        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer
         * @param readyToPlayCallback Provide a callback function if you'd like to load your code once the sound is ready to be played
-        * @param options Objects to provide with the current available options: autoplay, loop, distanceMax
+        * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel
         */
-        function Sound(name, url, scene, readyToPlayCallback, options) {
+        function Sound(name, urlOrArrayBuffer, scene, readyToPlayCallback, options) {
             var _this = this;
             this.autoplay = false;
             this.loop = false;
@@ -17,6 +17,10 @@
             this.refDistance = 1;
             this.rolloffFactor = 1;
             this.maxDistance = 100;
+            this.distanceModel = "linear";
+            this.panningModel = "HRTF";
+            this.startTime = 0;
+            this.startOffset = 0;
             this._position = BABYLON.Vector3.Zero();
             this._localDirection = new BABYLON.Vector3(1, 0, 0);
             this._volume = 1;
@@ -26,16 +30,16 @@
             this._isDirectional = false;
             // Used if you'd like to create a directional sound.
             // If not set, the sound will be omnidirectional
-            this._coneInnerAngle = null;
-            this._coneOuterAngle = null;
-            this._coneOuterGain = null;
+            this._coneInnerAngle = 360;
+            this._coneOuterAngle = 360;
+            this._coneOuterGain = 0;
             this._name = name;
             this._scene = scene;
             this._audioEngine = this._scene.getEngine().getAudioEngine();
             this._readyToPlayCallback = readyToPlayCallback;
 
             // Default custom attenuation function is a linear attenuation
-            this._customAttenuationFunction = function (currentVolume, currentDistance, maxDistance) {
+            this._customAttenuationFunction = function (currentVolume, currentDistance, maxDistance, refDistance, rolloffFactor) {
                 if (currentDistance < maxDistance) {
                     return currentVolume * (1 - currentDistance / maxDistance);
                 } else {
@@ -43,25 +47,16 @@
                 }
             };
             if (options) {
-                if (options.maxDistance) {
-                    this.maxDistance = options.maxDistance;
-                }
-                if (options.autoplay) {
-                    this.autoplay = options.autoplay;
-                }
-                if (options.loop) {
-                    this.loop = options.loop;
-                }
-                if (options.volume) {
-                    this._volume = options.volume;
-                }
-                if (options.useCustomAttenuation) {
-                    this.maxDistance = Number.MAX_VALUE;
-                    this.useCustomAttenuation = options.useCustomAttenuation;
-                }
-                if (options.spatialSound) {
-                    this.spatialSound = options.spatialSound;
-                }
+                this.autoplay = options.autoplay || false;
+                this.loop = options.loop || false;
+                this._volume = options.volume || 1;
+                this.spatialSound = options.spatialSound || false;
+                this.maxDistance = options.maxDistance || 100;
+                this.useCustomAttenuation = options.useCustomAttenation || false;
+                this.rolloffFactor = options.rolloffFactor || 1;
+                this.refDistance = options.refDistance || 1;
+                this.distanceModel = options.distanceModel || "linear";
+                this.panningModel = options.panningModel || "HRTF";
             }
 
             if (this._audioEngine.canUseWebAudio) {
@@ -73,16 +68,49 @@
                     this._audioNode = this._soundGain;
                 }
                 this._scene.mainSoundTrack.AddSound(this);
-                BABYLON.Tools.LoadFile(url, function (data) {
-                    _this._soundLoaded(data);
-                }, null, null, true);
+                if (typeof (urlOrArrayBuffer) === "string") {
+                    BABYLON.Tools.LoadFile(urlOrArrayBuffer, function (data) {
+                        _this._soundLoaded(data);
+                    }, null, null, true);
+                } else {
+                    if (urlOrArrayBuffer instanceof ArrayBuffer) {
+                        this._soundLoaded(urlOrArrayBuffer);
+                    } else {
+                        BABYLON.Tools.Error("Parameter must be a URL to the sound or an ArrayBuffer of the sound.");
+                    }
+                }
             }
         }
+        Sound.prototype.updateOptions = function (options) {
+            if (options) {
+                this.loop = options.loop || this.loop;
+                this.maxDistance = options.maxDistance || this.maxDistance;
+                this.useCustomAttenuation = options.useCustomAttenation || this.useCustomAttenuation;
+                this.rolloffFactor = options.rolloffFactor || this.rolloffFactor;
+                this.refDistance = options.refDistance || this.refDistance;
+                this.distanceModel = options.distanceModel || this.distanceModel;
+                this.panningModel = options.panningModel || this.panningModel;
+            }
+        };
+
         Sound.prototype._createSpatialParameters = function () {
             this._soundPanner = this._audioEngine.audioContext.createPanner();
-            this._soundPanner.distanceModel = "linear";
-            this._soundPanner.maxDistance = this.maxDistance;
-            this._soundGain.connect(this._soundPanner);
+
+            if (this.useCustomAttenuation) {
+                // Tricks to disable in a way embedded Web Audio attenuation
+                this._soundPanner.distanceModel = "linear";
+                this._soundPanner.maxDistance = Number.MAX_VALUE;
+                this._soundPanner.refDistance = 1;
+                this._soundPanner.rolloffFactor = 1;
+                this._soundPanner.panningModel = "HRTF";
+            } else {
+                this._soundPanner.distanceModel = this.distanceModel;
+                this._soundPanner.maxDistance = this.maxDistance;
+                this._soundPanner.refDistance = this.refDistance;
+                this._soundPanner.rolloffFactor = this.rolloffFactor;
+                this._soundPanner.panningModel = this.panningModel;
+            }
+            this._soundPanner.connect(this._soundGain);
             this._audioNode = this._soundPanner;
         };
 
@@ -141,7 +169,7 @@
         Sound.prototype.updateDistanceFromListener = function () {
             if (this._connectedMesh && this.useCustomAttenuation) {
                 var distance = this._connectedMesh.getDistanceToCamera(this._scene.activeCamera);
-                this._soundGain.gain.value = this._customAttenuationFunction(this._volume, distance, this.maxDistance);
+                this._soundGain.gain.value = this._customAttenuationFunction(this._volume, distance, this.maxDistance, this.refDistance, this.rolloffFactor);
             }
         };
 
@@ -174,7 +202,8 @@
                     }
                     this._soundSource.connect(this._audioNode);
                     this._soundSource.loop = this.loop;
-                    this._soundSource.start(startTime);
+                    this.startTime = startTime;
+                    this._soundSource.start(startTime, this.startOffset % this._soundSource.buffer.duration);
                     this._isPlaying = true;
                 } catch (ex) {
                     BABYLON.Tools.Error("Error while trying to play audio: " + this._name + ", " + ex.message);
@@ -193,7 +222,8 @@
         };
 
         Sound.prototype.pause = function () {
-            // TODO
+            this._soundSource.stop(0);
+            this.startOffset += this._audioEngine.audioContext.currentTime - this.startTime;
         };
 
         Sound.prototype.setVolume = function (newVolume) {
@@ -211,6 +241,10 @@
             if (!this.spatialSound) {
                 this._createSpatialParameters();
                 this.spatialSound = true;
+                if (this._isPlaying && this.loop) {
+                    this.stop();
+                    this.play();
+                }
             }
             meshToConnectTo.registerAfterWorldMatrixUpdate(function (connectedMesh) {
                 return _this._onRegisterAfterWorldMatrixUpdate(connectedMesh);

+ 72 - 25
Babylon/Audio/babylon.sound.ts

@@ -8,6 +8,10 @@
         public refDistance: number = 1;
         public rolloffFactor: number = 1;
         public maxDistance: number = 100;
+        public distanceModel: string = "linear"; 
+        public panningModel: string = "HRTF";
+        private startTime: number = 0;
+        private startOffset: number = 0;
         private _position: Vector3 = Vector3.Zero();
         private _localDirection: Vector3 = new Vector3(1,0,0);
         private _volume: number = 1;
@@ -24,28 +28,28 @@
         private _audioNode: AudioNode;
         // Used if you'd like to create a directional sound.
         // If not set, the sound will be omnidirectional
-        private _coneInnerAngle: number = null;
-        private _coneOuterAngle: number = null;
-        private _coneOuterGain: number = null;
+        private _coneInnerAngle: number = 360;
+        private _coneOuterAngle: number = 360;
+        private _coneOuterGain: number = 0;
         private _scene: BABYLON.Scene;
         private _name: string;
         private _connectedMesh: BABYLON.AbstractMesh;
-        private _customAttenuationFunction: (currentVolume: number, currentDistance: number, maxDistance: number) => number;
+        private _customAttenuationFunction: (currentVolume: number, currentDistance: number, maxDistance: number, refDistance: number, rolloffFactor: number) => number;
 
         /**
         * Create a sound and attach it to a scene
         * @param name Name of your sound 
-        * @param url Url to the sound to load async
+        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer 
         * @param readyToPlayCallback Provide a callback function if you'd like to load your code once the sound is ready to be played
-        * @param options Objects to provide with the current available options: autoplay, loop, distanceMax
+        * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel
         */
-        constructor(name: string, url: string, scene: BABYLON.Scene, readyToPlayCallback?: () => void, options?) {
+        constructor(name: string, urlOrArrayBuffer: any, scene: BABYLON.Scene, readyToPlayCallback?: () => void, options?) {
             this._name = name;
             this._scene = scene;
             this._audioEngine = this._scene.getEngine().getAudioEngine();
             this._readyToPlayCallback = readyToPlayCallback;
             // Default custom attenuation function is a linear attenuation
-            this._customAttenuationFunction = (currentVolume: number, currentDistance: number, maxDistance: number) => { 
+            this._customAttenuationFunction = (currentVolume: number, currentDistance: number, maxDistance: number, refDistance: number, rolloffFactor: number) => {
                 if (currentDistance < maxDistance) {
                     return currentVolume * (1 - currentDistance / maxDistance);
                 }
@@ -54,15 +58,16 @@
                 }
             };
             if (options) {
-                if (options.maxDistance) { this.maxDistance = options.maxDistance; }
-                if (options.autoplay) { this.autoplay = options.autoplay; }
-                if (options.loop) { this.loop = options.loop; }
-                if (options.volume) { this._volume = options.volume; }
-                if (options.useCustomAttenuation) {
-                    this.maxDistance = Number.MAX_VALUE;
-                    this.useCustomAttenuation = options.useCustomAttenuation;
-                }
-                if (options.spatialSound) { this.spatialSound = options.spatialSound; }
+                this.autoplay = options.autoplay || false;
+                this.loop = options.loop || false;
+                this._volume = options.volume || 1;
+                this.spatialSound = options.spatialSound || false;
+                this.maxDistance = options.maxDistance || 100;
+                this.useCustomAttenuation = options.useCustomAttenation || false;
+                this.rolloffFactor = options.rolloffFactor || 1;
+                this.refDistance = options.refDistance || 1;
+                this.distanceModel = options.distanceModel || "linear";
+                this.panningModel = options.panningModel || "HRTF";
             }
 
             if (this._audioEngine.canUseWebAudio) {
@@ -75,15 +80,51 @@
                     this._audioNode = this._soundGain;
                 }
                 this._scene.mainSoundTrack.AddSound(this);
-                BABYLON.Tools.LoadFile(url, (data) => { this._soundLoaded(data); }, null, null, true);
+                if (typeof (urlOrArrayBuffer) === "string") {
+                    BABYLON.Tools.LoadFile(urlOrArrayBuffer, (data) => { this._soundLoaded(data); }, null, null, true);
+                }
+                else {
+                    if (urlOrArrayBuffer instanceof ArrayBuffer) {
+                        this._soundLoaded(urlOrArrayBuffer);
+                    }
+                    else {
+                        BABYLON.Tools.Error("Parameter must be a URL to the sound or an ArrayBuffer of the sound.");
+                    }
+                }
+            }
+        }
+
+        public updateOptions(options) {
+            if (options) {
+                this.loop = options.loop || this.loop;
+                this.maxDistance = options.maxDistance || this.maxDistance;
+                this.useCustomAttenuation = options.useCustomAttenation || this.useCustomAttenuation;
+                this.rolloffFactor = options.rolloffFactor || this.rolloffFactor;
+                this.refDistance = options.refDistance || this.refDistance;
+                this.distanceModel = options.distanceModel || this.distanceModel;
+                this.panningModel = options.panningModel || this.panningModel;
             }
         }
 
         private _createSpatialParameters() {
             this._soundPanner = this._audioEngine.audioContext.createPanner();
-            this._soundPanner.distanceModel = "linear";
-            this._soundPanner.maxDistance = this.maxDistance;
-            this._soundGain.connect(this._soundPanner);
+
+            if (this.useCustomAttenuation) {
+                // Tricks to disable in a way embedded Web Audio attenuation 
+                this._soundPanner.distanceModel = "linear";
+                this._soundPanner.maxDistance = Number.MAX_VALUE;
+                this._soundPanner.refDistance = 1;
+                this._soundPanner.rolloffFactor = 1;
+                this._soundPanner.panningModel = "HRTF";
+            }
+            else {
+                this._soundPanner.distanceModel = this.distanceModel;
+                this._soundPanner.maxDistance = this.maxDistance;
+                this._soundPanner.refDistance = this.refDistance;
+                this._soundPanner.rolloffFactor = this.rolloffFactor;
+                this._soundPanner.panningModel = this.panningModel;
+            }
+            this._soundPanner.connect(this._soundGain);
             this._audioNode = this._soundPanner;
         }
 
@@ -142,11 +183,11 @@
         public updateDistanceFromListener() {
             if (this._connectedMesh && this.useCustomAttenuation) {
                 var distance = this._connectedMesh.getDistanceToCamera(this._scene.activeCamera);
-                this._soundGain.gain.value = this._customAttenuationFunction(this._volume, distance, this.maxDistance);
+                this._soundGain.gain.value = this._customAttenuationFunction(this._volume, distance, this.maxDistance, this.refDistance, this.rolloffFactor);
             }
         }
         
-        public setAttenuationFunction(callback: (currentVolume: number, currentDistance: number, maxDistance: number) => number) {
+        public setAttenuationFunction(callback: (currentVolume: number, currentDistance: number, maxDistance: number, refDistance: number, rolloffFactor: number) => number) {
             this._customAttenuationFunction = callback;
         }
 
@@ -176,7 +217,8 @@
                     }
                     this._soundSource.connect(this._audioNode);
                     this._soundSource.loop = this.loop;
-                    this._soundSource.start(startTime);
+                    this.startTime = startTime;
+                    this._soundSource.start(startTime, this.startOffset % this._soundSource.buffer.duration);
                     this._isPlaying = true;
                 }
                 catch (ex) {
@@ -196,7 +238,8 @@
         }
 
         public pause() {
-            // TODO
+            this._soundSource.stop(0);
+            this.startOffset += this._audioEngine.audioContext.currentTime - this.startTime;
         }
 
         public setVolume(newVolume: number) {
@@ -213,6 +256,10 @@
             if (!this.spatialSound) {
                 this._createSpatialParameters();
                 this.spatialSound = true;
+                if (this._isPlaying && this.loop) {
+                    this.stop();
+                    this.play();
+                }
             }
             meshToConnectTo.registerAfterWorldMatrixUpdate((connectedMesh: BABYLON.AbstractMesh) => this._onRegisterAfterWorldMatrixUpdate(connectedMesh));
         }

+ 4 - 0
Babylon/Mesh/babylon.InstancedMesh.js

@@ -121,6 +121,10 @@ var BABYLON;
         InstancedMesh.prototype.getLOD = function (camera) {
             this._currentLOD = this.sourceMesh.getLOD(this.getScene().activeCamera, this.getBoundingInfo().boundingSphere);
 
+            if (this._currentLOD === this.sourceMesh) {
+                return this;
+            }
+
             return this._currentLOD;
         };
 

+ 4 - 0
Babylon/Mesh/babylon.InstancedMesh.ts

@@ -93,6 +93,10 @@
         public getLOD(camera: Camera): AbstractMesh {
             this._currentLOD = <Mesh>this.sourceMesh.getLOD(this.getScene().activeCamera, this.getBoundingInfo().boundingSphere);
 
+            if (this._currentLOD === this.sourceMesh) {
+                return this;
+            }
+
             return this._currentLOD;
         }
 

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

@@ -234,7 +234,7 @@ var BABYLON;
 
             mesh._geometry = null;
 
-            if (meshes.length == 0 && shouldDispose) {
+            if (meshes.length === 0 && shouldDispose) {
                 this.dispose();
             }
         };
@@ -281,6 +281,9 @@ var BABYLON;
                     mesh._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
 
                     mesh._createGlobalSubMesh();
+
+                    //bounding info was just created again, world matrix should be applied again.
+                    mesh._updateBoundingInfo();
                 }
             }
 
@@ -333,8 +336,8 @@ var BABYLON;
         Geometry.prototype.dispose = function () {
             var meshes = this._meshes;
             var numOfMeshes = meshes.length;
-
-            for (var index = 0; index < numOfMeshes; index++) {
+            var index;
+            for (index = 0; index < numOfMeshes; index++) {
                 this.releaseForMesh(meshes[index]);
             }
             this._meshes = [];
@@ -388,7 +391,7 @@ var BABYLON;
                 }
             }
 
-            var geometry = new BABYLON.Geometry(id, this._scene, vertexData, updatable, null);
+            var geometry = new Geometry(id, this._scene, vertexData, updatable, null);
 
             geometry.delayLoadState = this.delayLoadState;
             geometry.delayLoadingFile = this.delayLoadingFile;
@@ -421,7 +424,7 @@ var BABYLON;
         // be aware Math.random() could cause collisions
         Geometry.RandomId = function () {
             return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
-                var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+                var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
                 return v.toString(16);
             });
         };

+ 23 - 22
Babylon/Mesh/babylon.geometry.ts

@@ -2,7 +2,7 @@
     export class Geometry implements IGetSetVerticesData {
         // Members
         public id: string;
-        public delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
+        public delayLoadState = Engine.DELAYLOADSTATE_NONE;
         public delayLoadingFile: string;
 
         // Private
@@ -47,7 +47,7 @@
         }
 
         public isReady(): boolean {
-            return this.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADED || this.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NONE;
+            return this.delayLoadState === Engine.DELAYLOADSTATE_LOADED || this.delayLoadState === Engine.DELAYLOADSTATE_NONE;
         }
 
         public setAllVerticesData(vertexData: VertexData, updatable?: boolean): void {
@@ -63,12 +63,12 @@
 
             this._vertexBuffers[kind] = new VertexBuffer(this._engine, data, kind, updatable, this._meshes.length === 0, stride);
 
-            if (kind === BABYLON.VertexBuffer.PositionKind) {
+            if (kind === VertexBuffer.PositionKind) {
                 stride = this._vertexBuffers[kind].getStrideSize();
 
                 this._totalVertices = data.length / stride;
 
-                var extend = BABYLON.Tools.ExtractMinAndMax(data, 0, this._totalVertices);
+                var extend = Tools.ExtractMinAndMax(data, 0, this._totalVertices);
 
                 var meshes = this._meshes;
                 var numOfMeshes = meshes.length;
@@ -76,7 +76,7 @@
                 for (var index = 0; index < numOfMeshes; index++) {
                     var mesh = meshes[index];
                     mesh._resetPointsArrayCache();
-                    mesh._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
+                    mesh._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
                     mesh._createGlobalSubMesh();
                     mesh.computeWorldMatrix(true);
                 }
@@ -244,7 +244,7 @@
 
             mesh._geometry = null;
 
-            if (meshes.length == 0 && shouldDispose) {
+            if (meshes.length === 0 && shouldDispose) {
                 this.dispose();
             }
         }
@@ -286,13 +286,14 @@
                 }
                 this._vertexBuffers[kind]._buffer.references = numOfMeshes;
 
-                if (kind === BABYLON.VertexBuffer.PositionKind) {
+                if (kind === VertexBuffer.PositionKind) {
                     mesh._resetPointsArrayCache();
 
-                    var extend = BABYLON.Tools.ExtractMinAndMax(this._vertexBuffers[kind].getData(), 0, this._totalVertices);
-                    mesh._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
+                    var extend = Tools.ExtractMinAndMax(this._vertexBuffers[kind].getData(), 0, this._totalVertices);
+                    mesh._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
 
                     mesh._createGlobalSubMesh();
+
                     //bounding info was just created again, world matrix should be applied again.
                     mesh._updateBoundingInfo();
                 }
@@ -308,7 +309,7 @@
         }
 
         public load(scene: Scene, onLoaded?: () => void): void {
-            if (this.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADING) {
+            if (this.delayLoadState === Engine.DELAYLOADSTATE_LOADING) {
                 return;
             }
 
@@ -319,13 +320,13 @@
                 return;
             }
 
-            this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADING;
+            this.delayLoadState = Engine.DELAYLOADSTATE_LOADING;
 
             scene._addPendingData(this);
-            BABYLON.Tools.LoadFile(this.delayLoadingFile, data => {
+            Tools.LoadFile(this.delayLoadingFile, data => {
                 this._delayLoadingFunction(JSON.parse(data), this);
 
-                this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
+                this.delayLoadState = Engine.DELAYLOADSTATE_LOADED;
                 this._delayInfo = [];
 
                 scene._removePendingData(this);
@@ -345,8 +346,8 @@
         public dispose(): void {
             var meshes = this._meshes;
             var numOfMeshes = meshes.length;
-
-            for (var index = 0; index < numOfMeshes; index++) {
+            var index: number;
+            for (index = 0; index < numOfMeshes; index++) {
                 this.releaseForMesh(meshes[index]);
             }
             this._meshes = [];
@@ -363,7 +364,7 @@
             this._indexBuffer = null;
             this._indices = [];
 
-            this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
+            this.delayLoadState = Engine.DELAYLOADSTATE_NONE;
             this.delayLoadingFile = null;
             this._delayLoadingFunction = null;
             this._delayInfo = [];
@@ -379,7 +380,7 @@
         }
 
         public copy(id: string): Geometry {
-            var vertexData = new BABYLON.VertexData();
+            var vertexData = new VertexData();
 
             vertexData.indices = [];
 
@@ -400,7 +401,7 @@
                 }
             }
 
-            var geometry = new BABYLON.Geometry(id, this._scene, vertexData, updatable, null);
+            var geometry = new Geometry(id, this._scene, vertexData, updatable, null);
 
             geometry.delayLoadState = this.delayLoadState;
             geometry.delayLoadingFile = this.delayLoadingFile;
@@ -412,8 +413,8 @@
             }
 
             // Bounding info
-            var extend = BABYLON.Tools.ExtractMinAndMax(this.getVerticesData(BABYLON.VertexBuffer.PositionKind), 0, this.getTotalVertices());
-            geometry._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
+            var extend = Tools.ExtractMinAndMax(this.getVerticesData(VertexBuffer.PositionKind), 0, this.getTotalVertices());
+            geometry._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
 
             return geometry;
         }
@@ -433,7 +434,7 @@
         // be aware Math.random() could cause collisions
         public static RandomId(): string {
             return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
-                var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+                var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
                 return v.toString(16);
             });
         }
@@ -688,4 +689,4 @@
             }
         }
     }
-} 
+} 

+ 16 - 15
Babylon/Mesh/babylon.polygonmesh.js

@@ -13,7 +13,7 @@ var BABYLON;
             this.index = index;
         }
         return IndexedVector2;
-    })(Vector2);
+    })(BABYLON.Vector2);
 
     var PolygonPoints = (function () {
         function PolygonPoints() {
@@ -23,7 +23,7 @@ var BABYLON;
             var _this = this;
             var result = new Array();
             originalPoints.forEach(function (point) {
-                if (result.length === 0 || !(Tools.WithinEpsilon(point.x, result[0].x, 0.00001) && Tools.WithinEpsilon(point.y, result[0].y, 0.00001))) {
+                if (result.length === 0 || !(BABYLON.Tools.WithinEpsilon(point.x, result[0].x, 0.00001) && BABYLON.Tools.WithinEpsilon(point.y, result[0].y, 0.00001))) {
                     var newPoint = new IndexedVector2(point, _this.elements.length);
                     result.push(newPoint);
                     _this.elements.push(newPoint);
@@ -34,8 +34,8 @@ var BABYLON;
         };
 
         PolygonPoints.prototype.computeBounds = function () {
-            var lmin = new Vector2(this.elements[0].x, this.elements[0].y);
-            var lmax = new Vector2(this.elements[0].x, this.elements[0].y);
+            var lmin = new BABYLON.Vector2(this.elements[0].x, this.elements[0].y);
+            var lmax = new BABYLON.Vector2(this.elements[0].x, this.elements[0].y);
 
             this.elements.forEach(function (point) {
                 // x
@@ -68,10 +68,10 @@ var BABYLON;
         }
         Polygon.Rectangle = function (xmin, ymin, xmax, ymax) {
             return [
-                new Vector2(xmin, ymin),
-                new Vector2(xmax, ymin),
-                new Vector2(xmax, ymax),
-                new Vector2(xmin, ymax)
+                new BABYLON.Vector2(xmin, ymin),
+                new BABYLON.Vector2(xmax, ymin),
+                new BABYLON.Vector2(xmax, ymax),
+                new BABYLON.Vector2(xmin, ymax)
             ];
         };
 
@@ -85,7 +85,7 @@ var BABYLON;
             var increment = (Math.PI * 2) / numberOfSides;
 
             for (var i = 0; i < numberOfSides; i++) {
-                result.push(new Vector2(cx + Math.cos(angle) * radius, cy + Math.sin(angle) * radius));
+                result.push(new BABYLON.Vector2(cx + Math.cos(angle) * radius, cy + Math.sin(angle) * radius));
                 angle -= increment;
             }
 
@@ -104,7 +104,7 @@ var BABYLON;
         };
 
         Polygon.StartingAt = function (x, y) {
-            return Path2.StartingAt(x, y);
+            return BABYLON.Path2.StartingAt(x, y);
         };
         return Polygon;
     })();
@@ -121,7 +121,7 @@ var BABYLON;
             this._scene = scene;
 
             var points;
-            if (contours instanceof Path2) {
+            if (contours instanceof BABYLON.Path2) {
                 points = contours.getPoints();
             } else {
                 points = contours;
@@ -136,7 +136,7 @@ var BABYLON;
 
         PolygonMeshBuilder.prototype.build = function (updatable) {
             if (typeof updatable === "undefined") { updatable = false; }
-            var result = new Mesh(this._name, this._scene);
+            var result = new BABYLON.Mesh(this._name, this._scene);
 
             var normals = [];
             var positions = [];
@@ -158,9 +158,9 @@ var BABYLON;
                 });
             });
 
-            result.setVerticesData(positions, VertexBuffer.PositionKind, updatable);
-            result.setVerticesData(normals, VertexBuffer.NormalKind, updatable);
-            result.setVerticesData(uvs, VertexBuffer.UVKind, updatable);
+            result.setVerticesData(positions, BABYLON.VertexBuffer.PositionKind, updatable);
+            result.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind, updatable);
+            result.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind, updatable);
             result.setIndices(indices);
 
             return result;
@@ -169,3 +169,4 @@ var BABYLON;
     })();
     BABYLON.PolygonMeshBuilder = PolygonMeshBuilder;
 })(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.polygonMesh.js.map

+ 1 - 1
Babylon/Mesh/babylon.polygonmesh.ts

@@ -94,7 +94,7 @@
         static StartingAt(x: number, y: number): Path2 {
             return Path2.StartingAt(x, y);
         }
-    }     
+    }
 
     export class PolygonMeshBuilder {
 

+ 1 - 1
Babylon/Physics/babylon.physicsEngine.ts

@@ -51,7 +51,7 @@
         }
 
         public _setGravity(gravity: Vector3): void {
-            this.gravity = gravity || new BABYLON.Vector3(0, -9.82, 0);
+            this.gravity = gravity || new Vector3(0, -9.82, 0);
             this._currentPlugin.setGravity(this.gravity);
         }
 

+ 10 - 9
Babylon/Tools/babylon.tools.js

@@ -7,11 +7,11 @@
         if (!source)
             return null;
 
-        if (source instanceof Mesh) {
+        if (source instanceof BABYLON.Mesh) {
             return null;
         }
 
-        if (source instanceof SubMesh) {
+        if (source instanceof BABYLON.SubMesh) {
             return source.clone(destinationObject);
         } else if (source.clone) {
             return source.clone();
@@ -53,11 +53,11 @@
         };
 
         Tools.ExtractMinAndMaxIndexed = function (positions, indices, indexStart, indexCount) {
-            var minimum = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
-            var maximum = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
+            var minimum = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+            var maximum = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 
             for (var index = indexStart; index < indexStart + indexCount; index++) {
-                var current = new Vector3(positions[indices[index] * 3], positions[indices[index] * 3 + 1], positions[indices[index] * 3 + 2]);
+                var current = new BABYLON.Vector3(positions[indices[index] * 3], positions[indices[index] * 3 + 1], positions[indices[index] * 3 + 2]);
 
                 minimum = BABYLON.Vector3.Minimize(current, minimum);
                 maximum = BABYLON.Vector3.Maximize(current, maximum);
@@ -70,11 +70,11 @@
         };
 
         Tools.ExtractMinAndMax = function (positions, start, count) {
-            var minimum = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
-            var maximum = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
+            var minimum = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+            var maximum = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 
             for (var index = start; index < start + count; index++) {
-                var current = new Vector3(positions[index * 3], positions[index * 3 + 1], positions[index * 3 + 2]);
+                var current = new BABYLON.Vector3(positions[index * 3], positions[index * 3 + 1], positions[index * 3 + 2]);
 
                 minimum = BABYLON.Vector3.Minimize(current, minimum);
                 maximum = BABYLON.Vector3.Maximize(current, maximum);
@@ -423,7 +423,7 @@
             }
 
             //At this point size can be a number, or an object (according to engine.prototype.createRenderTargetTexture method)
-            var texture = new RenderTargetTexture("screenShot", size, engine.scenes[0], false, false);
+            var texture = new BABYLON.RenderTargetTexture("screenShot", size, engine.scenes[0], false, false);
             texture.renderList = engine.scenes[0].meshes;
 
             texture.onAfterRender = function () {
@@ -804,3 +804,4 @@
     })();
     BABYLON.Tools = Tools;
 })(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.tools.js.map

+ 85 - 43
babylon.2.0-alpha.debug.js

@@ -3094,9 +3094,10 @@ var BABYLON;
                 max.z = v.z;
         };
 
-        Tools.WithinEpsilon = function (a, b) {
+        Tools.WithinEpsilon = function (a, b, epsilon) {
+            if (typeof epsilon === "undefined") { epsilon = 1.401298E-45; }
             var num = a - b;
-            return -1.401298E-45 <= num && num <= 1.401298E-45;
+            return -epsilon <= num && num <= epsilon;
         };
 
         Tools.DeepCopy = function (source, destination, doNotCopyList, mustCopyList) {
@@ -12643,6 +12644,10 @@ var BABYLON;
         InstancedMesh.prototype.getLOD = function (camera) {
             this._currentLOD = this.sourceMesh.getLOD(this.getScene().activeCamera, this.getBoundingInfo().boundingSphere);
 
+            if (this._currentLOD === this.sourceMesh) {
+                return this;
+            }
+
             return this._currentLOD;
         };
 
@@ -27389,7 +27394,7 @@ var BABYLON;
 
             mesh._geometry = null;
 
-            if (meshes.length == 0 && shouldDispose) {
+            if (meshes.length === 0 && shouldDispose) {
                 this.dispose();
             }
         };
@@ -27436,6 +27441,9 @@ var BABYLON;
                     mesh._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
 
                     mesh._createGlobalSubMesh();
+
+                    //bounding info was just created again, world matrix should be applied again.
+                    mesh._updateBoundingInfo();
                 }
             }
 
@@ -27488,8 +27496,8 @@ var BABYLON;
         Geometry.prototype.dispose = function () {
             var meshes = this._meshes;
             var numOfMeshes = meshes.length;
-
-            for (var index = 0; index < numOfMeshes; index++) {
+            var index;
+            for (index = 0; index < numOfMeshes; index++) {
                 this.releaseForMesh(meshes[index]);
             }
             this._meshes = [];
@@ -27543,7 +27551,7 @@ var BABYLON;
                 }
             }
 
-            var geometry = new BABYLON.Geometry(id, this._scene, vertexData, updatable, null);
+            var geometry = new Geometry(id, this._scene, vertexData, updatable, null);
 
             geometry.delayLoadState = this.delayLoadState;
             geometry.delayLoadingFile = this.delayLoadingFile;
@@ -27576,7 +27584,7 @@ var BABYLON;
         // be aware Math.random() could cause collisions
         Geometry.RandomId = function () {
             return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
-                var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+                var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
                 return v.toString(16);
             });
         };
@@ -29437,11 +29445,11 @@ var BABYLON;
         /**
         * Create a sound and attach it to a scene
         * @param name Name of your sound
-        * @param url Url to the sound to load async
+        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer
         * @param readyToPlayCallback Provide a callback function if you'd like to load your code once the sound is ready to be played
-        * @param options Objects to provide with the current available options: autoplay, loop, distanceMax
+        * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel
         */
-        function Sound(name, url, scene, readyToPlayCallback, options) {
+        function Sound(name, urlOrArrayBuffer, scene, readyToPlayCallback, options) {
             var _this = this;
             this.autoplay = false;
             this.loop = false;
@@ -29450,6 +29458,10 @@ var BABYLON;
             this.refDistance = 1;
             this.rolloffFactor = 1;
             this.maxDistance = 100;
+            this.distanceModel = "linear";
+            this.panningModel = "HRTF";
+            this.startTime = 0;
+            this.startOffset = 0;
             this._position = BABYLON.Vector3.Zero();
             this._localDirection = new BABYLON.Vector3(1, 0, 0);
             this._volume = 1;
@@ -29459,16 +29471,16 @@ var BABYLON;
             this._isDirectional = false;
             // Used if you'd like to create a directional sound.
             // If not set, the sound will be omnidirectional
-            this._coneInnerAngle = null;
-            this._coneOuterAngle = null;
-            this._coneOuterGain = null;
+            this._coneInnerAngle = 360;
+            this._coneOuterAngle = 360;
+            this._coneOuterGain = 0;
             this._name = name;
             this._scene = scene;
             this._audioEngine = this._scene.getEngine().getAudioEngine();
             this._readyToPlayCallback = readyToPlayCallback;
 
             // Default custom attenuation function is a linear attenuation
-            this._customAttenuationFunction = function (currentVolume, currentDistance, maxDistance) {
+            this._customAttenuationFunction = function (currentVolume, currentDistance, maxDistance, refDistance, rolloffFactor) {
                 if (currentDistance < maxDistance) {
                     return currentVolume * (1 - currentDistance / maxDistance);
                 } else {
@@ -29476,25 +29488,16 @@ var BABYLON;
                 }
             };
             if (options) {
-                if (options.maxDistance) {
-                    this.maxDistance = options.maxDistance;
-                }
-                if (options.autoplay) {
-                    this.autoplay = options.autoplay;
-                }
-                if (options.loop) {
-                    this.loop = options.loop;
-                }
-                if (options.volume) {
-                    this._volume = options.volume;
-                }
-                if (options.useCustomAttenuation) {
-                    this.maxDistance = Number.MAX_VALUE;
-                    this.useCustomAttenuation = options.useCustomAttenuation;
-                }
-                if (options.spatialSound) {
-                    this.spatialSound = options.spatialSound;
-                }
+                this.autoplay = options.autoplay || false;
+                this.loop = options.loop || false;
+                this._volume = options.volume || 1;
+                this.spatialSound = options.spatialSound || false;
+                this.maxDistance = options.maxDistance || 100;
+                this.useCustomAttenuation = options.useCustomAttenation || false;
+                this.rolloffFactor = options.rolloffFactor || 1;
+                this.refDistance = options.refDistance || 1;
+                this.distanceModel = options.distanceModel || "linear";
+                this.panningModel = options.panningModel || "HRTF";
             }
 
             if (this._audioEngine.canUseWebAudio) {
@@ -29506,16 +29509,49 @@ var BABYLON;
                     this._audioNode = this._soundGain;
                 }
                 this._scene.mainSoundTrack.AddSound(this);
-                BABYLON.Tools.LoadFile(url, function (data) {
-                    _this._soundLoaded(data);
-                }, null, null, true);
+                if (typeof (urlOrArrayBuffer) === "string") {
+                    BABYLON.Tools.LoadFile(urlOrArrayBuffer, function (data) {
+                        _this._soundLoaded(data);
+                    }, null, null, true);
+                } else {
+                    if (urlOrArrayBuffer instanceof ArrayBuffer) {
+                        this._soundLoaded(urlOrArrayBuffer);
+                    } else {
+                        BABYLON.Tools.Error("Parameter must be a URL to the sound or an ArrayBuffer of the sound.");
+                    }
+                }
             }
         }
+        Sound.prototype.updateOptions = function (options) {
+            if (options) {
+                this.loop = options.loop || this.loop;
+                this.maxDistance = options.maxDistance || this.maxDistance;
+                this.useCustomAttenuation = options.useCustomAttenation || this.useCustomAttenuation;
+                this.rolloffFactor = options.rolloffFactor || this.rolloffFactor;
+                this.refDistance = options.refDistance || this.refDistance;
+                this.distanceModel = options.distanceModel || this.distanceModel;
+                this.panningModel = options.panningModel || this.panningModel;
+            }
+        };
+
         Sound.prototype._createSpatialParameters = function () {
             this._soundPanner = this._audioEngine.audioContext.createPanner();
-            this._soundPanner.distanceModel = "linear";
-            this._soundPanner.maxDistance = this.maxDistance;
-            this._soundGain.connect(this._soundPanner);
+
+            if (this.useCustomAttenuation) {
+                // Tricks to disable in a way embedded Web Audio attenuation
+                this._soundPanner.distanceModel = "linear";
+                this._soundPanner.maxDistance = Number.MAX_VALUE;
+                this._soundPanner.refDistance = 1;
+                this._soundPanner.rolloffFactor = 1;
+                this._soundPanner.panningModel = "HRTF";
+            } else {
+                this._soundPanner.distanceModel = this.distanceModel;
+                this._soundPanner.maxDistance = this.maxDistance;
+                this._soundPanner.refDistance = this.refDistance;
+                this._soundPanner.rolloffFactor = this.rolloffFactor;
+                this._soundPanner.panningModel = this.panningModel;
+            }
+            this._soundPanner.connect(this._soundGain);
             this._audioNode = this._soundPanner;
         };
 
@@ -29574,7 +29610,7 @@ var BABYLON;
         Sound.prototype.updateDistanceFromListener = function () {
             if (this._connectedMesh && this.useCustomAttenuation) {
                 var distance = this._connectedMesh.getDistanceToCamera(this._scene.activeCamera);
-                this._soundGain.gain.value = this._customAttenuationFunction(this._volume, distance, this.maxDistance);
+                this._soundGain.gain.value = this._customAttenuationFunction(this._volume, distance, this.maxDistance, this.refDistance, this.rolloffFactor);
             }
         };
 
@@ -29607,7 +29643,8 @@ var BABYLON;
                     }
                     this._soundSource.connect(this._audioNode);
                     this._soundSource.loop = this.loop;
-                    this._soundSource.start(startTime);
+                    this.startTime = startTime;
+                    this._soundSource.start(startTime, this.startOffset % this._soundSource.buffer.duration);
                     this._isPlaying = true;
                 } catch (ex) {
                     BABYLON.Tools.Error("Error while trying to play audio: " + this._name + ", " + ex.message);
@@ -29626,7 +29663,8 @@ var BABYLON;
         };
 
         Sound.prototype.pause = function () {
-            // TODO
+            this._soundSource.stop(0);
+            this.startOffset += this._audioEngine.audioContext.currentTime - this.startTime;
         };
 
         Sound.prototype.setVolume = function (newVolume) {
@@ -29644,6 +29682,10 @@ var BABYLON;
             if (!this.spatialSound) {
                 this._createSpatialParameters();
                 this.spatialSound = true;
+                if (this._isPlaying && this.loop) {
+                    this.stop();
+                    this.play();
+                }
             }
             meshToConnectTo.registerAfterWorldMatrixUpdate(function (connectedMesh) {
                 return _this._onRegisterAfterWorldMatrixUpdate(connectedMesh);
@@ -30486,7 +30528,7 @@ var BABYLON;
             var _this = this;
             var result = new Array();
             originalPoints.forEach(function (point) {
-                if (result.length === 0 || !(BABYLON.Tools.WithinEpsilon(point.x, result[0].x) && BABYLON.Tools.WithinEpsilon(point.y, result[0].y))) {
+                if (result.length === 0 || !(BABYLON.Tools.WithinEpsilon(point.x, result[0].x, 0.00001) && BABYLON.Tools.WithinEpsilon(point.y, result[0].y, 0.00001))) {
                     var newPoint = new IndexedVector2(point, _this.elements.length);
                     result.push(newPoint);
                     _this.elements.push(newPoint);

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 6 - 6
babylon.2.0-alpha.js