Przeglądaj źródła

Merge remote-tracking branch 'upstream/master' into Development

sevan 8 lat temu
rodzic
commit
a34a7a9db0

+ 3 - 1
Tools/Gulp/config.json

@@ -228,7 +228,9 @@
             "../../src/Materials/babylon.colorCurves.js",
             "../../src/Materials/babylon.pbrMaterial.js",
             "../../src/Debug/babylon.debugLayer.js",
-            "../../src/PostProcess/babylon.standardRenderingPipeline.js"
+            "../../src/PostProcess/babylon.standardRenderingPipeline.js",
+            "../../src/Morph/babylon.morphTarget.js",
+            "../../src/Morph/babylon.morphTargetManager.js"
         ]
     },
     "modules": [

+ 3 - 1
Tools/Gulp/custom.config.json

@@ -197,7 +197,9 @@
             "../../src/Materials/babylon.colorCurves.js",
             "../../src/Materials/babylon.pbrMaterial.js",
             "../../src/Debug/babylon.debugLayer.js",
-            "../../src/PostProcess/babylon.standardRenderingPipeline.js"
+            "../../src/PostProcess/babylon.standardRenderingPipeline.js",
+            "../../src/Morph/babylon.morphTarget.js",
+            "../../src/Morph/babylon.morphTargetManager.js"
     ]
   }
 }

Plik diff jest za duży
+ 17 - 17
dist/preview release/babylon.core.js


Plik diff jest za duży
+ 3625 - 3573
dist/preview release/babylon.d.ts


Plik diff jest za duży
+ 39 - 39
dist/preview release/babylon.js


Plik diff jest za duży
+ 328 - 39
dist/preview release/babylon.max.js


Plik diff jest za duży
+ 3625 - 3573
dist/preview release/babylon.module.d.ts


Plik diff jest za duży
+ 26 - 26
dist/preview release/babylon.noworker.js


Plik diff jest za duży
+ 3 - 3
dist/preview release/inspector/babylon.inspector.bundle.js


Plik diff jest za duży
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


+ 1 - 0
dist/preview release/what's new.md

