Browse Source

New mesh.renderOutline feature

David Catuhe 11 years ago
parent
commit
71ffc27007

+ 3 - 2
Babylon/Cameras/babylon.followCamera.js

@@ -36,7 +36,7 @@ var BABYLON;
             var vz = dz * this.cameraAcceleration * 2;
             var vz = dz * this.cameraAcceleration * 2;
 
 
             if (vx > this.maxCameraSpeed || vx < -this.maxCameraSpeed) {
             if (vx > this.maxCameraSpeed || vx < -this.maxCameraSpeed) {
-                vx = vx < 1 ? -this.maxCameraSpeed : this.maxCameraSpeed; //max speed is 20
+                vx = vx < 1 ? -this.maxCameraSpeed : this.maxCameraSpeed;
             }
             }
 
 
             if (vy > this.maxCameraSpeed || vy < -this.maxCameraSpeed) {
             if (vy > this.maxCameraSpeed || vy < -this.maxCameraSpeed) {
@@ -56,6 +56,7 @@ var BABYLON;
             this.follow(this.target);
             this.follow(this.target);
         };
         };
         return FollowCamera;
         return FollowCamera;
-    })(TargetCamera);
+    })(BABYLON.TargetCamera);
     BABYLON.FollowCamera = FollowCamera;
     BABYLON.FollowCamera = FollowCamera;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.followCamera.js.map

+ 1 - 1
Babylon/Cameras/babylon.followCamera.ts

@@ -32,7 +32,7 @@
             var vz:number = dz * this.cameraAcceleration * 2;
             var vz:number = dz * this.cameraAcceleration * 2;
 
 
             if (vx > this.maxCameraSpeed || vx < -this.maxCameraSpeed) {
             if (vx > this.maxCameraSpeed || vx < -this.maxCameraSpeed) {
-                vx = vx < 1 ? -this.maxCameraSpeed : this.maxCameraSpeed; //max speed is 20
+                vx = vx < 1 ? -this.maxCameraSpeed : this.maxCameraSpeed;
             }
             }
 
 
             if (vy > this.maxCameraSpeed || vy < -this.maxCameraSpeed) {
             if (vy > this.maxCameraSpeed || vy < -this.maxCameraSpeed) {

+ 6 - 5
Babylon/Cameras/babylon.freeCamera.js

@@ -19,7 +19,7 @@ var BABYLON;
             this.applyGravity = false;
             this.applyGravity = false;
             this.angularSensibility = 2000.0;
             this.angularSensibility = 2000.0;
             this._keys = [];
             this._keys = [];
-            this._collider = new Collider();
+            this._collider = new BABYLON.Collider();
             this._needMoveForGravity = true;
             this._needMoveForGravity = true;
             this._oldPosition = BABYLON.Vector3.Zero();
             this._oldPosition = BABYLON.Vector3.Zero();
             this._diffPosition = BABYLON.Vector3.Zero();
             this._diffPosition = BABYLON.Vector3.Zero();
@@ -134,7 +134,7 @@ var BABYLON;
             element.addEventListener("mouseout", this._onMouseOut, false);
             element.addEventListener("mouseout", this._onMouseOut, false);
             element.addEventListener("mousemove", this._onMouseMove, false);
             element.addEventListener("mousemove", this._onMouseMove, false);
 
 
-            Tools.RegisterTopRootEvents([
+            BABYLON.Tools.RegisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keyup", handler: this._onKeyUp },
                 { name: "keyup", handler: this._onKeyUp },
                 { name: "blur", handler: this._onLostFocus }
                 { name: "blur", handler: this._onLostFocus }
@@ -151,7 +151,7 @@ var BABYLON;
             element.removeEventListener("mouseout", this._onMouseOut);
             element.removeEventListener("mouseout", this._onMouseOut);
             element.removeEventListener("mousemove", this._onMouseMove);
             element.removeEventListener("mousemove", this._onMouseMove);
 
 
-            Tools.UnregisterTopRootEvents([
+            BABYLON.Tools.UnregisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keyup", handler: this._onKeyUp },
                 { name: "keyup", handler: this._onKeyUp },
                 { name: "blur", handler: this._onLostFocus }
                 { name: "blur", handler: this._onLostFocus }
@@ -178,7 +178,7 @@ var BABYLON;
             this.getScene()._getNewPosition(this._oldPosition, velocity, this._collider, 3, this._newPosition);
             this.getScene()._getNewPosition(this._oldPosition, velocity, this._collider, 3, this._newPosition);
             this._newPosition.subtractToRef(this._oldPosition, this._diffPosition);
             this._newPosition.subtractToRef(this._oldPosition, this._diffPosition);
 
 
-            if (this._diffPosition.length() > Engine.CollisionsEpsilon) {
+            if (this._diffPosition.length() > BABYLON.Engine.CollisionsEpsilon) {
                 this.position.addInPlace(this._diffPosition);
                 this.position.addInPlace(this._diffPosition);
                 if (this.onCollide) {
                 if (this.onCollide) {
                     this.onCollide(this._collider.collidedMesh);
                     this.onCollide(this._collider.collidedMesh);
@@ -234,6 +234,7 @@ var BABYLON;
             _super.prototype._update.call(this);
             _super.prototype._update.call(this);
         };
         };
         return FreeCamera;
         return FreeCamera;
-    })(TargetCamera);
+    })(BABYLON.TargetCamera);
     BABYLON.FreeCamera = FreeCamera;
     BABYLON.FreeCamera = FreeCamera;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.freeCamera.js.map

+ 21 - 21
Babylon/Cameras/babylon.freeCamera.ts

@@ -8,7 +8,7 @@
         public checkCollisions = false;
         public checkCollisions = false;
         public applyGravity = false;
         public applyGravity = false;
         public angularSensibility = 2000.0;
         public angularSensibility = 2000.0;
-        public onCollide:(collidedMesh:AbstractMesh) => void;
+        public onCollide: (collidedMesh: AbstractMesh) => void;
 
 
         private _keys = [];
         private _keys = [];
         private _collider = new Collider();
         private _collider = new Collider();
@@ -16,26 +16,26 @@
         private _oldPosition = BABYLON.Vector3.Zero();
         private _oldPosition = BABYLON.Vector3.Zero();
         private _diffPosition = BABYLON.Vector3.Zero();
         private _diffPosition = BABYLON.Vector3.Zero();
         private _newPosition = BABYLON.Vector3.Zero();
         private _newPosition = BABYLON.Vector3.Zero();
-        private _attachedElement:HTMLElement;
-        private _localDirection:Vector3;
-        private _transformedDirection:Vector3;
+        private _attachedElement: HTMLElement;
+        private _localDirection: Vector3;
+        private _transformedDirection: Vector3;
 
 
-        private _onMouseDown:(e:MouseEvent) => any;
-        private _onMouseUp:(e:MouseEvent) => any;
-        private _onMouseOut:(e:MouseEvent) => any;
-        private _onMouseMove:(e:MouseEvent) => any;
-        private _onKeyDown:(e:KeyboardEvent) => any;
-        private _onKeyUp:(e:KeyboardEvent) => any;
-        public _onLostFocus:(e:FocusEvent) => any;
+        private _onMouseDown: (e: MouseEvent) => any;
+        private _onMouseUp: (e: MouseEvent) => any;
+        private _onMouseOut: (e: MouseEvent) => any;
+        private _onMouseMove: (e: MouseEvent) => any;
+        private _onKeyDown: (e: KeyboardEvent) => any;
+        private _onKeyUp: (e: KeyboardEvent) => any;
+        public _onLostFocus: (e: FocusEvent) => any;
 
 
-        public _waitingLockedTargetId:string;
+        public _waitingLockedTargetId: string;
 
 
-        constructor(name:string, position:Vector3, scene:Scene) {
+        constructor(name: string, position: Vector3, scene: Scene) {
             super(name, position, scene);
             super(name, position, scene);
         }
         }
 
 
         // Controls
         // Controls
-        public attachControl(element:HTMLElement, noPreventDefault?:boolean):void {
+        public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
             var previousPosition;
             var previousPosition;
             var engine = this.getEngine();
             var engine = this.getEngine();
 
 
@@ -155,7 +155,7 @@
             ]);
             ]);
         }
         }
 
 
