Browse Source

Merge pull request #3175 from BabylonJS/master

Nightly
David Catuhe 7 năm trước cách đây
mục cha
commit
79e93747ee
60 tập tin đã thay đổi với 19507 bổ sung41050 xóa
  1. BIN
      Playground/LogoPBT.png
  2. 7350 7335
      Playground/babylon.d.txt
  3. 27 0
      Playground/css/index.css
  4. 1 0
      Playground/debug.html
  5. 1 0
      Playground/index-local.html
  6. 4 3
      Playground/index.html
  7. 1 0
      Playground/indexStable.html
  8. 2 0
      Playground/js/index.js
  9. 432 0
      Playground/js/pbt.js
  10. 14 0
      Playground/package-lock.json
  11. 9 12
      Tools/Gulp/gulpfile.js
  12. BIN
      Viewer/assets/img/close.png
  13. BIN
      Viewer/assets/img/fullscreen.png
  14. BIN
      Viewer/assets/img/help-circle.png
  15. BIN
      Viewer/assets/img/loading.png
  16. 210 0
      Viewer/assets/pep.min.js
  17. 2 2
      Viewer/assets/templates/default/navbar.html
  18. 389 2302
      Viewer/dist/viewer.js
  19. 38 0
      Viewer/dist/viewer.min.js
  20. 8 12
      Viewer/src/configuration/types/default.ts
  21. 1 0
      Viewer/src/index.ts
  22. 14 0
      Viewer/src/templateManager.ts
  23. 1 1
      Viewer/src/viewer/defaultViewer.ts
  24. 9 15
      Viewer/webpack.config.js
  25. 7101 7086
      dist/preview release/babylon.d.ts
  26. 46 46
      dist/preview release/babylon.js
  27. 136 77
      dist/preview release/babylon.max.js
  28. 0 20612
      dist/preview release/babylon.module.d.ts
  29. 47 47
      dist/preview release/babylon.worker.js
  30. 2929 2914
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  31. 48 48
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  32. 133 74
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  33. 4 1
      dist/preview release/gui/babylon.gui.js
  34. 3 3
      dist/preview release/gui/babylon.gui.min.js
  35. 263 263
      dist/preview release/inspector/babylon.inspector.bundle.js
  36. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  37. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  38. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  39. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  40. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  41. 17 1
      dist/preview release/loaders/babylonjs.loaders.js
  42. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  43. 3 0
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  44. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  45. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  46. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  47. 3 3
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  48. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  49. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  50. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  51. 1 0
      dist/preview release/what's new.md
  52. 5 1
      gui/src/controls/container.ts
  53. 1 2
      package.json
  54. 1 1
      src/Engine/babylon.engine.ts
  55. 2 2
      src/Helpers/babylon.environmentHelper.ts
  56. 10 3
      src/Mesh/babylon.linesMesh.ts
  57. 10 2
      src/Mesh/babylon.mesh.vertexData.ts
  58. 38 15
      src/Mesh/babylon.meshBuilder.ts
  59. 68 48
      src/Tools/babylon.tools.ts
  60. 105 99
      src/babylon.scene.ts

BIN
Playground/LogoPBT.png


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 7350 - 7335
Playground/babylon.d.txt


+ 27 - 0
Playground/css/index.css

