Browse Source

Fixing LinesMesh cloning

David catuhe 10 years ago
parent
commit
2931ae3e7c
35 changed files with 1846 additions and 1769 deletions
  1. 1598 1589
      dist/preview release - beta/babylon.2.2.d.ts
  2. 34 27
      dist/preview release - beta/babylon.2.2.js
  3. 70 34
      dist/preview release - beta/babylon.2.2.max.js
  4. 33 26
      dist/preview release - beta/babylon.2.2.noworker.js
  5. 0 1
      src/Cameras/VR/babylon.vrDeviceOrientationCamera.js
  6. 0 1
      src/Cameras/VR/babylon.webVRCamera.js
  7. 0 1
      src/Culling/Octrees/babylon.octree.js
  8. 0 1
      src/Culling/Octrees/babylon.octreeBlock.js
  9. 0 1
      src/Lights/Shadows/babylon.shadowGenerator.js
  10. 0 1
      src/Loading/Plugins/babylon.babylonFileLoader.js
  11. 0 1
      src/Materials/Textures/Procedurals/babylon.customProceduralTexture.js
  12. 0 1
      src/Materials/Textures/Procedurals/babylon.proceduralTexture.js
  13. 0 1
      src/Materials/Textures/Procedurals/babylon.standardProceduralTexture.js
  14. 0 1
      src/Materials/Textures/babylon.baseTexture.js
  15. 0 1
      src/Materials/Textures/babylon.cubeTexture.js
  16. 0 1
      src/Materials/Textures/babylon.dynamicTexture.js
  17. 0 1
      src/Materials/Textures/babylon.mirrorTexture.js
  18. 0 1
      src/Materials/Textures/babylon.rawTexture.js
  19. 0 1
      src/Materials/Textures/babylon.renderTargetTexture.js
  20. 0 1
      src/Materials/Textures/babylon.texture.js
  21. 0 1
      src/Materials/Textures/babylon.videoTexture.js
  22. 37 8
      src/Math/babylon.math.js
  23. 6 5
      src/Math/babylon.math.ts
  24. 6 4
      src/Mesh/babylon.linesMesh.js
  25. 6 6
      src/Mesh/babylon.linesMesh.ts
  26. 2 2
      src/Mesh/babylon.mesh.js
  27. 2 2
      src/Mesh/babylon.mesh.ts
  28. 0 1
      src/Physics/Plugins/babylon.cannonJSPlugin.js
  29. 0 1
      src/Physics/Plugins/babylon.oimoJSPlugin.js
  30. 0 1
      src/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.js
  31. 0 1
      src/PostProcess/RenderPipeline/babylon.postProcessRenderPass.js
  32. 0 1
      src/PostProcess/RenderPipeline/babylon.postProcessRenderPipeline.js
  33. 0 1
      src/PostProcess/RenderPipeline/babylon.postProcessRenderPipelineManager.js
  34. 24 19
      src/Tools/babylon.tools.js
  35. 28 24
      src/Tools/babylon.tools.ts

File diff suppressed because it is too large
+ 1598 - 1589
dist/preview release - beta/babylon.2.2.d.ts


File diff suppressed because it is too large
+ 34 - 27
dist/preview release - beta/babylon.2.2.js


File diff suppressed because it is too large
+ 70 - 34
dist/preview release - beta/babylon.2.2.max.js


File diff suppressed because it is too large
+ 33 - 26
dist/preview release - beta/babylon.2.2.noworker.js


+ 0 - 1
src/Cameras/VR/babylon.vrDeviceOrientationCamera.js

@@ -46,4 +46,3 @@ var BABYLON;
     })(BABYLON.FreeCamera);
     BABYLON.VRDeviceOrientationFreeCamera = VRDeviceOrientationFreeCamera;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.vrDeviceOrientationCamera.js.map

+ 0 - 1
src/Cameras/VR/babylon.webVRCamera.js

@@ -72,4 +72,3 @@ var BABYLON;
     })(BABYLON.FreeCamera);
     BABYLON.WebVRFreeCamera = WebVRFreeCamera;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.webVRCamera.js.map