-        public detachControl(element:HTMLElement):void {
+        public detachControl(element: HTMLElement): void {
             if (this._attachedElement != element) {
             if (this._attachedElement != element) {
                 return;
                 return;
             }
             }
@@ -177,8 +177,8 @@
             }
             }
         }
         }
 
 
-        public _collideWithWorld(velocity:Vector3):void {
-            var globalPosition:Vector3;
+        public _collideWithWorld(velocity: Vector3): void {
+            var globalPosition: Vector3;
 
 
             if (this.parent) {
             if (this.parent) {
                 globalPosition = BABYLON.Vector3.TransformCoordinates(this.position, this.parent.getWorldMatrix());
                 globalPosition = BABYLON.Vector3.TransformCoordinates(this.position, this.parent.getWorldMatrix());
@@ -200,7 +200,7 @@
             }
             }
         }
         }
 
 
-        public _checkInputs():void {
+        public _checkInputs(): void {
             if (!this._localDirection) {
             if (!this._localDirection) {
                 this._localDirection = BABYLON.Vector3.Zero();
                 this._localDirection = BABYLON.Vector3.Zero();
                 this._transformedDirection = BABYLON.Vector3.Zero();
                 this._transformedDirection = BABYLON.Vector3.Zero();
@@ -227,11 +227,11 @@
             }
             }
         }
         }
 
 
-        public _decideIfNeedsToMove():boolean {
+        public _decideIfNeedsToMove(): boolean {
             return this._needMoveForGravity || Math.abs(this.cameraDirection.x) > 0 || Math.abs(this.cameraDirection.y) > 0 || Math.abs(this.cameraDirection.z) > 0;
             return this._needMoveForGravity || Math.abs(this.cameraDirection.x) > 0 || Math.abs(this.cameraDirection.y) > 0 || Math.abs(this.cameraDirection.z) > 0;
         }
         }
 
 
-        public _updatePosition():void {
+        public _updatePosition(): void {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
                 this._collideWithWorld(this.cameraDirection);
                 this._collideWithWorld(this.cameraDirection);
                 if (this.applyGravity) {
                 if (this.applyGravity) {
@@ -244,7 +244,7 @@
             }
             }
         }
         }
 
 
-        public _update():void {
+        public _update(): void {
             this._checkInputs();
             this._checkInputs();
             super._update();
             super._update();
         }
         }

+ 2 - 1
Babylon/Cameras/babylon.targetCamera.js

@@ -197,6 +197,7 @@ var BABYLON;
             return this._viewMatrix;
             return this._viewMatrix;
         };
         };
         return TargetCamera;
         return TargetCamera;
-    })(Camera);
+    })(BABYLON.Camera);
     BABYLON.TargetCamera = TargetCamera;
     BABYLON.TargetCamera = TargetCamera;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.targetCamera.js.map

+ 7 - 1
Babylon/Mesh/babylon.abstractMesh.js

@@ -25,6 +25,9 @@ var BABYLON;
             this.checkCollisions = false;
             this.checkCollisions = false;
             this.renderingGroupId = 0;
             this.renderingGroupId = 0;
             this.receiveShadows = false;
             this.receiveShadows = false;
+            this.renderOutline = false;
+            this.outlineColor = BABYLON.Color3.Red();
+            this.outlineWidth = 0.02;
             this.useOctreeForRenderingSelection = true;
             this.useOctreeForRenderingSelection = true;
             this.useOctreeForPicking = true;
             this.useOctreeForPicking = true;
             this.useOctreeForCollisions = true;
             this.useOctreeForCollisions = true;
@@ -748,7 +751,10 @@ var BABYLON;
 
 
             // Remove from scene
             // Remove from scene
             var index = this.getScene().meshes.indexOf(this);
             var index = this.getScene().meshes.indexOf(this);
-            this.getScene().meshes.splice(index, 1);
+            if (index != -1) {
+                // Remove from the scene if mesh found
+                this.getScene().meshes.splice(index, 1);
+            }
 
 
             if (!doNotRecurse) {
             if (!doNotRecurse) {
                 for (index = 0; index < this.getScene().particleSystems.length; index++) {
                 for (index = 0; index < this.getScene().particleSystems.length; index++) {

+ 8 - 5
Babylon/Mesh/babylon.abstractMesh.ts

@@ -46,6 +46,9 @@
         public material: Material;
         public material: Material;
         public receiveShadows = false;
         public receiveShadows = false;
         public actionManager: ActionManager;
         public actionManager: ActionManager;
+        public renderOutline = false;
+        public outlineColor = BABYLON.Color3.Red();
+        public outlineWidth = 0.02;
 
 
         public useOctreeForRenderingSelection = true;
         public useOctreeForRenderingSelection = true;
         public useOctreeForPicking = true;
         public useOctreeForPicking = true;
@@ -564,7 +567,7 @@
                 this._submeshesOctree = new BABYLON.Octree<SubMesh>(Octree.CreationFuncForSubMeshes, maxCapacity, maxDepth);
                 this._submeshesOctree = new BABYLON.Octree<SubMesh>(Octree.CreationFuncForSubMeshes, maxCapacity, maxDepth);
             }
             }
 
 
-            this.computeWorldMatrix(true);            
+            this.computeWorldMatrix(true);
 
 
             // Update octree
             // Update octree
             var bbox = this.getBoundingInfo().boundingBox;
             var bbox = this.getBoundingInfo().boundingBox;
@@ -593,7 +596,7 @@
 
 
         public _processCollisionsForSubMeshes(collider: Collider, transformMatrix: Matrix): void {
         public _processCollisionsForSubMeshes(collider: Collider, transformMatrix: Matrix): void {
             var subMeshes: SubMesh[];
             var subMeshes: SubMesh[];
-            var len: number;            
+            var len: number;
 
 
             // Octrees
             // Octrees
             if (this._submeshesOctree && this.useOctreeForCollisions) {
             if (this._submeshesOctree && this.useOctreeForCollisions) {
@@ -743,8 +746,8 @@
 
 
             // Remove from scene
             // Remove from scene
             var index = this.getScene().meshes.indexOf(this);
             var index = this.getScene().meshes.indexOf(this);
-            if (index != -1){
-                // Remove from the scene if mesh found
+            if (index != -1) {
+                // Remove from the scene if mesh found 
                 this.getScene().meshes.splice(index, 1);
                 this.getScene().meshes.splice(index, 1);
             }
             }
 
 
@@ -782,4 +785,4 @@
             }
             }
         }
         }
     }
     }