@@ -91,6 +91,33 @@ body {
 .wrapper .gutter.gutter-horizontal {
     background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==");
 }
+
+.pbt-fade {
+    opacity:0.5
+}
+
+.pbt-darken {
+    opacity:1
+}
+
+.pbt-back-highlight {
+    background-color:#CDC8F9;
+}
+
+.pbt-back-white{ 
+    background-color: white
+}
+
+.pbt-margin-decor-on {
+    background-color: #364249; 
+    width:5px;
+}
+
+.pbt-margin-decor-off {
+    background-color: #FF0000;
+    width:5px;
+}     
+
 .wrapper #jsEditor {
     padding-top:5px;
     height: calc(100% - 10px);

+ 1 - 0
Playground/debug.html

@@ -407,6 +407,7 @@
     <script src="https://code.jquery.com/jquery.js"></script>
 
     <script src="js/actions.js"></script>
+    <script src="js/pbt.js"></script>
     <script src="js/index.js"></script>
 </body>
 

+ 1 - 0
Playground/index-local.html

@@ -353,6 +353,7 @@
     <script src="https://code.jquery.com/jquery.js"></script>
 
     <script src="js/actions.js"></script>
+    <script src="js/pbt.js"></script>
     <script>
         BABYLONDEVTOOLS.Loader.require('js/index.js')
             .load();

+ 4 - 3
Playground/index.html

@@ -483,8 +483,9 @@
 
         <script src="https://code.jquery.com/jquery.js"></script>
 
-        <script src="js/actions.js"></script>
-        <script src="js/index.js"></script>
-    </body>
+    <script src="js/actions.js"></script>
+    <script src="js/pbt.js"></script>
+    <script src="js/index.js"></script>
+</body>
 
 </html>

+ 1 - 0
Playground/indexStable.html

@@ -378,6 +378,7 @@
     </script>
 
     <script src="js/actions.js"></script>
+    <script src="js/pbt.js"></script>
     <script src="js/index.js"></script>
 </body>
 

+ 2 - 0
Playground/js/index.js

@@ -325,6 +325,8 @@
                 var showInspector = false;
                 var showDebugLayer = false;
                 var initialTabIndex = 0;
+                showBJSPGMenu();
+                jsEditor.updateOptions({readOnly: false});
 
                 if (document.getElementsByClassName('insp-wrapper').length > 0) {
                     for (var i = 0; i < engine.scenes.length; i++) {

+ 432 - 0
Playground/js/pbt.js

@@ -0,0 +1,432 @@
+// jsEditor Manipulation
+var PBT = function() {
+    this.decorationStyles = new Array();
+    this.decorations = new Array();
+    var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
+    
+    this.clearDecorLines = function() {
+        this.decorations = jsEditor.deltaDecorations(this.decorations, []);
+    }
+
+    this.setDecorLines = function (lineRanges) {    
+        this.decorationStyles = [];
+
+    var endLineNm = jsEditor.getModel()._lines.length;
+        this.decorationStyles.push({ range: new monaco.Range(1,1,endLineNm,1), options: { isWholeLine: true, inlineClassName: 'pbt-fade' }});
+        
+        for(var i = 0; i < lineRanges.length; i +=2) {          
+            this.decorationStyles.push({ range: new monaco.Range(lineRanges[i],1,lineRanges[i + 1],1), options: { isWholeLine: true, linesDecorationsClassName: 'pbt-margin-decor-on' }});
+            this.decorationStyles.push({ range: new monaco.Range(lineRanges[i],1,lineRanges[i + 1],1), options: { isWholeLine: true, className: 'pbt-back-highlight' }});
+            this.decorationStyles.push({ range: new monaco.Range(lineRanges[i],1,lineRanges[i + 1],1), options: { isWholeLine: true, inlineClassName: 'pbt-darken' }});
+        }
+
+    this.decorations = jsEditor.deltaDecorations([this.decorations], this.decorationStyles);  
+    }
+
+    this.replaceLines = function(lineRange, text) {   
+        jsEditor.executeEdits("", [
+            { range: new monaco.Range(lineRange[0], 1, lineRange[1], 100000), text: text}
+       ]);
+    }
+
+    this.replaceText = function(line, start, end, text) {   
+        jsEditor.executeEdits("", [
+            { range: new monaco.Range(line, start, line, end), text: text}
+       ]);
+    }
+
+    this.getLineText = function(lineNm) {
+        return jsEditor.getModel().getLineContent(lineNm);
+    }
+
+    this.hideLines = function(lineRanges) {
+        var ranges = [];
+        for(var i = 0; i < lineRanges.length; i +=2) {
+            ranges.push(new monaco.Range(lineRanges[i], 1, lineRanges[i + 1], 100000));                
+        }
+        jsEditor.setHiddenAreas(ranges);
+    }
+
+    this.editOn = function() {
+        jsEditor.updateOptions({readOnly: false});
+    }
+
+    this.editOff = function() {
+        jsEditor.updateOptions({readOnly: true});
+    }
+
+    //hide menu items
+    this.hideMenu = function() {
+        var headings = document.getElementsByClassName('category');
+        
+        for (var i = 0; i < headings.length; i ++) {
+            headings[i].style.visibility = 'hidden';
+        }
+    
+        headings = document.getElementsByClassName('category right');
+        
+        for (var i = 0; i < headings.length; i ++) {
+            headings[i].style.visibility = 'visible';
+        }
+    }
+
+    //Standard GUI Dialogues
+    this.StandardDialog = function(options) {   
+        options = options||{};
+        var width = options.width||0.5;
+        var height = options.height||0.25;
+        var top = options.top||0;
+        var left = options.left||0;
+        var verticalAlignment = options.verticalAlignment||BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+        var horizontalAlignment = options.horizontalAlignment||BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+        var text = options.text||"Playground Based Tutorial";   
+        if(options.useImage === undefined) {
+            var useImage = true;
+        }
+        else {
+            var useImage = false;
+        }
+        var imageURL = options.imageURL||"LogoPBT.png";
+        var textBlockWidth = 0.95;
+        var textBlockLeft = "2%";
+        this.container = new BABYLON.GUI.Rectangle();
+        this.container.verticalAlignment = verticalAlignment;
+        this.container.horizontalAlignment = horizontalAlignment;
+        this.container.width = width;
+        this.container.height = height;
+        this.container.cornerRadius = 10;
+        this.container.color = "#364249";
+        this.container.thickness = 4;
+        this.container.background = "#CDC8F9";
+        this.container.top = top;
+        this.container.left = left;   
+        advancedTexture.addControl(this.container); 
+        if(useImage) {
+            this.logoPBT = BABYLON.GUI.Button.CreateImageOnlyButton("but", imageURL);
+            this.logoPBT.width = "100px";
+            this.logoPBT.height = "100px";
+            this.logoPBT.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+            this.logoPBT.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+            this.logoPBT.top = 2;
+            this.logoPBT.left=2;
+            this.logoPBT.color = "#CDC8F9";
+            this.container.addControl(this.logoPBT);
+            textBlockWidth = 0.6;
+            textBlockLeft = "35%";
+        }
+        this.textBlock = new BABYLON.GUI.TextBlock("text", text);
+        this.textBlock.width = textBlockWidth;
+        this.textBlock.height = 0.7
+        this.textBlock.textWrapping = true;
+        this.textBlock.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+        this.textBlock.color = "#364249";
+        this.textBlock.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+        this.textBlock.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+        this.textBlock.left = textBlockLeft;
+        this.textBlock.top = 2;
+        this.container.addControl(this.textBlock);
+
+        this.nextButton = BABYLON.GUI.Button.CreateSimpleButton("nextbut", "Next >");
+        this.nextButton.width = 0.2
+        this.nextButton.height = 0.15;
+        this.nextButton.color = "white";
+        this.nextButton.cornerRadius = 5;
+        this.nextButton.background = "#364249";
+        this.nextButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+        this.nextButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+        this.nextButton.left = "78%";
+        this.nextButton.top = "80%";
+        this.container.addControl(this.nextButton);
+
+        this.prevButton = BABYLON.GUI.Button.CreateSimpleButton("prevbut", "< Prev");
+        this.prevButton.width = 0.2
+        this.prevButton.height = 0.15;
+        this.prevButton.color = "white";
+        this.prevButton.cornerRadius = 5;
+        this.prevButton.background = "#364249";
+        this.prevButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+        this.prevButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+        this.prevButton.left = "2%";
+        this.prevButton.top = "80%";
+        this.container.addControl(this.prevButton); 
+
+        this.showNext = function() {
+            this.nextButton.isVisible = true;
+        }
+
+        this.hideNext = function() {
+            this.nextButton.isVisible = false;
+        }
+
+        this.getNextButton = function() {
+            return this.nextButton;
+        }
+
+        this.getPrevButton = function() {
+            return this.prevButton;
+        }
+
+        this.showPrev = function() {
+            this.prevButton.isVisible = true;
+        }
+
+        this.hidePrev = function() {
+            this.prevButton.isVisible = false;
+        }
+
+        this.setWidth = function(width) {
+            this.container.width = width;
+        }
+
+        this.setHeight = function(height) {
+            this.container.height = height;
+        }
+
+        this.setTop = function(top) {
+            this.container.top = top;
+        }
+
+        this.setLeft = function(left) {
+            this.container.left = left;
+        }
+
+        this.getWidth = function() {
+            return this.container.width;
+        }
+
+        this.getHeight = function() {
+            return this.container.height;
+        }
+
+        this.getTop = function() {
+            return this.container.top;
+        }
+
+        this.getLeft = function() {
+            return this.container.left;
+        }
+
+        this.setHorizontalAlignment = function(hrzAlgn) {
+            this.container.horizontalAlignment = hrzAlgn;
+        }
+
+        this.setVerticalAlignment = function(vrtAlign) {
+            this.container.VerticalAlignmenv = vrtAlign;
+        }
+
+        this.setText = function(text) {
+            this.textBlock.text = text;
+        }
+
+        this.show = function() {
+            this.container.isVisible = true;
+        }
+
+        this.hide = function() {
+            this.container.isVisible = false;
+        }
+
+        return this;
+    }
+
+//Radio and Checkbox Button GUI
+    this.ButtonGroup = function(name, type) {
+        this.name = name;
+        var type = type||"C"; 
+        type = type.substr(0,1).toUpperCase();
+        if(type !="R") {
+            if(type != "C") {
+                type = "C";
+            }
+        }
+        this.type = type;   
+        this.buttons = new Array();
+        
+        this.addButton = function(text, func, checked) {
+            this.buttons.push({
+                text: text||"", 
+                func: func||null, 
+                checked: checked||false
+        });
+        }
+        return this;
+    }
+
+    this.SelectionDialog = function(options) {
+        options = options||{};
+        var justStarted = true;
+        var width = options.width||0.15;
+        var top = options.top||0;
+        var left = options.left||0;  
+        var verticalAlignment = options.verticalAlignment||BABYLON.GUI.Control.VERTICAL_ALIGNMENT_BOTTOM;
+        var horizontalAlignment = options.horizontalAlignment||BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;    
+        var groups = options.groups; 
+        this.container = new BABYLON.GUI.Rectangle();
+        this.container.verticalAlignment = verticalAlignment;
+        this.container.horizontalAlignment = horizontalAlignment;   
+        this.container.width = 0.25;
+        var height = 36 * groups.length;
+        for(var i = 0; i < groups.length; i++) {
+            height += 32 * groups[i].buttons.length;
+        }
+        this.container.height = height + "px";
+        this.container.cornerRadius = 10;
+        this.container.color = "#364249";
+        this.container.thickness = 4;
+        this.container.background = "#CDC8F9";
+        this.container.top = top;
+        this.container.left = left;
+        advancedTexture.addControl(this.container);
+        
+        var panel = new BABYLON.GUI.StackPanel(); 
+        panel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+        panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+        panel.top = 5;
+        panel.left = 5;
+        this.container.addControl(panel);
+
+    var addRadio = function(text, parent, group, func, checked) {
+            checked = checked || false;
+            var button = new BABYLON.GUI.RadioButton();
+            button.width = "20px";
+            button.height = "20px";
+            button.color = "#364249";
+            button.background = "white"; 
+            button.group = group;
+            button.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+            button.justStarted = true;
+            button.func = func;
+
+        button.onIsCheckedChangedObservable.add(function(state) {                       		
+                if (state && !justStarted) {                  
+                    func();
+                }
+            }); 
+
+        var header = BABYLON.GUI.Control.AddHeader(button, text, "200px", { isHorizontal: true, controlFirst: true });
+            header.height = "30px";
+
+        parent.addControl(header);    
+            button.isChecked = checked; 
+        }
+
+        var addCheckbox = function(text, parent, func, checked) {
+            checked = checked || false;
+            var button = new BABYLON.GUI.Checkbox();
+            button.width = "20px";
+            button.height = "20px";
+            button.color = "#364249";
+            button.background = "white"; 
+            button.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+            
+            button.onIsCheckedChangedObservable.add(function(state) {	
+                func();	
+            }); 
+            
+            var header = BABYLON.GUI.Control.AddHeader(button, text, "200px", { isHorizontal: true, controlFirst: true });
+            header.height = "30px";
+            
+            parent.addControl(header);    
+            button.isChecked = checked;
+        }
+
+        var groupHeader = function(name) {
+            var groupHeading = new BABYLON.GUI.TextBlock("groupHead", name);
+            groupHeading.width = 0.9;
+            groupHeading.height = "30px";
+            groupHeading.textWrapping = true;
+            groupHeading.color = "black";
+            groupHeading.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+            groupHeading.left = "-2px";
+            panel.addControl(groupHeading);
+        }
+
+        var addSpacer = function(name) {
+            var separator = new BABYLON.GUI.Rectangle();
+            separator.width = 1;
+            separator.height = "2px";
+            separator.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+            separator.background = "#364249";
+            separator.color = "#364249";
+            panel.addControl(separator);
+            
+            groupHeader(name);
+        }
+
+        this.addGroup = function(group) {
+            if(group.type == "R") {
+                for(var i = 0; i < group.buttons.length; i++) {
+                    addRadio(group.buttons[i].text, panel, group.name, group.buttons[i].func, group.buttons[i].checked);
+                }
+            }
+            else {
+                for(var i = 0; i < group.buttons.length; i++) {
+                    addCheckbox(group.buttons[i].text, panel, group.buttons[i].func, group.buttons[i].checked);
+                }
+            }
+            
+            
+        }
+        
+        groupHeader(groups[0].name);
+        this.addGroup(groups[0]);
+        for(var i = 1; i < groups.length; i++) {
+            addSpacer(groups[i].name);
+            this.addGroup(groups[i]);
+        }
+
+        justStarted = false;
+
+        this.setWidth = function(width) {
+            this.container.width = width;
+        }
+
+        this.setTop = function(top) {
+            this.container.top = top;
+        }
+
+        this.setLeft = function(left) {
+            this.container.left = left;
+        }
+
+        this.getWidth = function() {
+            return this.container.width;
+        }
+
+        this.getTop = function() {
+            return this.container.top;
+        }
+
+        this.getLeft = function() {
+            return this.container.left;
+        }
+
+        this.setHorizontalAlignment = function(hrzAlgn) {
+            this.container.horizontalAlignment = hrzAlgn;
+        }
+
+        this.setVerticalAlignment = function(vrtAlign) {
+            this.container.VerticalAlignmenv = vrtAlign;
+        }
+
+        this.show = function() {
+            this.container.isVisible = true;
+        }
+
+        this.hide = function() {
+            this.container.isVisible = false;
+        }
+
+    return this;
+
+    }
+}
+
+showBJSPGMenu = function() {
+    var headings = document.getElementsByClassName('category');
+    
+    for (var i = 0; i < headings.length; i ++) {
+        headings[i].style.visibility = 'visible';
+    }
+}
+    

+ 14 - 0
Playground/package-lock.json

@@ -0,0 +1,14 @@
+{
+  "name": "babylonjsplayground",
+  "version": "3.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "monaco-editor": {
+      "version": "0.10.1",
+      "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.10.1.tgz",
+      "integrity": "sha1-jJbE8VtrUli/ksvek8rYp+MAfhQ=",
+      "dev": true
+    }
+  }
+}

+ 9 - 12
Tools/Gulp/gulpfile.js

@@ -244,9 +244,6 @@ gulp.task("typescript-compile", function () {
     return merge2([
         tsResult.dts
             .pipe(concat(config.build.declarationFilename))
-            .pipe(gulp.dest(config.build.outputDirectory)),
-        tsResult.dts
-            .pipe(concat(config.build.declarationModuleFilename))
             .pipe(addDtsExport("BABYLON", "babylonjs"))
             .pipe(gulp.dest(config.build.outputDirectory)),
         tsResult.js
@@ -501,16 +498,16 @@ gulp.task("watch", [], function () {
     return tasks;
 });
 
-gulp.task("intellisense", function() {
+gulp.task("intellisense", function () {
     gulp.src(config.build.intellisenseSources)
-    .pipe(concat(config.build.intellisenseFile))
-    .pipe(replace(/^\s*_.*?$/gm, ""))
-    .pipe(replace(/^\s*private .*?$/gm, ""))
-    .pipe(replace(/^\s*public _.*?$/gm, ""))
-    .pipe(replace(/^\s*protected .*?$/gm, ""))
-    .pipe(replace(/^\s*public static _.*?$/gm, ""))
-    .pipe(replace(/^\s*static _.*?$/gm, ""))
-    .pipe(gulp.dest(config.build.playgroundDirectory));
+        .pipe(concat(config.build.intellisenseFile))
+        .pipe(replace(/^\s*_.*?$/gm, ""))
+        .pipe(replace(/^\s*private .*?$/gm, ""))
+        .pipe(replace(/^\s*public _.*?$/gm, ""))
+        .pipe(replace(/^\s*protected .*?$/gm, ""))
+        .pipe(replace(/^\s*public static _.*?$/gm, ""))
+        .pipe(replace(/^\s*static _.*?$/gm, ""))
+        .pipe(gulp.dest(config.build.playgroundDirectory));
 });
 
 /**

BIN
Viewer/assets/img/close.png


BIN
Viewer/assets/img/fullscreen.png


BIN
Viewer/assets/img/help-circle.png


BIN
Viewer/assets/img/loading.png


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 210 - 0
Viewer/assets/pep.min.js


+ 2 - 2
Viewer/assets/templates/default/navbar.html

@@ -102,11 +102,11 @@
 </div>
 <div class="button-container flex-container">
     <!-- holding the buttons -->
-    {{#each buttons}}
+    {{#eachInMap buttons}}
     <div id="{{id}}" class="button">
         {{#if text}}
         <span>{{text}}</span>> {{/if}} {{#if image}}
         <img src="{{image}}" alt="{{altText}}"> {{/if}}
     </div>
-    {{/each}}
+    {{/eachInMap}}
 </div>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 389 - 2302
Viewer/dist/viewer.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 38 - 0
Viewer/dist/viewer.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 8 - 12
Viewer/src/configuration/types/default.ts


+ 1 - 0
Viewer/src/index.ts

@@ -14,6 +14,7 @@ import { AbstractViewer } from './viewer/viewer';
 import 'babylonjs';
 import 'babylonjs-loaders';
 import 'babylonjs-materials';
+import '../assets/pep.min';
 
 import { InitTags } from './initializer';
 

+ 14 - 0
Viewer/src/templateManager.ts

@@ -144,6 +144,20 @@ export class TemplateManager {
 
 
 import * as Handlebars from 'handlebars/dist/handlebars.min.js';
+// register a new helper. modified https://stackoverflow.com/questions/9838925/is-there-any-method-to-iterate-a-map-with-handlebars-js
+Handlebars.registerHelper('eachInMap', function (map, block) {
+    var out = '';
+    Object.keys(map).map(function (prop) {
+        let data = map[prop];
+        if (typeof data === 'object') {
+            data.id = data.id || prop;
+            out += block.fn(data);
+        } else {
+            out += block.fn({ id: prop, value: data });
+        }
+    });
+    return out;
+});
 
 export class Template {
 

+ 1 - 1
Viewer/src/viewer/defaultViewer.ts

@@ -107,7 +107,7 @@ export class DefaultViewer extends AbstractViewer {
                                     let requestFullScreen = viewerElement.requestFullscreen || viewerElement.webkitRequestFullscreen || (<any>viewerElement).msRequestFullscreen || (<any>viewerElement).mozRequestFullScreen;
                                     requestFullScreen.call(viewerElement);
                                 } else {
-                                    let exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen
+                                    let exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen || (<any>document).msExitFullscreen || document.mozCancelFullScreen
                                     exitFullscreen.call(document);
                                 }
 

+ 9 - 15
Viewer/webpack.config.js

@@ -5,7 +5,7 @@ const webpack = require('webpack');
 module.exports = {
     entry: {
         'viewer': './src/index.ts',
-        //'viewer.min': './src/index.ts',
+        'viewer.min': './src/index.ts',
     },
     output: {
         path: path.resolve(__dirname, 'dist'),
@@ -23,19 +23,10 @@ module.exports = {
         new webpack.WatchIgnorePlugin([
             /\.d\.ts$/
         ]),
-        /*new UglifyJSPlugin({
-
-            uglifyOptions: {
-                compress: {
-                    warnings: false,
-                },
-                output: {
-                    comments: false
-                }
-            },
-            sourceMap: true,
-            include: /\.min/,
-        })*/
+        new UglifyJSPlugin({
+            parallel: true,
+            test: /\.min\.js$/i,
+        })
     ],
     module: {
         loaders: [{
@@ -46,7 +37,10 @@ module.exports = {
         {
             test: /\.(html)$/,
             use: {
-                loader: 'html-loader'
+                loader: 'html-loader',
+                options: {
+                    minimize: true
+                }
             }
         },
         {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 7101 - 7086
dist/preview release/babylon.d.ts


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 46 - 46
dist/preview release/babylon.js


+ 136 - 77
dist/preview release/babylon.max.js

@@ -5781,7 +5781,6 @@ var BABYLON;
     var Tools = /** @class */ (function () {
         function Tools() {
         }
-        ;
         /**
          * Interpolates between a and b via alpha
          * @param a The lower value (returned when alpha = 0)
@@ -6164,7 +6163,6 @@ var BABYLON;
             }
             return img;
         };
-        //ANY
         Tools.LoadFile = function (url, callback, progressCallBack, database, useArrayBuffer, onError) {
             url = Tools.CleanUrl(url);
             url = Tools.PreprocessUrl(url);
@@ -6205,30 +6203,20 @@ var BABYLON;
                     database.loadFileFromDB(url, callback, progressCallBack, noIndexedDB, useArrayBuffer);
                 }
             };
+            // If file and file input are set
             if (url.indexOf("file:") !== -1) {
                 var fileName = decodeURIComponent(url.substring(5).toLowerCase());
                 if (BABYLON.FilesInput.FilesToLoad[fileName]) {
                     Tools.ReadFile(BABYLON.FilesInput.FilesToLoad[fileName], callback, progressCallBack, useArrayBuffer);
-                }
-                else {
-                    var errorMessage = "File: " + fileName + " not found. Did you forget to provide it?";
-                    if (onError) {
-                        var e = new Error(errorMessage);
-                        onError(undefined, e);
-                    }
-                    else {
-                        Tools.Error(errorMessage);
-                    }
+                    return request;
                 }
             }
+            // Caching all files
+            if (database && database.enableSceneOffline) {
+                database.openAsync(loadFromIndexedDB, noIndexedDB);
+            }
             else {
-                // Caching all files
-                if (database && database.enableSceneOffline) {
-                    database.openAsync(loadFromIndexedDB, noIndexedDB);
-                }
-                else {
-                    noIndexedDB();
-                }
+                noIndexedDB();
             }
             return request;
         };
@@ -6384,7 +6372,7 @@ var BABYLON;
                 }
             }
         };
-        Tools.DumpFramebuffer = function (width, height, engine, successCallback, mimeType) {
+        Tools.DumpFramebuffer = function (width, height, engine, successCallback, mimeType, fileName) {
             if (mimeType === void 0) { mimeType = "image/png"; }
             // Read the contents of the framebuffer
             var numberOfChannelsByLine = width * 4;
@@ -6415,38 +6403,63 @@ var BABYLON;
                 var castData = (imageData.data);
                 castData.set(data);
                 context.putImageData(imageData, 0, 0);
-                Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
+                Tools.EncodeScreenshotCanvasData(successCallback, mimeType, fileName);
             }
         };
-        Tools.EncodeScreenshotCanvasData = function (successCallback, mimeType) {
+        Tools.EncodeScreenshotCanvasData = function (successCallback, mimeType, fileName) {
             if (mimeType === void 0) { mimeType = "image/png"; }
             var base64Image = screenshotCanvas.toDataURL(mimeType);
             if (successCallback) {
                 successCallback(base64Image);
             }
             else {
-                //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() + 1)).slice(-2) + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
-                    a.setAttribute("download", "screenshot_" + stringDate + ".png");
-                    window.document.body.appendChild(a);
-                    a.addEventListener("click", function () {
-                        if (a.parentElement) {
-                            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);
+                // We need HTMLCanvasElement.toBlob for HD screenshots
+                if (!screenshotCanvas.toBlob) {
+                    //  low performance polyfill based on toDataURL (https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob)
+                    screenshotCanvas.toBlob = function (callback, type, quality) {
+                        var canvas = this;
+                        setTimeout(function () {
+                            var binStr = atob(canvas.toDataURL(type, quality).split(',')[1]), len = binStr.length, arr = new Uint8Array(len);
+                            for (var i = 0; i < len; i++) {
+                                arr[i] = binStr.charCodeAt(i);
+                            }
+                            callback(new Blob([arr], { type: type || 'image/png' }));
+                        });
+                    };
                 }
+                screenshotCanvas.toBlob(function (blob) {
+                    var url = URL.createObjectURL(blob);
+                    //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 = url;
+                        if (fileName) {
+                            a.setAttribute("download", fileName);
+                        }
+                        else {
+                            var date = new Date();
+                            var stringDate = (date.getFullYear() + "-" + (date.getMonth() + 1)).slice(-2) + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
+                            a.setAttribute("download", "screenshot_" + stringDate + ".png");
+                        }
+                        window.document.body.appendChild(a);
+                        a.addEventListener("click", function () {
+                            if (a.parentElement) {
+                                a.parentElement.removeChild(a);
+                            }
+                        });
+                        a.click();
+                    }
+                    else {
+                        var newWindow = window.open("");
+                        var img = newWindow.document.createElement("img");
+                        img.onload = function () {
+                            // no longer need to read the blob so it's revoked
+                            URL.revokeObjectURL(url);
+                        };
+                        img.src = url;
+                        newWindow.document.body.appendChild(img);
+                    }
+                });
             }
         };
         Tools.CreateScreenshot = function (engine, camera, size, successCallback, mimeType) {
@@ -6499,9 +6512,10 @@ var BABYLON;
             }
             Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
         };
-        Tools.CreateScreenshotUsingRenderTarget = function (engine, camera, size, successCallback, mimeType, samples) {
+        Tools.CreateScreenshotUsingRenderTarget = function (engine, camera, size, successCallback, mimeType, samples, antialiasing, fileName) {
             if (mimeType === void 0) { mimeType = "image/png"; }
             if (samples === void 0) { samples = 1; }
+            if (antialiasing === void 0) { antialiasing = false; }
             var width;
             var height;
             //If a precision value is specified
@@ -6542,8 +6556,11 @@ var BABYLON;
             var texture = new BABYLON.RenderTargetTexture("screenShot", size, scene, false, false, BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT, false, BABYLON.Texture.NEAREST_SAMPLINGMODE);
             texture.renderList = null;
             texture.samples = samples;
+            if (antialiasing) {
+                texture.addPostProcess(new BABYLON.FxaaPostProcess('antialiasing', 1.0, scene.activeCamera));
+            }
             texture.onAfterRenderObservable.add(function () {
-                Tools.DumpFramebuffer(width, height, engine, successCallback, mimeType);
+                Tools.DumpFramebuffer(width, height, engine, successCallback, mimeType, fileName);
             });
             scene.incrementRenderId();
             scene.resetCachedMaterial();
@@ -8522,7 +8539,7 @@ var BABYLON;
         });
         Object.defineProperty(Engine, "Version", {
             get: function () {
-                return "3.1-beta-4";
+                return "3.1-beta-5";
             },
             enumerable: true,
             configurable: true
@@ -20477,35 +20494,37 @@ var BABYLON;
                 this.simplificationQueue.executeNext();
             }
             if (this._engine.isDeterministicLockStep()) {
-                var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime)) / 1000;
-                var defaultTimeStep = (60.0 / 1000.0);
+                var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime)) + this._timeAccumulator;
+                var defaultFPS = (60.0 / 1000.0);
+                var defaultFrameTime = 1000 / 60; // frame time in MS
                 if (this._physicsEngine) {
-                    defaultTimeStep = this._physicsEngine.getTimeStep();
+                    defaultFrameTime = this._physicsEngine.getTimeStep() / 1000; //timestep in physics engine is in seconds
                 }
+                var stepsTaken = 0;
                 var maxSubSteps = this._engine.getLockstepMaxSteps();
-                this._timeAccumulator += deltaTime;
-                // compute the amount of fixed steps we should have taken since the last step
-                var internalSteps = Math.floor(this._timeAccumulator / defaultTimeStep);
+                var internalSteps = Math.floor(deltaTime / (1000 * defaultFPS));
                 internalSteps = Math.min(internalSteps, maxSubSteps);
-                for (this._currentInternalStep = 0; this._currentInternalStep < internalSteps; this._currentInternalStep++) {
+                do {
                     this.onBeforeStepObservable.notifyObservers(this);
                     // Animations
-                    this._animationRatio = defaultTimeStep * (60.0 / 1000.0);
+                    this._animationRatio = defaultFrameTime * defaultFPS;
                     this._animate();
                     this.onAfterAnimationsObservable.notifyObservers(this);
                     // Physics
                     if (this._physicsEngine) {
                         this.onBeforePhysicsObservable.notifyObservers(this);
-                        this._physicsEngine._step(defaultTimeStep);
+                        this._physicsEngine._step(defaultFPS);
                         this.onAfterPhysicsObservable.notifyObservers(this);
                     }
-                    this._timeAccumulator -= defaultTimeStep;
                     this.onAfterStepObservable.notifyObservers(this);
                     this._currentStepId++;
-                    if ((internalSteps > 1) && (this._currentInternalStep != internalSteps - 1)) {
+                    if ((internalSteps > 1) && (stepsTaken != internalSteps - 1)) {
                         this._evaluateActiveMeshes();
                     }
-                }
+                    stepsTaken++;
+                    deltaTime -= defaultFrameTime;
+                } while (deltaTime > 0 && stepsTaken > maxSubSteps);
+                this._timeAccumulator = deltaTime;
             }
             else {
                 // Animations
@@ -29677,11 +29696,17 @@ var BABYLON;
             var indices = [];
             var positions = [];
             var lines = options.lines;
+            var colors = options.colors;
+            var vertexColors = [];
             var idx = 0;
             for (var l = 0; l < lines.length; l++) {
                 var points = lines[l];
                 for (var index = 0; index < points.length; index++) {
                     positions.push(points[index].x, points[index].y, points[index].z);
+                    if (colors) {
+                        var color = colors[l];
+                        vertexColors.push(color[index].r, color[index].g, color[index].b, color[index].a);
+                    }
                     if (index > 0) {
                         indices.push(idx - 1);
                         indices.push(idx);
@@ -29692,6 +29717,9 @@ var BABYLON;
             var vertexData = new VertexData();
             vertexData.indices = indices;
             vertexData.positions = positions;
+            if (colors) {
+                vertexData.colors = vertexColors;
+            }
             return vertexData;
         };
         /**
@@ -47198,27 +47226,35 @@ var BABYLON;
 (function (BABYLON) {
     var LinesMesh = /** @class */ (function (_super) {
         __extends(LinesMesh, _super);
-        function LinesMesh(name, scene, parent, source, doNotCloneChildren, useVertexColor) {
+        function LinesMesh(name, scene, parent, source, doNotCloneChildren, useVertexColor, useVertexAlpha) {
             if (scene === void 0) { scene = null; }
             if (parent === void 0) { parent = null; }
             var _this = _super.call(this, name, scene, parent, source, doNotCloneChildren) || this;
             _this.useVertexColor = useVertexColor;
+            _this.useVertexAlpha = useVertexAlpha;
             _this.color = new BABYLON.Color3(1, 1, 1);
             _this.alpha = 1;
             if (source) {
                 _this.color = source.color.clone();
                 _this.alpha = source.alpha;
                 _this.useVertexColor = source.useVertexColor;
+                _this.useVertexAlpha = source.useVertexAlpha;
             }
             _this._intersectionThreshold = 0.1;
+            var defines = [];
             var options = {
                 attributes: [BABYLON.VertexBuffer.PositionKind],
                 uniforms: ["world", "viewProjection"],
                 needAlphaBlending: false,
+                defines: defines
             };
             if (!useVertexColor) {
                 options.uniforms.push("color");
-                options.needAlphaBlending = true;
+            }
+            else {
+                options.needAlphaBlending = (useVertexAlpha) ? true : false;
+                options.defines.push("#define VERTEXCOLOR");
+                options.attributes.push(BABYLON.VertexBuffer.ColorKind);
             }
             _this._colorShader = new BABYLON.ShaderMaterial("colorShader", _this.getScene(), "color", options);
             return _this;
@@ -48152,6 +48188,8 @@ var BABYLON;
          * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineSystem to this static function.
          * The parameter `lines` is an array of lines, each line being an array of successive Vector3.
          * The optional parameter `instance` is an instance of an existing LineSystem object to be updated with the passed `lines` parameter. The way to update it is the same than for
+         * The optional parameter `colors` is an array of line colors, each line colors being an array of successive Color4, one per line point.
+         * The optional parameter `useVertexAlpha' is to be set to `true` (default `false`) when the alpha value from the former `Color4` array must be used.
          * updating a simple Line mesh, you just need to update every line in the `lines` array : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines
          * When updating an instance, remember that only line point positions can change, not the number of points, neither the number of lines.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
@@ -48159,24 +48197,42 @@ var BABYLON;
         MeshBuilder.CreateLineSystem = function (name, options, scene) {
             var instance = options.instance;
             var lines = options.lines;
+            var colors = options.colors;
             if (instance) {
-                var positionFunction = function (positions) {
-                    var i = 0;
-                    for (var l = 0; l < lines.length; l++) {
-                        var points = lines[l];
-                        for (var p = 0; p < points.length; p++) {
-                            positions[i] = points[p].x;
-                            positions[i + 1] = points[p].y;
-                            positions[i + 2] = points[p].z;
-                            i += 3;
+                var positions = instance.getVerticesData(BABYLON.VertexBuffer.PositionKind);
+                var vertexColor;
+                var lineColors;
+                if (colors) {
+                    vertexColor = instance.getVerticesData(BABYLON.VertexBuffer.ColorKind);
+                }
+                var i = 0;
+                var c = 0;
+                for (var l = 0; l < lines.length; l++) {
+                    var points = lines[l];
+                    for (var p = 0; p < points.length; p++) {
+                        positions[i] = points[p].x;
+                        positions[i + 1] = points[p].y;
+                        positions[i + 2] = points[p].z;
+                        if (colors && vertexColor) {
+                            lineColors = colors[l];
+                            vertexColor[c] = lineColors[p].r;
+                            vertexColor[c + 1] = lineColors[p].g;
+                            vertexColor[c + 2] = lineColors[p].b;
+                            vertexColor[c + 3] = lineColors[p].a;
+                            c += 4;
                         }
+                        i += 3;
                     }
-                };
-                instance.updateMeshPositions(positionFunction, false);
+                }
+                instance.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions, false, false);
+                if (colors && vertexColor) {
+                    instance.updateVerticesData(BABYLON.VertexBuffer.ColorKind, vertexColor, false, false);
+                }
                 return instance;
             }
             // line system creation
-            var lineSystem = new BABYLON.LinesMesh(name, scene);
+            var useVertexColor = (colors) ? true : false;
+            var lineSystem = new BABYLON.LinesMesh(name, scene, null, undefined, undefined, useVertexColor, options.useVertexAlpha);
             var vertexData = BABYLON.VertexData.CreateLineSystem(options);
             vertexData.applyToMesh(lineSystem, options.updatable);
             return lineSystem;
@@ -48188,12 +48244,15 @@ var BABYLON;
          * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.
          * The parameter `points` is an array successive Vector3.
          * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines
+         * The optional parameter `colors` is an array of successive Color4, one per line point.
+         * The optional parameter `useVertexAlpha' is to be set to `true` (default `false`) when the alpha value from the former `Color4` array must be used.
          * When updating an instance, remember that only point positions can change, not the number of points.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateLines = function (name, options, scene) {
             if (scene === void 0) { scene = null; }
-            var lines = MeshBuilder.CreateLineSystem(name, { lines: [options.points], updatable: options.updatable, instance: options.instance }, scene);
+            var colors = (options.colors) ? [options.colors] : null;
+            var lines = MeshBuilder.CreateLineSystem(name, { lines: [options.points], updatable: options.updatable, instance: options.instance, colors: colors, useVertexAlpha: options.useVertexAlpha }, scene);
             return lines;
         };
         /**
@@ -52988,12 +53047,12 @@ var BABYLON;
             if (sceneFilename.name) {
                 sceneFilename = sceneFilename.name;
             }
-            var dotPosition = sceneFilename.lastIndexOf(".");
             var queryStringPosition = sceneFilename.indexOf("?");
-            if (queryStringPosition === -1) {
-                queryStringPosition = sceneFilename.length;
+            if (queryStringPosition !== -1) {
+                sceneFilename = sceneFilename.substring(0, queryStringPosition);
             }
-            var extension = sceneFilename.substring(dotPosition, queryStringPosition).toLowerCase();
+            var dotPosition = sceneFilename.lastIndexOf(".");
+            var extension = sceneFilename.substring(dotPosition, sceneFilename.length).toLowerCase();
             return SceneLoader._getPluginForExtension(extension);
         };
         // use babylon file loader directly if sceneFilename is prefixed with "data:"

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 20612
dist/preview release/babylon.module.d.ts


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 47 - 47
dist/preview release/babylon.worker.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2929 - 2914
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 48 - 48
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 133 - 74
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -5781,7 +5781,6 @@ var BABYLON;
     var Tools = /** @class */ (function () {
         function Tools() {
         }
-        ;
         /**
          * Interpolates between a and b via alpha
          * @param a The lower value (returned when alpha = 0)
@@ -6164,7 +6163,6 @@ var BABYLON;
             }
             return img;
         };
-        //ANY
         Tools.LoadFile = function (url, callback, progressCallBack, database, useArrayBuffer, onError) {
             url = Tools.CleanUrl(url);
             url = Tools.PreprocessUrl(url);
@@ -6205,30 +6203,20 @@ var BABYLON;
                     database.loadFileFromDB(url, callback, progressCallBack, noIndexedDB, useArrayBuffer);
                 }
             };
+            // If file and file input are set
             if (url.indexOf("file:") !== -1) {
                 var fileName = decodeURIComponent(url.substring(5).toLowerCase());
                 if (BABYLON.FilesInput.FilesToLoad[fileName]) {
                     Tools.ReadFile(BABYLON.FilesInput.FilesToLoad[fileName], callback, progressCallBack, useArrayBuffer);
+                    return request;
                 }
-                else {
-                    var errorMessage = "File: " + fileName + " not found. Did you forget to provide it?";
-                    if (onError) {
-                        var e = new Error(errorMessage);
-                        onError(undefined, e);
-                    }
-                    else {
-                        Tools.Error(errorMessage);
-                    }
-                }
+            }
+            // Caching all files
+            if (database && database.enableSceneOffline) {
+                database.openAsync(loadFromIndexedDB, noIndexedDB);
             }
             else {
-                // Caching all files
-                if (database && database.enableSceneOffline) {
-                    database.openAsync(loadFromIndexedDB, noIndexedDB);
-                }
-                else {
-                    noIndexedDB();
-                }
+                noIndexedDB();
             }
             return request;
         };
@@ -6384,7 +6372,7 @@ var BABYLON;
                 }
             }
         };
-        Tools.DumpFramebuffer = function (width, height, engine, successCallback, mimeType) {
+        Tools.DumpFramebuffer = function (width, height, engine, successCallback, mimeType, fileName) {
             if (mimeType === void 0) { mimeType = "image/png"; }
             // Read the contents of the framebuffer
             var numberOfChannelsByLine = width * 4;
@@ -6415,38 +6403,63 @@ var BABYLON;
                 var castData = (imageData.data);
                 castData.set(data);
                 context.putImageData(imageData, 0, 0);
-                Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
+                Tools.EncodeScreenshotCanvasData(successCallback, mimeType, fileName);
             }
         };
-        Tools.EncodeScreenshotCanvasData = function (successCallback, mimeType) {
+        Tools.EncodeScreenshotCanvasData = function (successCallback, mimeType, fileName) {
             if (mimeType === void 0) { mimeType = "image/png"; }
             var base64Image = screenshotCanvas.toDataURL(mimeType);
             if (successCallback) {
                 successCallback(base64Image);
             }
             else {
-                //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() + 1)).slice(-2) + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
-                    a.setAttribute("download", "screenshot_" + stringDate + ".png");
-                    window.document.body.appendChild(a);
-                    a.addEventListener("click", function () {
-                        if (a.parentElement) {
-                            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);
+                // We need HTMLCanvasElement.toBlob for HD screenshots
+                if (!screenshotCanvas.toBlob) {
+                    //  low performance polyfill based on toDataURL (https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob)
+                    screenshotCanvas.toBlob = function (callback, type, quality) {
+                        var canvas = this;
+                        setTimeout(function () {
+                            var binStr = atob(canvas.toDataURL(type, quality).split(',')[1]), len = binStr.length, arr = new Uint8Array(len);
+                            for (var i = 0; i < len; i++) {
+                                arr[i] = binStr.charCodeAt(i);
+                            }
+                            callback(new Blob([arr], { type: type || 'image/png' }));
+                        });
+                    };
                 }
+                screenshotCanvas.toBlob(function (blob) {
+                    var url = URL.createObjectURL(blob);
+                    //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 = url;
+                        if (fileName) {
+                            a.setAttribute("download", fileName);
+                        }
+                        else {
+                            var date = new Date();
+                            var stringDate = (date.getFullYear() + "-" + (date.getMonth() + 1)).slice(-2) + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
+                            a.setAttribute("download", "screenshot_" + stringDate + ".png");
+                        }
+                        window.document.body.appendChild(a);
+                        a.addEventListener("click", function () {
+                            if (a.parentElement) {
+                                a.parentElement.removeChild(a);
+                            }
+                        });
+                        a.click();
+                    }
+                    else {
+                        var newWindow = window.open("");
+                        var img = newWindow.document.createElement("img");
+                        img.onload = function () {
+                            // no longer need to read the blob so it's revoked
+                            URL.revokeObjectURL(url);
+                        };
+                        img.src = url;
+                        newWindow.document.body.appendChild(img);
+                    }
+                });
             }
         };
         Tools.CreateScreenshot = function (engine, camera, size, successCallback, mimeType) {
@@ -6499,9 +6512,10 @@ var BABYLON;
             }
             Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
         };
-        Tools.CreateScreenshotUsingRenderTarget = function (engine, camera, size, successCallback, mimeType, samples) {
+        Tools.CreateScreenshotUsingRenderTarget = function (engine, camera, size, successCallback, mimeType, samples, antialiasing, fileName) {
             if (mimeType === void 0) { mimeType = "image/png"; }
             if (samples === void 0) { samples = 1; }
+            if (antialiasing === void 0) { antialiasing = false; }
             var width;
             var height;
             //If a precision value is specified
@@ -6542,8 +6556,11 @@ var BABYLON;
             var texture = new BABYLON.RenderTargetTexture("screenShot", size, scene, false, false, BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT, false, BABYLON.Texture.NEAREST_SAMPLINGMODE);
             texture.renderList = null;
             texture.samples = samples;
+            if (antialiasing) {
+                texture.addPostProcess(new BABYLON.FxaaPostProcess('antialiasing', 1.0, scene.activeCamera));
+            }
             texture.onAfterRenderObservable.add(function () {
-                Tools.DumpFramebuffer(width, height, engine, successCallback, mimeType);
+                Tools.DumpFramebuffer(width, height, engine, successCallback, mimeType, fileName);
             });
             scene.incrementRenderId();
             scene.resetCachedMaterial();
@@ -8522,7 +8539,7 @@ var BABYLON;
         });
         Object.defineProperty(Engine, "Version", {
             get: function () {
-                return "3.1-beta-4";
+                return "3.1-beta-5";
             },
             enumerable: true,
             configurable: true
@@ -20477,35 +20494,37 @@ var BABYLON;
                 this.simplificationQueue.executeNext();
             }
             if (this._engine.isDeterministicLockStep()) {
-                var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime)) / 1000;
-                var defaultTimeStep = (60.0 / 1000.0);
+                var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime)) + this._timeAccumulator;
+                var defaultFPS = (60.0 / 1000.0);
+                var defaultFrameTime = 1000 / 60; // frame time in MS
                 if (this._physicsEngine) {
-                    defaultTimeStep = this._physicsEngine.getTimeStep();
+                    defaultFrameTime = this._physicsEngine.getTimeStep() / 1000; //timestep in physics engine is in seconds
                 }
+                var stepsTaken = 0;
                 var maxSubSteps = this._engine.getLockstepMaxSteps();
-                this._timeAccumulator += deltaTime;
-                // compute the amount of fixed steps we should have taken since the last step
-                var internalSteps = Math.floor(this._timeAccumulator / defaultTimeStep);
+                var internalSteps = Math.floor(deltaTime / (1000 * defaultFPS));
                 internalSteps = Math.min(internalSteps, maxSubSteps);
-                for (this._currentInternalStep = 0; this._currentInternalStep < internalSteps; this._currentInternalStep++) {
+                do {
                     this.onBeforeStepObservable.notifyObservers(this);
                     // Animations
-                    this._animationRatio = defaultTimeStep * (60.0 / 1000.0);
+                    this._animationRatio = defaultFrameTime * defaultFPS;
                     this._animate();
                     this.onAfterAnimationsObservable.notifyObservers(this);
                     // Physics
                     if (this._physicsEngine) {
                         this.onBeforePhysicsObservable.notifyObservers(this);
-                        this._physicsEngine._step(defaultTimeStep);
+                        this._physicsEngine._step(defaultFPS);
                         this.onAfterPhysicsObservable.notifyObservers(this);
                     }
-                    this._timeAccumulator -= defaultTimeStep;
                     this.onAfterStepObservable.notifyObservers(this);
                     this._currentStepId++;
-                    if ((internalSteps > 1) && (this._currentInternalStep != internalSteps - 1)) {
+                    if ((internalSteps > 1) && (stepsTaken != internalSteps - 1)) {
                         this._evaluateActiveMeshes();
                     }
-                }
+                    stepsTaken++;
+                    deltaTime -= defaultFrameTime;
+                } while (deltaTime > 0 && stepsTaken > maxSubSteps);
+                this._timeAccumulator = deltaTime;
             }
             else {
                 // Animations
@@ -29677,11 +29696,17 @@ var BABYLON;
             var indices = [];
             var positions = [];
             var lines = options.lines;
+            var colors = options.colors;
+            var vertexColors = [];
             var idx = 0;
             for (var l = 0; l < lines.length; l++) {
                 var points = lines[l];
                 for (var index = 0; index < points.length; index++) {
                     positions.push(points[index].x, points[index].y, points[index].z);
+                    if (colors) {
+                        var color = colors[l];
+                        vertexColors.push(color[index].r, color[index].g, color[index].b, color[index].a);
+                    }
                     if (index > 0) {
                         indices.push(idx - 1);
                         indices.push(idx);
@@ -29692,6 +29717,9 @@ var BABYLON;
             var vertexData = new VertexData();
             vertexData.indices = indices;
             vertexData.positions = positions;
+            if (colors) {
+                vertexData.colors = vertexColors;
+            }
             return vertexData;
         };
         /**
@@ -47044,27 +47072,35 @@ var BABYLON;
 (function (BABYLON) {
     var LinesMesh = /** @class */ (function (_super) {
         __extends(LinesMesh, _super);
-        function LinesMesh(name, scene, parent, source, doNotCloneChildren, useVertexColor) {
+        function LinesMesh(name, scene, parent, source, doNotCloneChildren, useVertexColor, useVertexAlpha) {
             if (scene === void 0) { scene = null; }
             if (parent === void 0) { parent = null; }
             var _this = _super.call(this, name, scene, parent, source, doNotCloneChildren) || this;
             _this.useVertexColor = useVertexColor;
+            _this.useVertexAlpha = useVertexAlpha;
             _this.color = new BABYLON.Color3(1, 1, 1);
             _this.alpha = 1;
             if (source) {
                 _this.color = source.color.clone();
                 _this.alpha = source.alpha;
                 _this.useVertexColor = source.useVertexColor;
+                _this.useVertexAlpha = source.useVertexAlpha;
             }
             _this._intersectionThreshold = 0.1;
+            var defines = [];
             var options = {
                 attributes: [BABYLON.VertexBuffer.PositionKind],
                 uniforms: ["world", "viewProjection"],
                 needAlphaBlending: false,
+                defines: defines
             };
             if (!useVertexColor) {
                 options.uniforms.push("color");
-                options.needAlphaBlending = true;
+            }
+            else {
+                options.needAlphaBlending = (useVertexAlpha) ? true : false;
+                options.defines.push("#define VERTEXCOLOR");
+                options.attributes.push(BABYLON.VertexBuffer.ColorKind);
             }
             _this._colorShader = new BABYLON.ShaderMaterial("colorShader", _this.getScene(), "color", options);
             return _this;
@@ -47998,6 +48034,8 @@ var BABYLON;
          * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineSystem to this static function.
          * The parameter `lines` is an array of lines, each line being an array of successive Vector3.
          * The optional parameter `instance` is an instance of an existing LineSystem object to be updated with the passed `lines` parameter. The way to update it is the same than for
+         * The optional parameter `colors` is an array of line colors, each line colors being an array of successive Color4, one per line point.
+         * The optional parameter `useVertexAlpha' is to be set to `true` (default `false`) when the alpha value from the former `Color4` array must be used.
          * updating a simple Line mesh, you just need to update every line in the `lines` array : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines
          * When updating an instance, remember that only line point positions can change, not the number of points, neither the number of lines.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
@@ -48005,24 +48043,42 @@ var BABYLON;
         MeshBuilder.CreateLineSystem = function (name, options, scene) {
             var instance = options.instance;
             var lines = options.lines;
+            var colors = options.colors;
             if (instance) {
-                var positionFunction = function (positions) {
-                    var i = 0;
-                    for (var l = 0; l < lines.length; l++) {
-                        var points = lines[l];
-                        for (var p = 0; p < points.length; p++) {
-                            positions[i] = points[p].x;
-                            positions[i + 1] = points[p].y;
-                            positions[i + 2] = points[p].z;
-                            i += 3;
-                        }
+                var positions = instance.getVerticesData(BABYLON.VertexBuffer.PositionKind);
+                var vertexColor;
+                var lineColors;
+                if (colors) {
+                    vertexColor = instance.getVerticesData(BABYLON.VertexBuffer.ColorKind);
+                }
+                var i = 0;
+                var c = 0;
+                for (var l = 0; l < lines.length; l++) {
+                    var points = lines[l];
+                    for (var p = 0; p < points.length; p++) {
+                        positions[i] = points[p].x;
+                        positions[i + 1] = points[p].y;
+                        positions[i + 2] = points[p].z;
+                        if (colors && vertexColor) {
+                            lineColors = colors[l];
+                            vertexColor[c] = lineColors[p].r;
+                            vertexColor[c + 1] = lineColors[p].g;
+                            vertexColor[c + 2] = lineColors[p].b;
+                            vertexColor[c + 3] = lineColors[p].a;
+                            c += 4;
+                        }
+                        i += 3;
                     }
-                };
-                instance.updateMeshPositions(positionFunction, false);
+                }
+                instance.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions, false, false);
+                if (colors && vertexColor) {
+                    instance.updateVerticesData(BABYLON.VertexBuffer.ColorKind, vertexColor, false, false);
+                }
                 return instance;
             }
             // line system creation
-            var lineSystem = new BABYLON.LinesMesh(name, scene);
+            var useVertexColor = (colors) ? true : false;
+            var lineSystem = new BABYLON.LinesMesh(name, scene, null, undefined, undefined, useVertexColor, options.useVertexAlpha);
             var vertexData = BABYLON.VertexData.CreateLineSystem(options);
             vertexData.applyToMesh(lineSystem, options.updatable);
             return lineSystem;
@@ -48034,12 +48090,15 @@ var BABYLON;
          * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.
          * The parameter `points` is an array successive Vector3.
          * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines
+         * The optional parameter `colors` is an array of successive Color4, one per line point.
+         * The optional parameter `useVertexAlpha' is to be set to `true` (default `false`) when the alpha value from the former `Color4` array must be used.
          * When updating an instance, remember that only point positions can change, not the number of points.
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.
          */
         MeshBuilder.CreateLines = function (name, options, scene) {
             if (scene === void 0) { scene = null; }
-            var lines = MeshBuilder.CreateLineSystem(name, { lines: [options.points], updatable: options.updatable, instance: options.instance }, scene);
+            var colors = (options.colors) ? [options.colors] : null;
+            var lines = MeshBuilder.CreateLineSystem(name, { lines: [options.points], updatable: options.updatable, instance: options.instance, colors: colors, useVertexAlpha: options.useVertexAlpha }, scene);
             return lines;
         };
         /**

+ 4 - 1
dist/preview release/gui/babylon.gui.js

@@ -1993,7 +1993,7 @@ var BABYLON;
                 }
             };
             Container.prototype._processPicking = function (x, y, type, buttonIndex) {
-                if (!this.isHitTestVisible || !this.isVisible || this.notRenderable) {
+                if (!this.isVisible || this.notRenderable) {
                     return false;
                 }
                 if (!_super.prototype.contains.call(this, x, y)) {
@@ -2006,6 +2006,9 @@ var BABYLON;
                         return true;
                     }
                 }
+                if (!this.isHitTestVisible) {
+                    return false;
+                }
                 return this._processObservables(type, x, y, buttonIndex);
             };
             Container.prototype._clipForChildren = function (context) {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
dist/preview release/gui/babylon.gui.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 263 - 263
dist/preview release/inspector/babylon.inspector.bundle.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 17 - 1
dist/preview release/loaders/babylonjs.loaders.js

@@ -3434,6 +3434,14 @@ var BABYLON;
                 this._loaderPendingCount = 0;
                 this._loaderTrackers = new Array();
                 this._parent = parent;
+                if (!GLTFLoader._progressEventFactory) {
+                    if (typeof window["ProgressEvent"] === "function") {
+                        GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByConstructor;
+                    }
+                    else {
+                        GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByDocument;
+                    }
+                }
             }
             GLTFLoader.RegisterExtension = function (extension) {
                 if (GLTFLoader.Extensions[extension.name]) {
@@ -3444,6 +3452,14 @@ var BABYLON;
                 // Keep the order of registration so that extensions registered first are called first.
                 GLTF2.GLTFLoaderExtension._Extensions.push(extension);
             };
+            GLTFLoader._createProgressEventByConstructor = function (name, data) {
+                return new ProgressEvent(name, data);
+            };
+            GLTFLoader._createProgressEventByDocument = function (name, data) {
+                var event = document.createEvent("ProgressEvent");
+                event.initProgressEvent(name, false, false, data.lengthComputable, data.loaded, data.total);
+                return event;
+            };
             GLTFLoader.prototype.dispose = function () {
                 if (this._disposed) {
                     return;
@@ -3504,7 +3520,7 @@ var BABYLON;
                     loaded += request._loaded;
                     total += request._total;
                 }
-                this._progressCallback(new ProgressEvent("GLTFLoaderProgress", {
+                this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
                     lengthComputable: true,
                     loaded: loaded,
                     total: total

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


+ 3 - 0
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -969,6 +969,9 @@ declare module BABYLON.GLTF2 {
             [name: string]: GLTFLoaderExtension;
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
+        private static _progressEventFactory;
+        private static _createProgressEventByConstructor(name, data);
+        private static _createProgressEventByDocument(name, data);
         constructor(parent: GLTFFileLoader);
         dispose(): void;
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
dist/preview release/materialsLibrary/babylonjs.materials.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


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

@@ -49,6 +49,7 @@
 - Added `enableDepthSort` parameter to the SPS in order to sort the particles from the camera position ([jerome](https://github.com/jbousquie)) 
 - Added `pivot` property to the SPS solid particles ([jerome](https://github.com/jbousquie)) 
 - Added the mesh facet depth sort to FacetData  ([jerome](https://github.com/jbousquie)) 
+- Added `LineSystem` and `LineMesh` per point colors ([jerome](https://github.com/jbousquie))  
 
 ## Bug fixes
 - Fixed a bug with PBR on iOS ([sebavan](https://github.com/sebavan))

+ 5 - 1
gui/src/controls/container.ts

@@ -175,7 +175,7 @@ module BABYLON.GUI {
         }
 
         public _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean {
-            if (!this.isHitTestVisible || !this.isVisible || this.notRenderable) {
+            if (!this.isVisible || this.notRenderable) {
                 return false;
             }
 
@@ -191,6 +191,10 @@ module BABYLON.GUI {
                 }
             }
 
+            if (!this.isHitTestVisible) {
+                return false;
+            }
+
             return this._processObservables(type, x, y, buttonIndex);
         }
 

+ 1 - 2
package.json

@@ -16,7 +16,6 @@
     "main": "dist/preview release/babylon.max.js",
     "files": [
         "dist/preview release/babylon.d.ts",
-        "dist/preview release/babylon.module.d.ts",
         "dist/preview release/babylon.js",
         "dist/preview release/babylon.max.js",
         "dist/preview release/babylon.worker.js",
@@ -50,7 +49,7 @@
         "dist/preview release/Oimo.js",
         "package.json"
     ],
-    "typings": "dist/preview release/babylon.module.d.ts",
+    "typings": "dist/preview release/babylon.d.ts",
     "keywords": [
         "3D",
         "javascript",

+ 1 - 1
src/Engine/babylon.engine.ts

@@ -531,7 +531,7 @@
         }
 
         public static get Version(): string {
-            return "3.1-beta-4";
+            return "3.1-beta-5";
         }
 
         // Updatable statics so stick with vars here

+ 2 - 2
src/Helpers/babylon.environmentHelper.ts

@@ -100,7 +100,7 @@ namespace BABYLON {
          */
         skyboxTexture: string | BaseTexture;
         /**
-         * The color mixed in the ground texture by default.
+         * The color mixed in the skybox texture by default.
          * BabylonJS clearColor by default.
          */
         skyboxColor: Color3;
@@ -123,7 +123,7 @@ namespace BABYLON {
         rootPosition: Vector3;
 
         /**
-         * Sets up the inmage processing in the scene.
+         * Sets up the image processing in the scene.
          * true by default.
          */
         setupImageProcessing: boolean;

+ 10 - 3
src/Mesh/babylon.linesMesh.ts

@@ -32,26 +32,33 @@
         private _intersectionThreshold: number;
         private _colorShader: ShaderMaterial;
 
-        constructor(name: string, scene: Nullable<Scene> = null, parent: Nullable<Node> = null, source?: LinesMesh, doNotCloneChildren?: boolean, public useVertexColor?: boolean) {
+        constructor(name: string, scene: Nullable<Scene> = null, parent: Nullable<Node> = null, source?: LinesMesh, doNotCloneChildren?: boolean, public useVertexColor?: boolean, public useVertexAlpha?: boolean) {
             super(name, scene, parent, source, doNotCloneChildren);
 
             if (source) {
                 this.color = source.color.clone();
                 this.alpha = source.alpha;
                 this.useVertexColor = source.useVertexColor;
+                this.useVertexAlpha = source.useVertexAlpha;
             }
 
             this._intersectionThreshold = 0.1;
 
+            var defines: String[] = []; 
             var options = {
                 attributes: [VertexBuffer.PositionKind],
                 uniforms: ["world", "viewProjection"],
                 needAlphaBlending: false,
+                defines: defines
             };
-
+            
             if (!useVertexColor) {
                 options.uniforms.push("color");
-                options.needAlphaBlending = true;
+            }
+            else {
+                options.needAlphaBlending = (useVertexAlpha) ? true : false;
+                options.defines.push("#define VERTEXCOLOR");
+                options.attributes.push(VertexBuffer.ColorKind);
             }
 
             this._colorShader = new ShaderMaterial("colorShader", this.getScene(), "color", options);

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

@@ -1265,17 +1265,22 @@
         /**
          * Creates the VertexData of the LineSystem.  
          */
-        public static CreateLineSystem(options: { lines: Vector3[][] }): VertexData {
+        public static CreateLineSystem(options: { lines: Vector3[][], colors?: Nullable<Color4[][]> }): VertexData {
             var indices = [];
             var positions = [];
             var lines = options.lines;
+            var colors = options.colors;
+            var vertexColors = [];
             var idx = 0;
 
             for (var l = 0; l < lines.length; l++) {
                 var points = lines[l];
                 for (var index = 0; index < points.length; index++) {
                     positions.push(points[index].x, points[index].y, points[index].z);
-
+                    if (colors) {
+                        var color = colors[l];
+                        vertexColors.push(color[index].r, color[index].g, color[index].b, color[index].a);
+                    }
                     if (index > 0) {
                         indices.push(idx - 1);
                         indices.push(idx);
@@ -1286,6 +1291,9 @@
             var vertexData = new VertexData();
             vertexData.indices = indices;
             vertexData.positions = positions;
+            if (colors) {
+                vertexData.colors = vertexColors;
+            }
             return vertexData;
         }
 

+ 38 - 15
src/Mesh/babylon.meshBuilder.ts

@@ -358,33 +358,53 @@
          * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineSystem to this static function.  
          * The parameter `lines` is an array of lines, each line being an array of successive Vector3.   
          * The optional parameter `instance` is an instance of an existing LineSystem object to be updated with the passed `lines` parameter. The way to update it is the same than for 
+         * The optional parameter `colors` is an array of line colors, each line colors being an array of successive Color4, one per line point.  
+         * The optional parameter `useVertexAlpha' is to be set to `true` (default `false`) when the alpha value from the former `Color4` array must be used.  
          * updating a simple Line mesh, you just need to update every line in the `lines` array : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines   
          * When updating an instance, remember that only line point positions can change, not the number of points, neither the number of lines.      
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateLineSystem(name: string, options: { lines: Vector3[][], updatable: boolean, instance: Nullable<LinesMesh> }, scene: Nullable<Scene>): LinesMesh {
+        public static CreateLineSystem(name: string, options: { lines: Vector3[][], updatable: boolean, instance: Nullable<LinesMesh>, colors?: Nullable<Color4[][]>, useVertexAlpha?: boolean }, scene: Nullable<Scene>): LinesMesh {
             var instance = options.instance;
             var lines = options.lines;
+            var colors = options.colors;
 
             if (instance) { // lines update
-                var positionFunction = (positions: FloatArray) => {
-                    var i = 0;
-                    for (var l = 0; l < lines.length; l++) {
-                        var points = lines[l];
-                        for (var p = 0; p < points.length; p++) {
-                            positions[i] = points[p].x;
-                            positions[i + 1] = points[p].y;
-                            positions[i + 2] = points[p].z;
-                            i += 3;
+                var positions = instance.getVerticesData(VertexBuffer.PositionKind)!;
+                var vertexColor;
+                var lineColors;
+                if (colors) {
+                    vertexColor = instance.getVerticesData(VertexBuffer.ColorKind)!;
+                }
+                var i = 0;
+                var c = 0;
+                for (var l = 0; l < lines.length; l++) {
+                    var points = lines[l];
+                    for (var p = 0; p < points.length; p++) {
+                        positions[i] = points[p].x;
+                        positions[i + 1] = points[p].y;
+                        positions[i + 2] = points[p].z;
+                        if (colors && vertexColor) {
+                            lineColors = colors[l];
+                            vertexColor[c] = lineColors[p].r;
+                            vertexColor[c + 1] = lineColors[p].g;
+                            vertexColor[c + 2] = lineColors[p].b;
+                            vertexColor[c + 3] = lineColors[p].a;
+                            c += 4;
                         }
+                        i += 3;
                     }
-                };
-                instance.updateMeshPositions(positionFunction, false);
+                }
+                instance.updateVerticesData(VertexBuffer.PositionKind, positions, false, false);
+                if (colors && vertexColor) {
+                    instance.updateVerticesData(VertexBuffer.ColorKind, vertexColor, false, false)
+                }
                 return instance;
             }
 
             // line system creation
-            var lineSystem = new LinesMesh(name, scene);
+            var useVertexColor = (colors) ? true : false;
+            var lineSystem = new LinesMesh(name, scene, null, undefined, undefined, useVertexColor, options.useVertexAlpha);
             var vertexData = VertexData.CreateLineSystem(options);
             vertexData.applyToMesh(lineSystem, options.updatable);
             return lineSystem;
@@ -397,11 +417,14 @@
          * Like every other parametric shape, it is dynamically updatable by passing an existing instance of LineMesh to this static function.  
          * The parameter `points` is an array successive Vector3.   
          * The optional parameter `instance` is an instance of an existing LineMesh object to be updated with the passed `points` parameter : http://doc.babylonjs.com/tutorials/How_to_dynamically_morph_a_mesh#lines-and-dashedlines    
+         * The optional parameter `colors` is an array of successive Color4, one per line point.  
+         * The optional parameter `useVertexAlpha' is to be set to `true` (default `false`) when the alpha value from the former `Color4` array must be used.  
          * When updating an instance, remember that only point positions can change, not the number of points.      
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateLines(name: string, options: { points: Vector3[], updatable: boolean, instance: Nullable<LinesMesh> }, scene: Nullable<Scene> = null): LinesMesh {
-            var lines = MeshBuilder.CreateLineSystem(name, { lines: [options.points], updatable: options.updatable, instance: options.instance }, scene);
+        public static CreateLines(name: string, options: { points: Vector3[], updatable: boolean, instance: Nullable<LinesMesh>, colors?: Color4[], useVertexAlpha?: boolean }, scene: Nullable<Scene> = null): LinesMesh {
+            var colors = (options.colors) ? [options.colors] : null;
+            var lines = MeshBuilder.CreateLineSystem(name, { lines: [options.points], updatable: options.updatable, instance: options.instance, colors: colors, useVertexAlpha: options.useVertexAlpha }, scene);
             return lines;
         }
 

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 68 - 48
src/Tools/babylon.tools.ts


+ 105 - 99
src/babylon.scene.ts

@@ -96,7 +96,7 @@
         private static _FOGMODE_EXP2 = 2;
         private static _FOGMODE_LINEAR = 3;
 
-        private static _uniqueIdCounter = 0;        
+        private static _uniqueIdCounter = 0;
 
         public static MinDeltaTime = 1.0;
         public static MaxDeltaTime = 1000.0;
@@ -147,7 +147,7 @@
             if (this._environmentTexture === value) {
                 return;
             }
-            
+
             this._environmentTexture = value;
             this.markAllMaterialsAsDirty(Material.TextureDirtyFlag);
         }
@@ -253,37 +253,37 @@
         * An event triggered before animating the scene
         * @type {BABYLON.Observable}
         */
-        public onBeforeAnimationsObservable = new Observable<Scene>();       
-        
+        public onBeforeAnimationsObservable = new Observable<Scene>();
+
         /**
         * An event triggered after animations processing
         * @type {BABYLON.Observable}
         */
-        public onAfterAnimationsObservable = new Observable<Scene>();               
+        public onAfterAnimationsObservable = new Observable<Scene>();
 
         /**
         * An event triggered before draw calls are ready to be sent
         * @type {BABYLON.Observable}
         */
-        public onBeforeDrawPhaseObservable = new Observable<Scene>();          
+        public onBeforeDrawPhaseObservable = new Observable<Scene>();
 
         /**
         * An event triggered after draw calls have been sent
         * @type {BABYLON.Observable}
         */
-        public onAfterDrawPhaseObservable = new Observable<Scene>();         
-        
+        public onAfterDrawPhaseObservable = new Observable<Scene>();
+
         /**
         * An event triggered when physic simulation is about to be run
         * @type {BABYLON.Observable}
         */
-        public onBeforePhysicsObservable = new Observable<Scene>();          
-        
+        public onBeforePhysicsObservable = new Observable<Scene>();
+
         /**
         * An event triggered when physic simulation has been done
         * @type {BABYLON.Observable}
         */
-        public onAfterPhysicsObservable = new Observable<Scene>();           
+        public onAfterPhysicsObservable = new Observable<Scene>();
 
         /**
         * An event triggered when the scene is ready
@@ -324,47 +324,47 @@
         * An event triggered when active meshes evaluation is about to start
         * @type {BABYLON.Observable}
         */
-        public onBeforeActiveMeshesEvaluationObservable = new Observable<Scene>();        
+        public onBeforeActiveMeshesEvaluationObservable = new Observable<Scene>();
 
         /**
         * An event triggered when active meshes evaluation is done
         * @type {BABYLON.Observable}
         */
-        public onAfterActiveMeshesEvaluationObservable = new Observable<Scene>();           
+        public onAfterActiveMeshesEvaluationObservable = new Observable<Scene>();
 
         /**
         * An event triggered when particles rendering is about to start
         * Note: This event can be trigger more than once per frame (because particles can be rendered by render target textures as well)
         * @type {BABYLON.Observable}
         */
-        public onBeforeParticlesRenderingObservable = new Observable<Scene>();        
-        
+        public onBeforeParticlesRenderingObservable = new Observable<Scene>();
+
         /**
         * An event triggered when particles rendering is done
         * Note: This event can be trigger more than once per frame (because particles can be rendered by render target textures as well)
         * @type {BABYLON.Observable}
         */
-        public onAfterParticlesRenderingObservable = new Observable<Scene>();  
+        public onAfterParticlesRenderingObservable = new Observable<Scene>();
 
         /**
         * An event triggered when sprites rendering is about to start
         * Note: This event can be trigger more than once per frame (because sprites can be rendered by render target textures as well)
         * @type {BABYLON.Observable}
         */
-        public onBeforeSpritesRenderingObservable = new Observable<Scene>();        
-        
+        public onBeforeSpritesRenderingObservable = new Observable<Scene>();
+
         /**
         * An event triggered when sprites rendering is done
         * Note: This event can be trigger more than once per frame (because sprites can be rendered by render target textures as well)
         * @type {BABYLON.Observable}
         */
-        public onAfterSpritesRenderingObservable = new Observable<Scene>();          
+        public onAfterSpritesRenderingObservable = new Observable<Scene>();
 
         /**
         * An event triggered when SceneLoader.Append or SceneLoader.Load or SceneLoader.ImportMesh were successfully executed
         * @type {BABYLON.Observable}
         */
-        public onDataLoadedObservable = new Observable<Scene>();            
+        public onDataLoadedObservable = new Observable<Scene>();
 
         /**
         * An event triggered when a camera is created
@@ -407,12 +407,12 @@
         * @type {BABYLON.Observable}
         */
         public onNewTransformNodeAddedObservable = new Observable<TransformNode>();
-        
+
         /**
         * An event triggered when a transform node is removed
         * @type {BABYLON.Observable}
         */
-        public onTransformNodeRemovedObservable = new Observable<TransformNode>();        
+        public onTransformNodeRemovedObservable = new Observable<TransformNode>();
 
         /**
         * An event triggered when a mesh is created
@@ -432,13 +432,13 @@
         * @type {BABYLON.Observable}
         */
         public OnBeforeRenderTargetsRenderObservable = new Observable<Scene>();
-        
+
         /**
         * An event triggered when render targets were rendered.
         * Can happen multiple times per frame.
         * @type {BABYLON.Observable}
         */
-        public OnAfterRenderTargetsRenderObservable = new Observable<Scene>();      
+        public OnAfterRenderTargetsRenderObservable = new Observable<Scene>();
 
         /**
         * An event triggered before calculating deterministic simulation step
@@ -553,7 +553,7 @@
          * You have the possibility to skip the process and the call to onKeyboardObservable by setting KeyboardInfoPre.skipOnPointerObservable to true
          */
         public onPreKeyboardObservable = new Observable<KeyboardInfoPre>();
-        
+
         /**
          * Observable event triggered each time an keyboard event is received from the hosting window
          */
@@ -1116,7 +1116,7 @@
 
         public getRenderTargetsDuration(): number {
             Tools.Warn("getRenderTargetsDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;            
+            return 0;
         }
 
         public getRenderDuration(): number {
@@ -1200,7 +1200,7 @@
         }
 
         private _processPointerMove(pickResult: Nullable<PickingInfo>, evt: PointerEvent): Scene {
-            
+
             var canvas = this._engine.getRenderingCanvas();
 
             if (!canvas) {
@@ -1252,7 +1252,7 @@
                 }
             }
 
-            return this;            
+            return this;
         }
 
         /**
@@ -1263,7 +1263,7 @@
             let evt = new PointerEvent("pointerdown");
 
             return this._processPointerDown(pickResult, evt);
-        }        
+        }
 
         private _processPointerDown(pickResult: Nullable<PickingInfo>, evt: PointerEvent): Scene {
             if (pickResult && pickResult.hit && pickResult.pickedMesh) {
@@ -1330,9 +1330,9 @@
             clickInfo.singleClick = true;
 
             return this._processPointerUp(pickResult, evt, clickInfo);
-        }    
+        }
 
-        private _processPointerUp(pickResult: Nullable<PickingInfo>, evt: PointerEvent, clickInfo: ClickInfo): Scene {            
+        private _processPointerUp(pickResult: Nullable<PickingInfo>, evt: PointerEvent, clickInfo: ClickInfo): Scene {
             if (pickResult && pickResult && pickResult.pickedMesh) {
                 this._pickedUpMesh = pickResult.pickedMesh;
                 if (this._pickedDownMesh === this._pickedUpMesh) {
@@ -1560,7 +1560,7 @@
                 }
 
                 // Meshes
-                var pickResult = this.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, this.pointerMovePredicate, false, this.cameraToUseForPointers);             
+                var pickResult = this.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, this.pointerMovePredicate, false, this.cameraToUseForPointers);
 
                 this._processPointerMove(pickResult, evt);
             };
@@ -1643,7 +1643,7 @@
                 this._pickedUpMesh = null;
                 this._meshPickProceed = false;
 
-                this._updatePointerPosition(evt);      
+                this._updatePointerPosition(evt);
                 this._initClickEvent(this.onPrePointerObservable, this.onPointerObservable, evt, (clickInfo: ClickInfo, pickResult: Nullable<PickingInfo>) => {
                     // PreObservable support
                     if (this.onPrePointerObservable.hasObservers()) {
@@ -1762,18 +1762,18 @@
             };
 
             let engine = this.getEngine();
-            this._onCanvasFocusObserver = engine.onCanvasFocusObservable.add(()=>{
+            this._onCanvasFocusObserver = engine.onCanvasFocusObservable.add(() => {
                 if (!canvas) {
                     return;
                 }
                 canvas.addEventListener("keydown", this._onKeyDown, false);
-                canvas.addEventListener("keyup", this._onKeyUp, false);   
+                canvas.addEventListener("keyup", this._onKeyUp, false);
             });
 
-            this._onCanvasBlurObserver = engine.onCanvasBlurObservable.add(()=>{       
+            this._onCanvasBlurObserver = engine.onCanvasBlurObservable.add(() => {
                 if (!canvas) {
                     return;
-                }                         
+                }
                 canvas.removeEventListener("keydown", this._onKeyDown);
                 canvas.removeEventListener("keyup", this._onKeyUp);
             });
@@ -1836,7 +1836,7 @@
             this.onKeyboardObservable.clear();
             this.onPreKeyboardObservable.clear();
             this.onPointerObservable.clear();
-            this.onPrePointerObservable.clear();     
+            this.onPrePointerObservable.clear();
         }
 
         // Ready
@@ -2082,7 +2082,7 @@
             this._useAlternateCameraConfiguration = active;
         }
 
-        public getViewMatrix(): Matrix {            
+        public getViewMatrix(): Matrix {
             return this._useAlternateCameraConfiguration ? this._alternateViewMatrix : this._viewMatrix;
         }
 
@@ -2145,7 +2145,7 @@
             if (!this._alternateSceneUbo) {
                 this._createAlternateUbo();
             }
-            
+
             if (this._alternateSceneUbo.useUbo) {
                 this._alternateSceneUbo.updateMatrix("viewProjection", this._alternateTransformMatrix);
                 this._alternateSceneUbo.updateMatrix("view", this._alternateViewMatrix);
@@ -2186,13 +2186,13 @@
             this.onMeshRemovedObservable.notifyObservers(toRemove);
 
             return index;
-        }        
+        }
 
         public addTransformNode(newTransformNode: TransformNode) {
             this.transformNodes.push(newTransformNode);
 
             this.onNewTransformNodeAddedObservable.notifyObservers(newTransformNode);
-        }        
+        }
 
         public removeTransformNode(toRemove: TransformNode): number {
             var index = this.transformNodes.indexOf(toRemove);
@@ -2620,7 +2620,7 @@
             return this.transformNodes.filter(function (m) {
                 return m.id === id;
             })
-        }        
+        }
 
         /**
          * Get a mesh with its auto-generated unique id
@@ -2669,7 +2669,7 @@
                 if (this.transformNodes[index].id === id) {
                     return this.transformNodes[index];
                 }
-            }            
+            }
 
             for (index = this.cameras.length - 1; index >= 0; index--) {
                 if (this.cameras[index].id === id) {
@@ -2752,7 +2752,7 @@
             }
 
             return null;
-        }        
+        }
 
         public getSoundByName(name: string): Nullable<Sound> {
             var index: number;
@@ -2923,7 +2923,7 @@
         public _isInIntermediateRendering(): boolean {
             return this._intermediateRendering
         }
-        
+
         private _activeMeshesFrozen = false;
 
         /**
@@ -2934,7 +2934,7 @@
             this._activeMeshesFrozen = true;
             return this;
         }
-        
+
         /**
          * Use this function to restart evaluating active meshes on every frame
          */
@@ -3010,7 +3010,7 @@
                 if (mesh.alwaysSelectAsActiveMesh || mesh.isVisible && mesh.visibility > 0 && ((mesh.layerMask & this.activeCamera.layerMask) !== 0) && mesh.isInFrustum(this._frustumPlanes)) {
                     this._activeMeshes.push(mesh);
                     this.activeCamera._activeMeshes.push(mesh);
-                        
+
                     mesh._activate(this._renderId);
                     if (meshLOD !== mesh) {
                         meshLOD._activate(this._renderId);
@@ -3057,7 +3057,7 @@
             if (sourceMesh.showBoundingBox || this.forceShowBoundingBoxes) {
                 let boundingInfo = sourceMesh.getBoundingInfo();
 
-                this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);    
+                this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
             }
 
             if (mesh && mesh.subMeshes) {
@@ -3107,7 +3107,7 @@
                 throw new Error("Active camera not set");
 
             Tools.StartPerformanceCounter("Rendering camera " + this.activeCamera.name);
-           
+
             // Viewport
             engine.setViewport(this.activeCamera.viewport);
 
@@ -3211,7 +3211,7 @@
                 }
                 engine.setDepthBuffer(true);
             }
-        
+
             // Activate HighlightLayer stencil
             if (renderhighlights) {
                 this._engine.setStencilBuffer(true);
@@ -3270,7 +3270,7 @@
 
             // Finalize frame
             this.postProcessManager._finalizeFrame(camera.isIntermediate);
-           
+
             // Reset some special arrays
             this._renderTargets.reset();
 
@@ -3291,7 +3291,7 @@
             if (this.activeCamera) {
                 this.activeCamera.update();
             }
-            
+
             // rig cameras
             for (var index = 0; index < camera._rigCameras.length; index++) {
                 this._renderForCamera(camera._rigCameras[index]);
@@ -3368,60 +3368,66 @@
                 this.simplificationQueue.executeNext();
             }
 
-            if(this._engine.isDeterministicLockStep()){
-              var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime)) / 1000;
+            if (this._engine.isDeterministicLockStep()) {
+                var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime)) + this._timeAccumulator;
+
+                var defaultFPS = (60.0 / 1000.0);
+
+                let defaultFrameTime = 1000 / 60; // frame time in MS
+
+                if (this._physicsEngine) {
+                    defaultFrameTime = this._physicsEngine.getTimeStep() / 1000; //timestep in physics engine is in seconds
+                }
+                let stepsTaken = 0;
+
+                var maxSubSteps = this._engine.getLockstepMaxSteps();
+
+                var internalSteps = Math.floor(deltaTime / (1000 * defaultFPS));
+                internalSteps = Math.min(internalSteps, maxSubSteps);
 
-              var defaultTimeStep = (60.0 / 1000.0);
-              if (this._physicsEngine) {
-                defaultTimeStep = this._physicsEngine.getTimeStep();
-              }
+                do {
+                    this.onBeforeStepObservable.notifyObservers(this);
 
-              var maxSubSteps = this._engine.getLockstepMaxSteps();
+                    // Animations
+                    this._animationRatio = defaultFrameTime * defaultFPS;
+                    this._animate();
+                    this.onAfterAnimationsObservable.notifyObservers(this);
 
-              this._timeAccumulator += deltaTime;
+                    // Physics
+                    if (this._physicsEngine) {
+                        this.onBeforePhysicsObservable.notifyObservers(this);
+                        this._physicsEngine._step(defaultFPS);
+                        this.onAfterPhysicsObservable.notifyObservers(this);
+                    }
 
-              // compute the amount of fixed steps we should have taken since the last step
-              var internalSteps = Math.floor(this._timeAccumulator / defaultTimeStep);
-              internalSteps = Math.min(internalSteps, maxSubSteps);
+                    this.onAfterStepObservable.notifyObservers(this);
+                    this._currentStepId++;
 
-              for(this._currentInternalStep = 0; this._currentInternalStep < internalSteps; this._currentInternalStep++){
+                    if ((internalSteps > 1) && (stepsTaken != internalSteps - 1)) {
+                        this._evaluateActiveMeshes();
+                    }
 
-                this.onBeforeStepObservable.notifyObservers(this);
+                    stepsTaken++;
+                    deltaTime -= defaultFrameTime;
 
+                } while (deltaTime > 0 && stepsTaken > maxSubSteps);
+
+                this._timeAccumulator = deltaTime;
+
+            }
+            else {
                 // Animations
-                this._animationRatio = defaultTimeStep * (60.0 / 1000.0);
+                var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime));
+                this._animationRatio = deltaTime * (60.0 / 1000.0);
                 this._animate();
                 this.onAfterAnimationsObservable.notifyObservers(this);
 
                 // Physics
                 if (this._physicsEngine) {
-                   this.onBeforePhysicsObservable.notifyObservers(this);
-                   this._physicsEngine._step(defaultTimeStep);
-                   this.onAfterPhysicsObservable.notifyObservers(this);
-                }
-                this._timeAccumulator -= defaultTimeStep;
-
-                this.onAfterStepObservable.notifyObservers(this);
-                this._currentStepId++;
-
-                if((internalSteps > 1) && (this._currentInternalStep != internalSteps - 1)) {
-                    this._evaluateActiveMeshes();
+                    this.onBeforePhysicsObservable.notifyObservers(this);
+                    this._physicsEngine._step(deltaTime / 1000.0);
+                    this.onAfterPhysicsObservable.notifyObservers(this);
                 }
-              }
-            }
-            else {
-              // Animations
-              var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime));
-              this._animationRatio = deltaTime * (60.0 / 1000.0);
-              this._animate();
-              this.onAfterAnimationsObservable.notifyObservers(this);
-
-              // Physics
-              if (this._physicsEngine) {
-                this.onBeforePhysicsObservable.notifyObservers(this);
-                this._physicsEngine._step(deltaTime / 1000.0);
-                this.onAfterPhysicsObservable.notifyObservers(this);
-              }
             }
 
             // Before render
@@ -4001,7 +4007,7 @@
             // Moving coordinates to local viewport world
             x = x / this._engine.getHardwareScalingLevel() - viewport.x;
             y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
-            
+
             result.update(x, y, viewport.width, viewport.height, world ? world : Matrix.Identity(), cameraViewSpace ? Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
             return this;
         }
@@ -4178,7 +4184,7 @@
         public pickSprite(x: number, y: number, predicate?: (sprite: Sprite) => boolean, fastCheck?: boolean, camera?: Camera): Nullable<PickingInfo> {
             if (!this._tempPickingRay) {
                 this._tempPickingRay = Ray.Zero();
-            }            
+            }
             this.createPickingRayInCameraSpaceToRef(x, y, this._tempPickingRay, camera);
 
             return this._internalPickSprites(this._tempPickingRay, predicate, fastCheck, camera);
@@ -4201,7 +4207,7 @@
                 if (!this._cachedRayForTransform) {
                     this._cachedRayForTransform = Ray.Zero();
                 }
-                
+
                 Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
                 return this._cachedRayForTransform;
             }, predicate, fastCheck);
@@ -4233,7 +4239,7 @@
                 if (!this._cachedRayForTransform) {
                     this._cachedRayForTransform = Ray.Zero();
                 }
-                
+
                 Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
                 return this._cachedRayForTransform;
             }, predicate);
@@ -4337,7 +4343,7 @@
 
             if (this.postProcessManager) {
                 this.postProcessManager._rebuild();
-            }         
+            }
 
             for (var layer of this.layers) {
                 layer._rebuild();
@@ -4357,7 +4363,7 @@
 
             if (this._postProcessRenderPipelineManager) {
                 this._postProcessRenderPipelineManager._rebuild();
-            }            
+            }
         }
 
         public _rebuildTextures(): void {