@@ -5,6 +5,7 @@
 ### Major updates
  - WebGL2 context support. WebGL2 is now used instead of WebGL 1 when available. [More info here](http://doc.babylonjs.com/overviews/webgl2) ([deltakosh](https://github.com/deltakosh))
  - Complete WebVR 1.1 support including controllers for HTC Vive and Occulus. [More info here](http://doc.babylonjs.com/overviews/webvr_camera) ([raanan](https://github.com/raananw))
+ - Support for Morph Targets. [More info here](http://doc.babylonjs.com/tutorials/how_to_use_morphtargets) ([deltakosh](https://github.com/deltakosh))
  - Added support for Exponential Shadow maps to replace Variance Shadow maps. [more info here](http://www.babylonjs-playground.com/debug.html#1CXNXC#3) - [Demo](http://www.babylonjs.com/Demos/AdvancedShadows/) - [Demo](http://www.babylonjs-playground.com/#1CXNXC#4) ([deltakosh](https://github.com/deltakosh))
  - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
  - Support for multisample render targets. [Demo](http://www.babylonjs-playground.com/#12MKMN) ([deltakosh](https://github.com/deltakosh))

+ 113 - 1
localDev/src/index.js

@@ -1,5 +1,117 @@
 /// <reference path="../../dist/preview release/babylon.d.ts"/>
 
+var scramble = function(data) {
+    for (index = 0; index < data.length; index ++) {
+        data[index] += 0.1 * Math.random();
+    }
+}
+
 // Playground like creation of the scene
 var createScene = function () {
-}
+
+    // This creates a basic Babylon Scene object (non-mesh)
+    var scene = new BABYLON.Scene(engine);
+
+    // This creates and positions a free camera (non-mesh)
+    var camera = new BABYLON.ArcRotateCamera("camera1", 1.14, 1.13, 10, BABYLON.Vector3.Zero(), scene);
+
+    // This targets the camera to scene origin
+    camera.setTarget(BABYLON.Vector3.Zero());
+
+    // This attaches the camera to the canvas
+    camera.attachControl(canvas, true);
+
+    // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
+    var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
+
+    // Default intensity is 1. Let's dim the light a small amount
+    light.intensity = 0.7;
+
+    // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
+    var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
+
+    var sphere2 = BABYLON.Mesh.CreateSphere("sphere2", 16, 2, scene);
+    sphere2.setEnabled(false);
+    sphere2.updateMeshPositions(scramble);
+
+    var sphere3 = BABYLON.Mesh.CreateSphere("sphere3", 16, 2, scene);
+    sphere3.setEnabled(false);
+
+    sphere3.scaling = new BABYLON.Vector3(2.1, 3.5, 1.0);
+    sphere3.bakeCurrentTransformIntoVertices();
+
+    var sphere4 = BABYLON.Mesh.CreateSphere("sphere4", 16, 2, scene);
+    sphere4.setEnabled(false);
+    sphere4.updateMeshPositions(scramble);
+
+    var sphere5 = BABYLON.Mesh.CreateSphere("sphere5", 16, 2, scene);
+    sphere5.setEnabled(false);
+
+    sphere5.scaling = new BABYLON.Vector3(1.0, 0.1, 1.0);
+    sphere5.bakeCurrentTransformIntoVertices();    
+
+    var manager = new BABYLON.MorphTargetManager();
+    sphere.morphTargetManager = manager;
+
+    var target0 = BABYLON.MorphTarget.FromMesh(sphere2, "sphere2", 0.25);
+    manager.addTarget(target0);
+
+    var target1 = BABYLON.MorphTarget.FromMesh(sphere3, "sphere3", 0.25);
+    manager.addTarget(target1);
+
+    var target2 = BABYLON.MorphTarget.FromMesh(sphere4, "sphere4", 0.25);
+    manager.addTarget(target2);   
+
+    var target3 = BABYLON.MorphTarget.FromMesh(sphere5, "sphere5", 0.25);
+    manager.addTarget(target3);       
+
+    var gui = new dat.GUI();
+    var options = {
+	    influence0: 0.25,
+        influence1: 0.25,
+        influence2: 0.25,
+        influence3: 0.25,
+    }
+
+    gui.add(options, "influence0", 0, 1).onChange(function(value) {
+		target0.influence = value;
+    });
+
+    gui.add(options, "influence1", 0, 1).onChange(function(value) {
+		target1.influence = value;
+    });
+
+    gui.add(options, "influence2", 0, 1).onChange(function(value) {
+		target2.influence = value;
+    });  
+
+    gui.add(options, "influence3", 0, 1).onChange(function(value) {
+		target3.influence = value;
+    });        
+
+    var button = { switch:function(){
+         if (sphere.morphTargetManager) {
+             sphere.morphTargetManager = null;
+         } else {
+             sphere.morphTargetManager = manager;
+         }
+    }};
+
+    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;
+
+};

+ 1 - 1
src/Materials/babylon.effect.ts

@@ -363,7 +363,7 @@
                                 maxIndex = this._indexParameters[indexSplits[1]];
                             }
 
-                            for (var i = minIndex; i <= maxIndex; i++) {
+                            for (var i = minIndex; i < maxIndex; i++) {
                                 includeContent += sourceIncludeContent.replace(/\{X\}/g, i) + "\n";
                             }
                         } else {

+ 52 - 2
src/Materials/babylon.materialHelper.ts

@@ -32,13 +32,17 @@
             }
         }
 
-        public static PrepareDefinesForAttributes(mesh: AbstractMesh, defines: MaterialDefines, useVertexColor: boolean, useBones: boolean): void {
+        public static PrepareDefinesForAttributes(mesh: AbstractMesh, defines: MaterialDefines, useVertexColor: boolean, useBones: boolean, useMorphTargets = false): void {
             if (!defines._areAttributesDirty) {
                 return;
-            }
+            }               
 
             defines["NORMAL"] = (defines._needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind));
 
+            if (defines._needNormals && mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
+                defines["TANGENT"] = true;
+            }
+
             if (defines._needUVs) {
                 defines["UV1"] = mesh.isVerticesDataPresent(VertexBuffer.UVKind);
                 defines["UV2"] = mesh.isVerticesDataPresent(VertexBuffer.UV2Kind);
@@ -61,6 +65,19 @@
                     defines["BonesPerMesh"] = 0;
                 }           
             }
+
+            if (useMorphTargets) {
+                if ((<any>mesh).morphTargetManager) {
+                    var manager = (<Mesh>mesh).morphTargetManager;
+                    defines["MORPHTARGETS_NORMAL"] = manager.supportsNormals && defines["NORMAL"] ;
+                    defines["MORPHTARGETS"] = (manager.numInfluencers > 0);
+                    defines["NUM_MORPH_INFLUENCERS"] = manager.numInfluencers;
+                } else {
+                    defines["MORPHTARGETS_NORMAL"] = false;
+                    defines["MORPHTARGETS"] = false;
+                    defines["NUM_MORPH_INFLUENCERS"] = 0;
+                }
+            }
         }
 
         public static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: MaterialDefines, specularSupported: boolean, maxSimultaneousLights = 4, disableLighting = false): boolean {
@@ -188,6 +205,10 @@
 
                 samplersList.push("shadowSampler" + lightIndex);
             }