-}
+}

+ 26 - 0
Babylon/Mesh/babylon.mesh.js

@@ -258,6 +258,17 @@ var BABYLON;
             engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount, instancesCount);
             engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount, instancesCount);
         };
         };
 
 
+        Mesh.prototype._fullDraw = function (subMesh, useTriangles, instancesCount) {
+            if (!this._geometry || !this._geometry.getVertexBuffers() || !this._geometry.getIndexBuffer()) {
+                return;
+            }
+
+            var engine = this.getScene().getEngine();
+
+            // Draw order
+            engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount, instancesCount);
+        };
+
         Mesh.prototype.registerBeforeRender = function (func) {
         Mesh.prototype.registerBeforeRender = function (func) {
             this._onBeforeRenderCallbacks.push(func);
             this._onBeforeRenderCallbacks.push(func);
         };
         };
@@ -396,6 +407,13 @@ var BABYLON;
                 return;
                 return;
             }
             }
 
 
+            // Outline - step 1
+            var savedDepthWrite = engine.getDepthWrite();
+            if (this.renderOutline) {
+                engine.setDepthWrite(false);
+                scene.getOutlineRenderer().render(subMesh, batch);
+            }
+
             effectiveMaterial._preBind();
             effectiveMaterial._preBind();
             var effect = effectiveMaterial.getEffect();
             var effect = effectiveMaterial.getEffect();
 
 
@@ -432,6 +450,14 @@ var BABYLON;
             // Unbind
             // Unbind
             effectiveMaterial.unbind();
             effectiveMaterial.unbind();
 
 
+            // Outline - step 2
+            if (this.renderOutline && savedDepthWrite) {
+                engine.setDepthWrite(true);
+                engine.setColorWrite(false);
+                scene.getOutlineRenderer().render(subMesh, batch);
+                engine.setColorWrite(true);
+            }
+
             for (callbackIndex = 0; callbackIndex < this._onAfterRenderCallbacks.length; callbackIndex++) {
             for (callbackIndex = 0; callbackIndex < this._onAfterRenderCallbacks.length; callbackIndex++) {
                 this._onAfterRenderCallbacks[callbackIndex]();
                 this._onAfterRenderCallbacks[callbackIndex]();
             }
             }

+ 26 - 0
Babylon/Mesh/babylon.mesh.ts

@@ -262,6 +262,17 @@
             engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount, instancesCount);
             engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount, instancesCount);
         }
         }
 
 
+        public _fullDraw(subMesh: SubMesh, useTriangles: boolean, instancesCount?: number): void {
+            if (!this._geometry || !this._geometry.getVertexBuffers() || !this._geometry.getIndexBuffer()) {
+                return;
+            }
+
+            var engine = this.getScene().getEngine();
+
+            // Draw order
+            engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount, instancesCount);
+        }
+
         public registerBeforeRender(func: () => void): void {
         public registerBeforeRender(func: () => void): void {
             this._onBeforeRenderCallbacks.push(func);
             this._onBeforeRenderCallbacks.push(func);
         }
         }
@@ -401,6 +412,13 @@
                 return;
                 return;
             }
             }
 
 
+            // Outline - step 1
+            var savedDepthWrite = engine.getDepthWrite();
+            if (this.renderOutline) {
+                engine.setDepthWrite(false);
+                scene.getOutlineRenderer().render(subMesh, batch);
+            }
+
             effectiveMaterial._preBind();
             effectiveMaterial._preBind();
             var effect = effectiveMaterial.getEffect();
             var effect = effectiveMaterial.getEffect();
 
 
@@ -436,6 +454,14 @@
             // Unbind
             // Unbind
             effectiveMaterial.unbind();
             effectiveMaterial.unbind();
 
 
+            // Outline - step 2
+            if (this.renderOutline && savedDepthWrite) {
+                engine.setDepthWrite(true);
+                engine.setColorWrite(false);
+                scene.getOutlineRenderer().render(subMesh, batch);
+                engine.setColorWrite(true);
+            }
+
             for (callbackIndex = 0; callbackIndex < this._onAfterRenderCallbacks.length; callbackIndex++) {
             for (callbackIndex = 0; callbackIndex < this._onAfterRenderCallbacks.length; callbackIndex++) {
                 this._onAfterRenderCallbacks[callbackIndex]();
                 this._onAfterRenderCallbacks[callbackIndex]();
             }
             }

+ 1 - 0
Babylon/Physics/Plugins/babylon.oimoJSPlugin.js

@@ -304,3 +304,4 @@ var BABYLON;
     })();
     })();
     BABYLON.OimoJSPlugin = OimoJSPlugin;
     BABYLON.OimoJSPlugin = OimoJSPlugin;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.oimoJSPlugin.js.map

+ 113 - 0
Babylon/Rendering/babylon.outlineRenderer.js

@@ -0,0 +1,113 @@
+var BABYLON;
+(function (BABYLON) {
+    var OutlineRenderer = (function () {
+        function OutlineRenderer(scene) {
+            this._scene = scene;
+        }
+        OutlineRenderer.prototype.render = function (subMesh, batch) {
+            var scene = this._scene;
+            var engine = this._scene.getEngine();
+
+            var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances !== null);
+
+            if (!this.isReady(subMesh, hardwareInstancedRendering)) {
+                return;
+            }
+
+            var mesh = subMesh.getRenderingMesh();
+            var material = subMesh.getMaterial();
+
+            engine.enableEffect(this._effect);
+            this._effect.setFloat("offset", mesh.outlineWidth);
+            this._effect.setColor3("color", mesh.outlineColor);
+            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+
+            // Bones
+            var useBones = mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
+            if (useBones) {
+                this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
+            }
+
+            mesh._bind(subMesh, this._effect, false);
+
+            // Alpha test
+            if (material && material.needAlphaTesting()) {
+                var alphaTexture = material.getAlphaTestTexture();
+                this._effect.setTexture("diffuseSampler", alphaTexture);
+                this._effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());
+            }
+
+            if (hardwareInstancedRendering) {
+                mesh._renderWithInstances(subMesh, false, batch, this._effect, engine);
+            } else {
+                if (batch.renderSelf[subMesh._id]) {
+                    this._effect.setMatrix("world", mesh.getWorldMatrix());
+
+                    // Draw
+                    mesh._draw(subMesh, true);
+                }
+
+                if (batch.visibleInstances[subMesh._id]) {
+                    for (var instanceIndex = 0; instanceIndex < batch.visibleInstances[subMesh._id].length; instanceIndex++) {
+                        var instance = batch.visibleInstances[subMesh._id][instanceIndex];
+
+                        this._effect.setMatrix("world", instance.getWorldMatrix());
+
+                        // Draw
+                        mesh._draw(subMesh, true);
+                    }
+                }
+            }
+        };
+
+        OutlineRenderer.prototype.isReady = function (subMesh, useInstances) {
+            var defines = [];
+            var attribs = [BABYLON.VertexBuffer.PositionKind, BABYLON.VertexBuffer.NormalKind];
+
+            var mesh = subMesh.getMesh();
+            var material = subMesh.getMaterial();
+
+            // Alpha test
+            if (material && material.needAlphaTesting()) {
+                defines.push("#define ALPHATEST");
+                if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
+                    attribs.push(BABYLON.VertexBuffer.UVKind);
+                    defines.push("#define UV1");
+                }
+                if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
+                    attribs.push(BABYLON.VertexBuffer.UV2Kind);
+                    defines.push("#define UV2");
+                }
+            }
+
+            // Bones
+            if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
+                attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
+                attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
+                defines.push("#define BONES");
+                defines.push("#define BonesPerMesh " + (mesh.skeleton.bones.length + 1));
+            }
+
+            // Instances
+            if (useInstances) {
+                defines.push("#define INSTANCES");
+                attribs.push("world0");
+                attribs.push("world1");
+                attribs.push("world2");
+                attribs.push("world3");
+            }
+
+            // Get correct effect
+            var join = defines.join("\n");
+            if (this._cachedDefines != join) {
+                this._cachedDefines = join;
+                this._effect = this._scene.getEngine().createEffect("outline", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color"], ["diffuseSampler"], join);
+            }
+
+            return this._effect.isReady();
+        };
+        return OutlineRenderer;
+    })();
+    BABYLON.OutlineRenderer = OutlineRenderer;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.outlineRenderer.js.map

