|
@@ -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);
|