+ 0 - 1
src/Culling/Octrees/babylon.octree.js

@@ -86,4 +86,3 @@ var BABYLON;
     })();
     BABYLON.Octree = Octree;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.octree.js.map

+ 0 - 1
src/Culling/Octrees/babylon.octreeBlock.js

@@ -120,4 +120,3 @@ var BABYLON;
     })();
     BABYLON.OctreeBlock = OctreeBlock;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.octreeBlock.js.map

+ 0 - 1
src/Lights/Shadows/babylon.shadowGenerator.js

@@ -333,4 +333,3 @@ var BABYLON;
     })();
     BABYLON.ShadowGenerator = ShadowGenerator;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.shadowGenerator.js.map

+ 0 - 1
src/Loading/Plugins/babylon.babylonFileLoader.js

@@ -1427,4 +1427,3 @@ var BABYLON;
         });
     })(Internals = BABYLON.Internals || (BABYLON.Internals = {}));
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.babylonFileLoader.js.map

+ 0 - 1
src/Materials/Textures/Procedurals/babylon.customProceduralTexture.js

@@ -123,4 +123,3 @@ var BABYLON;
     })(BABYLON.ProceduralTexture);
     BABYLON.CustomProceduralTexture = CustomProceduralTexture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.customProceduralTexture.js.map

+ 0 - 1
src/Materials/Textures/Procedurals/babylon.proceduralTexture.js

@@ -248,4 +248,3 @@ var BABYLON;
     })(BABYLON.Texture);
     BABYLON.ProceduralTexture = ProceduralTexture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.proceduralTexture.js.map

+ 0 - 1
src/Materials/Textures/Procedurals/babylon.standardProceduralTexture.js

@@ -418,4 +418,3 @@ var BABYLON;
     })(BABYLON.ProceduralTexture);
     BABYLON.MarbleProceduralTexture = MarbleProceduralTexture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.standardProceduralTexture.js.map

+ 0 - 1
src/Materials/Textures/babylon.baseTexture.js

@@ -125,4 +125,3 @@ var BABYLON;
     })();
     BABYLON.BaseTexture = BaseTexture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.baseTexture.js.map

+ 0 - 1
src/Materials/Textures/babylon.cubeTexture.js

@@ -59,4 +59,3 @@ var BABYLON;
     })(BABYLON.BaseTexture);
     BABYLON.CubeTexture = CubeTexture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.cubeTexture.js.map

+ 0 - 1
src/Materials/Textures/babylon.dynamicTexture.js

@@ -92,4 +92,3 @@ var BABYLON;
     })(BABYLON.Texture);
     BABYLON.DynamicTexture = DynamicTexture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.dynamicTexture.js.map

+ 0 - 1
src/Materials/Textures/babylon.mirrorTexture.js

@@ -43,4 +43,3 @@ var BABYLON;
     })(BABYLON.RenderTargetTexture);
     BABYLON.MirrorTexture = MirrorTexture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.mirrorTexture.js.map

+ 0 - 1
src/Materials/Textures/babylon.rawTexture.js

@@ -56,4 +56,3 @@ var BABYLON;
     })(BABYLON.Texture);
     BABYLON.RawTexture = RawTexture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.rawTexture.js.map

+ 0 - 1
src/Materials/Textures/babylon.renderTargetTexture.js

@@ -165,4 +165,3 @@ var BABYLON;
     })(BABYLON.Texture);
     BABYLON.RenderTargetTexture = RenderTargetTexture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.renderTargetTexture.js.map

+ 0 - 1
src/Materials/Textures/babylon.texture.js

@@ -212,4 +212,3 @@ var BABYLON;
     })(BABYLON.BaseTexture);
     BABYLON.Texture = Texture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.texture.js.map

+ 0 - 1
src/Materials/Textures/babylon.videoTexture.js

@@ -57,4 +57,3 @@ var BABYLON;
     })(BABYLON.Texture);
     BABYLON.VideoTexture = VideoTexture;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.videoTexture.js.map

+ 37 - 8
src/Math/babylon.math.js