+ 118 - 0
Babylon/Rendering/babylon.outlineRenderer.ts

@@ -0,0 +1,118 @@
+module BABYLON {
+    export class OutlineRenderer {
+        private _scene: Scene;
+        private _effect: Effect;
+        private _cachedDefines: string;
+
+        constructor(scene: Scene) {
+            this._scene = scene;
+        }
+
+        public render(subMesh: SubMesh, batch: _InstancesBatch) {
+            var scene = this._scene;
+            var engine = this._scene.getEngine();
+
+            var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances !== null);
+
+            if (!this.isReady(subMesh, hardwareInstancedRendering)) {
+                return;
+            }
+
+            var mesh = subMesh.getRenderingMesh();
+            var material = subMesh.getMaterial();
+
+            engine.enableEffect(this._effect);
+            this._effect.setFloat("offset", mesh.outlineWidth);
+            this._effect.setColor3("color", mesh.outlineColor);
+            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+
+            // Bones
+            var useBones = mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind);
+            if (useBones) {
+                this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
+            }
+
+            mesh._bind(subMesh, this._effect, false);
+
+            // Alpha test
+            if (material && material.needAlphaTesting()) {
+                var alphaTexture = material.getAlphaTestTexture();
+                this._effect.setTexture("diffuseSampler", alphaTexture);
+                this._effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());
+            }
+
+
+            if (hardwareInstancedRendering) {
+                mesh._renderWithInstances(subMesh, false, batch, this._effect, engine);
+            } else {
+                if (batch.renderSelf[subMesh._id]) {
+                    this._effect.setMatrix("world", mesh.getWorldMatrix());
+
+                    // Draw
+                    mesh._draw(subMesh, true);
+                }
+
+                if (batch.visibleInstances[subMesh._id]) {
+                    for (var instanceIndex = 0; instanceIndex < batch.visibleInstances[subMesh._id].length; instanceIndex++) {
+                        var instance = batch.visibleInstances[subMesh._id][instanceIndex];
+
+                        this._effect.setMatrix("world", instance.getWorldMatrix());
+
+                        // Draw
+                        mesh._draw(subMesh, true);
+                    }
+                }
+            }
+        }
+
+        public isReady(subMesh: SubMesh, useInstances: boolean): boolean {
+            var defines = [];
+            var attribs = [VertexBuffer.PositionKind, VertexBuffer.NormalKind];
+
+            var mesh = subMesh.getMesh();
+            var material = subMesh.getMaterial();
+
+            // Alpha test
+            if (material && material.needAlphaTesting()) {
+                defines.push("#define ALPHATEST");
+                if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
+                    attribs.push(BABYLON.VertexBuffer.UVKind);
+                    defines.push("#define UV1");
+                }
+                if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
+                    attribs.push(BABYLON.VertexBuffer.UV2Kind);
+                    defines.push("#define UV2");
+                }
+            }
+
+            // Bones
+            if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
+                attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
+                attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
+                defines.push("#define BONES");
+                defines.push("#define BonesPerMesh " + (mesh.skeleton.bones.length + 1));
+            }
+
+            // Instances
+            if (useInstances) {
+                defines.push("#define INSTANCES");
+                attribs.push("world0");
+                attribs.push("world1");
+                attribs.push("world2");
+                attribs.push("world3");
+            }
+
+            // Get correct effect      
+            var join = defines.join("\n");
+            if (this._cachedDefines != join) {
+                this._cachedDefines = join;
+                this._effect = this._scene.getEngine().createEffect("outline",
+                    attribs,
+                    ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color"],
+                    ["diffuseSampler"], join);
+            }
+
+            return this._effect.isReady();
+        }
+    }
+} 

+ 17 - 0
Babylon/Shaders/outline.fragment.fx

@@ -0,0 +1,17 @@
+precision mediump float;
+
+uniform vec3 color;
+
+#ifdef ALPHATEST
+varying vec2 vUV;
+uniform sampler2D diffuseSampler;
+#endif
+
+void main(void) {
+#ifdef ALPHATEST
+	if (texture2D(diffuseSampler, vUV).a < 0.4)
+		discard;
+#endif
+
+	gl_FragColor = vec4(color, 1.);
+}

+ 71 - 0
Babylon/Shaders/outline.vertex.fx

@@ -0,0 +1,71 @@
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+// Attribute
+attribute vec3 position;
+attribute vec3 normal;
+
+#ifdef BONES
+attribute vec4 matricesIndices;
+attribute vec4 matricesWeights;
+#endif
+
+// Uniform
+uniform float offset;
+
+#ifdef INSTANCES
+attribute vec4 world0;
+attribute vec4 world1;
+attribute vec4 world2;
+attribute vec4 world3;
+#else
+uniform mat4 world;
+#endif
+
+uniform mat4 viewProjection;
+#ifdef BONES
+uniform mat4 mBones[BonesPerMesh];
+#endif
+
+#ifdef ALPHATEST
+varying vec2 vUV;
+uniform mat4 diffuseMatrix;
+#ifdef UV1
+attribute vec2 uv;
+#endif
+#ifdef UV2
+attribute vec2 uv2;
+#endif
+#endif
+
+void main(void)
+{
+#ifdef INSTANCES
+	mat4 finalWorld = mat4(world0, world1, world2, world3);
+#else
+	mat4 finalWorld = world;
+#endif
+
+	vec3 offsetPosition = position + normal * offset;
+
+#ifdef BONES
+	mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;
+	mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;
+	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
+	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
+	finalWorld = finalWorld * (m0 + m1 + m2 + m3);
+	gl_Position = viewProjection * finalWorld * vec4(offsetPosition, 1.0);
+#else
+	gl_Position = viewProjection * finalWorld * vec4(offsetPosition, 1.0);
+#endif
+
+#ifdef ALPHATEST
+#ifdef UV1
+	vUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));
+#endif
+#ifdef UV2
+	vUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));
+#endif
+#endif
+}