+
+            if (defines["NUM_MORPH_INFLUENCERS"]) {
+                uniformsList.push("morphTargetInfluences");
+            }
         }
 
         public static HandleFallbacksForShadows(defines: MaterialDefines, fallbacks: EffectFallbacks, maxSimultaneousLights = 4): void {
@@ -218,6 +239,27 @@
             }
         }
 
+        public static PrepareAttributesForMorphTargets(attribs: string[], mesh: AbstractMesh, defines: MaterialDefines): void {
+            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++) {
+                    attribs.push(VertexBuffer.PositionKind + index);
+
+                    if (normal) {
+                        attribs.push(VertexBuffer.NormalKind + index);
+                    }
+
+                    if (attribs.length > maxAttributesCount) {
+                        Tools.Error("Cannot add more vertex attributes for mesh " + mesh.name);
+                    }
+                }
+            }
+        }
+
         public static PrepareAttributesForBones(attribs: string[], mesh: AbstractMesh, defines: MaterialDefines, fallbacks: EffectFallbacks): void {
             if (defines["NUM_BONE_INFLUENCERS"] > 0) {
                 fallbacks.addCPUSkinningFallback(0, mesh);
@@ -319,6 +361,14 @@
             }
         }
 
+        public static BindMorphTargetParameters(abstractMesh: AbstractMesh, effect: Effect): void {
+            if (!abstractMesh || !(<Mesh>abstractMesh).morphTargetManager) {
+                return;
+            }
+
+            effect.setFloatArray("morphTargetInfluences", (<Mesh>abstractMesh).morphTargetManager.influences);
+        }
+
         public static BindLogDepth(defines: MaterialDefines, effect: Effect, scene: Scene): void {
             if (defines["LOGARITHMICDEPTH"]) {
                 effect.setFloat("logarithmicDepthConstant", 2.0 / (Math.log(scene.activeCamera.maxZ + 1.0) / Math.LN2));

+ 18 - 1
src/Materials/babylon.pbrMaterial.ts

@@ -76,6 +76,10 @@
         public AOSTOREINMETALMAPRED = false;
         public MICROSURFACEMAP = false;
 
+        public MORPHTARGETS = false;
+        public MORPHTARGETS_NORMAL = false;
+        public NUM_MORPH_INFLUENCERS = 0;
+
         constructor() {
             super();
             this.rebuild();
@@ -1012,6 +1016,13 @@
                 if (useInstances) {
                     this._defines.INSTANCES = true;
                 }
+
+               if ((<any>mesh).morphTargetManager) {
+                    var manager = (<Mesh>mesh).morphTargetManager;
+                    this._defines.MORPHTARGETS_NORMAL = manager.supportsNormals && this._defines.NORMAL;
+                    this._defines.MORPHTARGETS = (manager.numInfluencers > 0);
+                    this._defines.NUM_MORPH_INFLUENCERS = manager.numInfluencers;
+                }
             }
 
             // Get correct effect
@@ -1109,6 +1120,7 @@
 
                 MaterialHelper.PrepareAttributesForBones(attribs, mesh, this._defines, fallbacks);
                 MaterialHelper.PrepareAttributesForInstances(attribs, this._defines);
+                MaterialHelper.PrepareAttributesForMorphTargets(attribs, mesh, this._defines);
 
                 // Legacy browser patch
                 var join = this._defines.toString();
@@ -1137,7 +1149,7 @@
                 
                 this._effect = scene.getEngine().createEffect("pbr",
                     attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, {maxSimultaneousLights: this.maxSimultaneousLights});
+                    join, fallbacks, this.onCompiled, this.onError, {maxSimultaneousLights: this.maxSimultaneousLights, maxSimultaneousMorphTargets: this._defines.NUM_MORPH_INFLUENCERS});
             }
             if (!this._effect.isReady()) {
                 return false;
@@ -1379,6 +1391,11 @@
                 // Fog
                 MaterialHelper.BindFogParameters(this._myScene, mesh, this._effect);
 
+                // Morph targets
+                if (this._defines.NUM_MORPH_INFLUENCERS) {
+                    MaterialHelper.BindMorphTargetParameters(mesh, this._effect);                
+                }
+
                 this._lightingInfos.x = this.directIntensity;
                 this._lightingInfos.y = this.emissiveIntensity;
                 this._lightingInfos.z = this.environmentIntensity;

+ 11 - 2
src/Materials/babylon.standardMaterial.ts

@@ -59,6 +59,9 @@ module BABYLON {
         public SHADOWFULLFLOAT = false;
         public CAMERACOLORGRADING = false;
         public CAMERACOLORCURVES = false;
+        public MORPHTARGETS = false;
+        public MORPHTARGETS_NORMAL = false;
+        public NUM_MORPH_INFLUENCERS = 0;
 
         constructor() {
             super();
@@ -586,7 +589,7 @@ module BABYLON {
             MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, defines);
 
             // Attribs
-            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true);
 
             // Values that need to be evaluated on every frame
             MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
@@ -687,6 +690,7 @@ module BABYLON {
 
                 MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
                 MaterialHelper.PrepareAttributesForInstances(attribs, defines);
+                MaterialHelper.PrepareAttributesForMorphTargets(attribs, mesh, defines);
                 
                 var shaderName = "default";
 
@@ -717,7 +721,7 @@ module BABYLON {
 
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
                     attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this._maxSimultaneousLights - 1 }), defines);
+                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this._maxSimultaneousLights, maxSimultaneousMorphTargets: defines.NUM_MORPH_INFLUENCERS }), defines);
             }
 
             if (!subMesh.effect.isReady()) {
@@ -910,6 +914,11 @@ module BABYLON {
                 // Fog
                 MaterialHelper.BindFogParameters(scene, mesh, effect);
 
+                // Morph targets
+                if (defines.NUM_MORPH_INFLUENCERS) {
+                    MaterialHelper.BindMorphTargetParameters(mesh, effect);                
+                }
+
                 // Log. depth
                 MaterialHelper.BindLogDepth(defines, effect, scene);
 

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

@@ -112,6 +112,13 @@
             this.setVerticesBuffer(buffer);
         }
 
+        public removeVerticesData(kind: string) {
+            if (this._vertexBuffers[kind]) {
+                this._vertexBuffers[kind].dispose();
+                delete this._vertexBuffers[kind];
+            }
+        }
+
         public setVerticesBuffer(buffer: VertexBuffer): void {
             var kind = buffer.getKind();
             if (this._vertexBuffers[kind]) {

+ 56 - 0
src/Mesh/babylon.mesh.ts

@@ -100,6 +100,21 @@
         private _LODLevels = new Array<Internals.MeshLODLevel>();
         public onLODLevelSelection: (distance: number, mesh: Mesh, selectedLevel: Mesh) => void;
 
+        // Morph
+        private _morphTargetManager: MorphTargetManager;
+
+        public get morphTargetManager(): MorphTargetManager {
+            return this._morphTargetManager;
+        }
+
+        public set morphTargetManager(value: MorphTargetManager) {
+            if (this._morphTargetManager === value) {
+                return;
+            }
+            this._morphTargetManager = value;
+            this._syncGeometryWithMorphTargetManager();
+        }
+
         // Private
         public _geometry: Geometry;
         public _delayInfo; //ANY
@@ -1417,6 +1432,8 @@
          * This also frees the memory allocated under the hood to all the buffers used by WebGL.
          */
         public dispose(doNotRecurse?: boolean): void {
+            this.morphTargetManager = undefined;
+
             if (this._geometry) {
                 this._geometry.releaseForMesh(this, true);
             }
@@ -1976,6 +1993,45 @@
                 serializationObject.actions = this.actionManager.serialize(this.name);
             }
         }
+        
+        public _syncGeometryWithMorphTargetManager() {
+            if (!this.geometry) {
+                return;
+            }
+
+            this._markSubMeshesAsAttributesDirty();
+
+            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);
+
+                    if (morphTarget.hasNormals) {
+                        this.geometry.setVerticesData(VertexBuffer.NormalKind + index, morphTarget.getNormals(), false, 3);
+                    }
+                }
+            } else {
+                var index = 0;
+                
+                // Positions
+                while (this.geometry.isVerticesDataPresent(VertexBuffer.PositionKind + index))
+                {
+                    this.geometry.removeVerticesData(VertexBuffer.PositionKind + index);
+                    
+                    if (this.geometry.isVerticesDataPresent(VertexBuffer.NormalKind + index))
+                    {
+                        this.geometry.removeVerticesData(VertexBuffer.NormalKind + index);
+                    }
+                    index++;
+                }    
+            }
+        }
 
         // Statics
         /**

+ 67 - 0
src/Morph/babylon.morphTarget.ts

@@ -0,0 +1,67 @@
+module BABYLON {
+    export class MorphTarget {
+        private _positions: Float32Array;
+        private _normals: Float32Array;
+        private _influence: number;
+
+        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(previous === 0 || influence === 0);
+            }
+        }
+
+        public constructor(public name: string, influence = 0) {
+            this.influence = influence;
+        }
+
+        public get hasNormals(): boolean {
+            return this._normals !== undefined;
+        }
+
+        public setPositions(data: Float32Array | number[]) {
+            this._positions = new Float32Array(data);
+        }
+
+        public getPositions(): Float32Array {
+            return this._positions;
+        }
+
+        public setNormals(data: Float32Array | number[]) {
+            this._normals = new Float32Array(data);
+        }
+
+        public getNormals(): Float32Array {
+            return this._normals;
+        }
+
+        // Statics
+        public static FromMesh(mesh: AbstractMesh, name?: string, influence?: number): MorphTarget {
+            if (!name) {
+                name = mesh.name;
+            }
+
+            var result = new MorphTarget(name, influence);
+
+            result.setPositions(mesh.getVerticesData(VertexBuffer.PositionKind));
+
+            if (mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                result.setNormals(mesh.getVerticesData(VertexBuffer.NormalKind));
+            }
+
+            return result;
+        }
+    }
+}

+ 98 - 0
src/Morph/babylon.morphTargetManager.ts

@@ -0,0 +1,98 @@
+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) {
+                scene = Engine.LastCreatedScene;
+            }
+
+            this._scene = scene;
+        }
+
+        public get vertexCount(): number {
+            return this._vertexCount
+        }
+
+        public get supportsNormals(): boolean {
+            return this._supportsNormals;
+        }
+
+        public get numInfluencers(): number {
+            return this._activeTargets.length;
+        }
+
+        public get influences(): Float32Array {
+            return this._influences;
+        }
+
+        public getActiveTarget(index: number): MorphTarget {
+            return this._activeTargets.data[index];
+        }
+       
+        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);
+            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.remove(this._targetObservable.splice(index, 1)[0]);
+                this._vertexCount = 0;
+                this._syncActiveTargets(true);
+            }
+        }
+
+        private _onInfluenceChanged(needUpdate: boolean): void {
+            this._syncActiveTargets(needUpdate);
+        }
+
+        private _syncActiveTargets(needUpdate: boolean): void {
+            this._activeTargets.reset();
+            var tempInfluences = [];
+            this._supportsNormals = true;
+            for (var target of this._targets) {
+                if (target.influence > 0) {
+                    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);
+
+            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();
+                    }
+                }
+            }
+        }
+    }
+}

+ 7 - 0
src/Shaders/ShadersInclude/morphTargetsVertex.fx

@@ -0,0 +1,7 @@
+#ifdef MORPHTARGETS
+	positionUpdated += (position{X} - position) * morphTargetInfluences[{X}];
+	
+	#ifdef MORPHTARGETS_NORMAL
+	normalUpdated += (normal{X} - normal) * morphTargetInfluences[{X}];
+	#endif	
+#endif

+ 7 - 0
src/Shaders/ShadersInclude/morphTargetsVertexDeclaration.fx

@@ -0,0 +1,7 @@
+#ifdef MORPHTARGETS
+	attribute vec3 position{X};
+
+	#ifdef MORPHTARGETS_NORMAL
+	attribute vec3 normal{X};
+	#endif
+#endif

+ 3 - 0
src/Shaders/ShadersInclude/morphTargetsVertexGlobalDeclaration.fx

@@ -0,0 +1,3 @@
+#ifdef MORPHTARGETS
+	uniform float morphTargetInfluences[NUM_MORPH_INFLUENCERS];
+#endif

+ 15 - 5
src/Shaders/default.vertex.fx

@@ -85,6 +85,9 @@ varying vec4 vColor;
 #include<fogVertexDeclaration>
 #include<shadowsVertexDeclaration>[0..maxSimultaneousLights]
 
+#include<morphTargetsVertexGlobalDeclaration>
+#include<morphTargetsVertexDeclaration>[0..maxSimultaneousMorphTargets]
+
 #ifdef REFLECTIONMAP_SKYBOX
 varying vec3 vPositionUVW;
 #endif
@@ -96,24 +99,31 @@ varying vec3 vDirectionW;
 #include<logDepthDeclaration>
 
 void main(void) {
+	vec3 positionUpdated = position;
+#ifdef NORMAL	
+	vec3 normalUpdated = normal;
+#endif
+
+#include<morphTargetsVertex>[0..maxSimultaneousMorphTargets]
+
 #ifdef REFLECTIONMAP_SKYBOX
-	vPositionUVW = position;
+	vPositionUVW = positionUpdated;
 #endif 
 
 #include<instancesVertex>
 #include<bonesVertex>
 
-	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
+	gl_Position = viewProjection * finalWorld * vec4(positionUpdated, 1.0);
 
-	vec4 worldPos = finalWorld * vec4(position, 1.0);
+	vec4 worldPos = finalWorld * vec4(positionUpdated, 1.0);
 	vPositionW = vec3(worldPos);
 
 #ifdef NORMAL
-	vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
+	vNormalW = normalize(vec3(finalWorld * vec4(normalUpdated, 0.0)));
 #endif
 
 #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
-	vDirectionW = normalize(vec3(finalWorld * vec4(position, 0.0)));
+	vDirectionW = normalize(vec3(finalWorld * vec4(positionUpdated, 0.0)));
 #endif
 
 	// Texture coordinates

+ 15 - 5
src/Shaders/pbr.vertex.fx

@@ -94,6 +94,9 @@ varying vec4 vColor;
 #include<fogVertexDeclaration>
 #include<shadowsVertexDeclaration>[0..maxSimultaneousLights]
 
+#include<morphTargetsVertexGlobalDeclaration>
+#include<morphTargetsVertexDeclaration>[0..maxSimultaneousMorphTargets]
+
 #ifdef REFLECTIONMAP_SKYBOX
 varying vec3 vPositionUVW;
 #endif
@@ -105,24 +108,31 @@ varying vec3 vDirectionW;
 #include<logDepthDeclaration>
 
 void main(void) {
+	vec3 positionUpdated = position;
+#ifdef NORMAL	
+	vec3 normalUpdated = normal;
+#endif
+
+#include<morphTargetsVertex>[0..maxSimultaneousMorphTargets]
+
 #ifdef REFLECTIONMAP_SKYBOX
-    vPositionUVW = position;
+    vPositionUVW = positionUpdated;
 #endif 
 
 #include<instancesVertex>
 #include<bonesVertex>
 
-    gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
+    gl_Position = viewProjection * finalWorld * vec4(positionUpdated, 1.0);
 
-    vec4 worldPos = finalWorld * vec4(position, 1.0);
+    vec4 worldPos = finalWorld * vec4(positionUpdated, 1.0);
     vPositionW = vec3(worldPos);
 
 #ifdef NORMAL
-    vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
+    vNormalW = normalize(vec3(finalWorld * vec4(normalUpdated, 0.0)));
 #endif
 
 #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
-    vDirectionW = normalize(vec3(finalWorld * vec4(position, 0.0)));
+    vDirectionW = normalize(vec3(finalWorld * vec4(positionUpdated, 0.0)));
 #endif
 
     // Texture coordinates