@@ -835,6 +835,14 @@ var BABYLON;
          * to something in order to rotate it from its local system to the given target system.
          */
         Vector3.RotationFromAxis = function (axis1, axis2, axis3) {
+            var rotation = Vector3.Zero();
+            Vector3.RotationFromAxisToRef(axis1, axis2, axis3, rotation);
+            return rotation;
+        };
+        /**
+         * The same than RotationFromAxis but updates the passed ref Vector3 parameter.
+         */
+        Vector3.RotationFromAxisToRef = function (axis1, axis2, axis3, ref) {
             var u = Vector3.Normalize(axis1);
             var w = Vector3.Normalize(axis3);
             // world axis
@@ -935,7 +943,9 @@ var BABYLON;
             if (dot < 0 && nbRevert < 2) {
                 yaw = Math.PI + yaw;
             }
-            return new Vector3(pitch, yaw, roll);
+            ref.x = pitch;
+            ref.y = yaw;
+            ref.z = roll;
         };
         return Vector3;
     })();
@@ -2815,7 +2825,13 @@ var BABYLON;
     })();
     BABYLON.Path2 = Path2;
     var Path3D = (function () {
-        function Path3D(path, firstNormal) {
+        /**
+        * new Path3D(path, normal, raw)
+        * path : an array of Vector3, the curve axis of the Path3D
+        * normal (optional) : Vector3, the first wanted normal to the curve. Ex (0, 1, 0) for a vertical normal.
+        * raw (optional, default false) : boolean, if true the returned Path3D isn't normalized. Useful to depict path acceleration or speed.
+        */
+        function Path3D(path, firstNormal, raw) {
             this.path = path;
             this._curve = new Array();
             this._distances = new Array();
@@ -2825,6 +2841,7 @@ var BABYLON;
             for (var p = 0; p < path.length; p++) {
                 this._curve[p] = path[p].clone(); // hard copy
             }
+            this._raw = raw || false;
             this._compute(firstNormal);
         }
         Path3D.prototype.getCurve = function () {
@@ -2856,16 +2873,24 @@ var BABYLON;
             var l = this._curve.length;
             // first and last tangents
             this._tangents[0] = this._getFirstNonNullVector(0);
-            this._tangents[0].normalize();
+            if (!this._raw) {
+                this._tangents[0].normalize();
+            }
             this._tangents[l - 1] = this._curve[l - 1].subtract(this._curve[l - 2]);
-            this._tangents[l - 1].normalize();
+            if (!this._raw) {
+                this._tangents[l - 1].normalize();
+            }
             // normals and binormals at first point : arbitrary vector with _normalVector()
             var tg0 = this._tangents[0];
             var pp0 = this._normalVector(this._curve[0], tg0, firstNormal);
             this._normals[0] = pp0;
-            this._normals[0].normalize();
+            if (!this._raw) {
+                this._normals[0].normalize();
+            }
             this._binormals[0] = Vector3.Cross(tg0, this._normals[0]);
-            this._binormals[0].normalize();
+            if (!this._raw) {
+                this._binormals[0].normalize();
+            }
             this._distances[0] = 0;
             // normals and binormals : next points
             var prev; // previous vector (segment)
@@ -2887,9 +2912,13 @@ var BABYLON;
                 curTang = this._tangents[i];
                 prevBinor = this._binormals[i - 1];
                 this._normals[i] = Vector3.Cross(prevBinor, curTang);
-                this._normals[i].normalize();
+                if (!this._raw) {
+                    this._normals[i].normalize();
+                }
                 this._binormals[i] = Vector3.Cross(curTang, this._normals[i]);
-                this._binormals[i].normalize();
+                if (!this._raw) {
+                    this._binormals[i].normalize();
+                }
             }
         };
         // private function getFirstNonNullVector(index)

+ 6 - 5
src/Math/babylon.math.ts

@@ -1094,10 +1094,10 @@
             // Rv3(w) = w1 = w invariant
             var u1: Vector3;
             var v1: Vector3;
-            if (Tools.WithinEpsilon(w.z, 0, Engine.Epsilon)) { 
+            if (Tools.WithinEpsilon(w.z, 0, Engine.Epsilon)) {
                 z = 1.0;
             }
-            else if (Tools.WithinEpsilon(w.x, 0, Engine.Epsilon)) { 
+            else if (Tools.WithinEpsilon(w.x, 0, Engine.Epsilon)) {
                 x = 1.0;
             }
             else {
@@ -1136,7 +1136,7 @@
             y = 0.0;
             z = 0.0;
             sign = -1;
-            if (Tools.WithinEpsilon(w.z, 0, Engine.Epsilon)) { 
+            if (Tools.WithinEpsilon(w.z, 0, Engine.Epsilon)) {
                 x = 1.0;
             }
             else {
@@ -3664,10 +3664,10 @@
                 if (!Tools.WithinEpsilon(vt.y, 1, Engine.Epsilon)) {     // search for a point in the plane 
                     point = new Vector3(0, -1, 0);
                 }
-                else if (!Tools.WithinEpsilon(vt.x, 1, Engine.Epsilon)) { 
+                else if (!Tools.WithinEpsilon(vt.x, 1, Engine.Epsilon)) {
                     point = new Vector3(1, 0, 0);
                 }
-                else if (!Tools.WithinEpsilon(vt.z, 1, Engine.Epsilon)) { 
+                else if (!Tools.WithinEpsilon(vt.z, 1, Engine.Epsilon)) {
                     point = new Vector3(0, 0, 1);
                 }
                 normal0 = Vector3.Cross(vt, point);
@@ -3843,3 +3843,4 @@
         }
     }
 }
+

+ 6 - 4
src/Mesh/babylon.linesMesh.js

@@ -8,12 +8,11 @@ var BABYLON;
 (function (BABYLON) {
     var LinesMesh = (function (_super) {
         __extends(LinesMesh, _super);
-        function LinesMesh(name, scene, updatable) {
-            if (updatable === void 0) { updatable = false; }
-            _super.call(this, name, scene);
+        function LinesMesh(name, scene, parent, source, doNotCloneChildren) {
+            if (parent === void 0) { parent = null; }
+            _super.call(this, name, scene, parent, source, doNotCloneChildren);
             this.color = new BABYLON.Color3(1, 1, 1);
             this.alpha = 1;
-            this._indices = new Array();
             this._colorShader = new BABYLON.ShaderMaterial("colorShader", scene, "color", {
                 attributes: ["position"],
                 uniforms: ["worldViewProjection", "color"],
@@ -64,6 +63,9 @@ var BABYLON;
             this._colorShader.dispose();
             _super.prototype.dispose.call(this, doNotRecurse);
         };
+        LinesMesh.prototype.clone = function (name, newParent, doNotCloneChildren) {
+            return new LinesMesh(name, this.getScene(), newParent, this, doNotCloneChildren);
+        };
         return LinesMesh;
     })(BABYLON.Mesh);
     BABYLON.LinesMesh = LinesMesh;

+ 6 - 6
src/Mesh/babylon.linesMesh.ts

@@ -4,13 +4,9 @@
         public alpha = 1;
 
         private _colorShader: ShaderMaterial;
-        private _ib: WebGLBuffer;
 
-        private _indicesLength: number;
-        private _indices = new Array<number>();
-
-        constructor(name: string, scene: Scene, updatable = false) {
-            super(name, scene);
+        constructor(name: string, scene: Scene, parent: Node = null, source?: Mesh, doNotCloneChildren?: boolean) {
+            super(name, scene, parent, source, doNotCloneChildren);
 
             this._colorShader = new ShaderMaterial("colorShader", scene, "color",
                 {
@@ -64,5 +60,9 @@
 
             super.dispose(doNotRecurse);
         }
+
+        public clone(name: string, newParent?: Node, doNotCloneChildren?: boolean): LinesMesh {
+            return new LinesMesh(name, this.getScene(), newParent, this, doNotCloneChildren);
+        }
     }
 } 

+ 2 - 2
src/Mesh/babylon.mesh.js

@@ -1223,7 +1223,7 @@ var BABYLON;
                 return linesInstance;
             }
             // lines creation
-            var lines = new BABYLON.LinesMesh(name, scene, updatable);
+            var lines = new BABYLON.LinesMesh(name, scene);
             var vertexData = BABYLON.VertexData.CreateLines(points);
             vertexData.applyToMesh(lines, updatable);
             return lines;
@@ -1277,7 +1277,7 @@ var BABYLON;
                 return linesInstance;
             }
             // dashed lines creation
-            var dashedLines = new BABYLON.LinesMesh(name, scene, updatable);
+            var dashedLines = new BABYLON.LinesMesh(name, scene);
             var vertexData = BABYLON.VertexData.CreateDashedLines(points, dashSize, gapSize, dashNb);
             vertexData.applyToMesh(dashedLines, updatable);
             dashedLines.dashSize = dashSize;

+ 2 - 2
src/Mesh/babylon.mesh.ts

@@ -1430,7 +1430,7 @@
             }
 
             // lines creation
-            var lines = new LinesMesh(name, scene, updatable);
+            var lines = new LinesMesh(name, scene);
             var vertexData = VertexData.CreateLines(points);
             vertexData.applyToMesh(lines, updatable);
             return lines;
@@ -1484,7 +1484,7 @@
                 return linesInstance;
             }
             // dashed lines creation
-            var dashedLines = new LinesMesh(name, scene, updatable);
+            var dashedLines = new LinesMesh(name, scene);
             var vertexData = VertexData.CreateDashedLines(points, dashSize, gapSize, dashNb);
             vertexData.applyToMesh(dashedLines, updatable);
             (<any>dashedLines).dashSize = dashSize;

+ 0 - 1
src/Physics/Plugins/babylon.cannonJSPlugin.js

@@ -251,4 +251,3 @@ var BABYLON;
     })();
     BABYLON.CannonJSPlugin = CannonJSPlugin;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.cannonJSPlugin.js.map

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

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

+ 0 - 1
src/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.js

@@ -138,4 +138,3 @@ var BABYLON;
     })();
     BABYLON.PostProcessRenderEffect = PostProcessRenderEffect;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.postProcessRenderEffect.js.map

+ 0 - 1
src/PostProcess/RenderPipeline/babylon.postProcessRenderPass.js

@@ -40,4 +40,3 @@ var BABYLON;
     })();
     BABYLON.PostProcessRenderPass = PostProcessRenderPass;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.postProcessRenderPass.js.map

+ 0 - 1
src/PostProcess/RenderPipeline/babylon.postProcessRenderPipeline.js

@@ -110,4 +110,3 @@ var BABYLON;
     })();
     BABYLON.PostProcessRenderPipeline = PostProcessRenderPipeline;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.postProcessRenderPipeline.js.map