+ 13 - 8
Babylon/babylon.engine.js

@@ -58,7 +58,7 @@
     };
     };
 
 
     var prepareWebGLTexture = function (texture, gl, scene, width, height, invertY, noMipmap, isCompressed, processFunction, samplingMode) {
     var prepareWebGLTexture = function (texture, gl, scene, width, height, invertY, noMipmap, isCompressed, processFunction, samplingMode) {
-        if (typeof samplingMode === "undefined") { samplingMode = Texture.TRILINEAR_SAMPLINGMODE; }
+        if (typeof samplingMode === "undefined") { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
         var engine = scene.getEngine();
         var engine = scene.getEngine();
         var potWidth = getExponantOfTwo(width, engine.getCaps().maxTextureSize);
         var potWidth = getExponantOfTwo(width, engine.getCaps().maxTextureSize);
         var potHeight = getExponantOfTwo(height, engine.getCaps().maxTextureSize);
         var potHeight = getExponantOfTwo(height, engine.getCaps().maxTextureSize);
@@ -135,7 +135,7 @@
             this._loadedTexturesCache = new Array();
             this._loadedTexturesCache = new Array();
             this._activeTexturesCache = new Array();
             this._activeTexturesCache = new Array();
             this._compiledEffects = {};
             this._compiledEffects = {};
-            this._depthMask = false;
+            this._depthMask = true;
             this._renderingCanvas = canvas;
             this._renderingCanvas = canvas;
             this._canvasClientRect = this._renderingCanvas.getBoundingClientRect();
             this._canvasClientRect = this._renderingCanvas.getBoundingClientRect();
 
 
@@ -827,9 +827,9 @@
         };
         };
 
 
         // States
         // States
-        Engine.prototype.setState = function (culling) {
+        Engine.prototype.setState = function (culling, force) {
             // Culling
             // Culling
-            if (this._cullingState !== culling) {
+            if (this._cullingState !== culling || force) {
                 if (culling) {
                 if (culling) {
                     this._gl.cullFace(this.cullBackFaces ? this._gl.BACK : this._gl.FRONT);
                     this._gl.cullFace(this.cullBackFaces ? this._gl.BACK : this._gl.FRONT);
                     this._gl.enable(this._gl.CULL_FACE);
                     this._gl.enable(this._gl.CULL_FACE);
@@ -849,6 +849,10 @@
             }
             }
         };
         };
 
 
+        Engine.prototype.getDepthWrite = function () {
+            return this._depthMask;
+        };
+
         Engine.prototype.setDepthWrite = function (enable) {
         Engine.prototype.setDepthWrite = function (enable) {
             this._gl.depthMask(enable);
             this._gl.depthMask(enable);
             this._depthMask = enable;
             this._depthMask = enable;
@@ -920,7 +924,7 @@
 
 
         Engine.prototype.createTexture = function (url, noMipmap, invertY, scene, samplingMode) {
         Engine.prototype.createTexture = function (url, noMipmap, invertY, scene, samplingMode) {
             var _this = this;
             var _this = this;
-            if (typeof samplingMode === "undefined") { samplingMode = Texture.TRILINEAR_SAMPLINGMODE; }
+            if (typeof samplingMode === "undefined") { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
             var texture = this._gl.createTexture();
             var texture = this._gl.createTexture();
 
 
             var extension = url.substr(url.length - 4, 4).toLowerCase();
             var extension = url.substr(url.length - 4, 4).toLowerCase();
@@ -940,7 +944,7 @@
                     var header = BABYLON.Internals.TGATools.GetTGAHeader(data);
                     var header = BABYLON.Internals.TGATools.GetTGAHeader(data);
 
 
                     prepareWebGLTexture(texture, _this._gl, scene, header.width, header.height, invertY, noMipmap, false, function () {
                     prepareWebGLTexture(texture, _this._gl, scene, header.width, header.height, invertY, noMipmap, false, function () {
-                        Internals.TGATools.UploadContent(_this._gl, data);
+                        BABYLON.Internals.TGATools.UploadContent(_this._gl, data);
                     }, samplingMode);
                     }, samplingMode);
                 }, null, scene.database, true);
                 }, null, scene.database, true);
             } else if (isDDS) {
             } else if (isDDS) {
@@ -950,7 +954,7 @@
                     var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap && ((info.width >> (info.mipmapCount - 1)) == 1);
                     var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap && ((info.width >> (info.mipmapCount - 1)) == 1);
                     prepareWebGLTexture(texture, _this._gl, scene, info.width, info.height, invertY, !loadMipmap, info.isFourCC, function () {
                     prepareWebGLTexture(texture, _this._gl, scene, info.width, info.height, invertY, !loadMipmap, info.isFourCC, function () {
                         console.log("loading " + url);
                         console.log("loading " + url);
-                        Internals.DDSTools.UploadDDSLevels(_this._gl, _this.getCaps().s3tc, data, info, loadMipmap, 1);
+                        BABYLON.Internals.DDSTools.UploadDDSLevels(_this._gl, _this.getCaps().s3tc, data, info, loadMipmap, 1);
                     }, samplingMode);
                     }, samplingMode);
                 }, null, scene.database, true);
                 }, null, scene.database, true);
             } else {
             } else {
@@ -1137,7 +1141,7 @@
                     gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
                     gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
                     gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
                     gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
 
 
-                    Internals.DDSTools.UploadDDSLevels(_this._gl, _this.getCaps().s3tc, data, info, loadMipmap, 6);
+                    BABYLON.Internals.DDSTools.UploadDDSLevels(_this._gl, _this.getCaps().s3tc, data, info, loadMipmap, 6);
 
 
                     if (!noMipmap && !info.isFourCC && info.mipmapCount == 1) {
                     if (!noMipmap && !info.isFourCC && info.mipmapCount == 1) {
                         gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
                         gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
@@ -1405,3 +1409,4 @@
     })();
     })();
     BABYLON.Engine = Engine;
     BABYLON.Engine = Engine;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.engine.js.map

+ 7 - 3
Babylon/babylon.engine.ts

@@ -207,7 +207,7 @@
         private _cullingState: boolean;
         private _cullingState: boolean;
         private _compiledEffects = {};
         private _compiledEffects = {};
         private _vertexAttribArrays: boolean[];
         private _vertexAttribArrays: boolean[];
-        private _depthMask = false;
+        private _depthMask = true;
         private _cachedViewport: Viewport;
         private _cachedViewport: Viewport;
         private _cachedVertexBuffers: any;
         private _cachedVertexBuffers: any;
         private _cachedIndexBuffer: WebGLBuffer;
         private _cachedIndexBuffer: WebGLBuffer;
@@ -856,9 +856,9 @@
         }
         }
 
 
         // States
         // States
