Selaa lähdekoodia

Small improvements for morph targets

David Catuhe 8 vuotta sitten
vanhempi
commit
1b47d3a45a

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 12 - 12
dist/preview release/babylon.core.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 776 - 773
dist/preview release/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 22 - 22
dist/preview release/babylon.js


+ 52 - 14
dist/preview release/babylon.max.js

@@ -25683,7 +25683,12 @@ var BABYLON;
                 return;
             }
             this._markSubMeshesAsAttributesDirty();
-            if (this._morphTargetManager) {
+            if (this._morphTargetManager && this._morphTargetManager.vertexCount) {
+                if (this._morphTargetManager.vertexCount !== this.getTotalVertices()) {
+                    BABYLON.Tools.Error("Mesh is incompatible with morph targets. Targets and mesh must all have the same vertices count.");
+                    this.morphTargetManager = undefined;
+                    return;
+                }
                 for (var index = 0; index < this.morphTargetManager.numInfluencers; index++) {
                     var morphTarget = this.morphTargetManager.getActiveTarget(index);
                     this.geometry.setVerticesData(BABYLON.VertexBuffer.PositionKind + index, morphTarget.getPositions(), false, 3);
@@ -30722,6 +30727,7 @@ var BABYLON;
         MaterialHelper.PrepareAttributesForMorphTargets = function (attribs, mesh, defines) {
             var influencers = defines["NUM_MORPH_INFLUENCERS"];
             if (influencers > 0) {
+                var maxAttributesCount = BABYLON.Engine.LastCreatedEngine.getCaps().maxVertexAttribs;
                 var manager = mesh.morphTargetManager;
                 var normal = manager.supportsNormals && defines["NORMAL"];
                 for (var index = 0; index < influencers; index++) {
@@ -30729,6 +30735,9 @@ var BABYLON;
                     if (normal) {
                         attribs.push(BABYLON.VertexBuffer.NormalKind + index);
                     }
+                    if (attribs.length > maxAttributesCount) {
+                        BABYLON.Tools.Error("Cannot add more vertex attributes for mesh " + mesh.name);
+                    }
                 }
             }
         };
@@ -42508,6 +42517,7 @@ var BABYLON;
         Geometry.prototype.removeVerticesData = function (kind) {
             if (this._vertexBuffers[kind]) {
                 this._vertexBuffers[kind].dispose();
+                delete this._vertexBuffers[kind];
             }
         };
         Geometry.prototype.setVerticesBuffer = function (buffer) {
@@ -61521,9 +61531,13 @@ var BABYLON;
                 return this._influence;
             },
             set: function (influence) {
+                if (this._influence === influence) {
+                    return;
+                }
+                var previous = this._influence;
                 this._influence = influence;
                 if (this.onInfluenceChanged.hasObservers) {
-                    this.onInfluenceChanged.notifyObservers(this);
+                    this.onInfluenceChanged.notifyObservers(previous === 0 || influence === 0);
                 }
             },
             enumerable: true,
@@ -61572,13 +61586,22 @@ var BABYLON;
     var MorphTargetManager = (function () {
         function MorphTargetManager(scene) {
             this._targets = new Array();
+            this._targetObservable = new Array();
             this._activeTargets = new BABYLON.SmartArray(16);
             this._supportsNormals = false;
+            this._vertexCount = 0;
             if (!scene) {
                 scene = BABYLON.Engine.LastCreatedScene;
             }
             this._scene = scene;
         }
+        Object.defineProperty(MorphTargetManager.prototype, "vertexCount", {
+            get: function () {
+                return this._vertexCount;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(MorphTargetManager.prototype, "supportsNormals", {
             get: function () {
                 return this._supportsNormals;
@@ -61604,22 +61627,32 @@ var BABYLON;
             return this._activeTargets.data[index];
         };
         MorphTargetManager.prototype.addTarget = function (target) {
+            var _this = this;
+            if (this._vertexCount) {
+                if (this._vertexCount !== target.getPositions().length / 3) {
+                    BABYLON.Tools.Error("Incompatible target. Targets must all have the same vertices count.");
+                    return;
+                }
+            }
             this._targets.push(target);
-            target.onInfluenceChanged.add(this._onInfluenceChanged.bind(this));
-            this._syncActiveTargets();
+            this._targetObservable.push(target.onInfluenceChanged.add(function (needUpdate) {
+                _this._syncActiveTargets(needUpdate);
+            }));
+            this._syncActiveTargets(true);
         };
         MorphTargetManager.prototype.removeTarget = function (target) {
             var index = this._targets.indexOf(target);
             if (index >= 0) {
                 this._targets.splice(index, 1);
-                target.onInfluenceChanged.removeCallback(this._onInfluenceChanged);
-                this._syncActiveTargets();
+                target.onInfluenceChanged.remove(this._targetObservable.splice(index, 1)[0]);
+                this._vertexCount = 0;
+                this._syncActiveTargets(true);
             }
         };
-        MorphTargetManager.prototype._onInfluenceChanged = function (target) {
-            this._syncActiveTargets();
+        MorphTargetManager.prototype._onInfluenceChanged = function (needUpdate) {
+            this._syncActiveTargets(needUpdate);
         };
-        MorphTargetManager.prototype._syncActiveTargets = function () {
+        MorphTargetManager.prototype._syncActiveTargets = function (needUpdate) {
             this._activeTargets.reset();
             var tempInfluences = [];
             this._supportsNormals = true;
@@ -61629,14 +61662,19 @@ var BABYLON;
                     this._activeTargets.push(target);
                     tempInfluences.push(target.influence);
                     this._supportsNormals = this._supportsNormals && target.hasNormals;
+                    if (this._vertexCount === 0) {
+                        this._vertexCount = target.getPositions().length / 3;
+                    }
                 }
             }
             this._influences = new Float32Array(tempInfluences);
-            // Flag meshes as dirty to resync with the active targets
-            for (var _b = 0, _c = this._scene.meshes; _b < _c.length; _b++) {
-                var mesh = _c[_b];
-                if (mesh.morphTargetManager === this) {
-                    mesh._syncGeometryWithMorphTargetManager();
+            if (needUpdate) {
+                // Flag meshes as dirty to resync with the active targets
+                for (var _b = 0, _c = this._scene.meshes; _b < _c.length; _b++) {
+                    var mesh = _c[_b];
+                    if (mesh.morphTargetManager === this) {
+                        mesh._syncGeometryWithMorphTargetManager();
+                    }
                 }
             }
         };

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 776 - 773
dist/preview release/babylon.module.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 22 - 22
dist/preview release/babylon.noworker.js


+ 13 - 0
localDev/src/index.js

@@ -99,6 +99,19 @@ var createScene = function () {
 
     gui.add(button,'switch');
 
+    var disposeButton = { dispose:function(){
+         sphere.dispose();
+    }};
+
+    gui.add(disposeButton,'dispose');
+
+    var removeButton = { removeLast:function(){
+         manager.removeTarget(target3);   
+    }};
+
+    gui.add(removeButton,'removeLast');
+
+
     return scene;
 
 };

+ 5 - 0
src/Materials/babylon.materialHelper.ts

@@ -243,6 +243,7 @@
             var influencers = defines["NUM_MORPH_INFLUENCERS"];
 
             if (influencers > 0) {
+                var maxAttributesCount = Engine.LastCreatedEngine.getCaps().maxVertexAttribs;
                 var manager = (<Mesh>mesh).morphTargetManager;
                 var normal = manager.supportsNormals && defines["NORMAL"];
                 for (var index = 0; index < influencers; index++) {
@@ -251,6 +252,10 @@
                     if (normal) {
                         attribs.push(VertexBuffer.NormalKind + index);
                     }
+
+                    if (attribs.length > maxAttributesCount) {
+                        Tools.Error("Cannot add more vertex attributes for mesh " + mesh.name);
+                    }
                 }
             }
         }

+ 1 - 0
src/Mesh/babylon.geometry.ts

@@ -115,6 +115,7 @@
         public removeVerticesData(kind: string) {
             if (this._vertexBuffers[kind]) {
                 this._vertexBuffers[kind].dispose();
+                delete this._vertexBuffers[kind];
             }
         }
 

+ 7 - 1
src/Mesh/babylon.mesh.ts

@@ -2001,7 +2001,13 @@
 
             this._markSubMeshesAsAttributesDirty();
 
-            if (this._morphTargetManager) {
+            if (this._morphTargetManager && this._morphTargetManager.vertexCount) {
+                if (this._morphTargetManager.vertexCount !== this.getTotalVertices()) {
+                    Tools.Error("Mesh is incompatible with morph targets. Targets and mesh must all have the same vertices count.");
+                    this.morphTargetManager = undefined;
+                    return;
+                }
+
                 for (var index = 0; index < this.morphTargetManager.numInfluencers; index++) {
                     var morphTarget = this.morphTargetManager.getActiveTarget(index);
                     this.geometry.setVerticesData(VertexBuffer.PositionKind + index, morphTarget.getPositions(), false, 3);

+ 7 - 2
src/Morph/babylon.morphTarget.ts

@@ -4,17 +4,22 @@ module BABYLON {
         private _normals: Float32Array;
         private _influence: number;
 
-        public onInfluenceChanged = new Observable<MorphTarget>();
+        public onInfluenceChanged = new Observable<boolean>();
 
         public get influence(): number {
             return this._influence;
         }
 
         public set influence(influence: number) {
+            if (this._influence === influence) {
+                return;
+            }
+
+            var previous = this._influence;
             this._influence = influence;
 
             if (this.onInfluenceChanged.hasObservers) {
-                this.onInfluenceChanged.notifyObservers(this);
+                this.onInfluenceChanged.notifyObservers(previous === 0 || influence === 0);
             }
         }
 

+ 34 - 11
src/Morph/babylon.morphTargetManager.ts

@@ -1,10 +1,12 @@
 module BABYLON {
     export class MorphTargetManager {
         private _targets = new Array<MorphTarget>();
+        private _targetObservable = new Array<Observer<boolean>>();
         private _activeTargets = new SmartArray<MorphTarget>(16);
         private _scene: Scene;
         private _influences: Float32Array;
         private _supportsNormals = false;
+        private _vertexCount = 0;
 
         public constructor(scene?: Scene) {
             if (!scene) {
@@ -14,6 +16,10 @@ module BABYLON {
             this._scene = scene;
         }
 
+        public get vertexCount(): number {
+            return this._vertexCount
+        }
+
         public get supportsNormals(): boolean {
             return this._supportsNormals;
         }
@@ -31,25 +37,36 @@ module BABYLON {
         }
        
         public addTarget(target: MorphTarget): void {
+            if (this._vertexCount) {
+                if (this._vertexCount !== target.getPositions().length / 3) {
+                    Tools.Error("Incompatible target. Targets must all have the same vertices count.");
+                    return;
+                }
+            }
+
             this._targets.push(target);
-            target.onInfluenceChanged.add(this._onInfluenceChanged.bind(this));
-            this._syncActiveTargets();        
+            this._targetObservable.push(target.onInfluenceChanged.add(needUpdate => {
+                this._syncActiveTargets(needUpdate);
+            }));
+            this._syncActiveTargets(true);        
         }
 
         public removeTarget(target: MorphTarget): void {
             var index = this._targets.indexOf(target);
             if (index >= 0) {
                 this._targets.splice(index, 1);
-                target.onInfluenceChanged.removeCallback(this._onInfluenceChanged);
-                this._syncActiveTargets();
+
+                target.onInfluenceChanged.remove(this._targetObservable.splice(index, 1)[0]);
+                this._vertexCount = 0;
+                this._syncActiveTargets(true);
             }
         }
 
-        private _onInfluenceChanged(target: MorphTarget): void {
-            this._syncActiveTargets();
+        private _onInfluenceChanged(needUpdate: boolean): void {
+            this._syncActiveTargets(needUpdate);
         }
 
-        private _syncActiveTargets(): void {
+        private _syncActiveTargets(needUpdate: boolean): void {
             this._activeTargets.reset();
             var tempInfluences = [];
             this._supportsNormals = true;
@@ -59,15 +76,21 @@ module BABYLON {
                     tempInfluences.push(target.influence);
 
                     this._supportsNormals = this._supportsNormals && target.hasNormals;
+
+                    if (this._vertexCount === 0) {
+                        this._vertexCount = target.getPositions().length / 3;
+                    }
                 }
             }
 
             this._influences = new Float32Array(tempInfluences);
 
-            // Flag meshes as dirty to resync with the active targets
-            for (var mesh of this._scene.meshes) {
-                if ((<any>mesh).morphTargetManager === this) {
-                    (<Mesh>mesh)._syncGeometryWithMorphTargetManager();
+            if (needUpdate) {
+                // Flag meshes as dirty to resync with the active targets
+                for (var mesh of this._scene.meshes) {
+                    if ((<any>mesh).morphTargetManager === this) {
+                        (<Mesh>mesh)._syncGeometryWithMorphTargetManager();
+                    }
                 }
             }
         }