+ 0 - 1
src/PostProcess/RenderPipeline/babylon.postProcessRenderPipelineManager.js

@@ -58,4 +58,3 @@ var BABYLON;
     })();
     BABYLON.PostProcessRenderPipelineManager = PostProcessRenderPipelineManager;
 })(BABYLON || (BABYLON = {}));
-//# sourceMappingURL=babylon.postProcessRenderPipelineManager.js.map

+ 24 - 19
src/Tools/babylon.tools.js

@@ -385,7 +385,7 @@ var BABYLON;
                 }
             }
         };
-        Tools.DumpFramebuffer = function (width, height, engine) {
+        Tools.DumpFramebuffer = function (width, height, engine, successCallback) {
             // Read the contents of the framebuffer
             var numberOfChannelsByLine = width * 4;
             var halfHeight = height / 2;
@@ -416,27 +416,32 @@ var BABYLON;
             castData.set(data);
             context.putImageData(imageData, 0, 0);
             var base64Image = screenshotCanvas.toDataURL();
-            //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
-            if (("download" in document.createElement("a"))) {
-                var a = window.document.createElement("a");
-                a.href = base64Image;
-                var date = new Date();
-                var stringDate = date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
-                a.setAttribute("download", "screenshot_" + stringDate + ".png");
-                window.document.body.appendChild(a);
-                a.addEventListener("click", function () {
-                    a.parentElement.removeChild(a);
-                });
-                a.click();
+            if (successCallback) {
+                successCallback(base64Image);
             }
             else {
-                var newWindow = window.open("");
-                var img = newWindow.document.createElement("img");
-                img.src = base64Image;
-                newWindow.document.body.appendChild(img);
+                //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
+                if (("download" in document.createElement("a"))) {
+                    var a = window.document.createElement("a");
+                    a.href = base64Image;
+                    var date = new Date();
+                    var stringDate = date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
+                    a.setAttribute("download", "screenshot_" + stringDate + ".png");
+                    window.document.body.appendChild(a);
+                    a.addEventListener("click", function () {
+                        a.parentElement.removeChild(a);
+                    });
+                    a.click();
+                }
+                else {
+                    var newWindow = window.open("");
+                    var img = newWindow.document.createElement("img");
+                    img.src = base64Image;
+                    newWindow.document.body.appendChild(img);
+                }
             }
         };
-        Tools.CreateScreenshot = function (engine, camera, size) {
+        Tools.CreateScreenshot = function (engine, camera, size, successCallback) {
             var width;
             var height;
             var scene = camera.getScene();
@@ -477,7 +482,7 @@ var BABYLON;
             var texture = new BABYLON.RenderTargetTexture("screenShot", size, scene, false, false);
             texture.renderList = scene.meshes;
             texture.onAfterRender = function () {
-                Tools.DumpFramebuffer(width, height, engine);
+                Tools.DumpFramebuffer(width, height, engine, successCallback);
             };
             scene.incrementRenderId();
             texture.render(true);

+ 28 - 24
src/Tools/babylon.tools.ts

@@ -462,7 +462,7 @@
             }
         }
 
-        public static DumpFramebuffer(width: number, height: number, engine: Engine): void {
+        public static DumpFramebuffer(width: number, height: number, engine: Engine, successCallback?: (data: String) => void): void {
             // Read the contents of the framebuffer
             var numberOfChannelsByLine = width * 4;
             var halfHeight = height / 2;
@@ -500,31 +500,35 @@
 
             var base64Image = screenshotCanvas.toDataURL();
 
-            //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
-            if (("download" in document.createElement("a"))) {
-                var a = window.document.createElement("a");
-                a.href = base64Image;
-                var date = new Date();
-                var stringDate = date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
-                a.setAttribute("download", "screenshot_" + stringDate + ".png");
-
-                window.document.body.appendChild(a);
-
-                a.addEventListener("click", () => {
-                    a.parentElement.removeChild(a);
-                });
-                a.click();
-
-                //Or opening a new tab with the image if it is not possible to automatically start download.
+            if (successCallback) {
+                successCallback(base64Image);
             } else {
-                var newWindow = window.open("");
-                var img = newWindow.document.createElement("img");
-                img.src = base64Image;
-                newWindow.document.body.appendChild(img);
+                //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
+                if (("download" in document.createElement("a"))) {
+                    var a = window.document.createElement("a");
+                    a.href = base64Image;
+                    var date = new Date();
+                    var stringDate = date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
+                    a.setAttribute("download", "screenshot_" + stringDate + ".png");
+
+                    window.document.body.appendChild(a);
+
+                    a.addEventListener("click", () => {
+                        a.parentElement.removeChild(a);
+                    });
+                    a.click();
+
+                    //Or opening a new tab with the image if it is not possible to automatically start download.
+                } else {
+                    var newWindow = window.open("");
+                    var img = newWindow.document.createElement("img");
+                    img.src = base64Image;
+                    newWindow.document.body.appendChild(img);
+                }
             }
         }
 
-        public static CreateScreenshot(engine: Engine, camera: Camera, size: any): void {
+        public static CreateScreenshot(engine: Engine, camera: Camera, size: any, successCallback?: (data: String) => void): void {
             var width: number;
             var height: number;
 
@@ -573,7 +577,7 @@
             texture.renderList = scene.meshes;
 
             texture.onAfterRender = () => {
-                Tools.DumpFramebuffer(width, height, engine);
+                Tools.DumpFramebuffer(width, height, engine, successCallback);
             };
 
             scene.incrementRenderId();
@@ -929,4 +933,4 @@
             }, callback);
         }
     }
-} 
+}