-        public setState(culling: boolean): void {
+        public setState(culling: boolean, force?: boolean): void {
             // Culling        
             // Culling        
-            if (this._cullingState !== culling) {
+            if (this._cullingState !== culling || force) {
                 if (culling) {
                 if (culling) {
                     this._gl.cullFace(this.cullBackFaces ? this._gl.BACK : this._gl.FRONT);
                     this._gl.cullFace(this.cullBackFaces ? this._gl.BACK : this._gl.FRONT);
                     this._gl.enable(this._gl.CULL_FACE);
                     this._gl.enable(this._gl.CULL_FACE);
@@ -878,6 +878,10 @@
             }
             }
         }
         }
 
 
+        public getDepthWrite(): boolean {
+            return this._depthMask;
+        }
+
         public setDepthWrite(enable: boolean): void {
         public setDepthWrite(enable: boolean): void {
             this._gl.depthMask(enable);
             this._gl.depthMask(enable);
             this._depthMask = enable;
             this._depthMask = enable;

+ 42 - 36
Babylon/babylon.scene.js

@@ -11,7 +11,7 @@
             this.cameraToUseForPointers = null;
             this.cameraToUseForPointers = null;
             // Fog
             // Fog
             this.fogMode = BABYLON.Scene.FOGMODE_NONE;
             this.fogMode = BABYLON.Scene.FOGMODE_NONE;
-            this.fogColor = new Color3(0.2, 0.2, 0.3);
+            this.fogColor = new BABYLON.Color3(0.2, 0.2, 0.3);
             this.fogDensity = 0.1;
             this.fogDensity = 0.1;
             this.fogStart = 0;
             this.fogStart = 0;
             this.fogEnd = 1000.0;
             this.fogEnd = 1000.0;
@@ -53,7 +53,7 @@
             // Imported meshes
             // Imported meshes
             this.importedMeshesFiles = new Array();
             this.importedMeshesFiles = new Array();
             this._actionManagers = new Array();
             this._actionManagers = new Array();
-            this._meshesForIntersections = new SmartArray(256);
+            this._meshesForIntersections = new BABYLON.SmartArray(256);
             this._totalVertices = 0;
             this._totalVertices = 0;
             this._activeVertices = 0;
             this._activeVertices = 0;
             this._activeParticles = 0;
             this._activeParticles = 0;
@@ -66,30 +66,31 @@
             this._animationRatio = 0;
             this._animationRatio = 0;
             this._renderId = 0;
             this._renderId = 0;
             this._executeWhenReadyTimeoutId = -1;
             this._executeWhenReadyTimeoutId = -1;
-            this._toBeDisposed = new SmartArray(256);
+            this._toBeDisposed = new BABYLON.SmartArray(256);
             this._onReadyCallbacks = new Array();
             this._onReadyCallbacks = new Array();
             this._pendingData = [];
             this._pendingData = [];
             this._onBeforeRenderCallbacks = new Array();
             this._onBeforeRenderCallbacks = new Array();
-            this._activeMeshes = new SmartArray(256);
-            this._processedMaterials = new SmartArray(256);
-            this._renderTargets = new SmartArray(256);
-            this._activeParticleSystems = new SmartArray(256);
-            this._activeSkeletons = new SmartArray(32);
+            this._activeMeshes = new BABYLON.SmartArray(256);
+            this._processedMaterials = new BABYLON.SmartArray(256);
+            this._renderTargets = new BABYLON.SmartArray(256);
+            this._activeParticleSystems = new BABYLON.SmartArray(256);
+            this._activeSkeletons = new BABYLON.SmartArray(32);
             this._activeAnimatables = new Array();
             this._activeAnimatables = new Array();
-            this._transformMatrix = Matrix.Zero();
-            this._scaledPosition = Vector3.Zero();
-            this._scaledVelocity = Vector3.Zero();
+            this._transformMatrix = BABYLON.Matrix.Zero();
+            this._scaledPosition = BABYLON.Vector3.Zero();
+            this._scaledVelocity = BABYLON.Vector3.Zero();
             this._engine = engine;
             this._engine = engine;
 
 
             engine.scenes.push(this);
             engine.scenes.push(this);
 
 
-            this._renderingManager = new RenderingManager(this);
+            this._renderingManager = new BABYLON.RenderingManager(this);
 
 
-            this.postProcessManager = new PostProcessManager(this);
+            this.postProcessManager = new BABYLON.PostProcessManager(this);
 
 
-            this.postProcessRenderPipelineManager = new PostProcessRenderPipelineManager();
+            this.postProcessRenderPipelineManager = new BABYLON.PostProcessRenderPipelineManager();
 
 
-            this._boundingBoxRenderer = new BoundingBoxRenderer(this);
+            this._boundingBoxRenderer = new BABYLON.BoundingBoxRenderer(this);
+            this._outlineRenderer = new BABYLON.OutlineRenderer(this);
 
 
             this.attachControl();
             this.attachControl();
         }
         }
@@ -122,6 +123,10 @@
             return this._boundingBoxRenderer;
             return this._boundingBoxRenderer;
         };
         };
 
 
+        Scene.prototype.getOutlineRenderer = function () {
+            return this._outlineRenderer;
+        };
+
         Scene.prototype.getEngine = function () {
         Scene.prototype.getEngine = function () {
             return this._engine;
             return this._engine;
         };
         };
@@ -228,16 +233,16 @@
                     if (pickResult.pickedMesh.actionManager) {
                     if (pickResult.pickedMesh.actionManager) {
                         switch (evt.button) {
                         switch (evt.button) {
                             case 0:
                             case 0:
-                                pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnLeftPickTrigger, ActionEvent.CreateNew(pickResult.pickedMesh));
+                                pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnLeftPickTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh));
                                 break;
                                 break;
                             case 1:
                             case 1:
-                                pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnCenterPickTrigger, ActionEvent.CreateNew(pickResult.pickedMesh));
+                                pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnCenterPickTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh));
                                 break;
                                 break;
                             case 2:
                             case 2:
-                                pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnRightPickTrigger, ActionEvent.CreateNew(pickResult.pickedMesh));
+                                pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnRightPickTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh));
                                 break;
                                 break;
                         }
                         }
-                        pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, ActionEvent.CreateNew(pickResult.pickedMesh));
+                        pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh));
                     }
                     }
                 }
                 }
 
 
@@ -248,17 +253,17 @@
 
 
             this._onKeyDown = function (evt) {
             this._onKeyDown = function (evt) {
                 if (_this.actionManager) {
                 if (_this.actionManager) {
-                    _this.actionManager.processTrigger(BABYLON.ActionManager.OnKeyDownTrigger, ActionEvent.CreateNewFromScene(_this, evt));
+                    _this.actionManager.processTrigger(BABYLON.ActionManager.OnKeyDownTrigger, BABYLON.ActionEvent.CreateNewFromScene(_this, evt));
                 }
                 }
             };
             };
 
 
             this._onKeyUp = function (evt) {
             this._onKeyUp = function (evt) {
                 if (_this.actionManager) {
                 if (_this.actionManager) {
-                    _this.actionManager.processTrigger(BABYLON.ActionManager.OnKeyUpTrigger, ActionEvent.CreateNewFromScene(_this, evt));
+                    _this.actionManager.processTrigger(BABYLON.ActionManager.OnKeyUpTrigger, BABYLON.ActionEvent.CreateNewFromScene(_this, evt));
                 }
                 }
             };
             };
 
 
