|
@@ -21200,7 +21200,14 @@ var BABYLON;
|
|
|
if (this._material === value) {
|
|
|
return;
|
|
|
}
|
|
|
+ // remove from material mesh map id needed
|
|
|
+ if (this._material && this._material.meshMap) {
|
|
|
+ this._material.meshMap[this.uniqueId] = undefined;
|
|
|
+ }
|
|
|
this._material = value;
|
|
|
+ if (value && value.meshMap) {
|
|
|
+ value.meshMap[this.uniqueId] = this;
|
|
|
+ }
|
|
|
if (this.onMaterialChangedObservable.hasObservers) {
|
|
|
this.onMaterialChangedObservable.notifyObservers(this);
|
|
|
}
|
|
@@ -25194,6 +25201,9 @@ var BABYLON;
|
|
|
this.multiMaterials = new Array();
|
|
|
/**
|
|
|
* All of the materials added to this scene
|
|
|
+ * In the context of a Scene, it is not supposed to be modified manually.
|
|
|
+ * Any addition or removal should be done using the addMaterial and removeMAterial Scene methods.
|
|
|
+ * Note also that the order of the Material wihin the array is not significant and might change.
|
|
|
* @see http://doc.babylonjs.com/babylon101/materials
|
|
|
*/
|
|
|
this.materials = new Array();
|
|
@@ -25208,7 +25218,7 @@ var BABYLON;
|
|
|
this.geometries = new Array();
|
|
|
/**
|
|
|
* All of the tranform nodes added to this scene
|
|
|
- * In the context a the Scene, it is not supposed to be modified manually.
|
|
|
+ * In the context of a Scene, it is not supposed to be modified manually.
|
|
|
* Any addition or removal should be done using the addTransformNode and removeTransformNode Scene methods.
|
|
|
* Note also that the order of the TransformNode wihin the array is not significant and might change.
|
|
|
* @see http://doc.babylonjs.com/how_to/transformnode
|
|
@@ -25893,6 +25903,7 @@ var BABYLON;
|
|
|
data: [],
|
|
|
length: 0
|
|
|
};
|
|
|
+ _this._preventFreeActiveMeshesAndRenderingGroups = false;
|
|
|
_this._activeMeshesFrozen = false;
|
|
|
/** @hidden */
|
|
|
_this._allowPostProcessClearColor = true;
|
|
@@ -25926,6 +25937,8 @@ var BABYLON;
|
|
|
if (options && options.useGeometryIdsMap === true) {
|
|
|
_this.geometriesById = {};
|
|
|
}
|
|
|
+ _this.useMaterialMeshMap = options && options.useGeometryIdsMap || false;
|
|
|
+ _this.useClonedMeshhMap = options && options.useClonedMeshhMap || false;
|
|
|
return _this;
|
|
|
}
|
|
|
Object.defineProperty(Scene.prototype, "environmentTexture", {
|
|
@@ -27910,7 +27923,8 @@ var BABYLON;
|
|
|
var index = this.meshes.indexOf(toRemove);
|
|
|
if (index !== -1) {
|
|
|
// Remove from the scene if mesh found
|
|
|
- this.meshes.splice(index, 1);
|
|
|
+ this.meshes[index] = this.meshes[this.meshes.length - 1];
|
|
|
+ this.meshes.pop();
|
|
|
}
|
|
|
this.onMeshRemovedObservable.notifyObservers(toRemove);
|
|
|
if (recursive) {
|
|
@@ -28077,9 +28091,15 @@ var BABYLON;
|
|
|
* @returns The index of the removed material
|
|
|
*/
|
|
|
Scene.prototype.removeMaterial = function (toRemove) {
|
|
|
- var index = this.materials.indexOf(toRemove);
|
|
|
+ var index = toRemove._indexInSceneMaterialArray;
|
|
|
if (index !== -1) {
|
|
|
- this.materials.splice(index, 1);
|
|
|
+ if (index !== this.materials.length - 1) {
|
|
|
+ var lastMaterial = this.materials[this.materials.length - 1];
|
|
|
+ this.materials[index] = lastMaterial;
|
|
|
+ lastMaterial._indexInSceneMaterialArray = index;
|
|
|
+ }
|
|
|
+ toRemove._indexInSceneMaterialArray = -1;
|
|
|
+ this.materials.pop();
|
|
|
}
|
|
|
this.onMaterialRemovedObservable.notifyObservers(toRemove);
|
|
|
return index;
|
|
@@ -28182,6 +28202,7 @@ var BABYLON;
|
|
|
* @param newMaterial The material to add
|
|
|
*/
|
|
|
Scene.prototype.addMaterial = function (newMaterial) {
|
|
|
+ newMaterial._indexInSceneMaterialArray = this.materials.length;
|
|
|
this.materials.push(newMaterial);
|
|
|
this.onNewMaterialAddedObservable.notifyObservers(newMaterial);
|
|
|
};
|
|
@@ -28819,10 +28840,35 @@ var BABYLON;
|
|
|
Scene.prototype.freeProcessedMaterials = function () {
|
|
|
this._processedMaterials.dispose();
|
|
|
};
|
|
|
+ Object.defineProperty(Scene.prototype, "blockfreeActiveMeshesAndRenderingGroups", {
|
|
|
+ /** Gets or sets a boolean blocking all the calls to freeActiveMeshes and freeRenderingGroups
|
|
|
+ * It can be used in order to prevent going through methods freeRenderingGroups and freeActiveMeshes several times to improve performance
|
|
|
+ * when disposing several meshes in a row or a hierarchy of meshes.
|
|
|
+ * When used, it is the responsability of the user to blockfreeActiveMeshesAndRenderingGroups back to false.
|
|
|
+ */
|
|
|
+ get: function () {
|
|
|
+ return this._preventFreeActiveMeshesAndRenderingGroups;
|
|
|
+ },
|
|
|
+ set: function (value) {
|
|
|
+ if (this._preventFreeActiveMeshesAndRenderingGroups === value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (value) {
|
|
|
+ this.freeActiveMeshes();
|
|
|
+ this.freeRenderingGroups();
|
|
|
+ }
|
|
|
+ this._preventFreeActiveMeshesAndRenderingGroups = value;
|
|
|
+ },
|
|
|
+ enumerable: true,
|
|
|
+ configurable: true
|
|
|
+ });
|
|
|
/**
|
|
|
* Clear the active meshes smart array preventing retention point in mesh dispose.
|
|
|
*/
|
|
|
Scene.prototype.freeActiveMeshes = function () {
|
|
|
+ if (this.blockfreeActiveMeshesAndRenderingGroups) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
this._activeMeshes.dispose();
|
|
|
if (this.activeCamera && this.activeCamera._activeMeshes) {
|
|
|
this.activeCamera._activeMeshes.dispose();
|
|
@@ -28840,6 +28886,9 @@ var BABYLON;
|
|
|
* Clear the info related to rendering groups preventing retention points during dispose.
|
|
|
*/
|
|
|
Scene.prototype.freeRenderingGroups = function () {
|
|
|
+ if (this.blockfreeActiveMeshesAndRenderingGroups) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
if (this._renderingManager) {
|
|
|
this._renderingManager.freeRenderingGroups();
|
|
|
}
|
|
@@ -32476,6 +32525,8 @@ var BABYLON;
|
|
|
_this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
|
|
|
/**
|
|
|
* Gets the list of instances created from this mesh
|
|
|
+ * it is not supposed to be modified manually.
|
|
|
+ * Note also that the order of the InstancedMesh wihin the array is not significant and might change.
|
|
|
* @see http://doc.babylonjs.com/how_to/how_to_use_instances
|
|
|
*/
|
|
|
_this.instances = new Array();
|
|
@@ -32505,6 +32556,12 @@ var BABYLON;
|
|
|
], ["_poseMatrix"]);
|
|
|
// Source mesh
|
|
|
_this._source = source;
|
|
|
+ if (scene.useClonedMeshhMap) {
|
|
|
+ if (!source.meshMap) {
|
|
|
+ source.meshMap = {};
|
|
|
+ }
|
|
|
+ source.meshMap[_this.uniqueId] = _this;
|
|
|
+ }
|
|
|
// Construction Params
|
|
|
// Clone parameters allowing mesh to be updated in case of parametric shapes.
|
|
|
_this._originalBuilderSideOrientation = source._originalBuilderSideOrientation;
|
|
@@ -34145,7 +34202,6 @@ var BABYLON;
|
|
|
* @param disposeMaterialAndTextures Set to true to also dispose referenced materials and textures (false by default)
|
|
|
*/
|
|
|
Mesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
|
|
|
- var _this = this;
|
|
|
if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
|
|
|
this.morphTargetManager = null;
|
|
|
if (this._geometry) {
|
|
@@ -34161,13 +34217,30 @@ var BABYLON;
|
|
|
this._onAfterRenderObservable.clear();
|
|
|
}
|
|
|
// Sources
|
|
|
- var meshes = this.getScene().meshes;
|
|
|
- meshes.forEach(function (abstractMesh) {
|
|
|
- var mesh = abstractMesh;
|
|
|
- if (mesh._source && mesh._source === _this) {
|
|
|
- mesh._source = null;
|
|
|
+ if (this._scene.useClonedMeshhMap) {
|
|
|
+ if (this.meshMap) {
|
|
|
+ for (var uniqueId in this.meshMap) {
|
|
|
+ var mesh = this.meshMap[uniqueId];
|
|
|
+ if (mesh) {
|
|
|
+ mesh._source = null;
|
|
|
+ this.meshMap[uniqueId] = undefined;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- });
|
|
|
+ if (this._source && this._source.meshMap) {
|
|
|
+ this._source.meshMap[this.uniqueId] = undefined;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ var meshes = this.getScene().meshes;
|
|
|
+ for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
|
|
|
+ var abstractMesh = meshes_1[_i];
|
|
|
+ var mesh = abstractMesh;
|
|
|
+ if (mesh._source && mesh._source === this) {
|
|
|
+ mesh._source = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
this._source = null;
|
|
|
// Instances
|
|
|
if (this._instanceDataStorage.instancesBuffer) {
|
|
@@ -35702,6 +35775,25 @@ var BABYLON;
|
|
|
}
|
|
|
return meshSubclass;
|
|
|
};
|
|
|
+ /** @hidden */
|
|
|
+ Mesh.prototype.addInstance = function (instance) {
|
|
|
+ instance._indexInSourceMeshInstanceArray = this.instances.length;
|
|
|
+ this.instances.push(instance);
|
|
|
+ };
|
|
|
+ /** @hidden */
|
|
|
+ Mesh.prototype.removeInstance = function (instance) {
|
|
|
+ // Remove from mesh
|
|
|
+ var index = instance._indexInSourceMeshInstanceArray;
|
|
|
+ if (index != -1) {
|
|
|
+ if (index !== this.instances.length - 1) {
|
|
|
+ var last = this.instances[this.instances.length - 1];
|
|
|
+ this.instances[index] = last;
|
|
|
+ last._indexInSourceMeshInstanceArray = index;
|
|
|
+ }
|
|
|
+ instance._indexInSourceMeshInstanceArray = -1;
|
|
|
+ this.instances.pop();
|
|
|
+ }
|
|
|
+ };
|
|
|
// Consts
|
|
|
/**
|
|
|
* Mesh side orientation : usually the external or front surface
|
|
@@ -36460,6 +36552,8 @@ var BABYLON;
|
|
|
* Stores the fill mode state
|
|
|
*/
|
|
|
this._fillMode = Material.TriangleFillMode;
|
|
|
+ /** @hidden */
|
|
|
+ this._indexInSceneMaterialArray = -1;
|
|
|
this.name = name;
|
|
|
this.id = name || BABYLON.Tools.RandomId();
|
|
|
this._scene = scene || BABYLON.Engine.LastCreatedScene;
|
|
@@ -36473,8 +36567,10 @@ var BABYLON;
|
|
|
this._uniformBuffer = new BABYLON.UniformBuffer(this._scene.getEngine());
|
|
|
this._useUBO = this.getScene().getEngine().supportsUniformBuffers;
|
|
|
if (!doNotAdd) {
|
|
|
- this._scene.materials.push(this);
|
|
|
- this._scene.onNewMaterialAddedObservable.notifyObservers(this);
|
|
|
+ this._scene.addMaterial(this);
|
|
|
+ }
|
|
|
+ if (scene.useMaterialMeshMap) {
|
|
|
+ this.meshMap = {};
|
|
|
}
|
|
|
}
|
|
|
Object.defineProperty(Material, "TriangleFillMode", {
|
|
@@ -37069,14 +37165,21 @@ var BABYLON;
|
|
|
* @returns an array of meshes bound to the material
|
|
|
*/
|
|
|
Material.prototype.getBindedMeshes = function () {
|
|
|
- var result = new Array();
|
|
|
- for (var index = 0; index < this._scene.meshes.length; index++) {
|
|
|
- var mesh = this._scene.meshes[index];
|
|
|
- if (mesh.material === this) {
|
|
|
- result.push(mesh);
|
|
|
+ var _this = this;
|
|
|
+ if (this.meshMap) {
|
|
|
+ var result = new Array();
|
|
|
+ for (var meshId in this.meshMap) {
|
|
|
+ var mesh = this.meshMap[meshId];
|
|
|
+ if (mesh) {
|
|
|
+ result.push(mesh);
|
|
|
+ }
|
|
|
}
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ var meshes = this._scene.meshes;
|
|
|
+ return meshes.filter(function (mesh) { return mesh.material === _this; });
|
|
|
}
|
|
|
- return result;
|
|
|
};
|
|
|
/**
|
|
|
* Force shader compilation
|
|
@@ -37242,35 +37345,33 @@ var BABYLON;
|
|
|
* Disposes the material
|
|
|
* @param forceDisposeEffect specifies if effects should be forcefully disposed
|
|
|
* @param forceDisposeTextures specifies if textures should be forcefully disposed
|
|
|
+ * @param notBoundToMesh specifies if the material that is being disposed is known to be not bound to any mesh
|
|
|
*/
|
|
|
- Material.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures) {
|
|
|
+ Material.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures, notBoundToMesh) {
|
|
|
+ var scene = this.getScene();
|
|
|
// Animations
|
|
|
- this.getScene().stopAnimation(this);
|
|
|
- this.getScene().freeProcessedMaterials();
|
|
|
+ scene.stopAnimation(this);
|
|
|
+ scene.freeProcessedMaterials();
|
|
|
// Remove from scene
|
|
|
- var index = this._scene.materials.indexOf(this);
|
|
|
- if (index >= 0) {
|
|
|
- this._scene.materials.splice(index, 1);
|
|
|
- }
|
|
|
- this._scene.onMaterialRemovedObservable.notifyObservers(this);
|
|
|
- // Remove from meshes
|
|
|
- for (index = 0; index < this._scene.meshes.length; index++) {
|
|
|
- var mesh = this._scene.meshes[index];
|
|
|
- if (mesh.material === this) {
|
|
|
- mesh.material = null;
|
|
|
- if (mesh.geometry) {
|
|
|
- var geometry = (mesh.geometry);
|
|
|
- if (this._storeEffectOnSubMeshes) {
|
|
|
- for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
|
|
|
- var subMesh = _a[_i];
|
|
|
- geometry._releaseVertexArrayObject(subMesh._materialEffect);
|
|
|
- if (forceDisposeEffect && subMesh._materialEffect) {
|
|
|
- this._scene.getEngine()._releaseEffect(subMesh._materialEffect);
|
|
|
- }
|
|
|
- }
|
|
|
+ scene.removeMaterial(this);
|
|
|
+ if (notBoundToMesh !== true) {
|
|
|
+ // Remove from meshes
|
|
|
+ if (this.meshMap) {
|
|
|
+ for (var meshId in this.meshMap) {
|
|
|
+ var mesh = this.meshMap[meshId];
|
|
|
+ if (mesh) {
|
|
|
+ mesh.material = null; // will set the entry in the map to undefined
|
|
|
+ this.releaseVertexArrayObject(mesh, forceDisposeEffect);
|
|
|
}
|
|
|
- else {
|
|
|
- geometry._releaseVertexArrayObject(this._effect);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ var meshes = scene.meshes;
|
|
|
+ for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
|
|
|
+ var mesh = meshes_1[_i];
|
|
|
+ if (mesh.material === this) {
|
|
|
+ mesh.material = null;
|
|
|
+ this.releaseVertexArrayObject(mesh, forceDisposeEffect);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -37279,7 +37380,7 @@ var BABYLON;
|
|
|
// Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
|
|
|
if (forceDisposeEffect && this._effect) {
|
|
|
if (!this._storeEffectOnSubMeshes) {
|
|
|
- this._scene.getEngine()._releaseEffect(this._effect);
|
|
|
+ scene.getEngine()._releaseEffect(this._effect);
|
|
|
}
|
|
|
this._effect = null;
|
|
|
}
|
|
@@ -37293,6 +37394,25 @@ var BABYLON;
|
|
|
this._onUnBindObservable.clear();
|
|
|
}
|
|
|
};
|
|
|
+ /** @hidden */
|
|
|
+ Material.prototype.releaseVertexArrayObject = function (mesh, forceDisposeEffect) {
|
|
|
+ if (mesh.geometry) {
|
|
|
+ var geometry = (mesh.geometry);
|
|
|
+ var scene = this.getScene();
|
|
|
+ if (this._storeEffectOnSubMeshes) {
|
|
|
+ for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
|
|
|
+ var subMesh = _a[_i];
|
|
|
+ geometry._releaseVertexArrayObject(subMesh._materialEffect);
|
|
|
+ if (forceDisposeEffect && subMesh._materialEffect) {
|
|
|
+ scene.getEngine()._releaseEffect(subMesh._materialEffect);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ geometry._releaseVertexArrayObject(this._effect);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
/**
|
|
|
* Serializes this material
|
|
|
* @returns the serialized material object
|
|
@@ -37925,9 +38045,11 @@ var BABYLON;
|
|
|
if (this._noUBO) {
|
|
|
return;
|
|
|
}
|
|
|
- var index = this._engine._uniformBuffers.indexOf(this);
|
|
|
+ var uniformBuffers = this._engine._uniformBuffers;
|
|
|
+ var index = uniformBuffers.indexOf(this);
|
|
|
if (index !== -1) {
|
|
|
- this._engine._uniformBuffers.splice(index, 1);
|
|
|
+ uniformBuffers[index] = uniformBuffers[uniformBuffers.length - 1];
|
|
|
+ uniformBuffers.pop();
|
|
|
}
|
|
|
if (!this._buffer) {
|
|
|
return;
|
|
@@ -64452,8 +64574,9 @@ var BABYLON;
|
|
|
* Disposes the material
|
|
|
* @param forceDisposeEffect specifies if effects should be forcefully disposed
|
|
|
* @param forceDisposeTextures specifies if textures should be forcefully disposed
|
|
|
+ * @param notBoundToMesh specifies if the material that is being disposed is known to be not bound to any mesh
|
|
|
*/
|
|
|
- ShaderMaterial.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures) {
|
|
|
+ ShaderMaterial.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures, notBoundToMesh) {
|
|
|
if (forceDisposeTextures) {
|
|
|
var name;
|
|
|
for (name in this._textures) {
|
|
@@ -64467,7 +64590,7 @@ var BABYLON;
|
|
|
}
|
|
|
}
|
|
|
this._textures = {};
|
|
|
- _super.prototype.dispose.call(this, forceDisposeEffect, forceDisposeTextures);
|
|
|
+ _super.prototype.dispose.call(this, forceDisposeEffect, forceDisposeTextures, notBoundToMesh);
|
|
|
};
|
|
|
/**
|
|
|
* Serializes this material in a JSON representation
|
|
@@ -64955,7 +65078,9 @@ var BABYLON;
|
|
|
__extends(InstancedMesh, _super);
|
|
|
function InstancedMesh(name, source) {
|
|
|
var _this = _super.call(this, name, source.getScene()) || this;
|
|
|
- source.instances.push(_this);
|
|
|
+ /** @hidden */
|
|
|
+ _this._indexInSourceMeshInstanceArray = -1;
|
|
|
+ source.addInstance(_this);
|
|
|
_this._sourceMesh = source;
|
|
|
_this.position.copyFrom(source.position);
|
|
|
_this.rotation.copyFrom(source.rotation);
|
|
@@ -65250,8 +65375,7 @@ var BABYLON;
|
|
|
InstancedMesh.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
|
|
|
if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
|
|
|
// Remove from mesh
|
|
|
- var index = this._sourceMesh.instances.indexOf(this);
|
|
|
- this._sourceMesh.instances.splice(index, 1);
|
|
|
+ this._sourceMesh.removeInstance(this);
|
|
|
_super.prototype.dispose.call(this, doNotRecurse, disposeMaterialAndTextures);
|
|
|
};
|
|
|
return InstancedMesh;
|
|
@@ -65417,7 +65541,7 @@ var BABYLON;
|
|
|
* @param doNotRecurse If children should be disposed
|
|
|
*/
|
|
|
LinesMesh.prototype.dispose = function (doNotRecurse) {
|
|
|
- this._colorShader.dispose();
|
|
|
+ this._colorShader.dispose(false, false, true);
|
|
|
_super.prototype.dispose.call(this, doNotRecurse);
|
|
|
};
|
|
|
/**
|