-            var eventPrefix = Tools.GetPointerPrefix();
+            var eventPrefix = BABYLON.Tools.GetPointerPrefix();
             this._engine.getRenderingCanvas().addEventListener(eventPrefix + "move", this._onPointerMove, false);
             this._engine.getRenderingCanvas().addEventListener(eventPrefix + "move", this._onPointerMove, false);
             this._engine.getRenderingCanvas().addEventListener(eventPrefix + "down", this._onPointerDown, false);
             this._engine.getRenderingCanvas().addEventListener(eventPrefix + "down", this._onPointerDown, false);
 
 
@@ -267,7 +272,7 @@
         };
         };
 
 
         Scene.prototype.detachControl = function () {
         Scene.prototype.detachControl = function () {
-            var eventPrefix = Tools.GetPointerPrefix();
+            var eventPrefix = BABYLON.Tools.GetPointerPrefix();
             this._engine.getRenderingCanvas().removeEventListener(eventPrefix + "move", this._onPointerMove);
             this._engine.getRenderingCanvas().removeEventListener(eventPrefix + "move", this._onPointerMove);
             this._engine.getRenderingCanvas().removeEventListener(eventPrefix + "down", this._onPointerDown);
             this._engine.getRenderingCanvas().removeEventListener(eventPrefix + "down", this._onPointerDown);
 
 
@@ -374,7 +379,7 @@
             this.stopAnimation(target);
             this.stopAnimation(target);
 
 
             if (!animatable) {
             if (!animatable) {
-                animatable = new Animatable(this, target, from, to, loop, speedRatio, onAnimationEnd);
+                animatable = new BABYLON.Animatable(this, target, from, to, loop, speedRatio, onAnimationEnd);
             }
             }
 
 
             // Local animations
             // Local animations
@@ -716,7 +721,7 @@
                 mesh._preActivate();
                 mesh._preActivate();
 
 
                 // Intersections
                 // Intersections
-                if (mesh.actionManager && mesh.actionManager.hasSpecificTriggers([ActionManager.OnIntersectionEnterTrigger, ActionManager.OnIntersectionExitTrigger])) {
+                if (mesh.actionManager && mesh.actionManager.hasSpecificTriggers([BABYLON.ActionManager.OnIntersectionEnterTrigger, BABYLON.ActionManager.OnIntersectionExitTrigger])) {
                     this._meshesForIntersections.pushNoDuplicate(mesh);
                     this._meshesForIntersections.pushNoDuplicate(mesh);
                 }
                 }
 
 
@@ -917,17 +922,17 @@
                 for (var actionIndex = 0; actionIndex < sourceMesh.actionManager.actions.length; actionIndex++) {
                 for (var actionIndex = 0; actionIndex < sourceMesh.actionManager.actions.length; actionIndex++) {
                     var action = sourceMesh.actionManager.actions[actionIndex];
                     var action = sourceMesh.actionManager.actions[actionIndex];
 
 
-                    if (action.trigger == ActionManager.OnIntersectionEnterTrigger || action.trigger == ActionManager.OnIntersectionExitTrigger) {
+                    if (action.trigger == BABYLON.ActionManager.OnIntersectionEnterTrigger || action.trigger == BABYLON.ActionManager.OnIntersectionExitTrigger) {
                         var otherMesh = action.getTriggerParameter();
                         var otherMesh = action.getTriggerParameter();
 
 
                         var areIntersecting = otherMesh.intersectsMesh(sourceMesh, false);
                         var areIntersecting = otherMesh.intersectsMesh(sourceMesh, false);
                         var currentIntersectionInProgress = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
                         var currentIntersectionInProgress = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
 
 
-                        if (areIntersecting && currentIntersectionInProgress === -1 && action.trigger == ActionManager.OnIntersectionEnterTrigger) {
-                            sourceMesh.actionManager.processTrigger(ActionManager.OnIntersectionEnterTrigger, ActionEvent.CreateNew(sourceMesh));
+                        if (areIntersecting && currentIntersectionInProgress === -1 && action.trigger == BABYLON.ActionManager.OnIntersectionEnterTrigger) {
+                            sourceMesh.actionManager.processTrigger(BABYLON.ActionManager.OnIntersectionEnterTrigger, BABYLON.ActionEvent.CreateNew(sourceMesh));
                             sourceMesh._intersectionsInProgress.push(otherMesh);
                             sourceMesh._intersectionsInProgress.push(otherMesh);
-                        } else if (!areIntersecting && currentIntersectionInProgress > -1 && action.trigger == ActionManager.OnIntersectionExitTrigger) {
-                            sourceMesh.actionManager.processTrigger(ActionManager.OnIntersectionExitTrigger, ActionEvent.CreateNew(sourceMesh));
+                        } else if (!areIntersecting && currentIntersectionInProgress > -1 && action.trigger == BABYLON.ActionManager.OnIntersectionExitTrigger) {
+                            sourceMesh.actionManager.processTrigger(BABYLON.ActionManager.OnIntersectionExitTrigger, BABYLON.ActionEvent.CreateNew(sourceMesh));
 
 
                             var indexOfOther = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
                             var indexOfOther = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
 
 
@@ -953,7 +958,7 @@
 
 
             // Actions
             // Actions
             if (this.actionManager) {
             if (this.actionManager) {
-                this.actionManager.processTrigger(ActionManager.OnEveryFrameTrigger, null);
+                this.actionManager.processTrigger(BABYLON.ActionManager.OnEveryFrameTrigger, null);
             }
             }
 
 
             // Before render
             // Before render
@@ -1143,7 +1148,7 @@
             if (typeof maxCapacity === "undefined") { maxCapacity = 64; }
             if (typeof maxCapacity === "undefined") { maxCapacity = 64; }
             if (typeof maxDepth === "undefined") { maxDepth = 2; }
             if (typeof maxDepth === "undefined") { maxDepth = 2; }
             if (!this._selectionOctree) {
             if (!this._selectionOctree) {
-                this._selectionOctree = new BABYLON.Octree(Octree.CreationFuncForMeshes, maxCapacity, maxDepth);
+                this._selectionOctree = new BABYLON.Octree(BABYLON.Octree.CreationFuncForMeshes, maxCapacity, maxDepth);
             }
             }
 
 
             var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
@@ -1155,8 +1160,8 @@
                 var minBox = mesh.getBoundingInfo().boundingBox.minimumWorld;
                 var minBox = mesh.getBoundingInfo().boundingBox.minimumWorld;
                 var maxBox = mesh.getBoundingInfo().boundingBox.maximumWorld;
                 var maxBox = mesh.getBoundingInfo().boundingBox.maximumWorld;
 
 
-                Tools.CheckExtends(minBox, min, max);
-                Tools.CheckExtends(maxBox, min, max);
+                BABYLON.Tools.CheckExtends(minBox, min, max);
+                BABYLON.Tools.CheckExtends(maxBox, min, max);
             }
             }
 
 
             // Update octree
             // Update octree
@@ -1250,12 +1255,12 @@
             }
             }
 
 
             if (this._pointerOverMesh && this._pointerOverMesh.actionManager) {
             if (this._pointerOverMesh && this._pointerOverMesh.actionManager) {
-                this._pointerOverMesh.actionManager.processTrigger(ActionManager.OnPointerOutTrigger, ActionEvent.CreateNew(this._pointerOverMesh));
+                this._pointerOverMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPointerOutTrigger, BABYLON.ActionEvent.CreateNew(this._pointerOverMesh));
             }
             }
 
 
             this._pointerOverMesh = mesh;
             this._pointerOverMesh = mesh;
             if (this._pointerOverMesh && this._pointerOverMesh.actionManager) {
             if (this._pointerOverMesh && this._pointerOverMesh.actionManager) {
-                this._pointerOverMesh.actionManager.processTrigger(ActionManager.OnPointerOverTrigger, ActionEvent.CreateNew(this._pointerOverMesh));
+                this._pointerOverMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPointerOverTrigger, BABYLON.ActionEvent.CreateNew(this._pointerOverMesh));
             }
             }
         };
         };
 
 
@@ -1382,3 +1387,4 @@
     })();
     })();
     BABYLON.Scene = Scene;
     BABYLON.Scene = Scene;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.scene.js.map

+ 11 - 5
Babylon/babylon.scene.ts

@@ -153,6 +153,7 @@
         private _scaledVelocity = Vector3.Zero();
         private _scaledVelocity = Vector3.Zero();
 
 
         private _boundingBoxRenderer: BoundingBoxRenderer;
         private _boundingBoxRenderer: BoundingBoxRenderer;
+        private _outlineRenderer: OutlineRenderer;
 
 
         private _viewMatrix: Matrix;
         private _viewMatrix: Matrix;
         private _projectionMatrix: Matrix;
         private _projectionMatrix: Matrix;
@@ -160,7 +161,7 @@
 
 
         private _selectionOctree: Octree<AbstractMesh>;
         private _selectionOctree: Octree<AbstractMesh>;
 
 
-        private _pointerOverMesh: AbstractMesh;
+        private _pointerOverMesh: AbstractMesh;      
 
 
         // Constructor
         // Constructor
         constructor(engine: Engine) {
         constructor(engine: Engine) {
@@ -175,6 +176,7 @@
             this.postProcessRenderPipelineManager = new PostProcessRenderPipelineManager();
             this.postProcessRenderPipelineManager = new PostProcessRenderPipelineManager();
 
 
             this._boundingBoxRenderer = new BoundingBoxRenderer(this);
             this._boundingBoxRenderer = new BoundingBoxRenderer(this);
+            this._outlineRenderer = new OutlineRenderer(this);
 
 
             this.attachControl();
             this.attachControl();
         }
         }
@@ -196,6 +198,10 @@
             return this._boundingBoxRenderer;
             return this._boundingBoxRenderer;
         }
         }
 
 
+        public getOutlineRenderer(): OutlineRenderer {
+            return this._outlineRenderer;
+        }
+
         public getEngine(): Engine {
         public getEngine(): Engine {
             return this._engine;
             return this._engine;
         }
         }
@@ -1001,11 +1007,11 @@
                         var areIntersecting = otherMesh.intersectsMesh(sourceMesh, false);
                         var areIntersecting = otherMesh.intersectsMesh(sourceMesh, false);
                         var currentIntersectionInProgress = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
                         var currentIntersectionInProgress = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
 
 
-                        if (areIntersecting && currentIntersectionInProgress === -1 && action.trigger == ActionManager.OnIntersectionEnterTrigger ) {
+                        if (areIntersecting && currentIntersectionInProgress === -1 && action.trigger == ActionManager.OnIntersectionEnterTrigger) {
                             sourceMesh.actionManager.processTrigger(ActionManager.OnIntersectionEnterTrigger, ActionEvent.CreateNew(sourceMesh));
                             sourceMesh.actionManager.processTrigger(ActionManager.OnIntersectionEnterTrigger, ActionEvent.CreateNew(sourceMesh));
                             sourceMesh._intersectionsInProgress.push(otherMesh);
                             sourceMesh._intersectionsInProgress.push(otherMesh);
 
 
-                        } else if (!areIntersecting && currentIntersectionInProgress > -1 && action.trigger == ActionManager.OnIntersectionExitTrigger ) {
+                        } else if (!areIntersecting && currentIntersectionInProgress > -1 && action.trigger == ActionManager.OnIntersectionExitTrigger) {
                             sourceMesh.actionManager.processTrigger(ActionManager.OnIntersectionExitTrigger, ActionEvent.CreateNew(sourceMesh));
                             sourceMesh.actionManager.processTrigger(ActionManager.OnIntersectionExitTrigger, ActionEvent.CreateNew(sourceMesh));
 
 
                             var indexOfOther = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
                             var indexOfOther = sourceMesh._intersectionsInProgress.indexOf(otherMesh);
@@ -1015,7 +1021,7 @@
                             }
                             }
                         }
                         }
                     }
                     }
-                }                
+                }
             }
             }
         }
         }
 
 
@@ -1269,7 +1275,7 @@
             x = x / this._engine.getHardwareScalingLevel() - viewport.x;
             x = x / this._engine.getHardwareScalingLevel() - viewport.x;
             y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
             y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
             return BABYLON.Ray.CreateNew(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
             return BABYLON.Ray.CreateNew(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
-     //       return BABYLON.Ray.CreateNew(x / window.devicePixelRatio, y / window.devicePixelRatio, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
+            //       return BABYLON.Ray.CreateNew(x / window.devicePixelRatio, y / window.devicePixelRatio, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
         }
         }
 
 
         private _internalPick(rayFunction: (world: Matrix) => Ray, predicate: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): PickingInfo {
         private _internalPick(rayFunction: (world: Matrix) => Ray, predicate: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): PickingInfo {

+ 2 - 0
Tools/BuildOurOwnBabylonJS/BuildOurOwnBabylonJS/babylonJS.xml

@@ -78,6 +78,8 @@
   <script src="Babylon/Cameras/babylon.arcRotateCamera.js"></script>
   <script src="Babylon/Cameras/babylon.arcRotateCamera.js"></script>
   <script src="Babylon/Cameras/babylon.touchCamera.js"></script>
   <script src="Babylon/Cameras/babylon.touchCamera.js"></script>
   <script src="Babylon/Cameras/babylon.freeCamera.js"></script>
   <script src="Babylon/Cameras/babylon.freeCamera.js"></script>
+  <script src="Babylon/Cameras/babylon.followCamera.js"></script>
+  <script src="Babylon/Cameras/babylon.targetCamera.js"></script>
   <script src="Babylon/Cameras/babylon.camera.js"></script>
   <script src="Babylon/Cameras/babylon.camera.js"></script>
   <script src="Babylon/Collisions/babylon.collider.js"></script>
   <script src="Babylon/Collisions/babylon.collider.js"></script>
   <script src="Babylon/Lights//Shadows/babylon.shadowGenerator.js"></script>
   <script src="Babylon/Lights//Shadows/babylon.shadowGenerator.js"></script>

File diff suppressed because it is too large
+ 4 - 2
babylon.1.14-beta-debug.js


File diff suppressed because it is too large
+ 7 - 7
babylon.1.14-beta.js